@@ -3956,6 +3956,60 @@ zbookmark_mem_compare(const void *a, const void *b)
39563956 return (memcmp (a , b , sizeof (zbookmark_phys_t )));
39573957}
39583958
3959+ /*
3960+ * Given a sorted array of zbookmark_phys_t's, process one object groups worth
3961+ * (object group = objset + object), add it to the nvlist, and return
3962+ * the number of zbookmark_phys_ts processed. 'nv' is assumed to be already
3963+ * allocated. 'count' is the number of items in the zb[] array.
3964+ */
3965+ static uint64_t
3966+ zpool_get_errlog_process_obj_group (zpool_handle_t * zhp , zbookmark_phys_t * zb ,
3967+ uint64_t count , nvlist_t * nv )
3968+ {
3969+ uint64_t error_count ;
3970+ uint64_t * block_ids = NULL ;
3971+ int64_t * indrt_levels = NULL ;
3972+ uint64_t i ;
3973+
3974+ if (count == 0 )
3975+ return (0 );
3976+
3977+ /* First see how many zbookmarks are of the same object group */
3978+ for (i = 0 ; i < count ; i ++ ) {
3979+ if (i > 0 && !(zb [i - 1 ].zb_objset == zb [i ].zb_objset &&
3980+ zb [i - 1 ].zb_object == zb [i ].zb_object )) {
3981+ /* We've hit a new object group */
3982+ break ;
3983+ }
3984+ }
3985+
3986+ error_count = i ;
3987+
3988+ block_ids = zfs_alloc (zhp -> zpool_hdl , error_count *
3989+ sizeof (* block_ids ));
3990+ indrt_levels = zfs_alloc (zhp -> zpool_hdl , error_count *
3991+ sizeof (* indrt_levels ));
3992+
3993+ /* Write our object group's objset and object */
3994+ VERIFY0 (nvlist_add_uint64 (nv , ZPOOL_ERR_DATASET , zb [0 ].zb_objset ));
3995+ VERIFY0 (nvlist_add_uint64 (nv , ZPOOL_ERR_OBJECT , zb [0 ].zb_object ));
3996+
3997+ /* Write all the error'd blocks for this group */
3998+ for (i = 0 ; i < error_count ; i ++ ) {
3999+ block_ids [i ] = zb [i ].zb_blkid ;
4000+ indrt_levels [i ] = zb [i ].zb_level ;
4001+ }
4002+ VERIFY0 (nvlist_add_uint64_array (nv , ZPOOL_ERR_BLOCKID , block_ids ,
4003+ error_count ));
4004+ VERIFY0 (nvlist_add_int64_array (nv , ZPOOL_ERR_LEVEL , indrt_levels ,
4005+ error_count ));
4006+
4007+ free (indrt_levels );
4008+ free (block_ids );
4009+
4010+ return (error_count );
4011+ }
4012+
39594013/*
39604014 * Retrieve the persistent error log, uniquify the members, and return to the
39614015 * caller.
@@ -3968,6 +4022,7 @@ zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
39684022 uint64_t count ;
39694023 zbookmark_phys_t * zb = NULL ;
39704024 int i ;
4025+ nvlist_t * nv ;
39714026
39724027 /*
39734028 * Retrieve the raw error list from the kernel. If the number of errors
@@ -4018,34 +4073,26 @@ zpool_get_errlog(zpool_handle_t *zhp, nvlist_t **nverrlistp)
40184073
40194074 verify (nvlist_alloc (nverrlistp , 0 , KM_SLEEP ) == 0 );
40204075
4076+
40214077 /*
4022- * Fill in the nverrlistp with nvlist's of dataset and object numbers.
4078+ * zb[count] is an array of zbookmarks which point to error'd out
4079+ * blocks. We logically group these into objset + object, which
4080+ * we'll call an "object group", which is usually a file (but
4081+ * can be something else.
4082+ *
4083+ * The 'i = i' in this for() loop is to get rid of a cstyle warning:
4084+ * "comma or semicolon followed by non-blank"
40234085 */
4024- for (i = 0 ; i < count ; i ++ ) {
4025- nvlist_t * nv ;
4026-
4027- /* ignoring zb_blkid and zb_level for now */
4028- if (i > 0 && zb [i - 1 ].zb_objset == zb [i ].zb_objset &&
4029- zb [i - 1 ].zb_object == zb [i ].zb_object )
4030- continue ;
4031-
4086+ for (i = 0 ; i < count ; i = i ) {
40324087 if (nvlist_alloc (& nv , NV_UNIQUE_NAME , KM_SLEEP ) != 0 )
40334088 goto nomem ;
4034- if (nvlist_add_uint64 (nv , ZPOOL_ERR_DATASET ,
4035- zb [i ].zb_objset ) != 0 ) {
4036- nvlist_free (nv );
4037- goto nomem ;
4038- }
4039- if (nvlist_add_uint64 (nv , ZPOOL_ERR_OBJECT ,
4040- zb [i ].zb_object ) != 0 ) {
4041- nvlist_free (nv );
4042- goto nomem ;
4043- }
4089+
4090+ i += zpool_get_errlog_process_obj_group (zhp , & zb [i ], count - i ,
4091+ nv );
40444092 if (nvlist_add_nvlist (* nverrlistp , "ejk" , nv ) != 0 ) {
40454093 nvlist_free (nv );
40464094 goto nomem ;
40474095 }
4048- nvlist_free (nv );
40494096 }
40504097
40514098 free ((void * )(uintptr_t )zc .zc_nvlist_dst );
@@ -4390,6 +4437,36 @@ zpool_obj_to_path(zpool_handle_t *zhp, uint64_t dsobj, uint64_t obj,
43904437 free (mntpnt );
43914438}
43924439
4440+ /*
4441+ * Given an dataset object number, return data block and indirect block size.
4442+ */
4443+ int
4444+ zpool_get_block_size (zpool_handle_t * zhp , uint64_t dsobj , uint64_t obj ,
4445+ uint64_t * data_blk_size , uint64_t * indrt_blk_size )
4446+ {
4447+ zfs_cmd_t zc = {"\0" };
4448+ char dsname [ZFS_MAX_DATASET_NAME_LEN ];
4449+ /* get the dataset's name */
4450+ zc .zc_obj = dsobj ;
4451+ (void ) strlcpy (zc .zc_name , zhp -> zpool_name , sizeof (zc .zc_name ));
4452+ int error = ioctl (zhp -> zpool_hdl -> libzfs_fd ,
4453+ ZFS_IOC_DSOBJ_TO_DSNAME , & zc );
4454+ if (error ) {
4455+ return (error );
4456+ }
4457+ (void ) strlcpy (dsname , zc .zc_value , sizeof (dsname ));
4458+
4459+ /* get data block and indirect block size */
4460+ (void ) strlcpy (zc .zc_name , dsname , sizeof (zc .zc_name ));
4461+ zc .zc_obj = obj ;
4462+ error = ioctl (zhp -> zpool_hdl -> libzfs_fd , ZFS_IOC_OBJ_TO_STATS , & zc );
4463+ if (error == 0 ) {
4464+ * data_blk_size = zc .zc_stat .zs_data_block_size ;
4465+ * indrt_blk_size = zc .zc_stat .zs_indirect_block_size ;
4466+ }
4467+ return (error );
4468+ }
4469+
43934470/*
43944471 * Wait while the specified activity is in progress in the pool.
43954472 */
0 commit comments