aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libzfs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libzfs')
-rw-r--r--lib/libzfs/Makefile.in1
-rw-r--r--lib/libzfs/libzfs_dataset.c41
-rw-r--r--lib/libzfs/libzfs_mount.c79
3 files changed, 110 insertions, 11 deletions
diff --git a/lib/libzfs/Makefile.in b/lib/libzfs/Makefile.in
index d73e8eb8b..73ec60585 100644
--- a/lib/libzfs/Makefile.in
+++ b/lib/libzfs/Makefile.in
@@ -63,6 +63,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/config/kernel-insert-inode-locked.m4 \
$(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
$(top_srcdir)/config/kernel-kobj-name-len.m4 \
+ $(top_srcdir)/config/kernel-mount-nodev.m4 \
$(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
$(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
$(top_srcdir)/config/kernel-rq-is_sync.m4 \
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c
index 378bbc7b1..5f8847a93 100644
--- a/lib/libzfs/libzfs_dataset.c
+++ b/lib/libzfs/libzfs_dataset.c
@@ -1313,6 +1313,25 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
}
}
+static boolean_t
+zfs_is_namespace_prop(zfs_prop_t prop)
+{
+ switch (prop) {
+
+ case ZFS_PROP_ATIME:
+ case ZFS_PROP_DEVICES:
+ case ZFS_PROP_EXEC:
+ case ZFS_PROP_SETUID:
+ case ZFS_PROP_READONLY:
+ case ZFS_PROP_XATTR:
+ case ZFS_PROP_NBMAND:
+ return (B_TRUE);
+
+ default:
+ return (B_FALSE);
+ }
+}
+
/*
* Given a property name and value, set the property for the given dataset.
*/
@@ -1408,12 +1427,22 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
if (do_prefix)
ret = changelist_postfix(cl);
- /*
- * Refresh the statistics so the new property value
- * is reflected.
- */
- if (ret == 0)
+ if (ret == 0) {
+ /*
+ * Refresh the statistics so the new property
+ * value is reflected.
+ */
(void) get_stats(zhp);
+
+ /*
+ * Remount the filesystem to propagate the change
+ * if one of the options handled by the generic
+ * Linux namespace layer has been modified.
+ */
+ if (zfs_is_namespace_prop(prop) &&
+ zfs_is_mounted(zhp, NULL))
+ ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
+ }
}
error:
@@ -1530,7 +1559,7 @@ error:
* True DSL properties are stored in an nvlist. The following two functions
* extract them appropriately.
*/
-static uint64_t
+uint64_t
getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
{
nvlist_t *nv;
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index 1dc58f924..6b70cbbec 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -315,6 +315,52 @@ do_unmount(const char *mntpt, int flags)
return (rc ? EINVAL : 0);
}
+static int
+zfs_add_option(zfs_handle_t *zhp, char *options, int len,
+ zfs_prop_t prop, char *on, char *off)
+{
+ char *source;
+ uint64_t value;
+
+ /* Skip adding duplicate default options */
+ if ((strstr(options, on) != NULL) || (strstr(options, off) != NULL))
+ return (0);
+
+ /*
+ * zfs_prop_get_int() to not used to ensure our mount options
+ * are not influenced by the current /etc/mtab contents.
+ */
+ value = getprop_uint64(zhp, prop, &source);
+
+ (void) strlcat(options, ",", len);
+ (void) strlcat(options, value ? on : off, len);
+
+ return (0);
+}
+
+static int
+zfs_add_options(zfs_handle_t *zhp, char *options, int len)
+{
+ int error = 0;
+
+ error = zfs_add_option(zhp, options, len,
+ ZFS_PROP_ATIME, MNTOPT_ATIME, MNTOPT_NOATIME);
+ error = error ? error : zfs_add_option(zhp, options, len,
+ ZFS_PROP_DEVICES, MNTOPT_DEVICES, MNTOPT_NODEVICES);
+ error = error ? error : zfs_add_option(zhp, options, len,
+ ZFS_PROP_EXEC, MNTOPT_EXEC, MNTOPT_NOEXEC);
+ error = error ? error : zfs_add_option(zhp, options, len,
+ ZFS_PROP_READONLY, MNTOPT_RO, MNTOPT_RW);
+ error = error ? error : zfs_add_option(zhp, options, len,
+ ZFS_PROP_SETUID, MNTOPT_SETUID, MNTOPT_NOSETUID);
+ error = error ? error : zfs_add_option(zhp, options, len,
+ ZFS_PROP_XATTR, MNTOPT_XATTR, MNTOPT_NOXATTR);
+ error = error ? error : zfs_add_option(zhp, options, len,
+ ZFS_PROP_NBMAND, MNTOPT_NBMAND, MNTOPT_NONBMAND);
+
+ return (error);
+}
+
/*
* Mount the given filesystem.
*/
@@ -325,12 +371,16 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
char mountpoint[ZFS_MAXPROPLEN];
char mntopts[MNT_LINE_MAX];
libzfs_handle_t *hdl = zhp->zfs_hdl;
- int rc;
+ int remount = 0, rc;
- if (options == NULL)
+ if (options == NULL) {
(void) strlcpy(mntopts, MNTOPT_DEFAULTS, sizeof (mntopts));
- else
+ } else {
(void) strlcpy(mntopts, options, sizeof (mntopts));
+ }
+
+ if (strstr(mntopts, MNTOPT_REMOUNT) != NULL)
+ remount = 1;
/*
* If the pool is imported read-only then all mounts must be read-only
@@ -339,6 +389,22 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
(void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts));
/*
+ * Append default mount options which apply to the mount point.
+ * This is done because under Linux (unlike Solaris) multiple mount
+ * points may reference a single super block. This means that just
+ * given a super block there is no back reference to update the per
+ * mount point options.
+ */
+ rc = zfs_add_options(zhp, mntopts, sizeof (mntopts));
+ if (rc) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "default options unavailable"));
+ return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
+ dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
+ mountpoint));
+ }
+
+ /*
* Append zfsutil option so the mount helper allow the mount
*/
strlcat(mntopts, "," MNTOPT_ZFSUTIL, sizeof (mntopts));
@@ -361,8 +427,7 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
* Determine if the mountpoint is empty. If so, refuse to perform the
* mount. We don't perform this check if 'remount' is specified.
*/
- if (strstr(mntopts, MNTOPT_REMOUNT) == NULL &&
- !dir_is_empty(mountpoint)) {
+ if (!remount && !dir_is_empty(mountpoint)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"directory is not empty"));
return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
@@ -403,6 +468,10 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
zhp->zfs_name));
}
+ /* remove the mounted entry before re-adding on remount */
+ if (remount)
+ libzfs_mnttab_remove(hdl, zhp->zfs_name);
+
/* add the mounted entry into our cache */
libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint, mntopts);
return (0);