Skip to content

Commit 4302fb5

Browse files
committed
Add support for zpool user properties
`zpool set org.freebsd:comment="this is my pool" poolname` Also stop truncating property values at MAXNAMELEN, use ZFS_MAXPROPLEN Signed-off-by: Allan Jude <[email protected]> Sponsored-by: Klara Inc.
1 parent b9d9845 commit 4302fb5

File tree

11 files changed

+2390
-2232
lines changed

11 files changed

+2390
-2232
lines changed

cmd/zpool/zpool_main.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6017,11 +6017,14 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
60176017
zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
60186018
sizeof (property)) == 0) {
60196019
propstr = property;
6020+
} else if (zfs_prop_user(pl->pl_user_prop) &&
6021+
zpool_get_userprop(zhp, pl->pl_user_prop, property,
6022+
sizeof (property), NULL) == 0) {
6023+
propstr = property;
60206024
} else {
60216025
propstr = "-";
60226026
}
60236027

6024-
60256028
/*
60266029
* If this is being called in scripted mode, or if this is the
60276030
* last column and it is left-justified, don't include a width
@@ -10003,6 +10006,17 @@ get_callback(zpool_handle_t *zhp, void *data)
1000310006
continue;
1000410007

1000510008
if (pl->pl_prop == ZPROP_INVAL &&
10009+
zfs_prop_user(pl->pl_user_prop)) {
10010+
srctype = ZPROP_SRC_LOCAL;
10011+
10012+
if (zpool_get_userprop(zhp, pl->pl_user_prop,
10013+
value, sizeof (value), &srctype) != 0)
10014+
continue;
10015+
10016+
zprop_print_one_property(zpool_get_name(zhp),
10017+
cbp, pl->pl_user_prop, value, srctype,
10018+
NULL, NULL);
10019+
} else if (pl->pl_prop == ZPROP_INVAL &&
1000610020
(zpool_prop_feature(pl->pl_user_prop) ||
1000710021
zpool_prop_unsupported(pl->pl_user_prop))) {
1000810022
srctype = ZPROP_SRC_LOCAL;

include/libzfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ _LIBZFS_H const char *zpool_get_state_str(zpool_handle_t *);
329329
_LIBZFS_H int zpool_set_prop(zpool_handle_t *, const char *, const char *);
330330
_LIBZFS_H int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
331331
size_t proplen, zprop_source_t *, boolean_t literal);
332+
_LIBZFS_H int zpool_get_userprop(zpool_handle_t *, const char *, char *,
333+
size_t proplen, zprop_source_t *);
332334
_LIBZFS_H uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
333335
zprop_source_t *);
334336
_LIBZFS_H int zpool_props_refresh(zpool_handle_t *);

lib/libnvpair/libnvpair.abi

Lines changed: 2046 additions & 2046 deletions
Large diffs are not rendered by default.

lib/libuutil/libuutil.abi

Lines changed: 123 additions & 123 deletions
Large diffs are not rendered by default.

lib/libzfs/libzfs.abi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@
481481
<elf-symbol name='zpool_get_state' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
482482
<elf-symbol name='zpool_get_state_str' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
483483
<elf-symbol name='zpool_get_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
484+
<elf-symbol name='zpool_get_userprop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
484485
<elf-symbol name='zpool_get_vdev_prop' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
485486
<elf-symbol name='zpool_get_vdev_prop_value' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
486487
<elf-symbol name='zpool_history_unpack' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -3310,6 +3311,14 @@
33103311
<parameter type-id='c19b74c3' name='literal'/>
33113312
<return type-id='95e97e5e'/>
33123313
</function-decl>
3314+
<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'>
3315+
<parameter type-id='4c81de99' name='zhp'/>
3316+
<parameter type-id='80f4b756' name='propname'/>
3317+
<parameter type-id='26a90f95' name='buf'/>
3318+
<parameter type-id='b59d7dce' name='len'/>
3319+
<parameter type-id='debc6aa3' name='srctype'/>
3320+
<return type-id='95e97e5e'/>
3321+
</function-decl>
33133322
<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'>
33143323
<parameter type-id='4c81de99' name='zhp'/>
33153324
<parameter type-id='80f4b756' name='propname'/>

lib/libzfs/libzfs_pool.c

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,37 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
423423
return (0);
424424
}
425425

426+
/*
427+
* Get a zpool property value for 'propname' and return the value in
428+
* a pre-allocated buffer.
429+
*/
430+
int
431+
zpool_get_userprop(zpool_handle_t *zhp, const char *propname, char *buf,
432+
size_t len, zprop_source_t *srctype)
433+
{
434+
nvlist_t *nv, *nvl;
435+
uint64_t ival;
436+
char *value;
437+
zprop_source_t source = ZPROP_SRC_LOCAL;
438+
439+
nvl = zhp->zpool_props;
440+
if (nvlist_lookup_nvlist(nvl, propname, &nv) == 0) {
441+
if (nvlist_lookup_uint64(nv, ZPROP_SOURCE, &ival) == 0)
442+
source = ival;
443+
verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
444+
} else {
445+
source = ZPROP_SRC_DEFAULT;
446+
value = "-";
447+
}
448+
449+
if (srctype)
450+
*srctype = source;
451+
452+
(void) strlcpy(buf, value, len);
453+
454+
return (0);
455+
}
456+
426457
/*
427458
* Check if the bootfs name has the same pool name as it is set to.
428459
* Assuming bootfs is a valid dataset name.
@@ -546,6 +577,35 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
546577
(void) no_memory(hdl);
547578
goto error;
548579
}
580+
continue;
581+
} else if (prop == ZPOOL_PROP_INVAL &&
582+
zfs_prop_user(propname)) {
583+
/*
584+
* This is a user property: make sure it's a
585+
* string, and that it's less than ZAP_MAXNAMELEN.
586+
*/
587+
if (nvpair_type(elem) != DATA_TYPE_STRING) {
588+
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
589+
"'%s' must be a string"), propname);
590+
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
591+
goto error;
592+
}
593+
594+
if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
595+
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
596+
"property name '%s' is too long"),
597+
propname);
598+
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
599+
goto error;
600+
}
601+
602+
(void) nvpair_value_string(elem, &strval);
603+
if (nvlist_add_string(retprops, propname,
604+
strval) != 0) {
605+
(void) no_memory(hdl);
606+
goto error;
607+
}
608+
549609
continue;
550610
}
551611

@@ -851,9 +911,30 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
851911
features = zpool_get_features(zhp);
852912

853913
if ((*plp)->pl_all && firstexpand) {
914+
/* Handle userprops in the all properties case */
915+
if (zhp->zpool_props == NULL && zpool_props_refresh(zhp))
916+
return (-1);
917+
918+
nvp = NULL;
919+
while ((nvp = nvlist_next_nvpair(zhp->zpool_props, nvp)) !=
920+
NULL) {
921+
char *propname = nvpair_name(nvp);
922+
923+
if (!zfs_prop_user(propname))
924+
continue;
925+
926+
entry = zfs_alloc(hdl, sizeof (zprop_list_t));
927+
entry->pl_prop = ZPROP_INVAL;
928+
entry->pl_user_prop = zfs_strdup(hdl, propname);
929+
entry->pl_width = strlen(entry->pl_user_prop);
930+
entry->pl_all = B_TRUE;
931+
932+
*last = entry;
933+
last = &entry->pl_next;
934+
}
935+
854936
for (i = 0; i < SPA_FEATURES; i++) {
855-
zprop_list_t *entry = zfs_alloc(hdl,
856-
sizeof (zprop_list_t));
937+
entry = zfs_alloc(hdl, sizeof (zprop_list_t));
857938
entry->pl_prop = ZPROP_INVAL;
858939
entry->pl_user_prop = zfs_asprintf(hdl, "feature@%s",
859940
spa_feature_table[i].fi_uname);
@@ -870,7 +951,6 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
870951
nvp != NULL; nvp = nvlist_next_nvpair(features, nvp)) {
871952
char *propname;
872953
boolean_t found;
873-
zprop_list_t *entry;
874954

875955
if (zfeature_is_supported(nvpair_name(nvp)))
876956
continue;
@@ -916,6 +996,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
916996
NULL, literal) == 0) {
917997
if (strlen(buf) > entry->pl_width)
918998
entry->pl_width = strlen(buf);
999+
} else if (entry->pl_prop == ZPROP_INVAL &&
1000+
zfs_prop_user(entry->pl_user_prop) &&
1001+
zpool_get_userprop(zhp, entry->pl_user_prop, buf,
1002+
sizeof (buf), NULL) == 0) {
1003+
if (strlen(buf) > entry->pl_width)
1004+
entry->pl_width = strlen(buf);
9191005
}
9201006
}
9211007

lib/libzfs/libzfs_util.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,7 @@ addlist(libzfs_handle_t *hdl, const char *propname, zprop_list_t **listp,
17501750
* a user-defined property.
17511751
*/
17521752
if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1753+
!zfs_prop_user(propname) &&
17531754
!zpool_prop_feature(propname) &&
17541755
!zpool_prop_unsupported(propname)) ||
17551756
((type == ZFS_TYPE_DATASET) && !zfs_prop_user(propname) &&

lib/libzfs_core/libzfs_core.abi

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@
214214
<elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
215215
<elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
216216
</elf-function-symbols>
217-
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
217+
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
218218
<type-decl name='variadic parameter type' id='2c1145c5'/>
219219
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
220220
<parameter type-id='c19b74c3' name='val'/>
@@ -229,7 +229,7 @@
229229
<return type-id='48b5725f'/>
230230
</function-decl>
231231
</abi-instr>
232-
<abi-instr address-size='64' path='atomic.c' language='LANG_C99'>
232+
<abi-instr address-size='64' path='lib/libspl/atomic.c' language='LANG_C99'>
233233
<type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
234234
<type-decl name='short int' size-in-bits='16' id='a2185560'/>
235235
<type-decl name='signed char' size-in-bits='8' id='28577a57'/>
@@ -573,12 +573,12 @@
573573
</function-decl>
574574
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
575575
</abi-instr>
576-
<abi-instr address-size='64' path='getexecname.c' language='LANG_C99'>
576+
<abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'>
577577
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
578578
<return type-id='80f4b756'/>
579579
</function-decl>
580580
</abi-instr>
581-
<abi-instr address-size='64' path='list.c' language='LANG_C99'>
581+
<abi-instr address-size='64' path='lib/libspl/list.c' language='LANG_C99'>
582582
<typedef-decl name='list_node_t' type-id='b0b5e45e' id='b21843b2'/>
583583
<typedef-decl name='list_t' type-id='e824dae9' id='0899125f'/>
584584
<class-decl name='list_node' size-in-bits='128' is-struct='yes' visibility='default' id='b0b5e45e'>
@@ -690,7 +690,7 @@
690690
<return type-id='95e97e5e'/>
691691
</function-decl>
692692
</abi-instr>
693-
<abi-instr address-size='64' path='mkdirp.c' language='LANG_C99'>
693+
<abi-instr address-size='64' path='lib/libspl/mkdirp.c' language='LANG_C99'>
694694
<typedef-decl name='__mode_t' type-id='f0981eeb' id='e1c52942'/>
695695
<typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
696696
<function-decl name='mkdirp' mangled-name='mkdirp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mkdirp'>
@@ -699,12 +699,12 @@
699699
<return type-id='95e97e5e'/>
700700
</function-decl>
701701
</abi-instr>
702-
<abi-instr address-size='64' path='os/linux/gethostid.c' language='LANG_C99'>
702+
<abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'>
703703
<function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'>
704704
<return type-id='7359adad'/>
705705
</function-decl>
706706
</abi-instr>
707-
<abi-instr address-size='64' path='os/linux/getmntany.c' language='LANG_C99'>
707+
<abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
708708
<array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
709709
<subrange length='3' type-id='7359adad' id='56f209d2'/>
710710
</array-type-def>
@@ -938,40 +938,40 @@
938938
<return type-id='95e97e5e'/>
939939
</function-decl>
940940
</abi-instr>
941-
<abi-instr address-size='64' path='os/linux/zone.c' language='LANG_C99'>
941+
<abi-instr address-size='64' path='lib/libspl/os/linux/zone.c' language='LANG_C99'>
942942
<typedef-decl name='zoneid_t' type-id='95e97e5e' id='4da03624'/>
943943
<function-decl name='getzoneid' mangled-name='getzoneid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getzoneid'>
944944
<return type-id='4da03624'/>
945945
</function-decl>
946946
</abi-instr>
947-
<abi-instr address-size='64' path='page.c' language='LANG_C99'>
947+
<abi-instr address-size='64' path='lib/libspl/page.c' language='LANG_C99'>
948948
<function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'>
949949
<return type-id='b59d7dce'/>
950950
</function-decl>
951951
</abi-instr>
952-
<abi-instr address-size='64' path='strlcat.c' language='LANG_C99'>
952+
<abi-instr address-size='64' path='lib/libspl/strlcat.c' language='LANG_C99'>
953953
<function-decl name='strlcat' mangled-name='strlcat' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcat'>
954954
<parameter type-id='26a90f95' name='dst'/>
955955
<parameter type-id='80f4b756' name='src'/>
956956
<parameter type-id='b59d7dce' name='dstsize'/>
957957
<return type-id='b59d7dce'/>
958958
</function-decl>
959959
</abi-instr>
960-
<abi-instr address-size='64' path='strlcpy.c' language='LANG_C99'>
960+
<abi-instr address-size='64' path='lib/libspl/strlcpy.c' language='LANG_C99'>
961961
<function-decl name='strlcpy' mangled-name='strlcpy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='strlcpy'>
962962
<parameter type-id='26a90f95' name='dst'/>
963963
<parameter type-id='80f4b756' name='src'/>
964964
<parameter type-id='b59d7dce' name='len'/>
965965
<return type-id='b59d7dce'/>
966966
</function-decl>
967967
</abi-instr>
968-
<abi-instr address-size='64' path='timestamp.c' language='LANG_C99'>
968+
<abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'>
969969
<function-decl name='print_timestamp' mangled-name='print_timestamp' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='print_timestamp'>
970970
<parameter type-id='3502e3ff' name='timestamp_fmt'/>
971971
<return type-id='48b5725f'/>
972972
</function-decl>
973973
</abi-instr>
974-
<abi-instr address-size='64' path='libzfs_core.c' language='LANG_C99'>
974+
<abi-instr address-size='64' path='lib/libzfs_core/libzfs_core.c' language='LANG_C99'>
975975
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
976976
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='2048' id='d1617432'>
977977
<subrange length='256' type-id='7359adad' id='36e5b9fa'/>
@@ -1927,7 +1927,7 @@
19271927
<return type-id='95e97e5e'/>
19281928
</function-type>
19291929
</abi-instr>
1930-
<abi-instr address-size='64' path='os/linux/libzfs_core_ioctl.c' language='LANG_C99'>
1930+
<abi-instr address-size='64' path='lib/libzfs_core/os/linux/libzfs_core_ioctl.c' language='LANG_C99'>
19311931
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32768' id='d16c6df4'>
19321932
<subrange length='4096' type-id='7359adad' id='bc1b5ddc'/>
19331933
</array-type-def>

lib/libzfsbootenv/libzfsbootenv.abi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<elf-symbol name='lzbe_remove_pair' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
1515
<elf-symbol name='lzbe_set_boot_device' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
1616
</elf-function-symbols>
17-
<abi-instr address-size='64' path='lzbe_device.c' language='LANG_C99'>
17+
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_device.c' language='LANG_C99'>
1818
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
1919
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
2020
<type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
@@ -41,7 +41,7 @@
4141
<return type-id='95e97e5e'/>
4242
</function-decl>
4343
</abi-instr>
44-
<abi-instr address-size='64' path='lzbe_pair.c' language='LANG_C99'>
44+
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_pair.c' language='LANG_C99'>
4545
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
4646
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
4747
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
@@ -76,7 +76,7 @@
7676
<return type-id='95e97e5e'/>
7777
</function-decl>
7878
</abi-instr>
79-
<abi-instr address-size='64' path='lzbe_util.c' language='LANG_C99'>
79+
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_util.c' language='LANG_C99'>
8080
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
8181
<subrange length='1' type-id='7359adad' id='52f813b4'/>
8282
</array-type-def>

0 commit comments

Comments
 (0)