aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c')
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c257
1 files changed, 41 insertions, 216 deletions
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
index e1b91fc47291..e5a7ca9ba3f5 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
@@ -806,190 +806,6 @@ zfs_close(zfs_handle_t *zhp)
free(zhp);
}
-typedef struct mnttab_node {
- struct mnttab mtn_mt;
- avl_node_t mtn_node;
-} mnttab_node_t;
-
-static int
-libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
-{
- const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
- const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
- int rv;
-
- rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
-
- return (TREE_ISIGN(rv));
-}
-
-void
-libzfs_mnttab_init(libzfs_handle_t *hdl)
-{
- pthread_mutex_init(&hdl->libzfs_mnttab_cache_lock, NULL);
- assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
- avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
- sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
-}
-
-static int
-libzfs_mnttab_update(libzfs_handle_t *hdl)
-{
- FILE *mnttab;
- struct mnttab entry;
-
- if ((mnttab = fopen(MNTTAB, "re")) == NULL)
- return (ENOENT);
-
- while (getmntent(mnttab, &entry) == 0) {
- mnttab_node_t *mtn;
- avl_index_t where;
-
- if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
- continue;
-
- mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
- mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
- mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
- mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
- mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
-
- /* Exclude duplicate mounts */
- if (avl_find(&hdl->libzfs_mnttab_cache, mtn, &where) != NULL) {
- free(mtn->mtn_mt.mnt_special);
- free(mtn->mtn_mt.mnt_mountp);
- free(mtn->mtn_mt.mnt_fstype);
- free(mtn->mtn_mt.mnt_mntopts);
- free(mtn);
- continue;
- }
-
- avl_add(&hdl->libzfs_mnttab_cache, mtn);
- }
-
- (void) fclose(mnttab);
- return (0);
-}
-
-void
-libzfs_mnttab_fini(libzfs_handle_t *hdl)
-{
- void *cookie = NULL;
- mnttab_node_t *mtn;
-
- while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))
- != NULL) {
- free(mtn->mtn_mt.mnt_special);
- free(mtn->mtn_mt.mnt_mountp);
- free(mtn->mtn_mt.mnt_fstype);
- free(mtn->mtn_mt.mnt_mntopts);
- free(mtn);
- }
- avl_destroy(&hdl->libzfs_mnttab_cache);
- (void) pthread_mutex_destroy(&hdl->libzfs_mnttab_cache_lock);
-}
-
-void
-libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
-{
- hdl->libzfs_mnttab_enable = enable;
-}
-
-int
-libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
- struct mnttab *entry)
-{
- FILE *mnttab;
- mnttab_node_t find;
- mnttab_node_t *mtn;
- int ret = ENOENT;
-
- if (!hdl->libzfs_mnttab_enable) {
- struct mnttab srch = { 0 };
-
- if (avl_numnodes(&hdl->libzfs_mnttab_cache))
- libzfs_mnttab_fini(hdl);
-
- if ((mnttab = fopen(MNTTAB, "re")) == NULL)
- return (ENOENT);
-
- srch.mnt_special = (char *)fsname;
- srch.mnt_fstype = (char *)MNTTYPE_ZFS;
- ret = getmntany(mnttab, entry, &srch) ? ENOENT : 0;
- (void) fclose(mnttab);
- return (ret);
- }
-
- pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
- if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) {
- int error;
-
- if ((error = libzfs_mnttab_update(hdl)) != 0) {
- pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
- return (error);
- }
- }
-
- find.mtn_mt.mnt_special = (char *)fsname;
- mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
- if (mtn) {
- *entry = mtn->mtn_mt;
- ret = 0;
- }
- pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
- return (ret);
-}
-
-void
-libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
- const char *mountp, const char *mntopts)
-{
- mnttab_node_t *mtn;
-
- pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
- if (avl_numnodes(&hdl->libzfs_mnttab_cache) != 0) {
- mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
- mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
- mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
- mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
- mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
- /*
- * Another thread may have already added this entry
- * via libzfs_mnttab_update. If so we should skip it.
- */
- if (avl_find(&hdl->libzfs_mnttab_cache, mtn, NULL) != NULL) {
- free(mtn->mtn_mt.mnt_special);
- free(mtn->mtn_mt.mnt_mountp);
- free(mtn->mtn_mt.mnt_fstype);
- free(mtn->mtn_mt.mnt_mntopts);
- free(mtn);
- } else {
- avl_add(&hdl->libzfs_mnttab_cache, mtn);
- }
- }
- pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
-}
-
-void
-libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
-{
- mnttab_node_t find;
- mnttab_node_t *ret;
-
- pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
- find.mtn_mt.mnt_special = (char *)fsname;
- if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))
- != NULL) {
- avl_remove(&hdl->libzfs_mnttab_cache, ret);
- free(ret->mtn_mt.mnt_special);
- free(ret->mtn_mt.mnt_mountp);
- free(ret->mtn_mt.mnt_fstype);
- free(ret->mtn_mt.mnt_mntopts);
- free(ret);
- }
- pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
-}
-
int
zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
{
@@ -1701,26 +1517,6 @@ zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl)
return (1);
}
-static boolean_t
-zfs_is_namespace_prop(zfs_prop_t prop)
-{
- switch (prop) {
-
- case ZFS_PROP_ATIME:
- case ZFS_PROP_RELATIME:
- 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.
*/
@@ -1778,7 +1574,7 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
int nvl_len = 0;
int added_resv = 0;
zfs_prop_t prop;
- boolean_t nsprop = B_FALSE;
+ uint32_t nspflags = 0;
nvpair_t *elem;
(void) snprintf(errbuf, sizeof (errbuf),
@@ -1825,7 +1621,7 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
elem = nvlist_next_nvpair(nvl, elem)) {
prop = zfs_name_to_prop(nvpair_name(elem));
- nsprop |= zfs_is_namespace_prop(prop);
+ nspflags |= zfs_namespace_prop_flag(prop);
assert(cl_idx < nvl_len);
/*
@@ -1926,8 +1722,8 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
* if one of the options handled by the generic
* Linux namespace layer has been modified.
*/
- if (nsprop && zfs_is_mounted(zhp, NULL))
- ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
+ if (nspflags && zfs_is_mounted(zhp, NULL))
+ ret = zfs_mount_setattr(zhp, nspflags);
}
}
@@ -2049,7 +1845,8 @@ zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
*/
if (zfs_is_namespace_prop(prop) &&
zfs_is_mounted(zhp, NULL))
- ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
+ ret = zfs_mount_setattr(zhp,
+ zfs_namespace_prop_flag(prop));
}
error:
@@ -3001,6 +2798,19 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
zcp_check(zhp, prop, val, NULL);
break;
+ case ZFS_PROP_SNAPSHOTS_CHANGED_NSECS:
+ {
+ if ((get_numeric_property(zhp, prop, src, &source,
+ &val) != 0) || val == 0) {
+ return (-1);
+ }
+
+ (void) snprintf(propbuf, proplen, "%llu",
+ (u_longlong_t)val);
+ }
+ zcp_check(zhp, prop, val, NULL);
+ break;
+
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
@@ -3537,9 +3347,13 @@ check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
/* we are in a non-global zone, but parent is in the global zone */
if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
- (void) zfs_standard_error(hdl, EPERM, errbuf);
- zfs_close(zhp);
- return (-1);
+ uint64_t zoned_uid = zfs_prop_get_int(zhp, ZFS_PROP_ZONED_UID);
+ if (zoned_uid == 0) {
+ (void) zfs_standard_error(hdl, EPERM, errbuf);
+ zfs_close(zhp);
+ return (-1);
+ }
+ /* zoned_uid set - let kernel decide */
}
/* make sure parent is a filesystem */
@@ -3587,7 +3401,8 @@ zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
* Fail if the initial prefixlen-ancestor does not already exist.
*/
int
-create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
+create_parents(libzfs_handle_t *hdl, char *target, int prefixlen,
+ nvlist_t *props)
{
zfs_handle_t *h;
char *cp;
@@ -3623,8 +3438,7 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
continue;
}
- if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
- NULL) != 0) {
+ if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, props) != 0) {
opname = dgettext(TEXT_DOMAIN, "create");
goto ancestorerr;
}
@@ -3663,6 +3477,17 @@ ancestorerr:
int
zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
{
+ return (zfs_create_ancestors_props(hdl, path, NULL));
+}
+
+/*
+ * Creates non-existing ancestors of the given path, applying extra
+ * properties provided in an nvlist.
+ */
+int
+zfs_create_ancestors_props(libzfs_handle_t *hdl, const char *path,
+ nvlist_t *props)
+{
int prefix;
char *path_copy;
char errbuf[ERRBUFLEN];
@@ -3685,7 +3510,7 @@ zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
return (-1);
if ((path_copy = strdup(path)) != NULL) {
- rc = create_parents(hdl, path_copy, prefix);
+ rc = create_parents(hdl, path_copy, prefix, props);
free(path_copy);
}
if (path_copy == NULL || rc != 0)