From ba1a4ff3002394f3aad3da50369b0f2cf808505d Mon Sep 17 00:00:00 2001 From: Eric Desrochers Date: Fri, 26 Aug 2016 09:39:11 -0400 Subject: [PATCH] Change /etc/mtab to /proc/self/mounts Misleading error message "The /dev/zfs device is missing and must be created.", if /etc/mtab is missing. Signed-off-by: Eric Desrochers --- cmd/mount_zfs/mount_zfs.c | 66 --------------------------------- cmd/zfs/zfs_main.c | 23 ++++++------ cmd/zinject/translate.c | 2 +- config/user-commands.m4 | 2 +- contrib/initramfs/scripts/zfs | 7 ++-- etc/init.d/zfs-functions.in | 2 +- etc/init.d/zfs-mount.in | 4 +- include/sys/mntent.h | 1 - lib/libspl/include/sys/mnttab.h | 2 +- lib/libzfs/libzfs_dataset.c | 11 +++--- lib/libzfs/libzfs_mount.c | 12 +++--- scripts/ziltest.sh | 2 +- 12 files changed, 33 insertions(+), 101 deletions(-) diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c index b78c91c7ccfd..b16171179251 100644 --- a/cmd/mount_zfs/mount_zfs.c +++ b/cmd/mount_zfs/mount_zfs.c @@ -283,66 +283,6 @@ parse_dataset(char *dataset) return (dataset); } -/* - * Update the mtab_* code to use the libmount library when it is commonly - * available otherwise fallback to legacy mode. The mount(8) utility will - * manage the lock file for us to prevent racing updates to /etc/mtab. - */ -static int -mtab_is_writeable(void) -{ - struct stat st; - int error, fd; - - error = lstat(MNTTAB, &st); - if (error || S_ISLNK(st.st_mode)) - return (0); - - fd = open(MNTTAB, O_RDWR | O_CREAT, 0644); - if (fd < 0) - return (0); - - close(fd); - return (1); -} - -static int -mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts) -{ - struct mntent mnt; - FILE *fp; - int error; - - mnt.mnt_fsname = dataset; - mnt.mnt_dir = mntpoint; - mnt.mnt_type = type; - mnt.mnt_opts = mntopts ? mntopts : ""; - mnt.mnt_freq = 0; - mnt.mnt_passno = 0; - - fp = setmntent(MNTTAB, "a+"); - if (!fp) { - (void) fprintf(stderr, gettext( - "filesystem '%s' was mounted, but %s " - "could not be opened due to error %d\n"), - dataset, MNTTAB, errno); - return (MOUNT_FILEIO); - } - - error = addmntent(fp, &mnt); - if (error) { - (void) fprintf(stderr, gettext( - "filesystem '%s' was mounted, but %s " - "could not be updated due to error %d\n"), - dataset, MNTTAB, errno); - return (MOUNT_FILEIO); - } - - (void) endmntent(fp); - - return (MOUNT_SUCCESS); -} - static void append_mntopt(const char *name, const char *val, char *mntopts, char *mtabopt, boolean_t quote) @@ -615,11 +555,5 @@ main(int argc, char **argv) } } - if (!nomtab && mtab_is_writeable()) { - error = mtab_update(dataset, mntpoint, MNTTYPE_ZFS, mtabopt); - if (error) - return (error); - } - return (MOUNT_SUCCESS); } diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 8a8f56af9928..c60b137b802d 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -6116,9 +6116,10 @@ share_mount(int op, int argc, char **argv) } /* - * When mount is given no arguments, go through /etc/mtab and - * display any active ZFS mounts. We hide any snapshots, since - * they are controlled automatically. + * When mount is given no arguments, go through + * /proc/self/mounts and display any active ZFS mounts. + * We hide any snapshots, since they are controlled + * automatically. */ /* Reopen MNTTAB to prevent reading stale data from open file */ @@ -6198,8 +6199,8 @@ unshare_unmount_compare(const void *larg, const void *rarg, void *unused) /* * Convenience routine used by zfs_do_umount() and manual_unmount(). Given an - * absolute path, find the entry /etc/mtab, verify that its a ZFS filesystem, - * and unmount it appropriately. + * absolute path, find the entry /proc/self/mounts, verify that its a + * ZFS filesystems, and unmount it appropriately. */ static int unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) @@ -6212,7 +6213,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) ino_t path_inode; /* - * Search for the path in /etc/mtab. Rather than looking for the + * Search for the path in /proc/self/mounts. Rather than looking for the * specific path, which can be fooled by non-standard paths (i.e. ".." * or "//"), we stat() the path and search for the corresponding * (major,minor) device pair. @@ -6243,8 +6244,8 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) "currently mounted\n"), cmdname, path); return (1); } - (void) fprintf(stderr, gettext("warning: %s not in mtab\n"), - path); + (void) fprintf(stderr, gettext("warning: %s not in" + "/proc/self/mounts\n"), path); if ((ret = umount2(path, flags)) != 0) (void) fprintf(stderr, gettext("%s: %s\n"), path, strerror(errno)); @@ -6355,9 +6356,9 @@ unshare_unmount(int op, int argc, char **argv) /* * We could make use of zfs_for_each() to walk all datasets in * the system, but this would be very inefficient, especially - * since we would have to linearly search /etc/mtab for each - * one. Instead, do one pass through /etc/mtab looking for - * zfs entries and call zfs_unmount() for each one. + * since we would have to linearly search /proc/self/mounts for + * each one. Instead, do one pass through /proc/self/mounts + * looking for zfs entries and call zfs_unmount() for each one. * * Things get a little tricky if the administrator has created * mountpoints beneath other ZFS filesystems. In this case, we diff --git a/cmd/zinject/translate.c b/cmd/zinject/translate.c index 5cc9d9fdc707..fe6e0007822e 100644 --- a/cmd/zinject/translate.c +++ b/cmd/zinject/translate.c @@ -120,7 +120,7 @@ parse_pathname(const char *inpath, char *dataset, char *relpath, #else if ((fp = fopen(MNTTAB, "r")) == NULL) { #endif - (void) fprintf(stderr, "cannot open /etc/mtab\n"); + (void) fprintf(stderr, "cannot open /proc/self/mounts\n"); return (-1); } diff --git a/config/user-commands.m4 b/config/user-commands.m4 index bda2b8652b53..c657fe60cb54 100644 --- a/config/user-commands.m4 +++ b/config/user-commands.m4 @@ -118,7 +118,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER_COMMANDS_LINUX], [ PAGESIZE=$($GETCONF PAGESIZE) AC_SUBST(PAGESIZE) - MNTTAB=/etc/mtab + MNTTAB=/proc/self/mounts AC_SUBST(MNTTAB) ]) diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs index 6a78a46d29a1..250dc5717189 100644 --- a/contrib/initramfs/scripts/zfs +++ b/contrib/initramfs/scripts/zfs @@ -288,9 +288,8 @@ load_module_initrd() wait_for_dev fi - # zpool import refuse to import without a valid mtab - [ ! -f /proc/mounts ] && mount proc /proc - [ ! -f /etc/mtab ] && cat /proc/mounts > /etc/mtab + # zpool import refuse to import without a valid /proc/self/mounts + [ ! -f /proc/self/mounts ] && mount proc /proc # Load the module load_module "zfs" || return 1 @@ -919,7 +918,7 @@ mountroot() # # but the MOUNTPOINT prefix is preserved on descendent filesystem # after the pivot into the regular root, which later breaks things - # like `zfs mount -a` and the /etc/mtab refresh. + # like `zfs mount -a` and the /proc/self/mounts refresh. # # * Mount additional filesystems required # Such as /usr, /var, /usr/local etc. diff --git a/etc/init.d/zfs-functions.in b/etc/init.d/zfs-functions.in index acfdf99263d8..97f2ea039d7b 100644 --- a/etc/init.d/zfs-functions.in +++ b/etc/init.d/zfs-functions.in @@ -368,7 +368,7 @@ read_mtab() # Set the variable. eval export MTAB_$mntpnt=\"$fs\" fi - done < /proc/mounts + done < /proc/self/mounts } in_mtab() diff --git a/etc/init.d/zfs-mount.in b/etc/init.d/zfs-mount.in index 34db057c813e..2722a31e4080 100755 --- a/etc/init.d/zfs-mount.in +++ b/etc/init.d/zfs-mount.in @@ -39,7 +39,7 @@ chkroot() { if [ "$2" = "/" ]; then return 0 fi - done < /etc/mtab + done < /proc/self/mounts return 1 } @@ -178,7 +178,7 @@ do_start() check_module_loaded "zfs" || exit 0 - # Ensure / exists in /etc/mtab, if not update mtab accordingly. + # Ensure / exists in /proc/self/mounts. # This should be handled by rc.sysinit but lets be paranoid. if ! chkroot then diff --git a/include/sys/mntent.h b/include/sys/mntent.h index fac751b462bc..1d89293789ed 100644 --- a/include/sys/mntent.h +++ b/include/sys/mntent.h @@ -36,7 +36,6 @@ #define MOUNT_SYSERR 0x02 /* System error (ENOMEM, etc) */ #define MOUNT_SOFTWARE 0x04 /* Internal mount bug */ #define MOUNT_USER 0x08 /* Interrupted by user (EINTR) */ -#define MOUNT_FILEIO 0x10 /* Error updating/locking /etc/mtab */ #define MOUNT_FAIL 0x20 /* Mount failed */ #define MOUNT_SOMEOK 0x40 /* At least on mount succeeded */ #define MOUNT_BUSY 0x80 /* Mount failed due to EBUSY */ diff --git a/lib/libspl/include/sys/mnttab.h b/lib/libspl/include/sys/mnttab.h index 21d89658c6bf..026a8fa7beee 100644 --- a/lib/libspl/include/sys/mnttab.h +++ b/lib/libspl/include/sys/mnttab.h @@ -38,7 +38,7 @@ #undef MNTTAB #endif /* MNTTAB */ -#define MNTTAB "/etc/mtab" +#define MNTTAB "/proc/self/mounts" #define MNT_LINE_MAX 4096 #define MNT_TOOLONG 1 /* entry exceeds MNT_LINE_MAX */ diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 794d35fbe3d8..d0c557b81081 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -1911,9 +1911,9 @@ zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie) * zfs_prop_get_int() are built using this interface. * * Certain properties can be overridden using 'mount -o'. In this case, scan - * the contents of the /etc/mtab entry, searching for the appropriate options. - * If they differ from the on-disk values, report the current values and mark - * the source "temporary". + * the contents of the /proc/self/mounts entry, searching for the + * appropriate options. If they differ from the on-disk values, report the + * current values and mark the source "temporary". */ static int get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, @@ -1984,8 +1984,9 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, /* * Because looking up the mount options is potentially expensive - * (iterating over all of /etc/mtab), we defer its calculation until - * we're looking up a property which requires its presence. + * (iterating over all of /proc/self/mounts), we defer its + * calculation until we're looking up a property which requires + * its presence. */ if (!zhp->zfs_mntcheck && (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index dfb748fc5176..96e671e753c7 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -259,9 +259,9 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, /* * The filesystem is mounted by invoking the system mount utility rather - * than by the system call mount(2). This ensures that the /etc/mtab + * than by the system call mount(2). This ensures that the /proc/self/mounts * file is correctly locked for the update. Performing our own locking - * and /etc/mtab update requires making an unsafe assumption about how + * and /proc/self/mounts update requires making an unsafe assumption about how * the mount utility performs its locking. Unfortunately, this also means * in the case of a mount failure we do not have the exact errno. We must * make due with return value from the mount process. @@ -289,8 +289,6 @@ do_mount(const char *src, const char *mntpt, char *opts) /* Return only the most critical mount error */ rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE); if (rc) { - if (rc & MOUNT_FILEIO) - return (EIO); if (rc & MOUNT_USER) return (EINTR); if (rc & MOUNT_SOFTWARE) @@ -348,7 +346,7 @@ zfs_add_option(zfs_handle_t *zhp, char *options, int len, /* * zfs_prop_get_int() to not used to ensure our mount options - * are not influenced by the current /etc/mtab contents. + * are not influenced by the current /proc/self/mounts contents. */ value = getprop_uint64(zhp, prop, &source); @@ -1182,8 +1180,8 @@ mountpoint_compare(const void *a, const void *b) * Unshare and unmount all datasets within the given pool. We don't want to * rely on traversing the DSL to discover the filesystems within the pool, * because this may be expensive (if not all of them are mounted), and can fail - * arbitrarily (on I/O error, for example). Instead, we walk /etc/mtab and - * gather all the filesystems that are currently mounted. + * arbitrarily (on I/O error, for example). Instead, we walk /proc/self/mounts + * and gather all the filesystems that are currently mounted. */ int zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) diff --git a/scripts/ziltest.sh b/scripts/ziltest.sh index 62cf09e88e0d..daffd651a2dd 100755 --- a/scripts/ziltest.sh +++ b/scripts/ziltest.sh @@ -185,7 +185,7 @@ CHECKSUM_BEFORE=$(sha256sum -b "$PAYLOAD") # # TX_WRITE (small file with ordering) # -cp /etc/mtab $ROOT/small_file +cp /proc/self/mounts $ROOT/small_file cp /etc/profile $ROOT/small_file #