From 3e4ed4213d7b4e8892e9def8b06363391d8dbd60 Mon Sep 17 00:00:00 2001 From: rob-wing <98866084+rob-wing@users.noreply.github.com> Date: Thu, 20 Apr 2023 09:07:56 -0800 Subject: [PATCH] Create zap for root vdev And add it to the AVZ, this is not backwards compatible with older pools due to an assertion in spa_sync() that verifies the number of ZAPs of all vdevs matches the number of ZAPs in the AVZ. Granted, the assertion only applies to #DEBUG builds - still, a feature flag is introduced to avoid the assertion, com.klarasystems:vdev_zaps_v2 Notably, this allows to get/set properties on the root vdev: % zpool set user:prop=value root-0 Before this commit, it was already possible to get/set properties on top-level vdevs with the syntax - (e.g. mirror-0): % zpool set user:prop=value mirror-0 This syntax also applies to the root vdev as it is is of type 'root' with a vdev_id of 0, root-0. The keyword 'root' as an alias for 'root-0'. The following tests have been added: - zpool get all properties from root vdev - zpool set a property on root vdev - verify root vdev ZAP is created Reviewed-by: Brian Behlendorf Signed-off-by: Rob Wing Sponsored-by: Seagate Technology Submitted-by: Klara, Inc. Closes #14405 --- cmd/zdb/zdb.c | 3 + cmd/zpool/zpool_main.c | 67 +++++++++++------ include/sys/fs/zfs.h | 1 + include/sys/vdev_impl.h | 1 + include/zfeature_common.h | 1 + lib/libzfs/libzfs.abi | 11 +-- lib/libzfs/libzfs_pool.c | 1 + lib/libzutil/zutil_import.c | 5 +- man/man7/zpool-features.7 | 16 ++++ module/zcommon/zfeature_common.c | 6 ++ module/zfs/spa.c | 11 +++ module/zfs/vdev.c | 31 +++++++- module/zfs/vdev_label.c | 6 ++ tests/runfiles/common.run | 4 +- tests/zfs-tests/tests/Makefile.am | 3 + .../cli_root/zpool_get/vdev_get.cfg | 73 +++++++++++++++++++ .../cli_root/zpool_get/vdev_get_001_pos.ksh | 62 ++++++++++++++++ .../cli_root/zpool_get/zpool_get.cfg | 1 + .../cli_root/zpool_set/vdev_set_001_pos.ksh | 52 +++++++++++++ .../functional/vdev_zaps/vdev_zaps.kshlib | 13 ++++ .../vdev_zaps/vdev_zaps_001_pos.ksh | 3 +- .../vdev_zaps/vdev_zaps_002_pos.ksh | 1 + .../vdev_zaps/vdev_zaps_003_pos.ksh | 1 + .../vdev_zaps/vdev_zaps_004_pos.ksh | 1 + .../vdev_zaps/vdev_zaps_005_pos.ksh | 1 + .../vdev_zaps/vdev_zaps_006_pos.ksh | 1 + .../vdev_zaps/vdev_zaps_007_pos.ksh | 1 + 27 files changed, 339 insertions(+), 38 deletions(-) create mode 100644 tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg create mode 100755 tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh create mode 100755 tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index e87826f7467b..c93ed4399afd 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -7630,6 +7630,9 @@ mos_leak_vdev(vdev_t *vd) mos_obj_refd(space_map_object(ms->ms_sm)); } + if (vd->vdev_root_zap != 0) + mos_obj_refd(vd->vdev_root_zap); + if (vd->vdev_top_zap != 0) { mos_obj_refd(vd->vdev_top_zap); mos_leak_vdev_top_zap(vd); diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 27e805943443..4965cba52692 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -10001,33 +10001,33 @@ get_callback_vdev(zpool_handle_t *zhp, char *vdevname, void *data) return (0); } -static int -get_callback_vdev_width_cb(void *zhp_data, nvlist_t *nv, void *data) -{ - zpool_handle_t *zhp = zhp_data; - zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; - char *vdevname = zpool_vdev_name(g_zfs, zhp, nv, - cbp->cb_vdevs.cb_name_flags); - int ret; - - /* Adjust the column widths for the vdev properties */ - ret = vdev_expand_proplist(zhp, vdevname, &cbp->cb_proplist); - - return (ret); -} - static int get_callback_vdev_cb(void *zhp_data, nvlist_t *nv, void *data) { zpool_handle_t *zhp = zhp_data; zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; - char *vdevname = zpool_vdev_name(g_zfs, zhp, nv, - cbp->cb_vdevs.cb_name_flags); + char *vdevname; + const char *type; int ret; - /* Display the properties */ + /* + * zpool_vdev_name() transforms the root vdev name (i.e., root-0) to the + * pool name for display purposes, which is not desired. Fallback to + * zpool_vdev_name() when not dealing with the root vdev. + */ + type = fnvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE); + if (zhp != NULL && strcmp(type, "root") == 0) + vdevname = strdup("root-0"); + else + vdevname = zpool_vdev_name(g_zfs, zhp, nv, + cbp->cb_vdevs.cb_name_flags); + + (void) vdev_expand_proplist(zhp, vdevname, &cbp->cb_proplist); + ret = get_callback_vdev(zhp, vdevname, data); + free(vdevname); + return (ret); } @@ -10042,7 +10042,6 @@ get_callback(zpool_handle_t *zhp, void *data) if (cbp->cb_type == ZFS_TYPE_VDEV) { if (strcmp(cbp->cb_vdevs.cb_names[0], "all-vdevs") == 0) { - for_each_vdev(zhp, get_callback_vdev_width_cb, data); for_each_vdev(zhp, get_callback_vdev_cb, data); } else { /* Adjust column widths for vdev properties */ @@ -10119,6 +10118,7 @@ zpool_do_get(int argc, char **argv) int ret; int c, i; char *propstr = NULL; + char *vdev = NULL; cb.cb_first = B_TRUE; @@ -10216,10 +10216,17 @@ zpool_do_get(int argc, char **argv) } else if (are_all_pools(1, argv)) { /* The first arg is a pool name */ if ((argc == 2 && strcmp(argv[1], "all-vdevs") == 0) || + (argc == 2 && strcmp(argv[1], "root") == 0) || are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb.cb_vdevs)) { + + if (strcmp(argv[1], "root") == 0) + vdev = strdup("root-0"); + else + vdev = strdup(argv[1]); + /* ... and the rest are vdev names */ - cb.cb_vdevs.cb_names = argv + 1; + cb.cb_vdevs.cb_names = &vdev; cb.cb_vdevs.cb_names_count = argc - 1; cb.cb_type = ZFS_TYPE_VDEV; argc = 1; /* One pool to process */ @@ -10264,6 +10271,9 @@ zpool_do_get(int argc, char **argv) else zprop_free_list(cb.cb_proplist); + if (vdev != NULL) + free(vdev); + return (ret); } @@ -10365,6 +10375,7 @@ zpool_do_set(int argc, char **argv) { set_cbdata_t cb = { 0 }; int error; + char *vdev = NULL; current_prop_type = ZFS_TYPE_POOL; if (argc > 1 && argv[1][0] == '-') { @@ -10413,13 +10424,20 @@ zpool_do_set(int argc, char **argv) /* argv[1], when supplied, is vdev name */ if (argc == 2) { - if (!are_vdevs_in_pool(1, argv + 1, argv[0], &cb.cb_vdevs)) { + + if (strcmp(argv[1], "root") == 0) + vdev = strdup("root-0"); + else + vdev = strdup(argv[1]); + + if (!are_vdevs_in_pool(1, &vdev, argv[0], &cb.cb_vdevs)) { (void) fprintf(stderr, gettext( "cannot find '%s' in '%s': device not in pool\n"), - argv[1], argv[0]); + vdev, argv[0]); + free(vdev); return (EINVAL); } - cb.cb_vdevs.cb_names = argv + 1; + cb.cb_vdevs.cb_names = &vdev; cb.cb_vdevs.cb_names_count = 1; cb.cb_type = ZFS_TYPE_VDEV; } @@ -10427,6 +10445,9 @@ zpool_do_set(int argc, char **argv) error = for_each_pool(1, argv, B_TRUE, NULL, ZFS_TYPE_POOL, B_FALSE, set_callback, &cb); + if (vdev != NULL) + free(vdev); + return (error); } diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 25babd4ea8cf..0734ff12280e 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -816,6 +816,7 @@ typedef struct zpool_load_policy { #define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read" #define ZPOOL_CONFIG_FEATURE_STATS "feature_stats" /* not stored on disk */ #define ZPOOL_CONFIG_ERRATA "errata" /* not stored on disk */ +#define ZPOOL_CONFIG_VDEV_ROOT_ZAP "com.klarasystems:vdev_zap_root" #define ZPOOL_CONFIG_VDEV_TOP_ZAP "com.delphix:vdev_zap_top" #define ZPOOL_CONFIG_VDEV_LEAF_ZAP "com.delphix:vdev_zap_leaf" #define ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS "com.delphix:has_per_vdev_zaps" diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h index 7cfffe3b4eed..ea3043c82a39 100644 --- a/include/sys/vdev_impl.h +++ b/include/sys/vdev_impl.h @@ -277,6 +277,7 @@ struct vdev { kthread_t *vdev_open_thread; /* thread opening children */ kthread_t *vdev_validate_thread; /* thread validating children */ uint64_t vdev_crtxg; /* txg when top-level was added */ + uint64_t vdev_root_zap; /* * Top-level vdev state. diff --git a/include/zfeature_common.h b/include/zfeature_common.h index ef915a70952e..7066c699e203 100644 --- a/include/zfeature_common.h +++ b/include/zfeature_common.h @@ -79,6 +79,7 @@ typedef enum spa_feature { SPA_FEATURE_HEAD_ERRLOG, SPA_FEATURE_BLAKE3, SPA_FEATURE_BLOCK_CLONING, + SPA_FEATURE_AVZ_V2, SPA_FEATURES } spa_feature_t; diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 41e74fd8db19..f9aed4e0d57e 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -595,7 +595,7 @@ - + @@ -5808,7 +5808,8 @@ - + + @@ -8694,8 +8695,8 @@ - - + + @@ -8772,7 +8773,7 @@ - + diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index f9b7cc004d6b..ae4c861590fd 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -2859,6 +2859,7 @@ zpool_vdev_is_interior(const char *name) strncmp(name, VDEV_TYPE_SPARE, strlen(VDEV_TYPE_SPARE)) == 0 || strncmp(name, VDEV_TYPE_REPLACING, strlen(VDEV_TYPE_REPLACING)) == 0 || + strncmp(name, VDEV_TYPE_ROOT, strlen(VDEV_TYPE_ROOT)) == 0 || strncmp(name, VDEV_TYPE_MIRROR, strlen(VDEV_TYPE_MIRROR)) == 0) return (B_TRUE); diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c index 65f462e42cd0..19d8a4742813 100644 --- a/lib/libzutil/zutil_import.c +++ b/lib/libzutil/zutil_import.c @@ -1927,9 +1927,8 @@ for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func, if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0) return (ret); - /* Don't run our function on root or indirect vdevs */ - if ((strcmp(type, VDEV_TYPE_ROOT) != 0) && - (strcmp(type, VDEV_TYPE_INDIRECT) != 0)) { + /* Don't run our function on indirect vdevs */ + if (strcmp(type, VDEV_TYPE_INDIRECT) != 0) { ret |= func(zhp, nv, data); } diff --git a/man/man7/zpool-features.7 b/man/man7/zpool-features.7 index 4cd7526858a3..efe9e833996a 100644 --- a/man/man7/zpool-features.7 +++ b/man/man7/zpool-features.7 @@ -858,6 +858,22 @@ by user and group. \*[instant-never] \*[remount-upgrade] . +.feature com.klarasystems vdev_zaps_v2 no +This feature creates a ZAP object for the root vdev. +.Pp +This feature becomes active after the next +.Nm zpool Cm import +or +.Nm zpool reguid . +. +Properties can be retrieved or set on the root vdev using +.Nm zpool Cm get +and +.Nm zpool Cm set +with +.Sy root +as the vdev name which is an alias for +.Sy root-0 . .feature org.openzfs zilsaxattr yes extensible_dataset This feature enables .Sy xattr Ns = Ns Sy sa diff --git a/module/zcommon/zfeature_common.c b/module/zcommon/zfeature_common.c index 6fe1da8ed46f..4c9b7ed72a0f 100644 --- a/module/zcommon/zfeature_common.c +++ b/module/zcommon/zfeature_common.c @@ -731,6 +731,12 @@ zpool_feature_init(void) ZFEATURE_FLAG_READONLY_COMPAT, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures); + zfeature_register(SPA_FEATURE_AVZ_V2, + "com.klarasystems:vdev_zaps_v2", "vdev_zaps_v2", + "Support for root vdev ZAP.", + ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, + sfeatures); + zfs_mod_list_supported_free(sfeatures); } diff --git a/module/zfs/spa.c b/module/zfs/spa.c index e76700a9caa3..67601211d6c2 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -3044,6 +3044,12 @@ vdev_count_verify_zaps(vdev_t *vd) spa_t *spa = vd->vdev_spa; uint64_t total = 0; + if (spa_feature_is_active(vd->vdev_spa, SPA_FEATURE_AVZ_V2) && + vd->vdev_root_zap != 0) { + total++; + ASSERT0(zap_lookup_int(spa->spa_meta_objset, + spa->spa_all_vdev_zaps, vd->vdev_root_zap)); + } if (vd->vdev_top_zap != 0) { total++; ASSERT0(zap_lookup_int(spa->spa_meta_objset, @@ -8626,6 +8632,11 @@ spa_avz_build(vdev_t *vd, uint64_t avz, dmu_tx_t *tx) { spa_t *spa = vd->vdev_spa; + if (vd->vdev_root_zap != 0 && + spa_feature_is_active(spa, SPA_FEATURE_AVZ_V2)) { + VERIFY0(zap_add_int(spa->spa_meta_objset, avz, + vd->vdev_root_zap, tx)); + } if (vd->vdev_top_zap != 0) { VERIFY0(zap_add_int(spa->spa_meta_objset, avz, vd->vdev_top_zap, tx)); diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 241be8fd856c..4bfd95861e02 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -397,7 +397,9 @@ vdev_prop_get_int(vdev_t *vd, vdev_prop_t prop, uint64_t *value) uint64_t objid; int err; - if (vd->vdev_top_zap != 0) { + if (vd->vdev_root_zap != 0) { + objid = vd->vdev_root_zap; + } else if (vd->vdev_top_zap != 0) { objid = vd->vdev_top_zap; } else if (vd->vdev_leaf_zap != 0) { objid = vd->vdev_leaf_zap; @@ -898,6 +900,14 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id, (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_CREATE_TXG, &vd->vdev_crtxg); + if (vd->vdev_ops == &vdev_root_ops && + (alloctype == VDEV_ALLOC_LOAD || + alloctype == VDEV_ALLOC_SPLIT || + alloctype == VDEV_ALLOC_ROOTPOOL)) { + (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_VDEV_ROOT_ZAP, + &vd->vdev_root_zap); + } + /* * If we're a top-level vdev, try to load the allocation parameters. */ @@ -3347,6 +3357,12 @@ vdev_construct_zaps(vdev_t *vd, dmu_tx_t *tx) vdev_zap_allocation_data(vd, tx); } } + if (vd->vdev_ops == &vdev_root_ops && vd->vdev_root_zap == 0 && + spa_feature_is_enabled(vd->vdev_spa, SPA_FEATURE_AVZ_V2)) { + if (!spa_feature_is_active(vd->vdev_spa, SPA_FEATURE_AVZ_V2)) + spa_feature_incr(vd->vdev_spa, SPA_FEATURE_AVZ_V2, tx); + vd->vdev_root_zap = vdev_create_link_zap(vd, tx); + } for (uint64_t i = 0; i < vd->vdev_children; i++) { vdev_construct_zaps(vd->vdev_child[i], tx); @@ -5683,12 +5699,17 @@ vdev_props_set_sync(void *arg, dmu_tx_t *tx) /* * Set vdev property values in the vdev props mos object. */ - if (vd->vdev_top_zap != 0) { + if (vd->vdev_root_zap != 0) { + objid = vd->vdev_root_zap; + } else if (vd->vdev_top_zap != 0) { objid = vd->vdev_top_zap; } else if (vd->vdev_leaf_zap != 0) { objid = vd->vdev_leaf_zap; } else { - panic("vdev not top or leaf"); + /* + * XXX: implement vdev_props_set_check() + */ + panic("vdev not root/top/leaf"); } switch (prop = vdev_name_to_prop(propname)) { @@ -5891,7 +5912,9 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl) nvlist_lookup_nvlist(innvl, ZPOOL_VDEV_PROPS_GET_PROPS, &nvprops); - if (vd->vdev_top_zap != 0) { + if (vd->vdev_root_zap != 0) { + objid = vd->vdev_root_zap; + } else if (vd->vdev_top_zap != 0) { objid = vd->vdev_top_zap; } else if (vd->vdev_leaf_zap != 0) { objid = vd->vdev_leaf_zap; diff --git a/module/zfs/vdev_label.c b/module/zfs/vdev_label.c index f61be65a2c72..85c7134ca4c4 100644 --- a/module/zfs/vdev_label.c +++ b/module/zfs/vdev_label.c @@ -573,6 +573,12 @@ vdev_config_generate(spa_t *spa, vdev_t *vd, boolean_t getstats, vd->vdev_top_zap); } + if (vd->vdev_ops == &vdev_root_ops && vd->vdev_root_zap != 0 && + spa_feature_is_active(vd->vdev_spa, SPA_FEATURE_AVZ_V2)) { + fnvlist_add_uint64(nv, ZPOOL_CONFIG_VDEV_ROOT_ZAP, + vd->vdev_root_zap); + } + if (vd->vdev_resilver_deferred) { ASSERT(vd->vdev_ops->vdev_op_leaf); ASSERT(spa->spa_resilver_deferred); diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index 4233c0285c4b..cc4ce03677cb 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -394,7 +394,7 @@ tags = ['functional', 'cli_root', 'zpool_export'] [tests/functional/cli_root/zpool_get] tests = ['zpool_get_001_pos', 'zpool_get_002_pos', 'zpool_get_003_pos', - 'zpool_get_004_neg', 'zpool_get_005_pos'] + 'zpool_get_004_neg', 'zpool_get_005_pos', 'vdev_get_001_pos'] tags = ['functional', 'cli_root', 'zpool_get'] [tests/functional/cli_root/zpool_history] @@ -482,7 +482,7 @@ tags = ['functional', 'cli_root', 'zpool_scrub'] [tests/functional/cli_root/zpool_set] tests = ['zpool_set_001_pos', 'zpool_set_002_neg', 'zpool_set_003_neg', - 'zpool_set_ashift', 'zpool_set_features'] + 'zpool_set_ashift', 'zpool_set_features', 'vdev_set_001_pos'] tags = ['functional', 'cli_root', 'zpool_set'] [tests/functional/cli_root/zpool_split] diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am index a470573616af..e671a3f6b02b 100644 --- a/tests/zfs-tests/tests/Makefile.am +++ b/tests/zfs-tests/tests/Makefile.am @@ -178,6 +178,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \ functional/cli_root/zpool_expand/zpool_expand.cfg \ functional/cli_root/zpool_export/zpool_export.cfg \ functional/cli_root/zpool_export/zpool_export.kshlib \ + functional/cli_root/zpool_get/vdev_get.cfg \ functional/cli_root/zpool_get/zpool_get.cfg \ functional/cli_root/zpool_get/zpool_get_parsable.cfg \ functional/cli_root/zpool_import/blockfiles/cryptv0.dat.bz2 \ @@ -1032,6 +1033,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_export/zpool_export_004_pos.ksh \ functional/cli_root/zpool_get/cleanup.ksh \ functional/cli_root/zpool_get/setup.ksh \ + functional/cli_root/zpool_get/vdev_get_001_pos.ksh \ functional/cli_root/zpool_get/zpool_get_001_pos.ksh \ functional/cli_root/zpool_get/zpool_get_002_pos.ksh \ functional/cli_root/zpool_get/zpool_get_003_pos.ksh \ @@ -1146,6 +1148,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_set/cleanup.ksh \ functional/cli_root/zpool_set/setup.ksh \ functional/cli_root/zpool/setup.ksh \ + functional/cli_root/zpool_set/vdev_set_001_pos.ksh \ functional/cli_root/zpool_set/zpool_set_001_pos.ksh \ functional/cli_root/zpool_set/zpool_set_002_neg.ksh \ functional/cli_root/zpool_set/zpool_set_003_neg.ksh \ diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg new file mode 100644 index 000000000000..71a64d4fae7a --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg @@ -0,0 +1,73 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2022, Klara Inc. +# + +# Set the expected properties of a vdev +typeset -a properties=( + capacity + state + guid + asize + psize + ashift + size + free + allocated + comment + expandsize + fragmentation + bootsize + parity + path + devid + physpath + encpath + fru + parent + children + numchildren + read_errors + write_errors + checksum_errors + initialize_errors + null_ops + read_ops + write_ops + free_ops + claim_ops + trim_ops + null_bytes + read_bytes + write_bytes + free_bytes + claim_bytes + trim_bytes + removing + allocating + failfast + checksum_n + checksum_t + io_n + io_t +) diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh new file mode 100755 index 000000000000..bca2337861d4 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get_001_pos.ksh @@ -0,0 +1,62 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2022, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_get/vdev_get.cfg + +# +# DESCRIPTION: +# +# zpool get root works as expected +# +# STRATEGY: +# +# 1. use zpool get to retrieve properties from root vdev +# 2. verify expected properties match detected properties +# + +log_assert "zpool get all on root vdev" + +EXPECT="$(zpool get -H all ${TESTPOOL} root | wc -l)" +if [ $? -ne 0 ]; then + log_fail "cannot retrieve properties from root vdev" +fi + +i=0; +while [ $i -lt "${#properties[@]}" ] +do + log_must zpool get -H "${properties[$i]}" "$TESTPOOL" root + i=$(($i+1)) +done + +EXPECT=$((EXPECT)) +if [ $i -gt $EXPECT ]; then + log_fail "found vdev properties not in vdev_get.cfg: $i/$EXPECT." +elif [ $i -lt $EXPECT ]; then + log_fail "expected properties not found in vdev_get.cfg: $i/$EXPECT." +fi + +log_pass "zpool get all on root vdev" diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg index 097cd52e4777..160a0ca2e6db 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg @@ -104,5 +104,6 @@ if is_linux || is_freebsd; then "feature@head_errlog" "feature@blake3" "feature@block_cloning" + "feature@vdev_zaps_v2" ) fi diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh new file mode 100755 index 000000000000..a1f3efb90577 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_set/vdev_set_001_pos.ksh @@ -0,0 +1,52 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2022, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# +# zpool set comment property on root vdev +# +# STRATEGY: +# 1. set a property on root vdev +# 2. verify the property is set +# + +log_assert "zpool set comment property on root vdev" + +log_must zpool set comment="openzfs" ${TESTPOOL} root + +COMMENT="$(zpool get -H -o value comment ${TESTPOOL} root)" +if [ $? -ne 0 ]; then + log_fail "cant retrieve comment property from root vdev" +fi + +if [ "$COMMENT" != "openzfs" ]; then + log_fail "unexpected value for comment property: $COMMENT != \"openzfs\"" +fi + +log_pass "zpool set comment property on root vdev" diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib index ad5bd9e7f81b..c68a5b2c4c83 100644 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib @@ -34,6 +34,10 @@ function get_top_vd_zap # dsk conf { get_conf_section "$1" "$2" | awk '/com.delphix:vdev_zap_top: [0-9]+/ {print $2}' } +function get_root_vd_zap # conf +{ + awk '/com.klarasystems:vdev_zap_root: [0-9]+/ {print $2}' "$1" +} function assert_has_sentinel # conf { @@ -54,6 +58,15 @@ function assert_zap_common # pool vd lvl zapobj fi } +function assert_root_zap # pool conf +{ + typeset pool=$1 + typeset conf=$2 + + root_zap=$(get_root_vd_zap $conf) + assert_zap_common $pool "root vdev" "root" $root_zap +} + function assert_top_zap # pool vd conf { typeset pool=$1 diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh index b67cc6d973e6..bdc8dcd468ae 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh @@ -21,7 +21,7 @@ # # Strategy: # 1. Create a pool with one disk. -# 2. Verify that the disk has a top and leaf ZAP in its config and the MOS. +# 2. Verify that the disk has a root, top and leaf ZAP in its config and the MOS. # . $STF_SUITE/include/libtest.shlib @@ -35,6 +35,7 @@ log_must zpool create -f $TESTPOOL $DISK conf="$TESTDIR/vz001" log_must eval "zdb -PC $TESTPOOL > $conf" +assert_root_zap $TESTPOOL "$conf" assert_top_zap $TESTPOOL $DISK "$conf" assert_leaf_zap $TESTPOOL $DISK "$conf" assert_has_sentinel "$conf" diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh index c571973b080b..35c4f64fa463 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh @@ -36,6 +36,7 @@ conf="$TESTDIR/vz002" log_must eval "zdb -PC $TESTPOOL > $conf" assert_has_sentinel "$conf" +assert_root_zap $TESTPOOL "$conf" for DISK in $DISKS; do assert_top_zap $TESTPOOL $DISK "$conf" assert_leaf_zap $TESTPOOL $DISK "$conf" diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh index 015729576a7d..bb6875c339c3 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh @@ -37,6 +37,7 @@ conf="$TESTDIR/vz003" log_must eval "zdb -PC $TESTPOOL > $conf" assert_has_sentinel "$conf" +assert_root_zap $TESTPOOL "$conf" assert_top_zap $TESTPOOL "type: 'mirror'" "$conf" for DISK in $DISKS; do assert_leaf_zap $TESTPOOL $DISK "$conf" diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh index 3d0f55d5a9a7..e82e398c6d27 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh @@ -40,6 +40,7 @@ log_must zpool create -f $TESTPOOL $DISK conf="$TESTDIR/vz004" log_must eval "zdb -PC $TESTPOOL > $conf" assert_has_sentinel "$conf" +assert_root_zap $TESTPOOL "$conf" orig_top=$(get_top_vd_zap $DISK $conf) orig_leaf=$(get_leaf_vd_zap $DISK $conf) assert_zap_common $TESTPOOL $DISK "top" $orig_top diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh index 1d82218bf283..4b9b45e149d7 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh @@ -37,6 +37,7 @@ log_must zpool create -f $TESTPOOL $DISK conf="$TESTDIR/vz005" log_must eval "zdb -PC $TESTPOOL > $conf" assert_has_sentinel "$conf" +assert_root_zap $TESTPOOL "$conf" orig_top=$(get_top_vd_zap $DISK $conf) orig_leaf=$(get_leaf_vd_zap $DISK $conf) assert_zap_common $TESTPOOL $DISK "top" $orig_top diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh index ce94336c7c5d..2ac493b8b0d2 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh @@ -39,6 +39,7 @@ conf="$TESTDIR/vz006" log_must eval "zdb -PC $TESTPOOL > $conf" assert_has_sentinel "$conf" +assert_root_zap $TESTPOOL "$conf" orig_top=$(get_top_vd_zap ${DISK_ARR[1]} $conf) assert_zap_common $TESTPOOL ${DISK_ARR[1]} "top" $orig_top assert_leaf_zap $TESTPOOL ${DISK_ARR[1]} "$conf" diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh index c7f12c633706..c7a4a62de436 100755 --- a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh +++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh @@ -39,6 +39,7 @@ conf="$TESTDIR/vz007" log_must eval "zdb -PC $TESTPOOL > $conf" assert_has_sentinel "$conf" +assert_root_zap $TESTPOOL "$conf" orig_top=$(get_top_vd_zap "type: 'mirror'" $conf) orig_leaf0=$(get_leaf_vd_zap ${DISK_ARR[0]} $conf) orig_leaf1=$(get_leaf_vd_zap ${DISK_ARR[1]} $conf)