[PATCH] mount: get most recently mounted fs from /etc/mtab.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I spent most of the day tracking down this subtle remount bug.  I
think this is the correct solution but I'd appreciate some
double-checking.  I suspect this bug will munge the mount options
whenever you remount a file system mounted on the same mountpoint as
another file system, using the mountpoint as the handle.

-VAL

commit c010b3a0783430e2b94f3b3dc0929ae299e383eb
Author: Valerie Aurora <vaurora@xxxxxxxxxx>
Date:   Tue Aug 3 16:32:52 2010 -0700

    mount: get most recently mounted fs from /etc/mtab.
    
    In mount, when using /etc/mtab to lookup a mount entry, get the most
    recently mounted entry instead of the first mounted entry.  You want
    to manipulate the most recent mount, not a covered mount.  See comment
    to umount_one_bw().
    
    This bug has been util-linux-ng since the first git checkin.  It
    finally showed up on my system with the change to stop using
    SETLOOP_AUTOCLEAR if /etc/mtab is writable (commit af092544).  If you
    do a remount of a file system mounted on the same dir as another file
    system, it will take the options from the first mount and write them
    out to /etc/mtab as the options to the second mount - including, in
    the case of a loop device, loop=/dev/loop0.  Then when you umount the
    second mount, it grabs the line from /etc/mtab and tries to tear down
    the loop device, which complains because it is still in use by the
    first mount.
    
    Reproducible test case (on a system with writable /etc/mtab):
    
    mount -o loop,ro /tmp/ro /mnt
    mount -t tmpfs tmpfs /mnt
    mount -o remount,ro /mnt
    cat /etc/mtab | tail -2
    
    Signed-off-by: Valerie Aurora <vaurora@xxxxxxxxxx>

diff --git a/mount/fstab.c b/mount/fstab.c
index 97d64a2..bfb2e5d 100644
--- a/mount/fstab.c
+++ b/mount/fstab.c
@@ -216,6 +216,24 @@ getmntfile (const char *name) {
 }
 
 /*
+ * Given the name NAME, and the place MCPREV we found it last time,
+ * try to find it in mtab.
+ */
+struct mntentchn *
+getmntfilebackward (const char *name, struct mntentchn *mcprev) {
+	struct mntentchn *mc, *mc0;
+
+	mc0 = mtab_head();
+	if (!mcprev)
+		mcprev = mc0;
+	for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_dir, name) ||
+		    streq(mc->m.mnt_fsname, name))
+			return mc;
+	return NULL;
+}
+
+/*
  * Given the directory name NAME, and the place MCPREV we found it last time,
  * try to find more occurrences.
  */
diff --git a/mount/fstab.h b/mount/fstab.h
index 38f7bab..e985506 100644
--- a/mount/fstab.h
+++ b/mount/fstab.h
@@ -15,6 +15,7 @@ struct mntentchn {
 
 struct mntentchn *mtab_head (void);
 struct mntentchn *getmntfile (const char *name);
+struct mntentchn *getmntfilebackward (const char *name, struct mntentchn *mcprev);
 struct mntentchn *getmntoptfile (const char *file);
 struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
 struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
diff --git a/mount/mount.c b/mount/mount.c
index 433941e..2e819e9 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -2140,10 +2140,11 @@ getfs(const char *spec, const char *uuid, const char *label)
 	/*
 	 * D) remount -- try /etc/mtab
 	 *    Earlier mtab was tried first, but this would sometimes try the
-	 *    wrong mount in case mtab had the root device entry wrong.
+	 *    wrong mount in case mtab had the root device entry wrong.  Try
+	 *    the last occurrence first, since that is the visible mount.
 	 */
 	if (!mc && (devname || spec))
-		mc = getmntfile (devname ? devname : spec);
+		mc = getmntfilebackward (devname ? devname : spec, NULL);
 
 	my_free(devname);
 	return mc;
--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux