| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -69,6 +69,7 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <sys/blkptr.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <sys/dsl_crypt.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <sys/dsl_scan.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <sys/btree.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <zfs_comutil.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <libnvpair.h>
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -151,6 +152,571 @@ static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    boolean_t);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void mos_obj_refd(uint64_t);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void mos_obj_refd_multiple(uint64_t);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t free,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    dmu_tx_t *tx);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef struct sublivelist_verify {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* all ALLOC'd blkptr_t in one sub-livelist */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_t sv_all_allocs;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* all FREE'd blkptr_t in one sub-livelist */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_t sv_all_frees;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* FREE's that haven't yet matched to an ALLOC, in one sub-livelist */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_t sv_pair;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* ALLOC's without a matching FREE, accumulates across sub-livelists */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_t sv_leftover;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} sublivelist_verify_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				livelist_compare(const void *larg, const void *rarg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					const blkptr_t *l = larg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					const blkptr_t *r = rarg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Sort them according to dva[0] */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t l_dva0_vdev, r_dva0_vdev;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					l_dva0_vdev = DVA_GET_VDEV(&l->blk_dva[0]);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					r_dva0_vdev = DVA_GET_VDEV(&r->blk_dva[0]);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (l_dva0_vdev < r_dva0_vdev)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (-1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					else if (l_dva0_vdev > r_dva0_vdev)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (+1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* if vdevs are equal, sort by offsets. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t l_dva0_offset;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t r_dva0_offset;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (l_dva0_offset < r_dva0_offset) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (-1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else if (l_dva0_offset > r_dva0_offset) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (+1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * Since we're storing blkptrs without cancelling FREE/ALLOC pairs,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * it's possible the offsets are equal. In that case, sort by txg
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (l->blk_birth < r->blk_birth) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (-1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else if (l->blk_birth > r->blk_birth) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (+1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef struct sublivelist_verify_block {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dva_t svb_dva;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * We need this to check if the block marked as allocated
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * in the livelist was freed (and potentially reallocated)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * in the metaslab spacemaps at a later TXG.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t svb_allocated_txg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} sublivelist_verify_block_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void zdb_print_blkptr(const blkptr_t *bp, int flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    dmu_tx_t *tx)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ASSERT3P(tx, ==, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct sublivelist_verify *sv = arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					char blkbuf[BP_SPRINTF_LEN];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_index_t where;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (free) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						zfs_btree_add(&sv->sv_pair, bp);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Check if the FREE is a duplicate */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (zfs_btree_find(&sv->sv_all_frees, bp, &where) != NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    free);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("\tERROR: Duplicate FREE: %s\n", blkbuf);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							zfs_btree_add_idx(&sv->sv_all_frees, bp, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Check if the ALLOC has been freed */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (zfs_btree_find(&sv->sv_pair, bp, &where) != NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							zfs_btree_remove_idx(&sv->sv_pair, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							for (int i = 0; i < SPA_DVAS_PER_BP; i++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (DVA_IS_EMPTY(&bp->blk_dva[i]))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								sublivelist_verify_block_t svb = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    .svb_dva = bp->blk_dva[i],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    .svb_allocated_txg = bp->blk_birth
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (zfs_btree_find(&sv->sv_leftover, &svb,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    &where) == NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									zfs_btree_add_idx(&sv->sv_leftover,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									    &svb, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Check if the ALLOC is a duplicate */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (zfs_btree_find(&sv->sv_all_allocs, bp, &where) != NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    free);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("\tERROR: Duplicate ALLOC: %s\n", blkbuf);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							zfs_btree_add_idx(&sv->sv_all_allocs, bp, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				sublivelist_verify_func(void *args, dsl_deadlist_entry_t *dle)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int err;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					char blkbuf[BP_SPRINTF_LEN];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct sublivelist_verify *sv = args;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_create(&sv->sv_all_allocs, livelist_compare,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sizeof (blkptr_t));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_create(&sv->sv_all_frees, livelist_compare,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sizeof (blkptr_t));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_create(&sv->sv_pair, livelist_compare,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sizeof (blkptr_t));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					err = bpobj_iterate_nofree(&dle->dle_bpobj, sublivelist_verify_blkptr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sv, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_clear(&sv->sv_all_allocs);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_destroy(&sv->sv_all_allocs);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_clear(&sv->sv_all_frees);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_destroy(&sv->sv_all_frees);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					blkptr_t *e;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_index_t *cookie = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					while ((e = zfs_btree_destroy_nodes(&sv->sv_pair, &cookie)) != NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), e, B_TRUE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						(void) printf("\tERROR: Unmatched FREE: %s\n", blkbuf);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_destroy(&sv->sv_pair);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (err);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				livelist_block_compare(const void *larg, const void *rarg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					const sublivelist_verify_block_t *l = larg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					const sublivelist_verify_block_t *r = rarg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (DVA_GET_VDEV(&l->svb_dva) < DVA_GET_VDEV(&r->svb_dva))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (-1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					else if (DVA_GET_VDEV(&l->svb_dva) > DVA_GET_VDEV(&r->svb_dva))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (+1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (DVA_GET_OFFSET(&l->svb_dva) < DVA_GET_OFFSET(&r->svb_dva))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (-1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					else if (DVA_GET_OFFSET(&l->svb_dva) > DVA_GET_OFFSET(&r->svb_dva))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (+1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (DVA_GET_ASIZE(&l->svb_dva) < DVA_GET_ASIZE(&r->svb_dva))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (-1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					else if (DVA_GET_ASIZE(&l->svb_dva) > DVA_GET_ASIZE(&r->svb_dva))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (+1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Check for errors in a livelist while tracking all unfreed ALLOCs in the
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * sublivelist_verify_t: sv->sv_leftover
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				livelist_verify(dsl_deadlist_t *dl, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_t *sv = arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dsl_deadlist_iterate(dl, sublivelist_verify_func, sv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Check for errors in the livelist entry and discard the intermediary
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * data structures
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* ARGSUSED */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				sublivelist_verify_lightweight(void *args, dsl_deadlist_entry_t *dle)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_t sv;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_create(&sv.sv_leftover, livelist_block_compare,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sizeof (sublivelist_verify_block_t));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int err = sublivelist_verify_func(&sv, dle);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_clear(&sv.sv_leftover);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_destroy(&sv.sv_leftover);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (err);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef struct metaslab_verify {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * Tree containing all the leftover ALLOCs from the livelists
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * that are part of this metaslab.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_t mv_livelist_allocs;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * Metaslab information.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t mv_vdid;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t mv_msid;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t mv_start;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t mv_end;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * What's currently allocated for this metaslab.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					range_tree_t *mv_allocated;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} metaslab_verify_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef void ll_iter_t(dsl_deadlist_t *ll, void *arg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef int (*zdb_log_sm_cb_t)(spa_t *spa, space_map_entry_t *sme, uint64_t txg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    void *arg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef struct unflushed_iter_cb_arg {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					spa_t *uic_spa;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t uic_txg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					void *uic_arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zdb_log_sm_cb_t uic_cb;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} unflushed_iter_cb_arg_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				iterate_through_spacemap_logs_cb(space_map_entry_t *sme, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unflushed_iter_cb_arg_t *uic = arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (uic->uic_cb(uic->uic_spa, sme, uic->uic_txg, uic->uic_arg));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				iterate_through_spacemap_logs(spa_t *spa, zdb_log_sm_cb_t cb, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (spa_log_sm_t *sls = avl_first(&spa->spa_sm_logs_by_txg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sls; sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						space_map_t *sm = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						VERIFY0(space_map_open(&sm, spa_meta_objset(spa),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    sls->sls_sm_obj, 0, UINT64_MAX, SPA_MINBLOCKSHIFT));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						unflushed_iter_cb_arg_t uic = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_spa = spa,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_txg = sls->sls_txg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_arg = arg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_cb = cb
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						VERIFY0(space_map_iterate(sm, space_map_length(sm),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    iterate_through_spacemap_logs_cb, &uic));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						space_map_close(sm);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					spa_config_exit(spa, SCL_CONFIG, FTAG);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				verify_livelist_allocs(metaslab_verify_t *mv, uint64_t txg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    uint64_t offset, uint64_t size)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_block_t svb;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					DVA_SET_VDEV(&svb.svb_dva, mv->mv_vdid);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					DVA_SET_OFFSET(&svb.svb_dva, offset);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					DVA_SET_ASIZE(&svb.svb_dva, size);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_index_t where;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t end_offset = offset + size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 *  Look for an exact match for spacemap entry in the livelist entries.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 *  Then, look for other livelist entries that fall within the range
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 *  of the spacemap entry as it may have been condensed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_block_t *found =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    zfs_btree_find(&mv->mv_livelist_allocs, &svb, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (found == NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						found = zfs_btree_next(&mv->mv_livelist_allocs, &where, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (; found != NULL && DVA_GET_VDEV(&found->svb_dva) == mv->mv_vdid &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    DVA_GET_OFFSET(&found->svb_dva) < end_offset;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    found = zfs_btree_next(&mv->mv_livelist_allocs, &where, &where)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (found->svb_allocated_txg <= txg) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("ERROR: Livelist ALLOC [%llx:%llx] "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "from TXG %llx FREED at TXG %llx\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_OFFSET(&found->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_ASIZE(&found->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)found->svb_allocated_txg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)txg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				metaslab_spacemap_validation_cb(space_map_entry_t *sme, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					metaslab_verify_t *mv = arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t offset = sme->sme_offset;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t size = sme->sme_run;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t txg = sme->sme_txg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (sme->sme_type == SM_ALLOC) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (range_tree_contains(mv->mv_allocated,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    offset, size)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("ERROR: DOUBLE ALLOC: "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "%llu [%llx:%llx] "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "%llu:%llu LOG_SM\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)txg, (u_longlong_t)offset,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)size, (u_longlong_t)mv->mv_vdid,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)mv->mv_msid);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							range_tree_add(mv->mv_allocated,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    offset, size);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (!range_tree_contains(mv->mv_allocated,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    offset, size)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("ERROR: DOUBLE FREE: "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "%llu [%llx:%llx] "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "%llu:%llu LOG_SM\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)txg, (u_longlong_t)offset,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)size, (u_longlong_t)mv->mv_vdid,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)mv->mv_msid);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							range_tree_remove(mv->mv_allocated,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    offset, size);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (sme->sme_type != SM_ALLOC) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * If something is freed in the spacemap, verify that
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * it is not listed as allocated in the livelist.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						verify_livelist_allocs(mv, txg, offset, size);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				spacemap_check_sm_log_cb(spa_t *spa, space_map_entry_t *sme,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    uint64_t txg, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					metaslab_verify_t *mv = arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t offset = sme->sme_offset;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t vdev_id = sme->sme_vdev;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					vdev_t *vd = vdev_lookup_top(spa, vdev_id);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* skip indirect vdevs */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!vdev_is_concrete(vd))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (vdev_id != mv->mv_vdid)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (ms->ms_id != mv->mv_msid)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (txg < metaslab_unflushed_txg(ms))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ASSERT3U(txg, ==, sme->sme_txg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (metaslab_spacemap_validation_cb(sme, mv));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				spacemap_check_sm_log(spa_t *spa, metaslab_verify_t *mv)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					iterate_through_spacemap_logs(spa, spacemap_check_sm_log_cb, mv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				spacemap_check_ms_sm(space_map_t  *sm, metaslab_verify_t *mv)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (sm == NULL)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					VERIFY0(space_map_iterate(sm, space_map_length(sm),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    metaslab_spacemap_validation_cb, mv));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void iterate_deleted_livelists(spa_t *spa, ll_iter_t func, void *arg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Transfer blocks from sv_leftover tree to the mv_livelist_allocs if
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * they are part of that metaslab (mv_msid).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				mv_populate_livelist_allocs(metaslab_verify_t *mv, sublivelist_verify_t *sv)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_index_t where;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_block_t *svb;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ASSERT3U(zfs_btree_numnodes(&mv->mv_livelist_allocs), ==, 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (svb = zfs_btree_first(&sv->sv_leftover, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    svb != NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    svb = zfs_btree_next(&sv->sv_leftover, &where, &where)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (DVA_GET_VDEV(&svb->svb_dva) != mv->mv_vdid)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (DVA_GET_OFFSET(&svb->svb_dva) < mv->mv_start &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    (DVA_GET_OFFSET(&svb->svb_dva) +
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    DVA_GET_ASIZE(&svb->svb_dva)) > mv->mv_start) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("ERROR: Found block that crosses "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "metaslab boundary: <%llu:%llx:%llx>\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_VDEV(&svb->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_OFFSET(&svb->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_ASIZE(&svb->svb_dva));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (DVA_GET_OFFSET(&svb->svb_dva) < mv->mv_start)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (DVA_GET_OFFSET(&svb->svb_dva) >= mv->mv_end)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if ((DVA_GET_OFFSET(&svb->svb_dva) +
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    DVA_GET_ASIZE(&svb->svb_dva)) > mv->mv_end) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("ERROR: Found block that crosses "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "metaslab boundary: <%llu:%llx:%llx>\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_VDEV(&svb->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_OFFSET(&svb->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)DVA_GET_ASIZE(&svb->svb_dva));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						zfs_btree_add(&mv->mv_livelist_allocs, svb);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (svb = zfs_btree_first(&mv->mv_livelist_allocs, &where);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    svb != NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    svb = zfs_btree_next(&mv->mv_livelist_allocs, &where, &where)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						zfs_btree_remove(&sv->sv_leftover, svb);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * [Livelist Check]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Iterate through all the sublivelists and:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * - report leftover frees
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * - report double ALLOCs/FREEs
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * - record leftover ALLOCs together with their TXG [see Cross Check]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * [Spacemap Check]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * for each metaslab:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * - iterate over spacemap and then the metaslab's entries in the
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *   spacemap log, then report any double FREEs and ALLOCs (do not
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *   blow up).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * [Cross Check]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * After finishing the Livelist Check phase and while being in the
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Spacemap Check phase, we find all the recorded leftover ALLOCs
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * of the livelist check that are part of the metaslab that we are
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * currently looking at in the Spacemap Check. We report any entries
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * that are marked as ALLOCs in the livelists but have been actually
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * freed (and potentially allocated again) after their TXG stamp in
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * the spacemaps. Also report any ALLOCs from the livelists that
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * belong to indirect vdevs (e.g. their vdev completed removal).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Note that this will miss Log Spacemap entries that cancelled each other
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * out before being flushed to the metaslab, so we are not guaranteed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * to match all erroneous ALLOCs.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				livelist_metaslab_validate(spa_t *spa)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) printf("Verifying deleted livelist entries\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_t sv;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_create(&sv.sv_leftover, livelist_block_compare,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sizeof (sublivelist_verify_block_t));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					iterate_deleted_livelists(spa, livelist_verify, &sv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) printf("Verifying metaslab entries\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					vdev_t *rvd = spa->spa_root_vdev;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (uint64_t c = 0; c < rvd->vdev_children; c++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						vdev_t *vd = rvd->vdev_child[c];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (!vdev_is_concrete(vd))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						for (uint64_t mid = 0; mid < vd->vdev_ms_count; mid++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							metaslab_t *m = vd->vdev_ms[mid];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) fprintf(stderr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "\rverifying concrete vdev %llu, "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    "metaslab %llu of %llu ...",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (longlong_t)vd->vdev_id,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (longlong_t)mid,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (longlong_t)vd->vdev_ms_count);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							uint64_t shift, start;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							range_seg_type_t type =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    metaslab_calculate_range_tree_type(vd, m,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    &start, &shift);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							metaslab_verify_t mv;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mv.mv_allocated = range_tree_create(NULL,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    type, NULL, start, shift);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mv.mv_vdid = vd->vdev_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mv.mv_msid = m->ms_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mv.mv_start = m->ms_start;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mv.mv_end = m->ms_start + m->ms_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							zfs_btree_create(&mv.mv_livelist_allocs,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    livelist_block_compare,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    sizeof (sublivelist_verify_block_t));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mv_populate_livelist_allocs(&mv, &sv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							spacemap_check_ms_sm(m->ms_sm, &mv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							spacemap_check_sm_log(spa, &mv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							range_tree_vacate(mv.mv_allocated, NULL, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							range_tree_destroy(mv.mv_allocated);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							zfs_btree_clear(&mv.mv_livelist_allocs);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							zfs_btree_destroy(&mv.mv_livelist_allocs);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * If there are any segments in the leftover tree after we walked
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * through all the metaslabs in the concrete vdevs then this means
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * that we have segments in the livelists that belong to indirect
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * vdevs and are marked as allocated.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (zfs_btree_numnodes(&sv.sv_leftover) == 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						zfs_btree_destroy(&sv.sv_leftover);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) printf("ERROR: Found livelist blocks marked as allocated "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "for indirect vdevs:\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_index_t *where = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sublivelist_verify_block_t *svb;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					while ((svb = zfs_btree_destroy_nodes(&sv.sv_leftover, &where)) !=
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    NULL) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						int vdev_id = DVA_GET_VDEV(&svb->svb_dva);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ASSERT3U(vdev_id, <, rvd->vdev_children);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						vdev_t *vd = rvd->vdev_child[vdev_id];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ASSERT(!vdev_is_concrete(vd));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						(void) printf("<%d:%llx:%llx> TXG %llx\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    vdev_id, (u_longlong_t)DVA_GET_OFFSET(&svb->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    (u_longlong_t)DVA_GET_ASIZE(&svb->svb_dva),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    (u_longlong_t)svb->svb_allocated_txg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) printf("\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_destroy(&sv.sv_leftover);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * These libumem hooks provide a reasonable set of defaults for the allocator's
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -172,7 +738,7 @@ static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				usage(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "Usage:\t%s [-AbcdDFGhikLMPsvX] [-e [-V] [-p <path> ...]] "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "Usage:\t%s [-AbcdDFGhikLMPsvXy] [-e [-V] [-p <path> ...]] "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "[-I <inflight I/Os>]\n"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]]\n"
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -234,7 +800,9 @@ usage(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "        -s report stats on zdb's I/O\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "        -S simulate dedup to measure effect\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "        -v verbose (applies to all "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "others)\n\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "others)\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "        -y perform livelist and metaslab "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "validation on any livelists being deleted\n\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "    Below options are intended for use "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "with other options:\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) fprintf(stderr, "        -A ignore assertions (-A), enable "
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -926,11 +1494,20 @@ dump_spacemap(objset_t *os, space_map_t *sm)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    sizeof (word), &word, DMU_READ_PREFETCH));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (sm_entry_is_debug(word)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							(void) printf("\t    [%6llu] %s: txg %llu pass %llu\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)entry_id,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    ddata[SM_DEBUG_ACTION_DECODE(word)],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)SM_DEBUG_TXG_DECODE(word),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    (u_longlong_t)SM_DEBUG_SYNCPASS_DECODE(word));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							uint64_t de_txg = SM_DEBUG_TXG_DECODE(word);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							uint64_t de_sync_pass = SM_DEBUG_SYNCPASS_DECODE(word);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (de_txg == 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								(void) printf(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    "\t    [%6llu] PADDING\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    (u_longlong_t)entry_id);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								(void) printf(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    "\t    [%6llu] %s: txg %llu pass %llu\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    (u_longlong_t)entry_id,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    ddata[SM_DEBUG_ACTION_DECODE(word)],
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    (u_longlong_t)de_txg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    (u_longlong_t)de_sync_pass);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							entry_id++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2214,6 +2791,11 @@ verify_dd_livelist(objset_t *os)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ASSERT(!dmu_objset_is_snapshot(os));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!dsl_deadlist_is_open(&dd->dd_livelist))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return (0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Iterate through the livelist to check for duplicates */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dsl_deadlist_iterate(&dd->dd_livelist, sublivelist_verify_lightweight,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dsl_pool_config_enter(dp, FTAG);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dsl_deadlist_space(&dd->dd_livelist, &ll_used,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    &ll_comp, &ll_uncomp);
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -4652,50 +5234,6 @@ static metaslab_ops_t zdb_metaslab_ops = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					NULL	/* alloc */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef int (*zdb_log_sm_cb_t)(spa_t *spa, space_map_entry_t *sme,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    uint64_t txg, void *arg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef struct unflushed_iter_cb_arg {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					spa_t *uic_spa;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t uic_txg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					void *uic_arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zdb_log_sm_cb_t uic_cb;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} unflushed_iter_cb_arg_t;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				iterate_through_spacemap_logs_cb(space_map_entry_t *sme, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unflushed_iter_cb_arg_t *uic = arg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return (uic->uic_cb(uic->uic_spa, sme, uic->uic_txg, uic->uic_arg));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				iterate_through_spacemap_logs(spa_t *spa, zdb_log_sm_cb_t cb, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (spa_log_sm_t *sls = avl_first(&spa->spa_sm_logs_by_txg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    sls; sls = AVL_NEXT(&spa->spa_sm_logs_by_txg, sls)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						space_map_t *sm = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						VERIFY0(space_map_open(&sm, spa_meta_objset(spa),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    sls->sls_sm_obj, 0, UINT64_MAX, SPA_MINBLOCKSHIFT));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						unflushed_iter_cb_arg_t uic = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_spa = spa,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_txg = sls->sls_txg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_arg = arg,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							.uic_cb = cb
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						VERIFY0(space_map_iterate(sm, space_map_length(sm),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    iterate_through_spacemap_logs_cb, &uic));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						space_map_close(sm);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					spa_config_exit(spa, SCL_CONFIG, FTAG);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* ARGSUSED */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				load_unflushed_svr_segs_cb(spa_t *spa, space_map_entry_t *sme,
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -5443,8 +5981,6 @@ count_block_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Iterate over livelists which have been destroyed by the user but
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * are still present in the MOS, waiting to be freed
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				typedef void ll_iter_t(dsl_deadlist_t *ll, void *arg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				iterate_deleted_livelists(spa_t *spa, ll_iter_t func, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -5515,6 +6051,7 @@ dump_livelist_cb(dsl_deadlist_t *ll, void *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ASSERT3P(arg, ==, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					global_feature_count[SPA_FEATURE_LIVELIST]++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dump_blkptr_list(ll, "Deleted Livelist");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dsl_deadlist_iterate(ll, sublivelist_verify_lightweight, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -6780,6 +7317,10 @@ dump_zpool(spa_t *spa)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					dsl_pool_t *dp = spa_get_dsl(spa);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int rc = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (dump_opt['y']) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						livelist_metaslab_validate(spa);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (dump_opt['S']) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						dump_simulated_ddt(spa);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -6925,7 +7466,7 @@ static int flagbits[256];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static char flagbitstr[16];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				zdb_print_blkptr(blkptr_t *bp, int flags)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				zdb_print_blkptr(const blkptr_t *bp, int flags)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					char blkbuf[BP_SPRINTF_LEN];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -7537,7 +8078,7 @@ main(int argc, char **argv)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					zfs_btree_verify_intensity = 3;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					while ((c = getopt(argc, argv,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "AbcCdDeEFGhiI:klLmMo:Op:PqRsSt:uU:vVx:XY")) != -1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    "AbcCdDeEFGhiI:klLmMo:Op:PqRsSt:uU:vVx:XYy")) != -1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						switch (c) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case 'b':
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case 'c':
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -7556,6 +8097,7 @@ main(int argc, char **argv)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case 's':
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case 'S':
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case 'u':
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case 'y':
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							dump_opt[c]++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							dump_all = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -7698,7 +8240,7 @@ main(int argc, char **argv)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						verbose = MAX(verbose, 1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (c = 0; c < 256; c++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (dump_all && strchr("AeEFklLOPRSX", c) == NULL)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (dump_all && strchr("AeEFklLOPRSXy", c) == NULL)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							dump_opt[c] = 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (dump_opt[c])
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							dump_opt[c] += verbose;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |