@@ -426,6 +426,37 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
426
426
return (0 );
427
427
}
428
428
429
+ /*
430
+ * Get a zpool property value for 'propname' and return the value in
431
+ * a pre-allocated buffer.
432
+ */
433
+ int
434
+ zpool_get_userprop (zpool_handle_t * zhp , const char * propname , char * buf ,
435
+ size_t len , zprop_source_t * srctype )
436
+ {
437
+ nvlist_t * nv , * nvl ;
438
+ uint64_t ival ;
439
+ const char * value ;
440
+ zprop_source_t source = ZPROP_SRC_LOCAL ;
441
+
442
+ nvl = zhp -> zpool_props ;
443
+ if (nvlist_lookup_nvlist (nvl , propname , & nv ) == 0 ) {
444
+ if (nvlist_lookup_uint64 (nv , ZPROP_SOURCE , & ival ) == 0 )
445
+ source = ival ;
446
+ verify (nvlist_lookup_string (nv , ZPROP_VALUE , & value ) == 0 );
447
+ } else {
448
+ source = ZPROP_SRC_DEFAULT ;
449
+ value = "-" ;
450
+ }
451
+
452
+ if (srctype )
453
+ * srctype = source ;
454
+
455
+ (void ) strlcpy (buf , value , len );
456
+
457
+ return (0 );
458
+ }
459
+
429
460
/*
430
461
* Check if the bootfs name has the same pool name as it is set to.
431
462
* Assuming bootfs is a valid dataset name.
@@ -549,6 +580,44 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
549
580
(void ) no_memory (hdl );
550
581
goto error ;
551
582
}
583
+ continue ;
584
+ } else if (prop == ZPOOL_PROP_INVAL &&
585
+ zfs_prop_user (propname )) {
586
+ /*
587
+ * This is a user property: make sure it's a
588
+ * string, and that it's less than ZAP_MAXNAMELEN.
589
+ */
590
+ if (nvpair_type (elem ) != DATA_TYPE_STRING ) {
591
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
592
+ "'%s' must be a string" ), propname );
593
+ (void ) zfs_error (hdl , EZFS_BADPROP , errbuf );
594
+ goto error ;
595
+ }
596
+
597
+ if (strlen (nvpair_name (elem )) >= ZAP_MAXNAMELEN ) {
598
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
599
+ "property name '%s' is too long" ),
600
+ propname );
601
+ (void ) zfs_error (hdl , EZFS_BADPROP , errbuf );
602
+ goto error ;
603
+ }
604
+
605
+ (void ) nvpair_value_string (elem , & strval );
606
+
607
+ if (strlen (strval ) >= ZFS_MAXPROPLEN ) {
608
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
609
+ "property value '%s' is too long" ),
610
+ strval );
611
+ (void ) zfs_error (hdl , EZFS_BADPROP , errbuf );
612
+ goto error ;
613
+ }
614
+
615
+ if (nvlist_add_string (retprops , propname ,
616
+ strval ) != 0 ) {
617
+ (void ) no_memory (hdl );
618
+ goto error ;
619
+ }
620
+
552
621
continue ;
553
622
}
554
623
@@ -855,9 +924,30 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
855
924
features = zpool_get_features (zhp );
856
925
857
926
if ((* plp )-> pl_all && firstexpand ) {
927
+ /* Handle userprops in the all properties case */
928
+ if (zhp -> zpool_props == NULL && zpool_props_refresh (zhp ))
929
+ return (-1 );
930
+
931
+ nvp = NULL ;
932
+ while ((nvp = nvlist_next_nvpair (zhp -> zpool_props , nvp )) !=
933
+ NULL ) {
934
+ const char * propname = nvpair_name (nvp );
935
+
936
+ if (!zfs_prop_user (propname ))
937
+ continue ;
938
+
939
+ entry = zfs_alloc (hdl , sizeof (zprop_list_t ));
940
+ entry -> pl_prop = ZPROP_USERPROP ;
941
+ entry -> pl_user_prop = zfs_strdup (hdl , propname );
942
+ entry -> pl_width = strlen (entry -> pl_user_prop );
943
+ entry -> pl_all = B_TRUE ;
944
+
945
+ * last = entry ;
946
+ last = & entry -> pl_next ;
947
+ }
948
+
858
949
for (i = 0 ; i < SPA_FEATURES ; i ++ ) {
859
- zprop_list_t * entry = zfs_alloc (hdl ,
860
- sizeof (zprop_list_t ));
950
+ entry = zfs_alloc (hdl , sizeof (zprop_list_t ));
861
951
entry -> pl_prop = ZPROP_USERPROP ;
862
952
entry -> pl_user_prop = zfs_asprintf (hdl , "feature@%s" ,
863
953
spa_feature_table [i ].fi_uname );
@@ -874,7 +964,6 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
874
964
nvp != NULL ; nvp = nvlist_next_nvpair (features , nvp )) {
875
965
char * propname ;
876
966
boolean_t found ;
877
- zprop_list_t * entry ;
878
967
879
968
if (zfeature_is_supported (nvpair_name (nvp )))
880
969
continue ;
@@ -920,6 +1009,12 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp,
920
1009
NULL , literal ) == 0 ) {
921
1010
if (strlen (buf ) > entry -> pl_width )
922
1011
entry -> pl_width = strlen (buf );
1012
+ } else if (entry -> pl_prop == ZPROP_INVAL &&
1013
+ zfs_prop_user (entry -> pl_user_prop ) &&
1014
+ zpool_get_userprop (zhp , entry -> pl_user_prop , buf ,
1015
+ sizeof (buf ), NULL ) == 0 ) {
1016
+ if (strlen (buf ) > entry -> pl_width )
1017
+ entry -> pl_width = strlen (buf );
923
1018
}
924
1019
}
925
1020
0 commit comments