@@ -520,7 +520,7 @@ get_usage(zpool_help_t idx)
520520 return (gettext ("\ttrim [-dw] [-r <rate>] [-c | -s] "
521521 "<-a | <pool> [<device> ...]>\n" ));
522522 case HELP_STATUS :
523- return (gettext ("\tstatus [-DdegiLPpstvx ] "
523+ return (gettext ("\tstatus [-DdegiLPpstx] [-v|-vv ] "
524524 "[-c script1[,script2,...]] ...\n"
525525 "\t [-j|--json [--json-flat-vdevs] [--json-int] "
526526 "[--json-pool-key-guid]] ...\n"
@@ -1049,6 +1049,9 @@ nice_num_str_nvlist(nvlist_t *item, const char *key, uint64_t value,
10491049 case ZFS_NICENUM_BYTES :
10501050 zfs_nicenum_format (value , buf , 256 , ZFS_NICENUM_BYTES );
10511051 break ;
1052+ case ZFS_NICENUM_RAW :
1053+ zfs_nicenum_format (value , buf , 256 , ZFS_NICENUM_RAW );
1054+ break ;
10521055 case ZFS_NICENUM_TIME :
10531056 zfs_nicenum_format (value , buf , 256 , ZFS_NICENUM_TIME );
10541057 break ;
@@ -2589,7 +2592,7 @@ typedef struct status_cbdata {
25892592 int cb_name_flags ;
25902593 int cb_namewidth ;
25912594 boolean_t cb_allpools ;
2592- boolean_t cb_verbose ;
2595+ int cb_verbosity ;
25932596 boolean_t cb_literal ;
25942597 boolean_t cb_explain ;
25952598 boolean_t cb_first ;
@@ -3321,7 +3324,7 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
33213324 nvlist_t * * child ;
33223325 boolean_t printed = B_FALSE ;
33233326
3324- assert (zhp != NULL || ! cb -> cb_verbose );
3327+ assert (zhp != NULL || cb -> cb_verbosity == 0 );
33253328
33263329 if (nvlist_lookup_nvlist_array (nv , ZPOOL_CONFIG_CHILDREN , & child ,
33273330 & children ) != 0 )
@@ -9522,7 +9525,7 @@ class_vdevs_nvlist(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
95229525 if (!cb -> cb_flat_vdevs )
95239526 class_obj = fnvlist_alloc ();
95249527
9525- assert (zhp != NULL || ! cb -> cb_verbose );
9528+ assert (zhp != NULL || cb -> cb_verbosity == 0 );
95269529
95279530 if (nvlist_lookup_nvlist_array (nv , ZPOOL_CONFIG_CHILDREN , & child ,
95289531 & children ) != 0 )
@@ -9626,57 +9629,96 @@ spares_nvlist(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
96269629 }
96279630}
96289631
9632+ /*
9633+ * Take a uint64 nvpair named 'name' from nverrlist, nicenum-ify it, and
9634+ * put it back in 'nverrlist', possibly as a string, with the same 'name'.
9635+ */
9636+ static void
9637+ convert_nvlist_uint64_to_nicenum (status_cbdata_t * cb , nvlist_t * parent ,
9638+ const char * name , enum zfs_nicenum_format format )
9639+ {
9640+ uint64_t val ;
9641+ nvpair_t * nvp ;
9642+
9643+ if (nvlist_lookup_nvpair (parent , name , & nvp ) != 0 )
9644+ return ; /* nothing by that name, ignore */
9645+
9646+ val = fnvpair_value_uint64 (nvp );
9647+ nvlist_remove_nvpair (parent , nvp );
9648+ nice_num_str_nvlist (parent , name , val ,
9649+ cb -> cb_literal , cb -> cb_json_as_int , format );
9650+ }
9651+
96299652static void
96309653errors_nvlist (zpool_handle_t * zhp , status_cbdata_t * cb , nvlist_t * item )
96319654{
9632- uint64_t nerr ;
9633- nvlist_t * config = zpool_get_config (zhp , NULL );
9634- if (nvlist_lookup_uint64 (config , ZPOOL_CONFIG_ERRCOUNT ,
9635- & nerr ) == 0 ) {
9636- nice_num_str_nvlist (item , ZPOOL_CONFIG_ERRCOUNT , nerr ,
9637- cb -> cb_literal , cb -> cb_json_as_int , ZFS_NICENUM_1024 );
9638- if (nerr != 0 && cb -> cb_verbose ) {
9639- nvlist_t * nverrlist = NULL ;
9640- if (zpool_get_errlog (zhp , & nverrlist ) == 0 ) {
9641- int i = 0 ;
9642- int count = 0 ;
9643- size_t len = MAXPATHLEN * 2 ;
9644- nvpair_t * elem = NULL ;
9645-
9646- for (nvpair_t * pair =
9647- nvlist_next_nvpair (nverrlist , NULL );
9648- pair != NULL ;
9649- pair = nvlist_next_nvpair (nverrlist , pair ))
9650- count ++ ;
9651- char * * errl = (char * * )malloc (
9652- count * sizeof (char * ));
9653-
9654- while ((elem = nvlist_next_nvpair (nverrlist ,
9655- elem )) != NULL ) {
9656- nvlist_t * nv ;
9657- uint64_t dsobj , obj ;
9658-
9659- verify (nvpair_value_nvlist (elem ,
9660- & nv ) == 0 );
9661- verify (nvlist_lookup_uint64 (nv ,
9662- ZPOOL_ERR_DATASET , & dsobj ) == 0 );
9663- verify (nvlist_lookup_uint64 (nv ,
9664- ZPOOL_ERR_OBJECT , & obj ) == 0 );
9665- errl [i ] = safe_malloc (len );
9666- zpool_obj_to_path (zhp , dsobj , obj ,
9667- errl [i ++ ], len );
9668- }
9669- nvlist_free (nverrlist );
9670- fnvlist_add_string_array (item , "errlist" ,
9671- (const char * * )errl , count );
9672- for (int i = 0 ; i < count ; ++ i )
9673- free (errl [i ]);
9674- free (errl );
9675- } else
9676- fnvlist_add_string (item , "errlist" ,
9677- strerror (errno ));
9655+ int verbosity = cb -> cb_verbosity ;
9656+ nvlist_t * nverrlist = NULL , * json ;
9657+ nvpair_t * elem ;
9658+ char * pathname ;
9659+ size_t len = MAXPATHLEN * 2 ;
9660+ nvlist_t * * ranges ;
9661+ uint_t count ;
9662+
9663+ if (zpool_get_errlog (zhp , & nverrlist ) != 0 )
9664+ return ;
9665+
9666+ pathname = safe_malloc (len );
9667+ json = fnvlist_alloc ();
9668+
9669+ elem = NULL ;
9670+ while ((elem = nvlist_next_nvpair (nverrlist , elem )) != NULL ) {
9671+ nvlist_t * nv ;
9672+ uint64_t dsobj , obj ;
9673+
9674+ verify (nvpair_value_nvlist (elem , & nv ) == 0 );
9675+
9676+ dsobj = fnvlist_lookup_uint64 (nv , ZPOOL_ERR_DATASET );
9677+ obj = fnvlist_lookup_uint64 (nv , ZPOOL_ERR_OBJECT );
9678+
9679+ zpool_obj_to_path (zhp , dsobj , obj , pathname , len );
9680+
9681+ /*
9682+ * Each JSON entry is a different file/zvol. If user has
9683+ * verbosity = 1, then just make a simple object containing
9684+ * the name.
9685+ */
9686+ if (verbosity <= 1 ) {
9687+ nvlist_t * nameonly ;
9688+ nameonly = fnvlist_alloc ();
9689+ fnvlist_add_string (nameonly , ZPOOL_ERR_NAME , pathname );
9690+ fnvlist_add_nvlist (json , pathname , nameonly );
9691+ nvlist_free (nameonly );
9692+ continue ;
9693+ }
9694+
9695+ fnvlist_add_string (nv , ZPOOL_ERR_NAME , pathname );
9696+
9697+ /* nicenum-ify our nvlist */
9698+ convert_nvlist_uint64_to_nicenum (cb , nv , ZPOOL_ERR_OBJECT ,
9699+ ZFS_NICENUM_RAW );
9700+ convert_nvlist_uint64_to_nicenum (cb , nv , ZPOOL_ERR_DATASET ,
9701+ ZFS_NICENUM_RAW );
9702+ convert_nvlist_uint64_to_nicenum (cb , nv , ZPOOL_ERR_BLOCK_SIZE ,
9703+ ZFS_NICENUM_1024 );
9704+
9705+ if (nvlist_lookup_nvlist_array (nv , ZPOOL_ERR_RANGES , & ranges ,
9706+ & count ) == 0 ) {
9707+ for (uint_t i = 0 ; i < count ; i ++ ) {
9708+ convert_nvlist_uint64_to_nicenum (cb , ranges [i ],
9709+ ZPOOL_ERR_START_BYTE , ZFS_NICENUM_1024 );
9710+ convert_nvlist_uint64_to_nicenum (cb , ranges [i ],
9711+ ZPOOL_ERR_END_BYTE , ZFS_NICENUM_1024 );
9712+ }
96789713 }
9714+
9715+ fnvlist_add_nvlist (json , pathname , nv );
96799716 }
9717+
9718+ /* Place our error list in a top level "errors" JSON object. */
9719+ fnvlist_add_nvlist (item , ZPOOL_ERR_JSON , json );
9720+ free (pathname );
9721+ nvlist_free (nverrlist );
96809722}
96819723
96829724static void
@@ -10348,12 +10390,14 @@ print_checkpoint_status(pool_checkpoint_stat_t *pcs)
1034810390}
1034910391
1035010392static void
10351- print_error_log (zpool_handle_t * zhp )
10393+ print_error_log (zpool_handle_t * zhp , int verbosity , boolean_t literal )
1035210394{
1035310395 nvlist_t * nverrlist = NULL ;
1035410396 nvpair_t * elem ;
1035510397 char * pathname ;
1035610398 size_t len = MAXPATHLEN * 2 ;
10399+ boolean_t started = B_FALSE ;
10400+ char last_pathname [MAXPATHLEN ] = "" ;
1035710401
1035810402 if (zpool_get_errlog (zhp , & nverrlist ) != 0 )
1035910403 return ;
@@ -10373,8 +10417,48 @@ print_error_log(zpool_handle_t *zhp)
1037310417 verify (nvlist_lookup_uint64 (nv , ZPOOL_ERR_OBJECT ,
1037410418 & obj ) == 0 );
1037510419 zpool_obj_to_path (zhp , dsobj , obj , pathname , len );
10376- (void ) printf ("%7s %s\n" , "" , pathname );
10420+ if (last_pathname [0 ] == '\0' ||
10421+ strncmp (pathname , last_pathname , len ) != 0 ) {
10422+ strlcpy (last_pathname , pathname ,
10423+ sizeof (last_pathname ));
10424+ if (started )
10425+ (void ) printf ("\n" );
10426+ else
10427+ started = B_TRUE ;
10428+ (void ) printf ("%7s %s " , "" , pathname );
10429+ } else if (verbosity > 1 ) {
10430+ (void ) printf ("," );
10431+ }
10432+ if (verbosity > 1 ) {
10433+ nvlist_t * * arr ;
10434+ uint_t count ;
10435+ if (nvlist_lookup_nvlist_array (nv , ZPOOL_ERR_RANGES ,
10436+ & arr , & count ) != 0 ) {
10437+ (void ) printf ("(no ranges)" );
10438+ continue ;
10439+ }
10440+
10441+ for (uint_t i = 0 ; i < count ; i ++ ) {
10442+ uint64_t start ;
10443+ uint64_t end ;
10444+ start = fnvlist_lookup_uint64 (arr [i ],
10445+ ZPOOL_ERR_START_BYTE );
10446+ end = fnvlist_lookup_uint64 (arr [i ],
10447+ ZPOOL_ERR_END_BYTE );
10448+ if (literal ) {
10449+ (void ) printf ("%lu-%lu" , start , end );
10450+ } else {
10451+ char s1 [32 ], s2 [32 ];
10452+ zfs_nicenum (start , s1 , sizeof (s1 ));
10453+ zfs_nicenum (end , s2 , sizeof (s2 ));
10454+ (void ) printf ("%s-%s" , s1 , s2 );
10455+ }
10456+ if (i != count - 1 )
10457+ (void ) printf ("," );
10458+ }
10459+ }
1037710460 }
10461+ (void ) printf ("\n" );
1037810462 free (pathname );
1037910463 nvlist_free (nverrlist );
1038010464}
@@ -11071,14 +11155,15 @@ status_callback(zpool_handle_t *zhp, void *data)
1107111155 if (nerr == 0 ) {
1107211156 (void ) printf (gettext (
1107311157 "errors: No known data errors\n" ));
11074- } else if (! cbp -> cb_verbose ) {
11158+ } else if (cbp -> cb_verbosity == 0 ) {
1107511159 color_start (ANSI_RED );
1107611160 (void ) printf (gettext ("errors: %llu data "
1107711161 "errors, use '-v' for a list\n" ),
1107811162 (u_longlong_t )nerr );
1107911163 color_end ();
1108011164 } else {
11081- print_error_log (zhp );
11165+ print_error_log (zhp , cbp -> cb_verbosity ,
11166+ cbp -> cb_literal );
1108211167 }
1108311168 }
1108411169
@@ -11205,7 +11290,7 @@ zpool_do_status(int argc, char **argv)
1120511290 get_timestamp_arg (* optarg );
1120611291 break ;
1120711292 case 'v' :
11208- cb .cb_verbose = B_TRUE ;
11293+ cb .cb_verbosity ++ ;
1120911294 break ;
1121011295 case 'j' :
1121111296 cb .cb_json = B_TRUE ;
0 commit comments