]> err.no Git - util-linux/commitdiff
mount: fix "mount -a" for auto-clear loopdevs and /proc/mounts
authorKarel Zak <kzak@redhat.com>
Thu, 29 Jul 2010 12:18:46 +0000 (14:18 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 29 Jul 2010 14:08:12 +0000 (16:08 +0200)
The "mount -a" uses /etc/mtab to detect already mounted file systems
from /etc/fstab -- this check requires the same FS name (1st field)
in fstab and mtab.

On systems with enabled auto-clear loop devies or systems without
regular mtab  (symlink to /proc/mounts) there is /dev/loopN rather
than image filename in mtab. For example:

  fstab:
     /mnt/store/foo.ISO /mnt/image auto defaults 0 0

  mtab:
     /dev/loop0 /mnt/image iso9960 rw 0 0

We have to scan all available loop devices to check if some of the
devices is not associated with the image file from fstab.

Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=618957
Signed-off-by: Karel Zak <kzak@redhat.com>
mount/mount.c

index fef1a852c4880f01cec7407291e093c8b254ae69..433941e1df8605e80e370f5a98f9e633700552e0 100644 (file)
@@ -1821,6 +1821,41 @@ mounted (const char *spec0, const char *node0) {
        return ret;
 }
 
+/* returns 0 if not mounted, 1 if mounted and -1 in case of error */
+static int
+is_fstab_entry_mounted(struct mntentchn *mc, int verbose)
+{
+       struct stat st;
+
+       if (mounted(mc->m.mnt_fsname, mc->m.mnt_dir))
+               goto yes;
+
+       /* extra care for loop devices */
+       if ((strstr(mc->m.mnt_opts, "loop=") ||
+            (stat(mc->m.mnt_fsname, &st) == 0 && S_ISREG(st.st_mode)))) {
+
+               char *p = strstr(mc->m.mnt_opts, "offset=");
+               uintmax_t offset = 0;
+
+               if (p && strtosize(p + 7, &offset) != 0) {
+                       if (verbose)
+                               printf(_("mount: ignore %s "
+                                       "(unparsable offset= option)\n"),
+                                       mc->m.mnt_fsname);
+                       return -1;
+               }
+               if (is_mounted_same_loopfile(mc->m.mnt_dir, mc->m.mnt_fsname, offset))
+                       goto yes;
+       }
+
+       return 0;
+yes:
+       if (verbose)
+               printf(_("mount: %s already mounted on %s\n"),
+                              mc->m.mnt_fsname, mc->m.mnt_dir);
+       return 1;
+}
+
 /* avoid using stat() on things we are not going to mount anyway.. */
 static int
 has_noauto (const char *opts) {
@@ -1866,16 +1901,8 @@ do_mount_all (char *types, char *options, char *test_opts) {
                if (matching_type (mc->m.mnt_type, types)
                    && matching_opts (mc->m.mnt_opts, test_opts)
                    && !streq (mc->m.mnt_dir, "/")
-                   && !streq (mc->m.mnt_dir, "root")) {
-
-                       if (mounted (mc->m.mnt_fsname, mc->m.mnt_dir)) {
-                               if (verbose)
-                                       printf(_("mount: %s already mounted "
-                                                "on %s\n"),
-                                              mc->m.mnt_fsname,
-                                              mc->m.mnt_dir);
-                               continue;
-                       }
+                   && !streq (mc->m.mnt_dir, "root")
+                   && !is_fstab_entry_mounted(mc, verbose)) {
 
                        mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp));
                        *mtmp = *mc;