@@ -1050,6 +1050,9 @@ nice_num_str_nvlist(nvlist_t *item, const char *key, uint64_t value,
10501050 case ZFS_NICENUM_BYTES :
10511051 zfs_nicenum_format (value , buf , 256 , ZFS_NICENUM_BYTES );
10521052 break ;
1053+ case ZFS_NICENUM_RAW :
1054+ zfs_nicenum_format (value , buf , 256 , ZFS_NICENUM_RAW );
1055+ break ;
10531056 case ZFS_NICENUM_TIME :
10541057 zfs_nicenum_format (value , buf , 256 , ZFS_NICENUM_TIME );
10551058 break ;
@@ -2590,7 +2593,7 @@ typedef struct status_cbdata {
25902593 int cb_name_flags ;
25912594 int cb_namewidth ;
25922595 boolean_t cb_allpools ;
2593- boolean_t cb_verbose ;
2596+ int cb_verbosity ;
25942597 boolean_t cb_literal ;
25952598 boolean_t cb_explain ;
25962599 boolean_t cb_first ;
@@ -3322,7 +3325,7 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
33223325 nvlist_t * * child ;
33233326 boolean_t printed = B_FALSE ;
33243327
3325- assert (zhp != NULL || ! cb -> cb_verbose );
3328+ assert (zhp != NULL || cb -> cb_verbosity == 0 );
33263329
33273330 if (nvlist_lookup_nvlist_array (nv , ZPOOL_CONFIG_CHILDREN , & child ,
33283331 & children ) != 0 )
@@ -9516,7 +9519,7 @@ class_vdevs_nvlist(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
95169519 if (!cb -> cb_flat_vdevs )
95179520 class_obj = fnvlist_alloc ();
95189521
9519- assert (zhp != NULL || ! cb -> cb_verbose );
9522+ assert (zhp != NULL || cb -> cb_verbosity == 0 );
95209523
95219524 if (nvlist_lookup_nvlist_array (nv , ZPOOL_CONFIG_CHILDREN , & child ,
95229525 & children ) != 0 )
@@ -9620,57 +9623,96 @@ spares_nvlist(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
96209623 }
96219624}
96229625
9626+ /*
9627+ * Take a uint64 nvpair named 'name' from nverrlist, nicenum-ify it, and
9628+ * put it back in 'nverrlist', possibly as a string, with the same 'name'.
9629+ */
9630+ static void
9631+ convert_nvlist_uint64_to_nicenum (status_cbdata_t * cb , nvlist_t * parent ,
9632+ const char * name , enum zfs_nicenum_format format )
9633+ {
9634+ uint64_t val ;
9635+ nvpair_t * nvp ;
9636+
9637+ if (nvlist_lookup_nvpair (parent , name , & nvp ) != 0 )
9638+ return ; /* nothing by that name, ignore */
9639+
9640+ val = fnvpair_value_uint64 (nvp );
9641+ nvlist_remove_nvpair (parent , nvp );
9642+ nice_num_str_nvlist (parent , name , val ,
9643+ cb -> cb_literal , cb -> cb_json_as_int , format );
9644+ }
9645+
96239646static void
96249647errors_nvlist (zpool_handle_t * zhp , status_cbdata_t * cb , nvlist_t * item )
96259648{
9626- uint64_t nerr ;
9627- nvlist_t * config = zpool_get_config (zhp , NULL );
9628- if (nvlist_lookup_uint64 (config , ZPOOL_CONFIG_ERRCOUNT ,
9629- & nerr ) == 0 ) {
9630- nice_num_str_nvlist (item , ZPOOL_CONFIG_ERRCOUNT , nerr ,
9631- cb -> cb_literal , cb -> cb_json_as_int , ZFS_NICENUM_1024 );
9632- if (nerr != 0 && cb -> cb_verbose ) {
9633- nvlist_t * nverrlist = NULL ;
9634- if (zpool_get_errlog (zhp , & nverrlist ) == 0 ) {
9635- int i = 0 ;
9636- int count = 0 ;
9637- size_t len = MAXPATHLEN * 2 ;
9638- nvpair_t * elem = NULL ;
9639-
9640- for (nvpair_t * pair =
9641- nvlist_next_nvpair (nverrlist , NULL );
9642- pair != NULL ;
9643- pair = nvlist_next_nvpair (nverrlist , pair ))
9644- count ++ ;
9645- char * * errl = (char * * )malloc (
9646- count * sizeof (char * ));
9647-
9648- while ((elem = nvlist_next_nvpair (nverrlist ,
9649- elem )) != NULL ) {
9650- nvlist_t * nv ;
9651- uint64_t dsobj , obj ;
9652-
9653- verify (nvpair_value_nvlist (elem ,
9654- & nv ) == 0 );
9655- verify (nvlist_lookup_uint64 (nv ,
9656- ZPOOL_ERR_DATASET , & dsobj ) == 0 );
9657- verify (nvlist_lookup_uint64 (nv ,
9658- ZPOOL_ERR_OBJECT , & obj ) == 0 );
9659- errl [i ] = safe_malloc (len );
9660- zpool_obj_to_path (zhp , dsobj , obj ,
9661- errl [i ++ ], len );
9662- }
9663- nvlist_free (nverrlist );
9664- fnvlist_add_string_array (item , "errlist" ,
9665- (const char * * )errl , count );
9666- for (int i = 0 ; i < count ; ++ i )
9667- free (errl [i ]);
9668- free (errl );
9669- } else
9670- fnvlist_add_string (item , "errlist" ,
9671- strerror (errno ));
9649+ int verbosity = cb -> cb_verbosity ;
9650+ nvlist_t * nverrlist = NULL , * json ;
9651+ nvpair_t * elem ;
9652+ char * pathname ;
9653+ size_t len = MAXPATHLEN * 2 ;
9654+ nvlist_t * * ranges ;
9655+ uint_t count ;
9656+
9657+ if (zpool_get_errlog (zhp , & nverrlist ) != 0 )
9658+ return ;
9659+
9660+ pathname = safe_malloc (len );
9661+ json = fnvlist_alloc ();
9662+
9663+ elem = NULL ;
9664+ while ((elem = nvlist_next_nvpair (nverrlist , elem )) != NULL ) {
9665+ nvlist_t * nv ;
9666+ uint64_t dsobj , obj ;
9667+
9668+ verify (nvpair_value_nvlist (elem , & nv ) == 0 );
9669+
9670+ dsobj = fnvlist_lookup_uint64 (nv , ZPOOL_ERR_DATASET );
9671+ obj = fnvlist_lookup_uint64 (nv , ZPOOL_ERR_OBJECT );
9672+
9673+ zpool_obj_to_path (zhp , dsobj , obj , pathname , len );
9674+
9675+ /*
9676+ * Each JSON entry is a different file/zvol. If user has
9677+ * verbosity = 1, then just make a simple object containing
9678+ * the name.
9679+ */
9680+ if (verbosity <= 1 ) {
9681+ nvlist_t * nameonly ;
9682+ nameonly = fnvlist_alloc ();
9683+ fnvlist_add_string (nameonly , ZPOOL_ERR_NAME , pathname );
9684+ fnvlist_add_nvlist (json , pathname , nameonly );
9685+ nvlist_free (nameonly );
9686+ continue ;
96729687 }
9688+
9689+ fnvlist_add_string (nv , ZPOOL_ERR_NAME , pathname );
9690+
9691+ /* nicenum-ify our nvlist */
9692+ convert_nvlist_uint64_to_nicenum (cb , nv , ZPOOL_ERR_OBJECT ,
9693+ ZFS_NICENUM_RAW );
9694+ convert_nvlist_uint64_to_nicenum (cb , nv , ZPOOL_ERR_DATASET ,
9695+ ZFS_NICENUM_RAW );
9696+ convert_nvlist_uint64_to_nicenum (cb , nv , ZPOOL_ERR_BLOCK_SIZE ,
9697+ ZFS_NICENUM_1024 );
9698+
9699+ if (nvlist_lookup_nvlist_array (nv , ZPOOL_ERR_RANGES , & ranges ,
9700+ & count ) == 0 ) {
9701+ for (uint_t i = 0 ; i < count ; i ++ ) {
9702+ convert_nvlist_uint64_to_nicenum (cb , ranges [i ],
9703+ ZPOOL_ERR_START_BYTE , ZFS_NICENUM_1024 );
9704+ convert_nvlist_uint64_to_nicenum (cb , ranges [i ],
9705+ ZPOOL_ERR_END_BYTE , ZFS_NICENUM_1024 );
9706+ }
9707+ }
9708+
9709+ fnvlist_add_nvlist (json , pathname , nv );
96739710 }
9711+
9712+ /* Place our error list in a top level "errors" JSON object. */
9713+ fnvlist_add_nvlist (item , ZPOOL_ERR_JSON , json );
9714+ free (pathname );
9715+ nvlist_free (nverrlist );
96749716}
96759717
96769718static void
@@ -10341,13 +10383,15 @@ print_checkpoint_status(pool_checkpoint_stat_t *pcs)
1034110383 space_buf );
1034210384}
1034310385
10386+
1034410387static void
10345- print_error_log (zpool_handle_t * zhp )
10388+ print_error_log (zpool_handle_t * zhp , int verbosity , boolean_t literal )
1034610389{
1034710390 nvlist_t * nverrlist = NULL ;
1034810391 nvpair_t * elem ;
10349- char * pathname ;
10392+ char * pathname , * last_pathname = NULL ;
1035010393 size_t len = MAXPATHLEN * 2 ;
10394+ boolean_t started = B_FALSE ;
1035110395
1035210396 if (zpool_get_errlog (zhp , & nverrlist ) != 0 )
1035310397 return ;
@@ -10367,9 +10411,49 @@ print_error_log(zpool_handle_t *zhp)
1036710411 verify (nvlist_lookup_uint64 (nv , ZPOOL_ERR_OBJECT ,
1036810412 & obj ) == 0 );
1036910413 zpool_obj_to_path (zhp , dsobj , obj , pathname , len );
10370- (void ) printf ("%7s %s\n" , "" , pathname );
10414+ if (last_pathname == NULL ||
10415+ 0 != strncmp (pathname , last_pathname , len )) {
10416+ last_pathname = strdup (pathname );
10417+ if (started )
10418+ (void ) printf ("\n" );
10419+ else
10420+ started = B_TRUE ;
10421+ (void ) printf ("%7s %s " , "" , pathname );
10422+ } else if (verbosity > 1 ) {
10423+ (void ) printf ("," );
10424+ }
10425+ if (verbosity > 1 ) {
10426+ nvlist_t * * arr ;
10427+ uint_t count ;
10428+ if (nvlist_lookup_nvlist_array (nv , ZPOOL_ERR_RANGES ,
10429+ & arr , & count ) != 0 ) {
10430+ printf ("(no ranges)" );
10431+ continue ;
10432+ }
10433+
10434+ for (uint_t i = 0 ; i < count ; i ++ ) {
10435+ uint64_t start ;
10436+ uint64_t end ;
10437+ start = fnvlist_lookup_uint64 (arr [i ],
10438+ ZPOOL_ERR_START_BYTE );
10439+ end = fnvlist_lookup_uint64 (arr [i ],
10440+ ZPOOL_ERR_END_BYTE );
10441+ if (literal ) {
10442+ (void ) printf ("%lu-%lu" , start , end );
10443+ } else {
10444+ char s1 [32 ], s2 [32 ];
10445+ zfs_nicenum (start , s1 , sizeof (s1 ));
10446+ zfs_nicenum (end , s2 , sizeof (s2 ));
10447+ (void ) printf ("%s-%s" , s1 , s2 );
10448+ }
10449+ if (i != count - 1 )
10450+ printf ("," );
10451+ }
10452+ }
1037110453 }
10454+ (void ) printf ("\n" );
1037210455 free (pathname );
10456+ free (last_pathname );
1037310457 nvlist_free (nverrlist );
1037410458}
1037510459
@@ -11065,14 +11149,15 @@ status_callback(zpool_handle_t *zhp, void *data)
1106511149 if (nerr == 0 ) {
1106611150 (void ) printf (gettext (
1106711151 "errors: No known data errors\n" ));
11068- } else if (! cbp -> cb_verbose ) {
11152+ } else if (0 == cbp -> cb_verbosity ) {
1106911153 color_start (ANSI_RED );
1107011154 (void ) printf (gettext ("errors: %llu data "
1107111155 "errors, use '-v' for a list\n" ),
1107211156 (u_longlong_t )nerr );
1107311157 color_end ();
1107411158 } else {
11075- print_error_log (zhp );
11159+ print_error_log (zhp , cbp -> cb_verbosity ,
11160+ cbp -> cb_literal );
1107611161 }
1107711162 }
1107811163
@@ -11199,7 +11284,7 @@ zpool_do_status(int argc, char **argv)
1119911284 get_timestamp_arg (* optarg );
1120011285 break ;
1120111286 case 'v' :
11202- cb .cb_verbose = B_TRUE ;
11287+ cb .cb_verbosity ++ ;
1120311288 break ;
1120411289 case 'j' :
1120511290 cb .cb_json = B_TRUE ;
0 commit comments