aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libzfs
diff options
context:
space:
mode:
authorAllan Jude <[email protected]>2021-11-30 09:46:25 -0500
committerGitHub <[email protected]>2021-11-30 07:46:25 -0700
commit2a673e76a928cca4df7794cdcaa02e0be149c4da (patch)
tree016afa631bb0d98f55b01e93ab80842fe6ffda27 /lib/libzfs
parent5f64bf7fdeebfbad50e98c6cd0c3a361a9aecabc (diff)
Vdev Properties Feature
Add properties, similar to pool properties, to each vdev. This makes use of the existing per-vdev ZAP that was added as part of device evacuation/removal. A large number of read-only properties are exposed, many of the members of struct vdev_t, that provide useful statistics. Adds support for read-only "removing" vdev property. Adds the "allocating" property that defaults to "on" and can be set to "off" to prevent future allocations from that top-level vdev. Supports user-defined vdev properties. Includes support for properties.vdev in SYSFS. Co-authored-by: Allan Jude <[email protected]> Co-authored-by: Mark Maybee <[email protected]> Reviewed-by: Matthew Ahrens <[email protected]> Reviewed-by: Mark Maybee <[email protected]> Signed-off-by: Allan Jude <[email protected]> Closes #11711
Diffstat (limited to 'lib/libzfs')
-rw-r--r--lib/libzfs/libzfs.abi199
-rw-r--r--lib/libzfs/libzfs_pool.c459
-rw-r--r--lib/libzfs/libzfs_util.c40
-rw-r--r--lib/libzfs/os/freebsd/libzfs_compat.c4
4 files changed, 687 insertions, 15 deletions
diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi
index ab6d27e91..8a696206a 100644
--- a/lib/libzfs/libzfs.abi
+++ b/lib/libzfs/libzfs.abi
@@ -259,6 +259,22 @@
<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='update_vdev_config_dev_strs' 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'/>
+ <elf-symbol name='vdev_prop_column_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_default_numeric' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_default_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_get_table' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_get_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_index_to_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_random_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_readonly' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_user' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='vdev_prop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfeature_depends_on' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfeature_is_supported' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfeature_is_valid_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -463,6 +479,7 @@
<elf-symbol name='zpool_find_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_find_vdev_by_physpath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_free_handles' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_get_all_vdev_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_config' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_get_errlog' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -477,6 +494,8 @@
<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_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'/>
<elf-symbol name='zpool_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_import_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -514,6 +533,7 @@
<elf-symbol name='zpool_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_prop_unsupported' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_prop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_prop_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_props_refresh' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_read_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_refresh_stats' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -523,6 +543,7 @@
<elf-symbol name='zpool_search_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zpool_set_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_skip_pool' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_sync_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -557,6 +578,7 @@
<elf-symbol name='zprop_register_number' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zprop_register_string' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zprop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='zprop_valid_char' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zprop_valid_for_type' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zprop_values' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zprop_width' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -2683,6 +2705,73 @@
<parameter type-id='5d0c23fb' name='prop'/>
<return type-id='c19b74c3'/>
</function-decl>
+ <function-decl name='vdev_prop_get_table' mangled-name='vdev_prop_get_table' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_table'>
+ <return type-id='76c8174b'/>
+ </function-decl>
+ <function-decl name='vdev_prop_init' mangled-name='vdev_prop_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_init'>
+ <return type-id='48b5725f'/>
+ </function-decl>
+ <function-decl name='vdev_name_to_prop' mangled-name='vdev_name_to_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_name_to_prop'>
+ <parameter type-id='80f4b756' name='propname'/>
+ <return type-id='5aa5c90c'/>
+ </function-decl>
+ <function-decl name='vdev_prop_user' mangled-name='vdev_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_user'>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='vdev_prop_to_name' mangled-name='vdev_prop_to_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_to_name'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_get_type' mangled-name='vdev_prop_get_type' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_get_type'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='31429eff'/>
+ </function-decl>
+ <function-decl name='vdev_prop_readonly' mangled-name='vdev_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_readonly'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='vdev_prop_default_string' mangled-name='vdev_prop_default_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_string'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_default_numeric' mangled-name='vdev_prop_default_numeric' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_default_numeric'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='vdev_prop_string_to_index' mangled-name='vdev_prop_string_to_index' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_string_to_index'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <parameter type-id='80f4b756' name='string'/>
+ <parameter type-id='5d6479ae' name='index'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='vdev_prop_index_to_string' mangled-name='vdev_prop_index_to_string' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_index_to_string'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <parameter type-id='9c313c2d' name='index'/>
+ <parameter type-id='7d3cd834' name='string'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_prop_vdev' mangled-name='zpool_prop_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_vdev'>
+ <parameter type-id='80f4b756' name='name'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
+ <function-decl name='vdev_prop_random_value' mangled-name='vdev_prop_random_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_random_value'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <parameter type-id='9c313c2d' name='seed'/>
+ <return type-id='9c313c2d'/>
+ </function-decl>
+ <function-decl name='vdev_prop_values' mangled-name='vdev_prop_values' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_values'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_column_name' mangled-name='vdev_prop_column_name' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_column_name'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='80f4b756'/>
+ </function-decl>
+ <function-decl name='vdev_prop_align_right' mangled-name='vdev_prop_align_right' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_prop_align_right'>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <return type-id='c19b74c3'/>
+ </function-decl>
</abi-instr>
<abi-instr address-size='64' path='../../module/zcommon/zprop_common.c' language='LANG_C99'>
<function-decl name='zprop_register_impl' mangled-name='zprop_register_impl' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_register_impl'>
@@ -2784,6 +2873,10 @@
<parameter type-id='c19b74c3' name='headcheck'/>
<return type-id='c19b74c3'/>
</function-decl>
+ <function-decl name='zprop_valid_char' mangled-name='zprop_valid_char' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_valid_char'>
+ <parameter type-id='a84c031d' name='c'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zprop_width' mangled-name='zprop_width' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zprop_width'>
<parameter type-id='95e97e5e' name='prop'/>
<parameter type-id='37e3bd22' name='fixed'/>
@@ -2886,6 +2979,7 @@
<enumerator name='ZFS_TYPE_VOLUME' value='4'/>
<enumerator name='ZFS_TYPE_POOL' value='8'/>
<enumerator name='ZFS_TYPE_BOOKMARK' value='16'/>
+ <enumerator name='ZFS_TYPE_VDEV' value='32'/>
</enum-decl>
<typedef-decl name='zfs_type_t' type-id='5d8f7321' id='2e45de5d'/>
<enum-decl name='dmu_objset_type' id='6b1b19f9'>
@@ -4216,6 +4310,53 @@
<enumerator name='ZPOOL_NUM_PROPS' value='33'/>
</enum-decl>
<typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/>
+ <enum-decl name='vdev_prop_t' naming-typedef-id='5aa5c90c' id='1573bec8'>
+ <underlying-type type-id='9cac1fee'/>
+ <enumerator name='VDEV_PROP_INVAL' value='-1'/>
+ <enumerator name='VDEV_PROP_NAME' value='0'/>
+ <enumerator name='VDEV_PROP_CAPACITY' value='1'/>
+ <enumerator name='VDEV_PROP_STATE' value='2'/>
+ <enumerator name='VDEV_PROP_GUID' value='3'/>
+ <enumerator name='VDEV_PROP_ASIZE' value='4'/>
+ <enumerator name='VDEV_PROP_PSIZE' value='5'/>
+ <enumerator name='VDEV_PROP_ASHIFT' value='6'/>
+ <enumerator name='VDEV_PROP_SIZE' value='7'/>
+ <enumerator name='VDEV_PROP_FREE' value='8'/>
+ <enumerator name='VDEV_PROP_ALLOCATED' value='9'/>
+ <enumerator name='VDEV_PROP_COMMENT' value='10'/>
+ <enumerator name='VDEV_PROP_EXPANDSZ' value='11'/>
+ <enumerator name='VDEV_PROP_FRAGMENTATION' value='12'/>
+ <enumerator name='VDEV_PROP_BOOTSIZE' value='13'/>
+ <enumerator name='VDEV_PROP_PARITY' value='14'/>
+ <enumerator name='VDEV_PROP_PATH' value='15'/>
+ <enumerator name='VDEV_PROP_DEVID' value='16'/>
+ <enumerator name='VDEV_PROP_PHYS_PATH' value='17'/>
+ <enumerator name='VDEV_PROP_ENC_PATH' value='18'/>
+ <enumerator name='VDEV_PROP_FRU' value='19'/>
+ <enumerator name='VDEV_PROP_PARENT' value='20'/>
+ <enumerator name='VDEV_PROP_CHILDREN' value='21'/>
+ <enumerator name='VDEV_PROP_NUMCHILDREN' value='22'/>
+ <enumerator name='VDEV_PROP_READ_ERRORS' value='23'/>
+ <enumerator name='VDEV_PROP_WRITE_ERRORS' value='24'/>
+ <enumerator name='VDEV_PROP_CHECKSUM_ERRORS' value='25'/>
+ <enumerator name='VDEV_PROP_INITIALIZE_ERRORS' value='26'/>
+ <enumerator name='VDEV_PROP_OPS_NULL' value='27'/>
+ <enumerator name='VDEV_PROP_OPS_READ' value='28'/>
+ <enumerator name='VDEV_PROP_OPS_WRITE' value='29'/>
+ <enumerator name='VDEV_PROP_OPS_FREE' value='30'/>
+ <enumerator name='VDEV_PROP_OPS_CLAIM' value='31'/>
+ <enumerator name='VDEV_PROP_OPS_TRIM' value='32'/>
+ <enumerator name='VDEV_PROP_BYTES_NULL' value='33'/>
+ <enumerator name='VDEV_PROP_BYTES_READ' value='34'/>
+ <enumerator name='VDEV_PROP_BYTES_WRITE' value='35'/>
+ <enumerator name='VDEV_PROP_BYTES_FREE' value='36'/>
+ <enumerator name='VDEV_PROP_BYTES_CLAIM' value='37'/>
+ <enumerator name='VDEV_PROP_BYTES_TRIM' value='38'/>
+ <enumerator name='VDEV_PROP_REMOVING' value='39'/>
+ <enumerator name='VDEV_PROP_ALLOCATING' value='40'/>
+ <enumerator name='VDEV_NUM_PROPS' value='41'/>
+ </enum-decl>
+ <typedef-decl name='vdev_prop_t' type-id='1573bec8' id='5aa5c90c'/>
<enum-decl name='vdev_state' id='21566197'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='VDEV_STATE_UNKNOWN' value='0'/>
@@ -4342,9 +4483,16 @@
<function-decl name='zpool_expand_proplist' mangled-name='zpool_expand_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_expand_proplist'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='e4378506' name='plp'/>
+ <parameter type-id='2e45de5d' name='type'/>
<parameter type-id='c19b74c3' name='literal'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='vdev_expand_proplist' mangled-name='vdev_expand_proplist' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='vdev_expand_proplist'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='vdevname'/>
+ <parameter type-id='e4378506' name='plp'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='propname'/>
@@ -4680,6 +4828,40 @@
<parameter type-id='b59d7dce' name='rlen'/>
<return type-id='901b78d1'/>
</function-decl>
+ <function-decl name='zpool_get_vdev_prop_value' mangled-name='zpool_get_vdev_prop_value' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_vdev_prop_value'>
+ <parameter type-id='5ce45b60' name='nvprop'/>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <parameter type-id='26a90f95' name='prop_name'/>
+ <parameter type-id='26a90f95' name='buf'/>
+ <parameter type-id='b59d7dce' name='len'/>
+ <parameter type-id='debc6aa3' name='srctype'/>
+ <parameter type-id='c19b74c3' name='literal'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_get_vdev_prop' mangled-name='zpool_get_vdev_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_vdev_prop'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='vdevname'/>
+ <parameter type-id='5aa5c90c' name='prop'/>
+ <parameter type-id='26a90f95' name='prop_name'/>
+ <parameter type-id='26a90f95' name='buf'/>
+ <parameter type-id='b59d7dce' name='len'/>
+ <parameter type-id='debc6aa3' name='srctype'/>
+ <parameter type-id='c19b74c3' name='literal'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_get_all_vdev_props' mangled-name='zpool_get_all_vdev_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_all_vdev_props'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='vdevname'/>
+ <parameter type-id='857bb57e' name='outnvl'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
+ <function-decl name='zpool_set_vdev_prop' mangled-name='zpool_set_vdev_prop' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_set_vdev_prop'>
+ <parameter type-id='4c81de99' name='zhp'/>
+ <parameter type-id='80f4b756' name='vdevname'/>
+ <parameter type-id='80f4b756' name='propname'/>
+ <parameter type-id='80f4b756' name='propval'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
</abi-instr>
<abi-instr address-size='64' path='libzfs_sendrecv.c' language='LANG_C99'>
<class-decl name='sendflags' size-in-bits='544' is-struct='yes' visibility='default' id='f6aa15be'>
@@ -4922,7 +5104,19 @@
<enumerator name='GET_COL_SOURCE' value='5'/>
</enum-decl>
<typedef-decl name='zfs_get_column_t' type-id='223bdcaa' id='19cefcee'/>
- <class-decl name='zprop_get_cbdata' size-in-bits='640' is-struct='yes' visibility='default' id='f3d3c319'>
+ <class-decl name='vdev_cbdata' size-in-bits='192' is-struct='yes' visibility='default' id='b8006be8'>
+ <data-member access='public' layout-offset-in-bits='0'>
+ <var-decl name='cb_name_flags' type-id='95e97e5e' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='64'>
+ <var-decl name='cb_names' type-id='9b23c9ad' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='128'>
+ <var-decl name='cb_names_count' type-id='f0981eeb' visibility='default'/>
+ </data-member>
+ </class-decl>
+ <typedef-decl name='vdev_cbdata_t' type-id='b8006be8' id='a9679c94'/>
+ <class-decl name='zprop_get_cbdata' size-in-bits='832' is-struct='yes' visibility='default' id='f3d3c319'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='cb_sources' type-id='95e97e5e' visibility='default'/>
</data-member>
@@ -4947,6 +5141,9 @@
<data-member access='public' layout-offset-in-bits='576'>
<var-decl name='cb_type' type-id='2e45de5d' visibility='default'/>
</data-member>
+ <data-member access='public' layout-offset-in-bits='640'>
+ <var-decl name='cb_vdevs' type-id='a9679c94' visibility='default'/>
+ </data-member>
</class-decl>
<typedef-decl name='zprop_get_cbdata_t' type-id='f3d3c319' id='f3d87113'/>
<typedef-decl name='zprop_func' type-id='2e711a2a' id='1ec3747a'/>
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index 8ed96275c..6e302ad4b 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -29,6 +29,7 @@
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2018, loli10K <[email protected]>
* Copyright (c) 2021, Colm Buckley <[email protected]>
+ * Copyright (c) 2021, Klara Inc.
*/
#include <errno.h>
@@ -61,6 +62,7 @@ static boolean_t zpool_vdev_is_interior(const char *name);
typedef struct prop_flags {
int create:1; /* Validate property on creation */
int import:1; /* Validate property on import */
+ int vdevprop:1; /* Validate property as a VDEV property */
} prop_flags_t;
/*
@@ -478,6 +480,35 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
const char *propname = nvpair_name(elem);
+ if (flags.vdevprop && zpool_prop_vdev(propname)) {
+ vdev_prop_t vprop = vdev_name_to_prop(propname);
+
+ if (vdev_prop_readonly(vprop)) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "'%s' "
+ "is readonly"), propname);
+ (void) zfs_error(hdl, EZFS_PROPREADONLY,
+ errbuf);
+ goto error;
+ }
+
+ if (zprop_parse_value(hdl, elem, vprop, ZFS_TYPE_VDEV,
+ retprops, &strval, &intval, errbuf) != 0)
+ goto error;
+
+ continue;
+ } else if (flags.vdevprop && vdev_prop_user(propname)) {
+ if (nvlist_add_nvpair(retprops, elem) != 0) {
+ (void) no_memory(hdl);
+ goto error;
+ }
+ continue;
+ } else if (flags.vdevprop) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "invalid property: '%s'"), propname);
+ (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+ goto error;
+ }
+
prop = zpool_name_to_prop(propname);
if (prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname)) {
int err;
@@ -806,7 +837,7 @@ zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
int
zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
- boolean_t literal)
+ zfs_type_t type, boolean_t literal)
{
libzfs_handle_t *hdl = zhp->zpool_hdl;
zprop_list_t *entry;
@@ -817,9 +848,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
boolean_t firstexpand = (NULL == *plp);
int i;
- if (zprop_expand_list(hdl, plp, ZFS_TYPE_POOL) != 0)
+ if (zprop_expand_list(hdl, plp, type) != 0)
return (-1);
+ if (type == ZFS_TYPE_VDEV)
+ return (0);
+
last = plp;
while (*last != NULL)
last = &(*last)->pl_next;
@@ -899,6 +933,77 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
return (0);
}
+int
+vdev_expand_proplist(zpool_handle_t *zhp, const char *vdevname,
+ zprop_list_t **plp)
+{
+ zprop_list_t *entry;
+ char buf[ZFS_MAXPROPLEN];
+ char *strval = NULL;
+ int err = 0;
+ nvpair_t *elem = NULL;
+ nvlist_t *vprops = NULL;
+ nvlist_t *propval = NULL;
+ const char *propname;
+ vdev_prop_t prop;
+ zprop_list_t **last;
+
+ for (entry = *plp; entry != NULL; entry = entry->pl_next) {
+ if (entry->pl_fixed)
+ continue;
+
+ if (zpool_get_vdev_prop(zhp, vdevname, entry->pl_prop,
+ entry->pl_user_prop, buf, sizeof (buf), NULL,
+ B_FALSE) == 0) {
+ if (strlen(buf) > entry->pl_width)
+ entry->pl_width = strlen(buf);
+ }
+ if (entry->pl_prop == VDEV_PROP_NAME &&
+ strlen(vdevname) > entry->pl_width)
+ entry->pl_width = strlen(vdevname);
+ }
+
+ /* Handle the all properties case */
+ last = plp;
+ if (*last != NULL && (*last)->pl_all == B_TRUE) {
+ while (*last != NULL)
+ last = &(*last)->pl_next;
+
+ err = zpool_get_all_vdev_props(zhp, vdevname, &vprops);
+ if (err != 0)
+ return (err);
+
+ while ((elem = nvlist_next_nvpair(vprops, elem)) != NULL) {
+ propname = nvpair_name(elem);
+
+ /* Skip properties that are not user defined */
+ if ((prop = vdev_name_to_prop(propname)) !=
+ VDEV_PROP_USER)
+ continue;
+
+ if (nvpair_value_nvlist(elem, &propval) != 0)
+ continue;
+
+ verify(nvlist_lookup_string(propval, ZPROP_VALUE,
+ &strval) == 0);
+
+ if ((entry = zfs_alloc(zhp->zpool_hdl,
+ sizeof (zprop_list_t))) == NULL)
+ return (ENOMEM);
+
+ entry->pl_prop = prop;
+ entry->pl_user_prop = zfs_strdup(zhp->zpool_hdl,
+ propname);
+ entry->pl_width = strlen(strval);
+ entry->pl_all = B_TRUE;
+ *last = entry;
+ last = &entry->pl_next;
+ }
+ }
+
+ return (0);
+}
+
/*
* Get the state for the given feature on the given ZFS pool.
*/
@@ -4959,3 +5064,353 @@ zpool_load_compat(const char *compat, boolean_t *features, char *report,
strlcpy(report, gettext("compatibility set ok"), rlen);
return (ZPOOL_COMPATIBILITY_OK);
}
+
+static int
+zpool_vdev_guid(zpool_handle_t *zhp, const char *vdevname, uint64_t *vdev_guid)
+{
+ nvlist_t *tgt;
+ boolean_t avail_spare, l2cache;
+
+ verify(zhp != NULL);
+ if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "pool is in an unavailable state"));
+ return (zfs_error(zhp->zpool_hdl, EZFS_POOLUNAVAIL, errbuf));
+ }
+
+ if ((tgt = zpool_find_vdev(zhp, vdevname, &avail_spare, &l2cache,
+ NULL)) == NULL) {
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "can not find %s in %s"),
+ vdevname, zhp->zpool_name);
+ return (zfs_error(zhp->zpool_hdl, EZFS_NODEVICE, errbuf));
+ }
+
+ verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID, vdev_guid) == 0);
+ return (0);
+}
+
+/*
+ * Get a vdev property value for 'prop' and return the value in
+ * a pre-allocated buffer.
+ */
+int
+zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name,
+ char *buf, size_t len, zprop_source_t *srctype, boolean_t literal)
+{
+ nvlist_t *nv;
+ uint64_t intval;
+ char *strval;
+ zprop_source_t src = ZPROP_SRC_NONE;
+
+ if (prop == VDEV_PROP_USER) {
+ /* user property, prop_name must contain the property name */
+ assert(prop_name != NULL);
+ if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
+ verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE,
+ &intval) == 0);
+ src = intval;
+ verify(nvlist_lookup_string(nv, ZPROP_VALUE,
+ &strval) == 0);
+ } else {
+ /* user prop not found */
+ return (-1);
+ }
+ (void) strlcpy(buf, strval, len);
+ if (srctype)
+ *srctype = src;
+ return (0);
+ }
+
+ if (prop_name == NULL)
+ prop_name = (char *)vdev_prop_to_name(prop);
+
+ switch (vdev_prop_get_type(prop)) {
+ case PROP_TYPE_STRING:
+ if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
+ verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE,
+ &intval) == 0);
+ src = intval;
+ verify(nvlist_lookup_string(nv, ZPROP_VALUE,
+ &strval) == 0);
+ } else {
+ src = ZPROP_SRC_DEFAULT;
+ if ((strval = (char *)vdev_prop_default_string(prop))
+ == NULL)
+ strval = "-";
+ }
+ (void) strlcpy(buf, strval, len);
+ break;
+
+ case PROP_TYPE_NUMBER:
+ if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
+ verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE,
+ &intval) == 0);
+ src = intval;
+ verify(nvlist_lookup_uint64(nv, ZPROP_VALUE,
+ &intval) == 0);
+ } else {
+ src = ZPROP_SRC_DEFAULT;
+ intval = vdev_prop_default_numeric(prop);
+ }
+
+ switch (prop) {
+ case VDEV_PROP_ASIZE:
+ case VDEV_PROP_PSIZE:
+ case VDEV_PROP_SIZE:
+ case VDEV_PROP_ALLOCATED:
+ case VDEV_PROP_FREE:
+ case VDEV_PROP_READ_ERRORS:
+ case VDEV_PROP_WRITE_ERRORS:
+ case VDEV_PROP_CHECKSUM_ERRORS:
+ case VDEV_PROP_INITIALIZE_ERRORS:
+ case VDEV_PROP_OPS_NULL:
+ case VDEV_PROP_OPS_READ:
+ case VDEV_PROP_OPS_WRITE:
+ case VDEV_PROP_OPS_FREE:
+ case VDEV_PROP_OPS_CLAIM:
+ case VDEV_PROP_OPS_TRIM:
+ case VDEV_PROP_BYTES_NULL:
+ case VDEV_PROP_BYTES_READ:
+ case VDEV_PROP_BYTES_WRITE:
+ case VDEV_PROP_BYTES_FREE:
+ case VDEV_PROP_BYTES_CLAIM:
+ case VDEV_PROP_BYTES_TRIM:
+ if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) zfs_nicenum(intval, buf, len);
+ }
+ break;
+ case VDEV_PROP_EXPANDSZ:
+ if (intval == 0) {
+ (void) strlcpy(buf, "-", len);
+ } else if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) zfs_nicenum(intval, buf, len);
+ }
+ break;
+ case VDEV_PROP_CAPACITY:
+ if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) snprintf(buf, len, "%llu%%",
+ (u_longlong_t)intval);
+ }
+ break;
+ case VDEV_PROP_FRAGMENTATION:
+ if (intval == UINT64_MAX) {
+ (void) strlcpy(buf, "-", len);
+ } else {
+ (void) snprintf(buf, len, "%llu%%",
+ (u_longlong_t)intval);
+ }
+ break;
+ case VDEV_PROP_STATE:
+ if (literal) {
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ } else {
+ (void) strlcpy(buf, zpool_state_to_name(intval,
+ VDEV_AUX_NONE), len);
+ }
+ break;
+ default:
+ (void) snprintf(buf, len, "%llu",
+ (u_longlong_t)intval);
+ }
+ break;
+
+ case PROP_TYPE_INDEX:
+ if (nvlist_lookup_nvlist(nvprop, prop_name, &nv) == 0) {
+ verify(nvlist_lookup_uint64(nv, ZPROP_SOURCE,
+ &intval) == 0);
+ src = intval;
+ verify(nvlist_lookup_uint64(nv, ZPROP_VALUE,
+ &intval) == 0);
+ } else {
+ src = ZPROP_SRC_DEFAULT;
+ intval = vdev_prop_default_numeric(prop);
+ }
+ if (vdev_prop_index_to_string(prop, intval,
+ (const char **)&strval) != 0)
+ return (-1);
+ (void) strlcpy(buf, strval, len);
+ break;
+
+ default:
+ abort();
+ }
+
+ if (srctype)
+ *srctype = src;
+
+ return (0);
+}
+
+/*
+ * Get a vdev property value for 'prop_name' and return the value in
+ * a pre-allocated buffer.
+ */
+int
+zpool_get_vdev_prop(zpool_handle_t *zhp, const char *vdevname, vdev_prop_t prop,
+ char *prop_name, char *buf, size_t len, zprop_source_t *srctype,
+ boolean_t literal)
+{
+ nvlist_t *reqnvl, *reqprops;
+ nvlist_t *retprops = NULL;
+ uint64_t vdev_guid;
+ int ret;
+
+ if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
+ return (ret);
+
+ if (nvlist_alloc(&reqnvl, NV_UNIQUE_NAME, 0) != 0)
+ return (no_memory(zhp->zpool_hdl));
+ if (nvlist_alloc(&reqprops, NV_UNIQUE_NAME, 0) != 0)
+ return (no_memory(zhp->zpool_hdl));
+
+ fnvlist_add_uint64(reqnvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid);
+
+ if (prop != VDEV_PROP_USER) {
+ /* prop_name overrides prop value */
+ if (prop_name != NULL)
+ prop = vdev_name_to_prop(prop_name);
+ else
+ prop_name = (char *)vdev_prop_to_name(prop);
+ assert(prop < VDEV_NUM_PROPS);
+ }
+
+ assert(prop_name != NULL);
+ if (nvlist_add_uint64(reqprops, prop_name, prop) != 0) {
+ nvlist_free(reqnvl);
+ nvlist_free(reqprops);
+ return (no_memory(zhp->zpool_hdl));
+ }
+
+ fnvlist_add_nvlist(reqnvl, ZPOOL_VDEV_PROPS_GET_PROPS, reqprops);
+
+ ret = lzc_get_vdev_prop(zhp->zpool_name, reqnvl, &retprops);
+
+ if (ret == 0) {
+ ret = zpool_get_vdev_prop_value(retprops, prop, prop_name, buf,
+ len, srctype, literal);
+ } else {
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot get vdev property %s from"
+ " %s in %s"), prop_name, vdevname, zhp->zpool_name);
+ (void) zpool_standard_error(zhp->zpool_hdl, ret, errbuf);
+ }
+
+ nvlist_free(reqnvl);
+ nvlist_free(reqprops);
+ nvlist_free(retprops);
+
+ return (ret);
+}
+
+/*
+ * Get all vdev properties
+ */
+int
+zpool_get_all_vdev_props(zpool_handle_t *zhp, const char *vdevname,
+ nvlist_t **outnvl)
+{
+ nvlist_t *nvl = NULL;
+ uint64_t vdev_guid;
+ int ret;
+
+ if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
+ return (ret);
+
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
+ return (no_memory(zhp->zpool_hdl));
+
+ fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_GET_VDEV, vdev_guid);
+
+ ret = lzc_get_vdev_prop(zhp->zpool_name, nvl, outnvl);
+
+ nvlist_free(nvl);
+
+ if (ret) {
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot get vdev properties for"
+ " %s in %s"), vdevname, zhp->zpool_name);
+ (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
+ }
+
+ return (ret);
+}
+
+/*
+ * Set vdev property
+ */
+int
+zpool_set_vdev_prop(zpool_handle_t *zhp, const char *vdevname,
+ const char *propname, const char *propval)
+{
+ int ret;
+ vdev_prop_t vprop;
+ nvlist_t *nvl = NULL;
+ nvlist_t *outnvl = NULL;
+ nvlist_t *props;
+ nvlist_t *realprops;
+ prop_flags_t flags = { 0 };
+ uint64_t version;
+ uint64_t vdev_guid;
+
+ if ((ret = zpool_vdev_guid(zhp, vdevname, &vdev_guid)) != 0)
+ return (ret);
+
+ vprop = vdev_name_to_prop(propname);
+
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
+ return (no_memory(zhp->zpool_hdl));
+ if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
+ return (no_memory(zhp->zpool_hdl));
+
+ fnvlist_add_uint64(nvl, ZPOOL_VDEV_PROPS_SET_VDEV, vdev_guid);
+
+ if (nvlist_add_string(props, propname, propval) != 0) {
+ nvlist_free(props);
+ return (no_memory(zhp->zpool_hdl));
+ }
+
+ char errbuf[1024];
+ (void) snprintf(errbuf, sizeof (errbuf),
+ dgettext(TEXT_DOMAIN, "cannot set property %s for %s on %s"),
+ propname, vdevname, zhp->zpool_name);
+
+ flags.vdevprop = 1;
+ version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
+ if ((realprops = zpool_valid_proplist(zhp->zpool_hdl,
+ zhp->zpool_name, props, version, flags, errbuf)) == NULL) {
+ nvlist_free(props);
+ nvlist_free(nvl);
+ return (-1);
+ }
+
+ nvlist_free(props);
+ props = realprops;
+
+ fnvlist_add_nvlist(nvl, ZPOOL_VDEV_PROPS_SET_PROPS, props);
+
+ ret = lzc_set_vdev_prop(zhp->zpool_name, nvl, &outnvl);
+
+ nvlist_free(props);
+ nvlist_free(nvl);
+ nvlist_free(outnvl);
+
+ if (ret)
+ (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf);
+
+ return (ret);
+}
diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c
index c3c009ae3..b3f39afe2 100644
--- a/lib/libzfs/libzfs_util.c
+++ b/lib/libzfs/libzfs_util.c
@@ -296,6 +296,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
case EZFS_REBUILDING:
return (dgettext(TEXT_DOMAIN, "currently sequentially "
"resilvering"));
+ case EZFS_VDEV_NOTSUP:
+ return (dgettext(TEXT_DOMAIN, "operation not supported "
+ "on this type of vdev"));
case EZFS_UNKNOWN:
return (dgettext(TEXT_DOMAIN, "unknown error"));
default:
@@ -716,6 +719,9 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
case ZFS_ERR_BADPROP:
zfs_verror(hdl, EZFS_BADPROP, fmt, ap);
break;
+ case ZFS_ERR_VDEV_NOTSUP:
+ zfs_verror(hdl, EZFS_VDEV_NOTSUP, fmt, ap);
+ break;
case ZFS_ERR_IOC_CMD_UNAVAIL:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs "
"module does not support this operation. A reboot may "
@@ -1034,6 +1040,7 @@ libzfs_init(void)
zfs_prop_init();
zpool_prop_init();
zpool_feature_init();
+ vdev_prop_init();
libzfs_mnttab_init(hdl);
fletcher_4_init();
@@ -1267,7 +1274,8 @@ zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
/* first property is always NAME */
assert(cbp->cb_proplist->pl_prop ==
- ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME));
+ ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
+ ((type == ZFS_TYPE_VDEV) ? VDEV_PROP_NAME : ZFS_PROP_NAME)));
/*
* Go through and calculate the widths for each column. For the
@@ -1284,12 +1292,16 @@ zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
if (pl->pl_prop != ZPROP_INVAL) {
const char *propname = (type == ZFS_TYPE_POOL) ?
zpool_prop_to_name(pl->pl_prop) :
- zfs_prop_to_name(pl->pl_prop);
+ ((type == ZFS_TYPE_VDEV) ?
+ vdev_prop_to_name(pl->pl_prop) :
+ zfs_prop_to_name(pl->pl_prop));
+ assert(propname != NULL);
len = strlen(propname);
if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
cbp->cb_colwidths[GET_COL_PROPERTY] = len;
} else {
+ assert(pl->pl_user_prop != NULL);
len = strlen(pl->pl_user_prop);
if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
cbp->cb_colwidths[GET_COL_PROPERTY] = len;
@@ -1314,9 +1326,10 @@ zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
/*
* 'NAME' and 'SOURCE' columns
*/
- if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
- ZFS_PROP_NAME) &&
- pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
+ if (pl->pl_prop == ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
+ ((type == ZFS_TYPE_VDEV) ? VDEV_PROP_NAME :
+ ZFS_PROP_NAME)) && pl->pl_width >
+ cbp->cb_colwidths[GET_COL_NAME]) {
cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
strlen(dgettext(TEXT_DOMAIN, "inherited from"));
@@ -1597,6 +1610,9 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
if (type == ZFS_TYPE_POOL) {
proptype = zpool_prop_get_type(prop);
propname = zpool_prop_to_name(prop);
+ } else if (type == ZFS_TYPE_VDEV) {
+ proptype = vdev_prop_get_type(prop);
+ propname = vdev_prop_to_name(prop);
} else {
proptype = zfs_prop_get_type(prop);
propname = zfs_prop_to_name(prop);
@@ -1747,15 +1763,15 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
prop = ZPROP_INVAL;
/*
- * When no property table entry can be found, return failure if
- * this is a pool property or if this isn't a user-defined
- * dataset property,
+ * Return failure if no property table entry was found and this isn't
+ * a user-defined property.
*/
if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
!zpool_prop_feature(propname) &&
!zpool_prop_unsupported(propname)) ||
- (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
- !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
+ ((type == ZFS_TYPE_DATASET) && !zfs_prop_user(propname) &&
+ !zfs_prop_userquota(propname) && !zfs_prop_written(propname)) ||
+ ((type == ZFS_TYPE_VDEV) && !vdev_prop_user(propname)))) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid property '%s'"), propname);
return (zfs_error(hdl, EZFS_BADPROP,
@@ -1938,8 +1954,8 @@ zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
return (-1);
- entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
- ZFS_PROP_NAME;
+ entry->pl_prop = ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
+ ((type == ZFS_TYPE_VDEV) ? VDEV_PROP_NAME : ZFS_PROP_NAME));
entry->pl_width = zprop_width(entry->pl_prop,
&entry->pl_fixed, type);
entry->pl_all = B_TRUE;
diff --git a/lib/libzfs/os/freebsd/libzfs_compat.c b/lib/libzfs/os/freebsd/libzfs_compat.c
index f143f9cb6..e3f17662a 100644
--- a/lib/libzfs/os/freebsd/libzfs_compat.c
+++ b/lib/libzfs/os/freebsd/libzfs_compat.c
@@ -305,6 +305,10 @@ zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"bookmarks can not be jailed"));
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
+ case ZFS_TYPE_VDEV:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "vdevs can not be jailed"));
+ return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
case ZFS_TYPE_POOL:
case ZFS_TYPE_FILESYSTEM:
/* OK */