From 0cac8948216a298deaf5fd30837ed9cc80618f80 Mon Sep 17 00:00:00 2001 From: Karel Zak 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 --- 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