diff options
Diffstat (limited to 'cmd/zdb/zdb.c')
-rw-r--r-- | cmd/zdb/zdb.c | 117 |
1 files changed, 74 insertions, 43 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 253a1346a..0ced25865 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -87,8 +87,8 @@ static void usage(void) { (void) fprintf(stderr, - "Usage: %s [-udibcsv] [-U cachefile_path] " - "[-S user:cksumalg] " + "Usage: %s [-udibcsvL] [-U cachefile_path] [-t txg]\n" + "\t [-S user:cksumalg] " "dataset [object...]\n" " %s -C [pool]\n" " %s -l dev\n" @@ -108,6 +108,8 @@ usage(void) "dump blkptr signatures\n"); (void) fprintf(stderr, " -v verbose (applies to all others)\n"); (void) fprintf(stderr, " -l dump label contents\n"); + (void) fprintf(stderr, " -L disable leak tracking (do not " + "load spacemaps)\n"); (void) fprintf(stderr, " -U cachefile_path -- use alternate " "cachefile\n"); (void) fprintf(stderr, " -R read and display block from a " @@ -115,6 +117,8 @@ usage(void) (void) fprintf(stderr, " -e Pool is exported/destroyed/" "has altroot\n"); (void) fprintf(stderr, " -p <Path to vdev dir> (use with -e)\n"); + (void) fprintf(stderr, " -t <txg> highest txg to use when " + "searching for uberblocks\n"); (void) fprintf(stderr, "Specify an option more than once (e.g. -bb) " "to make only that option verbose\n"); (void) fprintf(stderr, "Default is to dump everything non-verbosely\n"); @@ -517,44 +521,52 @@ dump_metaslabs(spa_t *spa) } static void +dump_dtl_seg(space_map_t *sm, uint64_t start, uint64_t size) +{ + char *prefix = (void *)sm; + + (void) printf("%s [%llu,%llu) length %llu\n", + prefix, + (u_longlong_t)start, + (u_longlong_t)(start + size), + (u_longlong_t)(size)); +} + +static void dump_dtl(vdev_t *vd, int indent) { - avl_tree_t *t = &vd->vdev_dtl_map.sm_root; - space_seg_t *ss; - vdev_t *pvd; - int c; + spa_t *spa = vd->vdev_spa; + boolean_t required; + char *name[DTL_TYPES] = { "missing", "partial", "scrub", "outage" }; + char prefix[256]; + + spa_vdev_state_enter(spa); + required = vdev_dtl_required(vd); + (void) spa_vdev_state_exit(spa, NULL, 0); if (indent == 0) (void) printf("\nDirty time logs:\n\n"); - (void) printf("\t%*s%s\n", indent, "", + (void) printf("\t%*s%s [%s]\n", indent, "", vd->vdev_path ? vd->vdev_path : - vd->vdev_parent ? vd->vdev_ops->vdev_op_type : - spa_name(vd->vdev_spa)); - - for (ss = avl_first(t); ss; ss = AVL_NEXT(t, ss)) { - /* - * Everything in this DTL must appear in all parent DTL unions. - */ - for (pvd = vd; pvd; pvd = pvd->vdev_parent) - ASSERT(vdev_dtl_contains(&pvd->vdev_dtl_map, - ss->ss_start, ss->ss_end - ss->ss_start)); - (void) printf("\t%*soutage [%llu,%llu] length %llu\n", - indent, "", - (u_longlong_t)ss->ss_start, - (u_longlong_t)ss->ss_end - 1, - (u_longlong_t)(ss->ss_end - ss->ss_start)); - } - - (void) printf("\n"); + vd->vdev_parent ? vd->vdev_ops->vdev_op_type : spa_name(spa), + required ? "DTL-required" : "DTL-expendable"); - if (dump_opt['d'] > 5 && vd->vdev_children == 0) { - dump_spacemap(vd->vdev_spa->spa_meta_objset, &vd->vdev_dtl, - &vd->vdev_dtl_map); - (void) printf("\n"); + for (int t = 0; t < DTL_TYPES; t++) { + space_map_t *sm = &vd->vdev_dtl[t]; + if (sm->sm_space == 0) + continue; + (void) snprintf(prefix, sizeof (prefix), "\t%*s%s", + indent + 2, "", name[t]); + mutex_enter(sm->sm_lock); + space_map_walk(sm, dump_dtl_seg, (void *)prefix); + mutex_exit(sm->sm_lock); + if (dump_opt['d'] > 5 && vd->vdev_children == 0) + dump_spacemap(spa->spa_meta_objset, + &vd->vdev_dtl_smo, sm); } - for (c = 0; c < vd->vdev_children; c++) + for (int c = 0; c < vd->vdev_children; c++) dump_dtl(vd->vdev_child[c], indent + 4); } @@ -668,7 +680,8 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp, break; fill += cbp->blk_fill; } - ASSERT3U(fill, ==, bp->blk_fill); + if (!err) + ASSERT3U(fill, ==, bp->blk_fill); (void) arc_buf_remove_ref(buf, &buf); } @@ -1481,8 +1494,9 @@ zdb_count_block(spa_t *spa, zdb_cb_t *zcb, blkptr_t *bp, dmu_object_type_t type) } } - VERIFY(zio_wait(zio_claim(NULL, spa, spa_first_txg(spa), bp, - NULL, NULL, ZIO_FLAG_MUSTSUCCEED)) == 0); + if (!dump_opt['L']) + VERIFY(zio_wait(zio_claim(NULL, spa, spa_first_txg(spa), bp, + NULL, NULL, ZIO_FLAG_MUSTSUCCEED)) == 0); } static int @@ -1557,9 +1571,11 @@ dump_block_stats(spa_t *spa) int c, e; if (!dump_opt['S']) { - (void) printf("\nTraversing all blocks to %sverify" - " nothing leaked ...\n", - dump_opt['c'] ? "verify checksums and " : ""); + (void) printf("\nTraversing all blocks %s%s%s%s...\n", + (dump_opt['c'] || !dump_opt['L']) ? "to verify " : "", + dump_opt['c'] ? "checksums " : "", + (dump_opt['c'] && !dump_opt['L']) ? "and verify " : "", + !dump_opt['L'] ? "nothing leaked " : ""); } /* @@ -1570,7 +1586,8 @@ dump_block_stats(spa_t *spa) * it's not part of any space map) is a double allocation, * reference to a freed block, or an unclaimed log block. */ - zdb_leak_init(spa); + if (!dump_opt['L']) + zdb_leak_init(spa); /* * If there's a deferred-free bplist, process that first. @@ -1612,7 +1629,8 @@ dump_block_stats(spa_t *spa) /* * Report any leaked segments. */ - zdb_leak_fini(spa); + if (!dump_opt['L']) + zdb_leak_fini(spa); /* * If we're interested in printing out the blkptr signatures, @@ -1638,14 +1656,16 @@ dump_block_stats(spa_t *spa) tzb = &zcb.zcb_type[ZB_TOTAL][DMU_OT_TOTAL]; if (tzb->zb_asize == alloc + logalloc) { - (void) printf("\n\tNo leaks (block sum matches space" - " maps exactly)\n"); + if (!dump_opt['L']) + (void) printf("\n\tNo leaks (block sum matches space" + " maps exactly)\n"); } else { (void) printf("block traversal size %llu != alloc %llu " - "(leaked %lld)\n", + "(%s %lld)\n", (u_longlong_t)tzb->zb_asize, (u_longlong_t)alloc + logalloc, - (u_longlong_t)(alloc + logalloc - tzb->zb_asize)); + (dump_opt['L']) ? "unreachable" : "leaked", + (longlong_t)(alloc + logalloc - tzb->zb_asize)); leaks = 1; } @@ -2235,7 +2255,7 @@ main(int argc, char **argv) dprintf_setup(&argc, argv); - while ((c = getopt(argc, argv, "udibcsvCS:U:lRep:")) != -1) { + while ((c = getopt(argc, argv, "udibcsvCLS:U:lRep:t:")) != -1) { switch (c) { case 'u': case 'd': @@ -2249,6 +2269,9 @@ main(int argc, char **argv) dump_opt[c]++; dump_all = 0; break; + case 'L': + dump_opt[c]++; + break; case 'v': verbose++; break; @@ -2279,6 +2302,14 @@ main(int argc, char **argv) else usage(); break; + case 't': + ub_max_txg = strtoull(optarg, NULL, 0); + if (ub_max_txg < TXG_INITIAL) { + (void) fprintf(stderr, "incorrect txg " + "specified: %s\n", optarg); + usage(); + } + break; default: usage(); break; |