Wednesday, May 18, 2011

How linux mount uses /etc/mtab

From linux man page
The programs mount and umount maintain a list of currently mounted filesystems in the file /etc/mtab.  If no arguments are given to mount, this list is printed.
When  the  proc  filesystem  is  mounted (say at /proc), the files /etc/mtab and /proc/mounts have very similar contents. The former has somewhat more information, such as the mount options used, but is not necessarily up-to-date (cf. the -n option below). It is possible to replace /etc/mtab by a symbolic link to /proc/mounts, and especially when you have very large numbers of mounts things will be much faster with that symlink, but some information is lost that way, and in particular using the "user" option will fail.

To know how mount command uses mtab file can be found by tracing the calls of mount

XXX:~ # strace mount -o loop ubuntu-10.04.2-desktop-amd64.iso temp_mount 
 
would generate output of the all system calls that the mount command made
stat("ubuntu-10.04.2-desktop-amd64.iso", {st_mode=S_IFREG|0644, st_size=721129472, ...}) = 0 
getcwd("/home/XXX", 4095)          = 15
readlink("/home/XXX/ubuntu-10.04.2-desktop-amd64.iso", 0x7fff11803d10, 4096) = -1 EINVAL (Invalid argument)
getcwd("/home/XXX", 4095)          = 10
readlink("/home/XXX/temp_mount", 0x7fff11803a40, 4096) = -1 EINVAL (Invalid argument)
Checks if the given path is a softlink, then does verification from mtab if a mount has been done already. 


stat("/sbin/mount.iso9660", 0x7fff118048c0) = -1 ENOENT (No such file or directory)
mount("/dev/loop0", "temp_mount", "iso9660", MS_MGC_VAL, NULL) = 0
readlink("/dev", 0x7fff11803a40, 4096)  = -1 EINVAL (Invalid argument)
readlink("/dev/loop0", 0x7fff11803a40, 4096) = -1 EINVAL (Invalid argument)
getcwd("/home/XXX", 4095)          = 10
readlink("/home/XXX/temp_mount", 0x7fff11803a40, 4096) = -1 EINVAL (Invalid argument)
lstat("/etc/mtab", {st_mode=S_IFREG|0644, st_size=795, ...}) = 0
read_link("/home/XXX/temp_mount", 0x7fff11803a40, 4096) = -1 EINVAL (Invalid argument)
Checks the filesystem type and gets ready to call the corresponding filesystem mount command


getpid()                                = 1052
open("/etc/mtab~1052", O_WRONLY|O_CREAT, 0600) = 3
close(3)                                = 0
link("/etc/mtab~1052", "/etc/mtab~")    = 0
open("/etc/mtab~", O_WRONLY)            = 3
fcntl(3, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0
unlink("/etc/mtab~1052")                = 0
umask(077)                              = 022
open("/etc/mtab", O_RDWR|O_CREAT|O_APPEND, 0666) = 5
umask(022)                              = 077

Finds the current PID, then creates a /etc/mtab~ file. Since there shouldn't be two process with same pid, this should be open the only process which has this file open and even if this process dies and a new mount process is run with the same pid, the new process would be able to use the old file as the 'open' is not called with O_EXCL is not used. Once it ensures that /etc/mtab~1052 has been created using 'open' it goes ahead with set /etc/mtab~ and /etc/mtab~1052 as hard link. 

A crash here after creating hard link before 'unlink' of /etc/mtab~ creates problems with mount or umount commands. If a programs dies after creating the file /etc/mtab~, any new mount/umount operations would try to call 'link' which would fail as there is an already /etc/mtab~ file and would assume that somebody is trying to write to the /etc/mtab file.

Rest of the trace for the mount command is

open("/etc/mtab", O_RDWR|O_CREAT|O_APPEND, 0666) = 5
umask(022)                              = 077
fstat(5, {st_mode=S_IFREG|0644, st_size=795, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7a6819a000
fstat(5, {st_mode=S_IFREG|0644, st_size=795, ...}) = 0
lseek(5, 0, SEEK_SET)                   = 0
read(5, "/dev/sda6 / ext3 rw,errors=remou"..., 795) = 795
write(5, "/dev/loop0 /home/XXX/temp_m"..., 52) = 52
close(5)                                = 0
munmap(0x7f7a6819a000, 4096)            = 0
close(3)                                = 0
unlink("/etc/mtab~")                    = 0

mount will the open the /etc/mtab and append the new mounted filesystem. Removes /etc/mtab~ before exiting.

No comments:

Post a Comment