]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
mount: use libmount to detect already mounted bind mounts
authorKarel Zak <kzak@redhat.com>
Tue, 31 May 2011 16:02:29 +0000 (18:02 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 31 May 2011 16:04:36 +0000 (18:04 +0200)
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

index 29963c21113f4ebc386170b09eafab9b6ccf6ada..3ba705f3ee292e0bf79295610536e66f99401b21 100644 (file)
@@ -212,7 +212,7 @@ static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_sizelimit,
         *opt_encryption, *opt_speed, *opt_comment, *opt_uhelper, *opt_helper;
 
 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 */