diff options
author | Allan Jude <[email protected]> | 2023-04-21 13:20:36 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2023-04-21 10:20:36 -0700 |
commit | 8eae2d214cfa53862833eeeda9a5c1e9d5ded47d (patch) | |
tree | 29dfb37fc683a015473e70c8c90a6284d5df463e /lib | |
parent | 135d9a9048e3716c755373182720d0eba170285f (diff) |
Add support for zpool user properties
Usage:
zpool set org.freebsd:comment="this is my pool" poolname
Tests are based on zfs_set's user property tests.
Also stop truncating property values at MAXNAMELEN, use ZFS_MAXPROPLEN.
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Allan Jude <[email protected]>
Signed-off-by: Mateusz Piotrowski <[email protected]>
Sponsored-by: Beckhoff Automation GmbH & Co. KG.
Sponsored-by: Klara Inc.
Closes #11680
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs.abi | 131 | ||||
-rw-r--r-- | lib/libzfs/libzfs_pool.c | 101 | ||||
-rw-r--r-- | lib/libzfs/libzfs_util.c | 1 |
3 files changed, 169 insertions, 64 deletions
diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index f9aed4e0d..732863dcf 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -259,8 +259,8 @@ <elf-symbol name='tpool_suspend' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='tpool_suspended' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='tpool_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='use_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='update_vdev_config_dev_strs' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='use_color' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='vdev_expand_proplist' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='vdev_name_to_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='vdev_prop_align_right' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -492,6 +492,7 @@ <elf-symbol name='zpool_get_state' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_get_state_str' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_get_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zpool_get_userprop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_get_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_get_vdev_prop_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zpool_history_unpack' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -2267,32 +2268,19 @@ <parameter type-id='58603c44'/> <return type-id='9c313c2d'/> </function-decl> - <function-decl name='zfs_iter_children' mangled-name='zfs_iter_children' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='zfs_iter_children_v2' mangled-name='zfs_iter_children_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children_v2'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_dependents' mangled-name='zfs_iter_dependents' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='allowrecursion'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> + <parameter type-id='9200a744'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='d8e49ab9'/> + <parameter type-id='eaa32e2f'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zfs_iter_dependents_v2' mangled-name='zfs_iter_dependents_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents_v2'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='c19b74c3' name='allowrecursion'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> + <parameter type-id='9200a744'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='c19b74c3'/> + <parameter type-id='d8e49ab9'/> + <parameter type-id='eaa32e2f'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zfs_iter_mounted' mangled-name='zfs_iter_mounted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_mounted'> @@ -3324,17 +3312,11 @@ <parameter type-id='58603c44'/> <return type-id='80f4b756'/> </function-decl> - <function-decl name='zfs_iter_filesystems' mangled-name='zfs_iter_filesystems' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='zfs_iter_filesystems_v2' mangled-name='zfs_iter_filesystems_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems_v2'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> + <parameter type-id='9200a744'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='d8e49ab9'/> + <parameter type-id='eaa32e2f'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zfs_parent_name' mangled-name='zfs_parent_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parent_name'> @@ -3907,35 +3889,20 @@ <parameter type-id='b59d7dce'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='zfs_iter_snapshots' mangled-name='zfs_iter_snapshots' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='c19b74c3' name='simple'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <parameter type-id='9c313c2d' name='min_txg'/> - <parameter type-id='9c313c2d' name='max_txg'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='zfs_iter_snapshots_v2' mangled-name='zfs_iter_snapshots_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_v2'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> - <parameter type-id='9c313c2d' name='min_txg'/> - <parameter type-id='9c313c2d' name='max_txg'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='zfs_iter_bookmarks' mangled-name='zfs_iter_bookmarks' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_bookmarks'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> + <parameter type-id='9200a744'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='d8e49ab9'/> + <parameter type-id='eaa32e2f'/> + <parameter type-id='9c313c2d'/> + <parameter type-id='9c313c2d'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zfs_iter_bookmarks_v2' mangled-name='zfs_iter_bookmarks_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_bookmarks_v2'> - <parameter type-id='9200a744' name='zhp'/> - <parameter type-id='95e97e5e' name='flags'/> - <parameter type-id='d8e49ab9' name='func'/> - <parameter type-id='eaa32e2f' name='data'/> + <parameter type-id='9200a744'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='d8e49ab9'/> + <parameter type-id='eaa32e2f'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zfs_destroy_snaps_nvl_os' mangled-name='zfs_destroy_snaps_nvl_os' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_destroy_snaps_nvl_os'> @@ -5131,6 +5098,27 @@ <parameter type-id='5ce45b60'/> <return type-id='9200a744'/> </function-decl> + <function-decl name='zfs_iter_filesystems' mangled-name='zfs_iter_filesystems' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_filesystems'> + <parameter type-id='9200a744' name='zhp'/> + <parameter type-id='d8e49ab9' name='func'/> + <parameter type-id='eaa32e2f' name='data'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_iter_snapshots' mangled-name='zfs_iter_snapshots' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots'> + <parameter type-id='9200a744' name='zhp'/> + <parameter type-id='c19b74c3' name='simple'/> + <parameter type-id='d8e49ab9' name='func'/> + <parameter type-id='eaa32e2f' name='data'/> + <parameter type-id='9c313c2d' name='min_txg'/> + <parameter type-id='9c313c2d' name='max_txg'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_iter_bookmarks' mangled-name='zfs_iter_bookmarks' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_bookmarks'> + <parameter type-id='9200a744' name='zhp'/> + <parameter type-id='d8e49ab9' name='func'/> + <parameter type-id='eaa32e2f' name='data'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zfs_iter_snapshots_sorted' mangled-name='zfs_iter_snapshots_sorted' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_sorted'> <parameter type-id='9200a744' name='zhp'/> <parameter type-id='d8e49ab9' name='callback'/> @@ -5163,6 +5151,19 @@ <parameter type-id='eaa32e2f' name='arg'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zfs_iter_children' mangled-name='zfs_iter_children' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_children'> + <parameter type-id='9200a744' name='zhp'/> + <parameter type-id='d8e49ab9' name='func'/> + <parameter type-id='eaa32e2f' name='data'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='zfs_iter_dependents' mangled-name='zfs_iter_dependents' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_dependents'> + <parameter type-id='9200a744' name='zhp'/> + <parameter type-id='c19b74c3' name='allowrecursion'/> + <parameter type-id='d8e49ab9' name='func'/> + <parameter type-id='eaa32e2f' name='data'/> + <return type-id='95e97e5e'/> + </function-decl> </abi-instr> <abi-instr address-size='64' path='lib/libzfs/libzfs_mount.c' language='LANG_C99'> <array-type-def dimensions='1' type-id='6028cbfe' size-in-bits='256' id='b39b9aa7'> @@ -5395,9 +5396,6 @@ <parameter type-id='9cf59a50'/> <return type-id='48b5725f'/> </function-decl> - <function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'> <parameter type-id='80f4b756'/> <parameter type-id='d50d396c'/> @@ -6169,6 +6167,14 @@ <parameter type-id='4c81de99' name='zhp'/> <return type-id='80f4b756'/> </function-decl> + <function-decl name='zpool_get_userprop' mangled-name='zpool_get_userprop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_userprop'> + <parameter type-id='4c81de99' name='zhp'/> + <parameter type-id='80f4b756' name='propname'/> + <parameter type-id='26a90f95' name='buf'/> + <parameter type-id='b59d7dce' name='len'/> + <parameter type-id='debc6aa3' name='srctype'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_set_prop' mangled-name='zpool_set_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_prop'> <parameter type-id='4c81de99' name='zhp'/> <parameter type-id='80f4b756' name='propname'/> @@ -7852,6 +7858,9 @@ <function-decl name='zfs_version_print' mangled-name='zfs_version_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_print'> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='use_color' mangled-name='use_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='use_color'> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='printf_color' mangled-name='printf_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='printf_color'> <parameter type-id='80f4b756' name='color'/> <parameter type-id='80f4b756' name='format'/> diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index ae4c86159..4fb71b4e0 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -427,6 +427,37 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, } /* + * Get a zpool property value for 'propname' and return the value in + * a pre-allocated buffer. + */ +int +zpool_get_userprop(zpool_handle_t *zhp, const char *propname, char *buf, + size_t len, zprop_source_t *srctype) +{ + nvlist_t *nv, *nvl; + uint64_t ival; + const char *value; + zprop_source_t source = ZPROP_SRC_LOCAL; + + nvl = zhp->zpool_props; + if (nvlist_lookup_nvlist(nvl, propname, &nv) == 0) { + if (nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0) + source = ival; + verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); + } else { + source = ZPROP_SRC_DEFAULT; + value = "-"; + } + + if (srctype) + *srctype = source; + + (void) strlcpy(buf, value, len); + + return (0); +} + +/* * Check if the bootfs name has the same pool name as it is set to. * Assuming bootfs is a valid dataset name. */ @@ -550,6 +581,44 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname, goto error; } continue; + } else if (prop == ZPOOL_PROP_INVAL && + zfs_prop_user(propname)) { + /* + * This is a user property: make sure it's a + * string, and that it's less than ZAP_MAXNAMELEN. + */ + if (nvpair_type(elem) != DATA_TYPE_STRING) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "'%s' must be a string"), propname); + (void) zfs_error(hdl, EZFS_BADPROP, errbuf); + goto error; + } + + if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "property name '%s' is too long"), + propname); + (void) zfs_error(hdl, EZFS_BADPROP, errbuf); + goto error; + } + + (void) nvpair_value_string(elem, &strval); + + if (strlen(strval) >= ZFS_MAXPROPLEN) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "property value '%s' is too long"), + strval); + (void) zfs_error(hdl, EZFS_BADPROP, errbuf); + goto error; + } + + if (nvlist_add_string(retprops, propname, + strval) != 0) { + (void) no_memory(hdl); + goto error; + } + + continue; } /* @@ -855,9 +924,30 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp, features = zpool_get_features(zhp); if ((*plp)->pl_all && firstexpand) { + /* Handle userprops in the all properties case */ + if (zhp->zpool_props == NULL && zpool_props_refresh(zhp)) + return (-1); + + nvp = NULL; + while ((nvp = nvlist_next_nvpair(zhp->zpool_props, nvp)) != + NULL) { + const char *propname = nvpair_name(nvp); + + if (!zfs_prop_user(propname)) + continue; + + entry = zfs_alloc(hdl, sizeof (zprop_list_t)); + entry->pl_prop = ZPROP_USERPROP; + entry->pl_user_prop = zfs_strdup(hdl, propname); + entry->pl_width = strlen(entry->pl_user_prop); + entry->pl_all = B_TRUE; + + *last = entry; + last = &entry->pl_next; + } + for (i = 0; i < SPA_FEATURES; i++) { - zprop_list_t *entry = zfs_alloc(hdl, - sizeof (zprop_list_t)); + entry = zfs_alloc(hdl, sizeof (zprop_list_t)); entry->pl_prop = ZPROP_USERPROP; entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s", spa_feature_table[i].fi_uname); @@ -874,7 +964,6 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp, nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) { char *propname; boolean_t found; - zprop_list_t *entry; if (zfeature_is_supported(nvpair_name(nvp))) continue; @@ -920,6 +1009,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp, NULL, literal) == 0) { if (strlen(buf) > entry->pl_width) entry->pl_width = strlen(buf); + } else if (entry->pl_prop == ZPROP_INVAL && + zfs_prop_user(entry->pl_user_prop) && + zpool_get_userprop(zhp, entry->pl_user_prop, buf, + sizeof (buf), NULL) == 0) { + if (strlen(buf) > entry->pl_width) + entry->pl_width = strlen(buf); } } diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 393971ddf..4b8a20160 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -1774,6 +1774,7 @@ addlist(libzfs_handle_t *hdl, const char *propname, zprop_list_t **listp, * a user-defined property. */ if (prop == ZPROP_USERPROP && ((type == ZFS_TYPE_POOL && + !zfs_prop_user(propname) && !zpool_prop_feature(propname) && !zpool_prop_unsupported(propname)) || ((type == ZFS_TYPE_DATASET) && !zfs_prop_user(propname) && |