diff --git a/util-linux-2.19-kernel-version.patch b/util-linux-2.19-kernel-version.patch new file mode 100644 index 0000000..c15b93f --- /dev/null +++ b/util-linux-2.19-kernel-version.patch @@ -0,0 +1,32 @@ +From fa7e0d6d442de9f5940f99fd93f4522602439131 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 6 Jun 2011 12:35:26 +0200 +Subject: [PATCH] lib: [linux_version.c] accommodate two-component linux + version (e.g. 3.0) + +Signed-off-by: Karel Zak +--- + lib/linux_version.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/linux_version.c b/lib/linux_version.c +index f9fbd8d..ada566a 100644 +--- a/lib/linux_version.c ++++ b/lib/linux_version.c +@@ -16,10 +16,10 @@ get_linux_version (void) + return kver; + if (uname (&uts)) + kver = 0; +- else if (sscanf (uts.release, "%d.%d.%d", &major, &minor, &teeny) != 3) +- kver = 0; +- else ++ else if (sscanf (uts.release, "%d.%d.%d", &major, &minor, &teeny) == 3) + kver = KERNEL_VERSION (major, minor, teeny); ++ else if (sscanf (uts.release, "%d.%d", &major, &minor) == 2) ++ kver = KERNEL_VERSION (major, minor, 0); + + return kver; + } +-- +1.7.5.2 + diff --git a/util-linux-2.19-libmount-mounted.patch b/util-linux-2.19-libmount-mounted.patch new file mode 100644 index 0000000..99b8e38 --- /dev/null +++ b/util-linux-2.19-libmount-mounted.patch @@ -0,0 +1,290 @@ +From 5c60a0eab5155043f58fa88909d89e0b06cad2f8 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Tue, 31 May 2011 18:01:36 +0200 +Subject: [PATCH] libmount: add mnt_table_is_mounted() + +Signed-off-by: Karel Zak +--- + shlibs/mount/src/libmount.h.in | 3 + + shlibs/mount/src/libmount.sym | 1 + + shlibs/mount/src/tab.c | 210 ++++++++++++++++++++++++++++++++++++++++ + shlibs/mount/src/tab_update.c | 2 +- + 4 files changed, 215 insertions(+), 1 deletions(-) + +diff --git a/shlibs/mount/src/libmount.h.in b/shlibs/mount/src/libmount.h.in +index 3ea2f92..1522208 100644 +--- a/shlibs/mount/src/libmount.h.in ++++ b/shlibs/mount/src/libmount.h.in +@@ -308,6 +308,9 @@ extern int mnt_table_find_next_fs(struct libmnt_table *tb, + int (*match_func)(struct libmnt_fs *, void *), void *userdata, + struct libmnt_fs **fs); + ++extern int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs); ++ ++ + /* tab_update.c */ + extern struct libmnt_update *mnt_new_update(void); + extern void mnt_free_update(struct libmnt_update *upd); +diff --git a/shlibs/mount/src/libmount.sym b/shlibs/mount/src/libmount.sym +index 0b7c560..a498916 100644 +--- a/shlibs/mount/src/libmount.sym ++++ b/shlibs/mount/src/libmount.sym +@@ -195,6 +195,7 @@ global: + mnt_update_is_ready; + mnt_update_set_fs; + mnt_update_table; ++ mnt_table_is_fs_mounted; + local: + *; + }; +diff --git a/shlibs/mount/src/tab.c b/shlibs/mount/src/tab.c +index 2a6a235..38a5d5b 100644 +--- a/shlibs/mount/src/tab.c ++++ b/shlibs/mount/src/tab.c +@@ -712,6 +712,175 @@ struct libmnt_fs *mnt_table_find_pair(struct libmnt_table *tb, const char *sourc + return NULL; + } + ++/* ++ * @tb: /proc/self/mountinfo ++ * @fs: filesystem ++ * @mountflags: MS_BIND or 0 ++ * @fsroot: fs-root that will be probably used in the mountinfo file ++ * for @fs after mount(2) ++ * ++ * For btrfs subvolumes this function returns NULL, but @fsroot properly set. ++ * ++ * Returns: entry from @tb that will be used as a source for @fs if the @fs is ++ * bindmount. ++ */ ++struct libmnt_fs *mnt_table_get_fs_root(struct libmnt_table *tb, ++ struct libmnt_fs *fs, ++ unsigned long mountflags, ++ char **fsroot) ++{ ++ char *root = NULL, *mnt = NULL; ++ const char *fstype; ++ struct libmnt_fs *src_fs = NULL; ++ ++ assert(tb); ++ assert(fs); ++ assert(fsroot); ++ ++ DBG(TAB, mnt_debug("lookup fs-root for %s", mnt_fs_get_source(fs))); ++ ++ fstype = mnt_fs_get_fstype(fs); ++ ++ if (mountflags & MS_BIND) { ++ const char *src, *src_root; ++ ++ DBG(TAB, mnt_debug("fs-root for bind")); ++ ++ src = mnt_resolve_spec(mnt_fs_get_source(fs), tb->cache); ++ if (!src) ++ goto err; ++ ++ mnt = mnt_get_mountpoint(src); ++ if (!mnt) ++ goto err; ++ ++ root = mnt_get_fs_root(src, mnt); ++ ++ src_fs = mnt_table_find_target(tb, mnt, MNT_ITER_BACKWARD); ++ if (!src_fs) { ++ DBG(TAB, mnt_debug("not found '%s' in mountinfo -- using default", mnt)); ++ goto dflt; ++ } ++ ++ /* on btrfs the subvolume is used as fs-root in ++ * /proc/self/mountinfo, so we have to get the original subvolume ++ * name from src_fs and prepend the subvolume name to the ++ * fs-root path ++ */ ++ src_root = mnt_fs_get_root(src_fs); ++ if (src_root && !startswith(root, src_root)) { ++ size_t sz = strlen(root) + strlen(src_root) + 1; ++ char *tmp = malloc(sz); ++ ++ if (!tmp) ++ goto err; ++ snprintf(tmp, sz, "%s%s", src_root, root); ++ free(root); ++ root = tmp; ++ } ++ } ++ ++ /* ++ * btrfs-subvolume mount -- get subvolume name and use it as a root-fs path ++ */ ++ else if (fstype && !strcmp(fstype, "btrfs")) { ++ char *vol = NULL, *p; ++ size_t sz, volsz = 0; ++ ++ if (mnt_fs_get_option(fs, "subvol", &vol, &volsz)) ++ goto dflt; ++ ++ DBG(TAB, mnt_debug("setting FS root: btrfs subvol")); ++ ++ sz = volsz; ++ if (*vol != '/') ++ sz++; ++ root = malloc(sz + 1); ++ if (!root) ++ goto err; ++ p = root; ++ if (*vol != '/') ++ *p++ = '/'; ++ memcpy(p, vol, volsz); ++ *(root + sz) = '\0'; ++ } ++dflt: ++ if (!root) { ++ root = strdup("/"); ++ if (!root) ++ goto err; ++ } ++ *fsroot = root; ++ ++ DBG(TAB, mnt_debug("FS root result: %s", root)); ++ ++ free(mnt); ++ return src_fs; ++err: ++ free(root); ++ free(mnt); ++ return NULL; ++} ++ ++/** ++ * mnt_table_is_mounted: ++ * @tb: /proc/self/mountinfo file ++ * @fstab_fs: /etc/fstab entry ++ * ++ * Checks if the @fstab_fs entry is already in the @tb table. The "swap" ++ * is ignored. ++ * ++ * TODO: check for loopdev (see mount/mount.c is_fstab_entry_mounted(). ++ * ++ * Returns: 0 or 1 ++ */ ++int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs) ++{ ++ char *root = NULL; ++ struct libmnt_fs *src_fs; ++ const char *src, *tgt; ++ int flags = 0, rc = 0; ++ ++ assert(tb); ++ assert(fstab_fs); ++ ++ if (fstab_fs->flags & MNT_FS_SWAP) ++ return 0; ++ ++ if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0) ++ flags = MS_BIND; ++ ++ src_fs = mnt_table_get_fs_root(tb, fstab_fs, flags, &root); ++ if (src_fs) ++ src = mnt_fs_get_srcpath(src_fs); ++ else ++ src = mnt_resolve_spec(mnt_fs_get_source(fstab_fs), tb->cache); ++ ++ tgt = mnt_fs_get_target(fstab_fs); ++ ++ if (tgt || src || root) { ++ struct libmnt_iter itr; ++ struct libmnt_fs *fs; ++ ++ mnt_reset_iter(&itr, MNT_ITER_FORWARD); ++ ++ while(mnt_table_next_fs(tb, &itr, &fs) == 0) { ++ const char *s = mnt_fs_get_srcpath(fs), ++ *t = mnt_fs_get_target(fs), ++ *r = mnt_fs_get_root(fs); ++ ++ if (s && t && r && !strcmp(t, tgt) && ++ !strcmp(s, src) && !strcmp(r, root)) ++ break; ++ } ++ if (fs) ++ rc = 1; /* success */ ++ } ++ ++ free(root); ++ return rc; ++} ++ + #ifdef TEST_PROGRAM + + static int parser_errcb(struct libmnt_table *tb, const char *filename, int line) +@@ -869,6 +1038,46 @@ done: + return rc; + } + ++static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[]) ++{ ++ struct libmnt_table *tb = NULL, *fstab = NULL; ++ struct libmnt_fs *fs; ++ struct libmnt_iter *itr = NULL; ++ int rc; ++ ++ tb = mnt_new_table_from_file("/proc/self/mountinfo"); ++ if (!tb) { ++ fprintf(stderr, "failed to parse mountinfo\n"); ++ return -1; ++ } ++ ++ fstab = create_table(argv[1]); ++ if (!fstab) ++ goto done; ++ ++ itr = mnt_new_iter(MNT_ITER_FORWARD); ++ if (!itr) ++ goto done; ++ ++ while(mnt_table_next_fs(fstab, itr, &fs) == 0) { ++ if (mnt_table_is_fs_mounted(tb, fs)) ++ printf("%s already mounted on %s\n", ++ mnt_fs_get_source(fs), ++ mnt_fs_get_target(fs)); ++ else ++ printf("%s not mounted on %s\n", ++ mnt_fs_get_source(fs), ++ mnt_fs_get_target(fs)); ++ } ++ ++ rc = 0; ++done: ++ mnt_free_table(tb); ++ mnt_free_table(fstab); ++ mnt_free_iter(itr); ++ return rc; ++} ++ + int main(int argc, char *argv[]) + { + struct libmnt_test tss[] = { +@@ -877,6 +1086,7 @@ int main(int argc, char *argv[]) + { "--find-backward", test_find_bw, " " }, + { "--find-pair", test_find_pair, " " }, + { "--copy-fs", test_copy_fs, " copy root FS from the file" }, ++ { "--is-mounted", test_is_mounted, " check what from are already mounted" }, + { NULL } + }; + +diff --git a/shlibs/mount/src/tab_update.c b/shlibs/mount/src/tab_update.c +index 5abb566..9817f20 100644 +--- a/shlibs/mount/src/tab_update.c ++++ b/shlibs/mount/src/tab_update.c +@@ -410,7 +410,7 @@ static int set_fs_root(struct libmnt_fs *result, struct libmnt_fs *fs, unsigned + mnt_fs_set_fstype(result, mnt_fs_get_fstype(src_fs)); + + /* on btrfs the subvolume is used as fs-root in +- * /proc/self/mountinfo, so we have get the original subvolume ++ * /proc/self/mountinfo, so we have to get the original subvolume + * name from src_fs and prepend the subvolume name to the + * fs-root path + */ +-- +1.7.5.2 + diff --git a/util-linux-2.19-mount-a-bind.patch b/util-linux-2.19-mount-a-bind.patch new file mode 100644 index 0000000..5d6eb59 --- /dev/null +++ b/util-linux-2.19-mount-a-bind.patch @@ -0,0 +1,105 @@ +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 + diff --git a/util-linux-2.19-mount-fsname.patch b/util-linux-2.19-mount-fsname.patch new file mode 100644 index 0000000..686d7fb --- /dev/null +++ b/util-linux-2.19-mount-fsname.patch @@ -0,0 +1,33 @@ +From aab72640daa7ee2db3d42fc8278ab86e3aef2d71 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 2 Jun 2011 14:53:42 +0200 +Subject: [PATCH] mount: canonicalize fstab mnt_dir + +Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=709681 +Signed-off-by: Karel Zak +--- + mount/fstab.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/mount/fstab.c b/mount/fstab.c +index 8ce733b..4fa26b4 100644 +--- a/mount/fstab.c ++++ b/mount/fstab.c +@@ -455,7 +455,13 @@ getfs_by_dir (const char *dir) { + + cdir = canonicalize(dir); + for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { +- if (streq(mc->m.mnt_dir, cdir)) { ++ int ok = streq(mc->m.mnt_dir, cdir); ++ if (!ok) { ++ char *dr = canonicalize(mc->m.mnt_dir); ++ ok = dr ? streq(dr, cdir) : 0; ++ free(dr); ++ } ++ if (ok) { + free(cdir); + return mc; + } +-- +1.7.5.2 + diff --git a/util-linux-2.19-mount-mountpoint.patch b/util-linux-2.19-mount-mountpoint.patch new file mode 100644 index 0000000..bd97aa7 --- /dev/null +++ b/util-linux-2.19-mount-mountpoint.patch @@ -0,0 +1,76 @@ +From 067e9b4934372f72b89b2c0442a3d28290834537 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Wed, 29 Jun 2011 09:02:50 +0200 +Subject: [PATCH] mount: first look for mountpoint + + # mount + +The current code looks for a device and then for a mountpoint in +/etc/fstab. This is not user friendly solution. People usually use + + # mount /dir + +to mount any filesystem. It makes more sense to check for mountpoint +and if not found then for device. + +This is also important for bind mounts, for example if you have in +your fstab: + + /dev/sda1 /mnt/foo auto defaults + /mnt/foo /mnt/bar none bind + +then + # mount /mnt/foo + +should be interpreted as the first entry and /dev/sda1 should be +mounted. + +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=716483 +Signed-off-by: Karel Zak +--- + mount/mount.8 | 11 +++++++++++ + mount/mount.c | 4 ++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/mount/mount.8 b/mount/mount.8 +index 8982537..e9a52dd 100644 +--- a/mount/mount.8 ++++ b/mount/mount.8 +@@ -101,6 +101,17 @@ the pathname + refers to the root of the filesystem on + .IR device . + ++If only directory or device is given, for example: ++.RS ++ ++.br ++.BI "mount /dir" ++.br ++ ++.RE ++then mount looks for a mountpoint and if not found then for a device in the ++/etc/fstab file. ++ + .B The listing and help. + .RS + Three forms of invocation do not actually mount anything: +diff --git a/mount/mount.c b/mount/mount.c +index 3ba705f..00637f5 100644 +--- a/mount/mount.c ++++ b/mount/mount.c +@@ -2347,10 +2347,10 @@ getfs(const char *spec, const char *uuid, const char *label) + else if (label) + mc = getfs_by_label(label); + else { +- mc = getfs_by_spec(spec); ++ mc = getfs_by_dir(spec); + + if (!mc) +- mc = getfs_by_dir(spec); ++ mc = getfs_by_spec(spec); + } + if (mc) + return mc; +-- +1.7.5.4 + diff --git a/util-linux.spec b/util-linux.spec index f700e0d..8b59dad 100644 --- a/util-linux.spec +++ b/util-linux.spec @@ -2,7 +2,7 @@ Summary: A collection of basic system utilities Name: util-linux Version: 2.19.1 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2 and GPLv2+ and GPLv3+ and LGPLv2+ and BSD with advertising and Public Domain Group: System Environment/Base URL: http://kernel.org/~kzak/util-linux/ @@ -84,6 +84,18 @@ Patch7: util-linux-ng-2.13-login-lastlog.patch # 231192 - ipcs is not printing correct values on pLinux Patch8: util-linux-ng-2.15-ipcs-32bit.patch +### Upstream patches +### +# kernel "3.0" +Patch9: util-linux-2.19-kernel-version.patch +# 709319 - 'mount -a' mounts already mounted directories +Patch10: util-linux-2.19-libmount-mounted.patch +Patch11: util-linux-2.19-mount-a-bind.patch +# 709681 - failure to mount if a mount point ends with a slash in /etc/fstab +Patch12: util-linux-2.19-mount-fsname.patch +# 716483 - /var/tmp --(BIND-mounted)--> /tmp disrupts/hangs bootup +Patch13: util-linux-2.19-mount-mountpoint.patch + %description The util-linux package contains a large variety of low-level system utilities that are necessary for a Linux system to function. Among @@ -197,6 +209,12 @@ cp %{SOURCE8} %{SOURCE9} . %patch5 -p1 %patch7 -p1 %patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 + %build unset LINGUAS || : @@ -742,6 +760,12 @@ fi %changelog +* Mon Jul 4 2011 Karel Zak 2.19.1-2 +- fix #716483 - /var/tmp --(BIND-mounted)--> /tmp disrupts/hangs bootup +- fix #709681 - failure to mount if a mount point ends with a slash in /etc/fstab +- fix #709319 - 'mount -a' mounts already mounted directories +- fix kernel version parsing + * Fri May 6 2011 Karel Zak 2.19.1-1 - upgrade to the release 2.19.1 ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19.1-ReleaseNotes