Blob Blame History Raw
From 0cac8948216a298deaf5fd30837ed9cc80618f80 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 31 May 2011 18:02:29 +0200
Subject: [PATCH] mount: use libmount to detect already mounted bind mounts

It's pretty tricky to detect that a bind mount from fstab is already
mounted on system without /etc/mtab. Let's use functionality from
libmount.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=701176
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 mount/mount.c |   42 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/mount/mount.c b/mount/mount.c
index 29963c2..3ba705f 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -212,7 +212,7 @@ static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_sizelimit,
         *opt_encryption, *opt_speed, *opt_comment, *opt_uhelper;
 
 static int is_readonly(const char *node);
-static int mounted (const char *spec0, const char *node0);
+static int mounted (const char *spec0, const char *node0, struct mntentchn *fstab_mc);
 static int check_special_mountprog(const char *spec, const char *node,
 		const char *type, int flags, char *extra_opts, int *status);
 
@@ -1562,7 +1562,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
   /* The "mount -f" checks for for existing record in /etc/mtab (with
    * regular non-fake mount this is usually done by kernel)
    */
-  if (!(flags & MS_REMOUNT) && fake && mounted (spec, node))
+  if (!(flags & MS_REMOUNT) && fake && mounted (spec, node, NULL))
       die(EX_USAGE, _("mount: according to mtab, "
                       "%s is already mounted on %s\n"),
 		      spec, node);
@@ -2016,13 +2016,46 @@ mount_one (const char *spec, const char *node, const char *types,
 	return try_mount_one (spec, node, types, opts, freq, pass, 0);
 }
 
+#ifdef HAVE_LIBMOUNT_MOUNT
+static struct libmnt_table *minfo;	/* parsed mountinfo file */
+#endif
+
 /* Check if an fsname/dir pair was already in the old mtab.  */
 static int
-mounted (const char *spec0, const char *node0) {
+mounted (const char *spec0, const char *node0, struct mntentchn *fstab_mc) {
 	struct mntentchn *mc, *mc0;
 	const char *spec, *node;
 	int ret = 0;
 
+#ifdef HAVE_LIBMOUNT_MOUNT
+	/*
+	 * Use libmount to check for already mounted bind mounts on systems
+	 * without mtab.
+	 */
+	if (fstab_mc && fstab_mc->m.mnt_opts &&
+	    mtab_is_a_symlink() && strstr(fstab_mc->m.mnt_opts, "bind")) {
+
+		struct libmnt_fs *fs = mnt_new_fs();
+		int rc = fs ? 0 : -1;
+
+		if (!rc)
+			rc = mnt_fs_set_fstype(fs, fstab_mc->m.mnt_type);
+		if (!rc)
+			rc = mnt_fs_set_source(fs, fstab_mc->m.mnt_fsname);
+		if (!rc)
+			rc = mnt_fs_set_target(fs, fstab_mc->m.mnt_dir);
+		if (!rc)
+			rc =  mnt_fs_set_options(fs, fstab_mc->m.mnt_opts);
+		if (!rc && !minfo)
+			 minfo = mnt_new_table_from_file("/proc/self/mountinfo");
+		if (!rc && minfo)
+			rc = mnt_table_is_fs_mounted(minfo, fs);
+
+		mnt_free_fs(fs);
+		if (rc == 1)
+			return 1;
+	}
+#endif
 	/* Handle possible UUID= and LABEL= in spec */
 	spec = spec_to_devname(spec0);
 	if (!spec)
@@ -2030,6 +2063,7 @@ mounted (const char *spec0, const char *node0) {
 
 	node = canonicalize(node0);
 
+
 	mc0 = mtab_head();
 	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
 		if (streq (spec, mc->m.mnt_fsname) &&
@@ -2050,7 +2084,7 @@ is_fstab_entry_mounted(struct mntentchn *mc, int verbose)
 {
 	struct stat st;
 
-	if (mounted(mc->m.mnt_fsname, mc->m.mnt_dir))
+	if (mounted(mc->m.mnt_fsname, mc->m.mnt_dir, mc))
 		goto yes;
 
 	/* extra care for loop devices */
-- 
1.7.5.2