Change /etc/mtab to /proc/self/mounts
Fix misleading error message: "The /dev/zfs device is missing and must be created.", if /etc/mtab is missing. Reviewed-by: Richard Laager <rlaager@wiktel.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Eric Desrochers <eric.desrochers@canonical.com> Closes #4680 Closes #5029
This commit is contained in:
parent
25e2ab16be
commit
792517389f
|
@ -294,11 +294,11 @@ mtab_is_writeable(void)
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int error, fd;
|
int error, fd;
|
||||||
|
|
||||||
error = lstat(MNTTAB, &st);
|
error = lstat("/etc/mtab", &st);
|
||||||
if (error || S_ISLNK(st.st_mode))
|
if (error || S_ISLNK(st.st_mode))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
fd = open(MNTTAB, O_RDWR | O_CREAT, 0644);
|
fd = open("/etc/mtab", O_RDWR | O_CREAT, 0644);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
@ -320,21 +320,21 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
||||||
mnt.mnt_freq = 0;
|
mnt.mnt_freq = 0;
|
||||||
mnt.mnt_passno = 0;
|
mnt.mnt_passno = 0;
|
||||||
|
|
||||||
fp = setmntent(MNTTAB, "a+");
|
fp = setmntent("/etc/mtab", "a+");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
(void) fprintf(stderr, gettext(
|
(void) fprintf(stderr, gettext(
|
||||||
"filesystem '%s' was mounted, but %s "
|
"filesystem '%s' was mounted, but /etc/mtab "
|
||||||
"could not be opened due to error %d\n"),
|
"could not be opened due to error %d\n"),
|
||||||
dataset, MNTTAB, errno);
|
dataset, errno);
|
||||||
return (MOUNT_FILEIO);
|
return (MOUNT_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = addmntent(fp, &mnt);
|
error = addmntent(fp, &mnt);
|
||||||
if (error) {
|
if (error) {
|
||||||
(void) fprintf(stderr, gettext(
|
(void) fprintf(stderr, gettext(
|
||||||
"filesystem '%s' was mounted, but %s "
|
"filesystem '%s' was mounted, but /etc/mtab "
|
||||||
"could not be updated due to error %d\n"),
|
"could not be updated due to error %d\n"),
|
||||||
dataset, MNTTAB, errno);
|
dataset, errno);
|
||||||
return (MOUNT_FILEIO);
|
return (MOUNT_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6146,9 +6146,10 @@ share_mount(int op, int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When mount is given no arguments, go through /etc/mtab and
|
* When mount is given no arguments, go through
|
||||||
* display any active ZFS mounts. We hide any snapshots, since
|
* /proc/self/mounts and display any active ZFS mounts.
|
||||||
* they are controlled automatically.
|
* We hide any snapshots, since they are controlled
|
||||||
|
* automatically.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Reopen MNTTAB to prevent reading stale data from open file */
|
/* Reopen MNTTAB to prevent reading stale data from open file */
|
||||||
|
@ -6228,8 +6229,8 @@ unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convenience routine used by zfs_do_umount() and manual_unmount(). Given an
|
* 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,
|
* absolute path, find the entry /proc/self/mounts, verify that its a
|
||||||
* and unmount it appropriately.
|
* ZFS filesystems, and unmount it appropriately.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
|
unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
|
||||||
|
@ -6242,7 +6243,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
|
||||||
ino_t path_inode;
|
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. ".."
|
* specific path, which can be fooled by non-standard paths (i.e. ".."
|
||||||
* or "//"), we stat() the path and search for the corresponding
|
* or "//"), we stat() the path and search for the corresponding
|
||||||
* (major,minor) device pair.
|
* (major,minor) device pair.
|
||||||
|
@ -6273,8 +6274,8 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
|
||||||
"currently mounted\n"), cmdname, path);
|
"currently mounted\n"), cmdname, path);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
(void) fprintf(stderr, gettext("warning: %s not in mtab\n"),
|
(void) fprintf(stderr, gettext("warning: %s not in"
|
||||||
path);
|
"/proc/self/mounts\n"), path);
|
||||||
if ((ret = umount2(path, flags)) != 0)
|
if ((ret = umount2(path, flags)) != 0)
|
||||||
(void) fprintf(stderr, gettext("%s: %s\n"), path,
|
(void) fprintf(stderr, gettext("%s: %s\n"), path,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -6385,9 +6386,9 @@ unshare_unmount(int op, int argc, char **argv)
|
||||||
/*
|
/*
|
||||||
* We could make use of zfs_for_each() to walk all datasets in
|
* We could make use of zfs_for_each() to walk all datasets in
|
||||||
* the system, but this would be very inefficient, especially
|
* the system, but this would be very inefficient, especially
|
||||||
* since we would have to linearly search /etc/mtab for each
|
* since we would have to linearly search /proc/self/mounts for
|
||||||
* one. Instead, do one pass through /etc/mtab looking for
|
* each one. Instead, do one pass through /proc/self/mounts
|
||||||
* zfs entries and call zfs_unmount() for each one.
|
* looking for zfs entries and call zfs_unmount() for each one.
|
||||||
*
|
*
|
||||||
* Things get a little tricky if the administrator has created
|
* Things get a little tricky if the administrator has created
|
||||||
* mountpoints beneath other ZFS filesystems. In this case, we
|
* mountpoints beneath other ZFS filesystems. In this case, we
|
||||||
|
|
|
@ -120,7 +120,7 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
||||||
#else
|
#else
|
||||||
if ((fp = fopen(MNTTAB, "r")) == NULL) {
|
if ((fp = fopen(MNTTAB, "r")) == NULL) {
|
||||||
#endif
|
#endif
|
||||||
(void) fprintf(stderr, "cannot open /etc/mtab\n");
|
(void) fprintf(stderr, "cannot open %s\n", MNTTAB);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER_COMMANDS_LINUX], [
|
||||||
PAGESIZE=$($GETCONF PAGESIZE)
|
PAGESIZE=$($GETCONF PAGESIZE)
|
||||||
AC_SUBST(PAGESIZE)
|
AC_SUBST(PAGESIZE)
|
||||||
|
|
||||||
MNTTAB=/etc/mtab
|
MNTTAB=/proc/self/mounts
|
||||||
AC_SUBST(MNTTAB)
|
AC_SUBST(MNTTAB)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -288,9 +288,8 @@ load_module_initrd()
|
||||||
wait_for_dev
|
wait_for_dev
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# zpool import refuse to import without a valid mtab
|
# zpool import refuse to import without a valid /proc/self/mounts
|
||||||
[ ! -f /proc/mounts ] && mount proc /proc
|
[ ! -f /proc/self/mounts ] && mount proc /proc
|
||||||
[ ! -f /etc/mtab ] && cat /proc/mounts > /etc/mtab
|
|
||||||
|
|
||||||
# Load the module
|
# Load the module
|
||||||
load_module "zfs" || return 1
|
load_module "zfs" || return 1
|
||||||
|
@ -919,7 +918,7 @@ mountroot()
|
||||||
#
|
#
|
||||||
# but the MOUNTPOINT prefix is preserved on descendent filesystem
|
# but the MOUNTPOINT prefix is preserved on descendent filesystem
|
||||||
# after the pivot into the regular root, which later breaks things
|
# 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
|
# * Mount additional filesystems required
|
||||||
# Such as /usr, /var, /usr/local etc.
|
# Such as /usr, /var, /usr/local etc.
|
||||||
|
|
|
@ -368,7 +368,7 @@ read_mtab()
|
||||||
# Set the variable.
|
# Set the variable.
|
||||||
eval export MTAB_$mntpnt=\"$fs\"
|
eval export MTAB_$mntpnt=\"$fs\"
|
||||||
fi
|
fi
|
||||||
done < /proc/mounts
|
done < /proc/self/mounts
|
||||||
}
|
}
|
||||||
|
|
||||||
in_mtab()
|
in_mtab()
|
||||||
|
|
|
@ -39,7 +39,7 @@ chkroot() {
|
||||||
if [ "$2" = "/" ]; then
|
if [ "$2" = "/" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
done < /etc/mtab
|
done < /proc/self/mounts
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ do_start()
|
||||||
|
|
||||||
check_module_loaded "zfs" || exit 0
|
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.
|
# This should be handled by rc.sysinit but lets be paranoid.
|
||||||
if ! chkroot
|
if ! chkroot
|
||||||
then
|
then
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#undef MNTTAB
|
#undef MNTTAB
|
||||||
#endif /* MNTTAB */
|
#endif /* MNTTAB */
|
||||||
|
|
||||||
#define MNTTAB "/etc/mtab"
|
#define MNTTAB "/proc/self/mounts"
|
||||||
#define MNT_LINE_MAX 4096
|
#define MNT_LINE_MAX 4096
|
||||||
|
|
||||||
#define MNT_TOOLONG 1 /* entry exceeds MNT_LINE_MAX */
|
#define MNT_TOOLONG 1 /* entry exceeds MNT_LINE_MAX */
|
||||||
|
|
|
@ -1908,9 +1908,9 @@ zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
|
||||||
* zfs_prop_get_int() are built using this interface.
|
* zfs_prop_get_int() are built using this interface.
|
||||||
*
|
*
|
||||||
* Certain properties can be overridden using 'mount -o'. In this case, scan
|
* Certain properties can be overridden using 'mount -o'. In this case, scan
|
||||||
* the contents of the /etc/mtab entry, searching for the appropriate options.
|
* the contents of the /proc/self/mounts entry, searching for the
|
||||||
* If they differ from the on-disk values, report the current values and mark
|
* appropriate options. If they differ from the on-disk values, report the
|
||||||
* the source "temporary".
|
* current values and mark the source "temporary".
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
|
get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
|
||||||
|
@ -1981,8 +1981,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
|
* Because looking up the mount options is potentially expensive
|
||||||
* (iterating over all of /etc/mtab), we defer its calculation until
|
* (iterating over all of /proc/self/mounts), we defer its
|
||||||
* we're looking up a property which requires its presence.
|
* calculation until we're looking up a property which requires
|
||||||
|
* its presence.
|
||||||
*/
|
*/
|
||||||
if (!zhp->zfs_mntcheck &&
|
if (!zhp->zfs_mntcheck &&
|
||||||
(mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
|
(mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
|
||||||
|
|
|
@ -347,8 +347,8 @@ zfs_add_option(zfs_handle_t *zhp, char *options, int len,
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zfs_prop_get_int() to not used to ensure our mount options
|
* zfs_prop_get_int() is 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);
|
value = getprop_uint64(zhp, prop, &source);
|
||||||
|
|
||||||
|
@ -1184,8 +1184,8 @@ mountpoint_compare(const void *a, const void *b)
|
||||||
* Unshare and unmount all datasets within the given pool. We don't want to
|
* 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,
|
* 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
|
* 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
|
* arbitrarily (on I/O error, for example). Instead, we walk /proc/self/mounts
|
||||||
* gather all the filesystems that are currently mounted.
|
* and gather all the filesystems that are currently mounted.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
|
zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
|
||||||
|
|
|
@ -67,9 +67,9 @@ libzfs_error_init(int error)
|
||||||
"loaded.\nTry running '/sbin/modprobe zfs' as root "
|
"loaded.\nTry running '/sbin/modprobe zfs' as root "
|
||||||
"to load them.\n"));
|
"to load them.\n"));
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
return (dgettext(TEXT_DOMAIN, "The /dev/zfs device is "
|
return (dgettext(TEXT_DOMAIN, "/dev/zfs and /proc/self/mounts "
|
||||||
"missing and must be created.\nTry running 'udevadm "
|
"are required.\nTry running 'udevadm trigger' and 'mount "
|
||||||
"trigger' as root to create it.\n"));
|
"-t proc proc /proc' as root.\n"));
|
||||||
case ENOEXEC:
|
case ENOEXEC:
|
||||||
return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be "
|
return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be "
|
||||||
"auto-loaded.\nTry running '/sbin/modprobe zfs' as "
|
"auto-loaded.\nTry running '/sbin/modprobe zfs' as "
|
||||||
|
|
|
@ -185,7 +185,11 @@ CHECKSUM_BEFORE=$(sha256sum -b "$PAYLOAD")
|
||||||
#
|
#
|
||||||
# TX_WRITE (small file with ordering)
|
# TX_WRITE (small file with ordering)
|
||||||
#
|
#
|
||||||
cp /etc/mtab $ROOT/small_file
|
if is_linux; then
|
||||||
|
cp /proc/self/mounts $ROOT/small_file
|
||||||
|
else
|
||||||
|
cp /etc/mtab $ROOT/small_file
|
||||||
|
fi
|
||||||
cp /etc/profile $ROOT/small_file
|
cp /etc/profile $ROOT/small_file
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -40,11 +40,16 @@
|
||||||
|
|
||||||
verify_runnable "global"
|
verify_runnable "global"
|
||||||
|
|
||||||
log_assert "zfs fails with unexpected scenarios."
|
log_assert "zfs fails with unexpected scenario."
|
||||||
|
|
||||||
#verify zfs failed if ZFS_DEV cannot be opened
|
#verify zfs failed if ZFS_DEV cannot be opened
|
||||||
ZFS_DEV=/dev/zfs
|
ZFS_DEV=/dev/zfs
|
||||||
|
|
||||||
|
if is_linux; then
|
||||||
|
# On Linux, we use /proc/self/mounts, which cannot be moved.
|
||||||
|
MNTTAB=
|
||||||
|
fi
|
||||||
|
|
||||||
for file in $ZFS_DEV $MNTTAB; do
|
for file in $ZFS_DEV $MNTTAB; do
|
||||||
if [[ -e $file ]]; then
|
if [[ -e $file ]]; then
|
||||||
$MV $file ${file}.bak
|
$MV $file ${file}.bak
|
||||||
|
@ -55,4 +60,4 @@ for file in $ZFS_DEV $MNTTAB; do
|
||||||
$MV ${file}.bak $file
|
$MV ${file}.bak $file
|
||||||
done
|
done
|
||||||
|
|
||||||
log_pass "zfs fails with unexpected scenarios as expected."
|
log_pass "zfs fails with unexpected scenario as expected."
|
||||||
|
|
Loading…
Reference in New Issue