Chapter 26. Initialization and Mounting

As mentioned previously, mount table entries can be sourced from two places. Static entries may be defined by using the MTAB_ENTRY() macro. Such entries will be automatically mounted on system startup. For each entry in the mount table that has a non-null name field the filesystem table is searched for a match with the fsname field. If a match is found the filesystem's mount entry is called and if successful the mount table entry marked valid and the fs field initialized. The mount() function is responsible for initializing the root field.

The size of the mount table is defined by the configuration value CYGNUM_FILEIO_MTAB_MAX. Any entries that have not been statically defined are available for use by dynamic mounts.

A filesystem may be mounted dynamically by calling mount(). This function has the following prototype:

int mount(const char *devname,
          const char *dir,
          const char *fsname);

The devname argument identifies a device that will be used by this filesystem and will be assigned to the devname field of the mount table entry.

The dir argument is the mount point name, it will be assigned to the name field of the mount table entry.

The fsname argument is the name of the implementing filesystem, it will be assigned to the fsname entry of the mount table entry. This argument may also contain options that control the mode in which the filesystem is mounted.

Since these three arguments are assigned directly to the mount table entry, the memory pointed to by these arguments must not change for the duration of the mount. This means they must be allocated from memory that will persist unchanged until unmounting, such as constant strings, dynamically allocated memory, or static or automatic variables that do not pass out of scope or get their values changed before unmounting.

The options attached to the fsname argument consist of a comma separated list of single keywords or keyword=value pairs separated from the filesystem name by a colon. For example, to mount the FAT filesystem with write-through cache synchronization the string would be: "fatfs:sync=write" and to mount it read-only: "fatfs:readonly".

The process of mounting a filesystem dynamically is as follows. First a search is made of the mount table for an entry with a NULL name field to be used for the new mount point. The filesystem table is then searched for an entry whose name matches fsname. If this is successful then the mount table entry is initialized and the filesystem's mount() operation called. If this is successful, the mount table entry is marked valid and the fs field initialized.

Mounting a filesystem dynamically at the current working directory name, does not in fact change the current directory to one on the newly mounted filesystem. Instead the current working directory remains on the previous filesystem (or no filesystem in the case of '/' with no filesystems previously mounted). This is in line with usual POSIX/UNIX behaviour. To change to the new filesystem, a chdir() call must be made, even if it is to the current directory name as given by getcwd(). This is especially relevant when mounting a filesystem on '/' as the current working directory is usually also '/' .

Normally you can access files and directories with both absolute paths (for example '/fs/dir1/file1.txt') or paths relative to the current working directory (for example './dir1/file1.txt' or just 'dir1/file1.txt'). As a special exception, you cannot use relative paths if your current working directory is the root directory '/', unless there is a filesystem mounted directly on '/'. This is a deliberate simplification due to the fact that the current working directory is not really a valid directory and there is no true filesystem at '/' to navigate within. Instead it is recommended to either change directory into a filesystem after mounting using chdir(), use absolute paths, or mount a filesystem at '/'.

It should also be noted that there is no requirement for there to be a directory entry for a filesystem mount point if mounted within another filesystem. So for example, there need not be a directory named “/dev” in the directory list of “/” even though there is a filesystem mounted on “/dev”.

Unmounting a filesystem is done by the umount() function. This can unmount filesystems whether they were mounted statically or dynamically.

The umount() function has the following prototype:

int umount( const char *name );

The mount table is searched for a match between the name argument and the entry name field. When a match is found the filesystem's umount() operation, with the force argument set to false is called and if successful, the mount table entry is invalidated by setting its valid field false and the name field to NULL.

There is also an umount_force() function with the following prototype:

int umount_force( const char *name );

The main difference between this and the standard umount() function is that it forces the filesystem to be unmounted. In the FILEIO package this means that all open files will be forced to close, the current directory will be moved away from the filesystem if it points to it and any threads waiting for access to the filesystem will be forced to return. In general, any buffered data not yet written to the medium will be lost; such buffering may take place in libraries like C standard I/O, C++ streams or the filesystem itself. If the programmer wishes for buffered data to be committed beforehand, they must use whatever mechanism has been provided by the layers performing the buffering. This is not always the case however, such as if the reason to force an unmounting is because the medium has been removed. When the filesystem's umount() function is called, the force argument will be set true, and the filesystem should take steps to free all resources and detach from the underlying device.

Care must be taken if mounting a filesystem on “/” as it will not be possible to unmount the filesystem later if it is in use as the current working directory. Instead it will be necessary to change directory to a different filesystem before unmounting.