aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/cmd/zdb/zdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/cmd/zdb/zdb.c')
-rw-r--r--sys/contrib/openzfs/cmd/zdb/zdb.c276
1 files changed, 191 insertions, 85 deletions
diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c b/sys/contrib/openzfs/cmd/zdb/zdb.c
index 45eb9c783659..70096b809656 100644
--- a/sys/contrib/openzfs/cmd/zdb/zdb.c
+++ b/sys/contrib/openzfs/cmd/zdb/zdb.c
@@ -107,7 +107,9 @@ extern uint_t zfs_reconstruct_indirect_combinations_max;
extern uint_t zfs_btree_verify_intensity;
static const char cmdname[] = "zdb";
-uint8_t dump_opt[256];
+uint8_t dump_opt[512];
+
+#define ALLOCATED_OPT 256
typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
@@ -127,6 +129,7 @@ static zfs_range_tree_t *mos_refd_objs;
static spa_t *spa;
static objset_t *os;
static boolean_t kernel_init_done;
+static boolean_t corruption_found = B_FALSE;
static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *,
boolean_t);
@@ -176,7 +179,7 @@ static int
sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
dmu_tx_t *tx)
{
- ASSERT3P(tx, ==, NULL);
+ ASSERT0P(tx);
struct sublivelist_verify *sv = arg;
sublivelist_verify_block_refcnt_t current = {
.svbr_blk = *bp,
@@ -208,7 +211,7 @@ sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
sublivelist_verify_block_t svb = {
.svb_dva = bp->blk_dva[i],
.svb_allocated_txg =
- BP_GET_LOGICAL_BIRTH(bp)
+ BP_GET_BIRTH(bp)
};
if (zfs_btree_find(&sv->sv_leftover, &svb,
@@ -250,6 +253,7 @@ sublivelist_verify_func(void *args, dsl_deadlist_entry_t *dle)
&e->svbr_blk, B_TRUE);
(void) printf("\tERROR: %d unmatched FREE(s): %s\n",
e->svbr_refcnt, blkbuf);
+ corruption_found = B_TRUE;
}
zfs_btree_destroy(&sv->sv_pair);
@@ -405,6 +409,7 @@ verify_livelist_allocs(metaslab_verify_t *mv, uint64_t txg,
(u_longlong_t)DVA_GET_ASIZE(&found->svb_dva),
(u_longlong_t)found->svb_allocated_txg,
(u_longlong_t)txg);
+ corruption_found = B_TRUE;
}
}
}
@@ -426,6 +431,7 @@ metaslab_spacemap_validation_cb(space_map_entry_t *sme, void *arg)
(u_longlong_t)txg, (u_longlong_t)offset,
(u_longlong_t)size, (u_longlong_t)mv->mv_vdid,
(u_longlong_t)mv->mv_msid);
+ corruption_found = B_TRUE;
} else {
zfs_range_tree_add(mv->mv_allocated,
offset, size);
@@ -439,6 +445,7 @@ metaslab_spacemap_validation_cb(space_map_entry_t *sme, void *arg)
(u_longlong_t)txg, (u_longlong_t)offset,
(u_longlong_t)size, (u_longlong_t)mv->mv_vdid,
(u_longlong_t)mv->mv_msid);
+ corruption_found = B_TRUE;
} else {
zfs_range_tree_remove(mv->mv_allocated,
offset, size);
@@ -526,6 +533,7 @@ mv_populate_livelist_allocs(metaslab_verify_t *mv, sublivelist_verify_t *sv)
(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));
+ corruption_found = B_TRUE;
continue;
}
@@ -542,6 +550,7 @@ mv_populate_livelist_allocs(metaslab_verify_t *mv, sublivelist_verify_t *sv)
(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));
+ corruption_found = B_TRUE;
continue;
}
@@ -619,8 +628,9 @@ livelist_metaslab_validate(spa_t *spa)
metaslab_calculate_range_tree_type(vd, m,
&start, &shift);
metaslab_verify_t mv;
- mv.mv_allocated = zfs_range_tree_create(NULL,
- type, NULL, start, shift);
+ mv.mv_allocated = zfs_range_tree_create_flags(
+ NULL, type, NULL, start, shift,
+ 0, "livelist_metaslab_validate:mv_allocated");
mv.mv_vdid = vd->vdev_id;
mv.mv_msid = m->ms_id;
mv.mv_start = m->ms_start;
@@ -654,6 +664,7 @@ livelist_metaslab_validate(spa_t *spa)
}
(void) printf("ERROR: Found livelist blocks marked as allocated "
"for indirect vdevs:\n");
+ corruption_found = B_TRUE;
zfs_btree_index_t *where = NULL;
sublivelist_verify_block_t *svb;
@@ -797,8 +808,8 @@ usage(void)
"[default is 200]\n");
(void) fprintf(stderr, " -K --key=KEY "
"decryption key for encrypted dataset\n");
- (void) fprintf(stderr, " -o --option=\"OPTION=INTEGER\" "
- "set global variable to an unsigned 32-bit integer\n");
+ (void) fprintf(stderr, " -o --option=\"NAME=VALUE\" "
+ "set the named tunable to the given value\n");
(void) fprintf(stderr, " -p --path==PATH "
"use one or more with -e to specify path to vdev dir\n");
(void) fprintf(stderr, " -P --parseable "
@@ -826,7 +837,7 @@ usage(void)
(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");
- zdb_exit(1);
+ zdb_exit(2);
}
static void
@@ -891,9 +902,9 @@ dump_packed_nvlist(objset_t *os, uint64_t object, void *data, size_t size)
size_t nvsize = *(uint64_t *)data;
char *packed = umem_alloc(nvsize, UMEM_NOFAIL);
- VERIFY(0 == dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
+ VERIFY0(dmu_read(os, object, 0, nvsize, packed, DMU_READ_PREFETCH));
- VERIFY(nvlist_unpack(packed, nvsize, &nv, 0) == 0);
+ VERIFY0(nvlist_unpack(packed, nvsize, &nv, 0));
umem_free(packed, nvsize);
@@ -1454,8 +1465,8 @@ get_obsolete_refcount(vdev_t *vd)
refcount++;
}
} else {
- ASSERT3P(vd->vdev_obsolete_sm, ==, NULL);
- ASSERT3U(obsolete_sm_object, ==, 0);
+ ASSERT0P(vd->vdev_obsolete_sm);
+ ASSERT0(obsolete_sm_object);
}
for (unsigned c = 0; c < vd->vdev_children; c++) {
refcount += get_obsolete_refcount(vd->vdev_child[c]);
@@ -1577,9 +1588,8 @@ dump_spacemap(objset_t *os, space_map_t *sm)
continue;
}
- uint8_t words;
char entry_type;
- uint64_t entry_off, entry_run, entry_vdev = SM_NO_VDEVID;
+ uint64_t entry_off, entry_run, entry_vdev;
if (sm_entry_is_single_word(word)) {
entry_type = (SM_TYPE_DECODE(word) == SM_ALLOC) ?
@@ -1587,35 +1597,43 @@ dump_spacemap(objset_t *os, space_map_t *sm)
entry_off = (SM_OFFSET_DECODE(word) << mapshift) +
sm->sm_start;
entry_run = SM_RUN_DECODE(word) << mapshift;
- words = 1;
+
+ (void) printf("\t [%6llu] %c "
+ "range: %012llx-%012llx size: %08llx\n",
+ (u_longlong_t)entry_id, entry_type,
+ (u_longlong_t)entry_off,
+ (u_longlong_t)(entry_off + entry_run - 1),
+ (u_longlong_t)entry_run);
} else {
/* it is a two-word entry so we read another word */
ASSERT(sm_entry_is_double_word(word));
uint64_t extra_word;
offset += sizeof (extra_word);
+ ASSERT3U(offset, <, space_map_length(sm));
VERIFY0(dmu_read(os, space_map_object(sm), offset,
sizeof (extra_word), &extra_word,
DMU_READ_PREFETCH));
- ASSERT3U(offset, <=, space_map_length(sm));
-
entry_run = SM2_RUN_DECODE(word) << mapshift;
entry_vdev = SM2_VDEV_DECODE(word);
entry_type = (SM2_TYPE_DECODE(extra_word) == SM_ALLOC) ?
'A' : 'F';
entry_off = (SM2_OFFSET_DECODE(extra_word) <<
mapshift) + sm->sm_start;
- words = 2;
- }
- (void) printf("\t [%6llu] %c range:"
- " %010llx-%010llx size: %06llx vdev: %06llu words: %u\n",
- (u_longlong_t)entry_id,
- entry_type, (u_longlong_t)entry_off,
- (u_longlong_t)(entry_off + entry_run),
- (u_longlong_t)entry_run,
- (u_longlong_t)entry_vdev, words);
+ if (zopt_metaslab_args == 0 ||
+ zopt_metaslab[0] == entry_vdev) {
+ (void) printf("\t [%6llu] %c "
+ "range: %012llx-%012llx size: %08llx "
+ "vdev: %llu\n",
+ (u_longlong_t)entry_id, entry_type,
+ (u_longlong_t)entry_off,
+ (u_longlong_t)(entry_off + entry_run - 1),
+ (u_longlong_t)entry_run,
+ (u_longlong_t)entry_vdev);
+ }
+ }
if (entry_type == 'A')
alloc += entry_run;
@@ -1651,6 +1669,16 @@ dump_metaslab_stats(metaslab_t *msp)
}
static void
+dump_allocated(void *arg, uint64_t start, uint64_t size)
+{
+ uint64_t *off = arg;
+ if (*off != start)
+ (void) printf("ALLOC: %"PRIu64" %"PRIu64"\n", *off,
+ start - *off);
+ *off = start + size;
+}
+
+static void
dump_metaslab(metaslab_t *msp)
{
vdev_t *vd = msp->ms_group->mg_vd;
@@ -1666,13 +1694,24 @@ dump_metaslab(metaslab_t *msp)
(u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
(u_longlong_t)space_map_object(sm), freebuf);
- if (dump_opt['m'] > 2 && !dump_opt['L']) {
+ if (dump_opt[ALLOCATED_OPT] ||
+ (dump_opt['m'] > 2 && !dump_opt['L'])) {
mutex_enter(&msp->ms_lock);
VERIFY0(metaslab_load(msp));
+ }
+
+ if (dump_opt['m'] > 2 && !dump_opt['L']) {
zfs_range_tree_stat_verify(msp->ms_allocatable);
dump_metaslab_stats(msp);
- metaslab_unload(msp);
- mutex_exit(&msp->ms_lock);
+ }
+
+ if (dump_opt[ALLOCATED_OPT]) {
+ uint64_t off = msp->ms_start;
+ zfs_range_tree_walk(msp->ms_allocatable, dump_allocated,
+ &off);
+ if (off != msp->ms_start + msp->ms_size)
+ (void) printf("ALLOC: %"PRIu64" %"PRIu64"\n", off,
+ msp->ms_size - off);
}
if (dump_opt['m'] > 1 && sm != NULL &&
@@ -1687,6 +1726,12 @@ dump_metaslab(metaslab_t *msp)
SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
}
+ if (dump_opt[ALLOCATED_OPT] ||
+ (dump_opt['m'] > 2 && !dump_opt['L'])) {
+ metaslab_unload(msp);
+ mutex_exit(&msp->ms_lock);
+ }
+
if (vd->vdev_ops == &vdev_draid_ops)
ASSERT3U(msp->ms_size, <=, 1ULL << vd->vdev_ms_shift);
else
@@ -1723,8 +1768,9 @@ print_vdev_metaslab_header(vdev_t *vd)
}
}
- (void) printf("\tvdev %10llu %s",
- (u_longlong_t)vd->vdev_id, bias_str);
+ (void) printf("\tvdev %10llu\t%s metaslab shift %4llu",
+ (u_longlong_t)vd->vdev_id, bias_str,
+ (u_longlong_t)vd->vdev_ms_shift);
if (ms_flush_data_obj != 0) {
(void) printf(" ms_unflushed_phys object %llu",
@@ -1791,7 +1837,7 @@ print_vdev_indirect(vdev_t *vd)
vdev_indirect_births_t *vib = vd->vdev_indirect_births;
if (vim == NULL) {
- ASSERT3P(vib, ==, NULL);
+ ASSERT0P(vib);
return;
}
@@ -1864,7 +1910,7 @@ dump_metaslabs(spa_t *spa)
(void) printf("\nMetaslabs:\n");
- if (!dump_opt['d'] && zopt_metaslab_args > 0) {
+ if (zopt_metaslab_args > 0) {
c = zopt_metaslab[0];
if (c >= children)
@@ -1991,7 +2037,7 @@ dump_ddt_log(ddt_t *ddt)
c += strlcpy(&flagstr[c], " UNKNOWN",
sizeof (flagstr) - c);
flagstr[1] = '[';
- flagstr[c++] = ']';
+ flagstr[c] = ']';
}
uint64_t count = avl_numnodes(&ddl->ddl_tree);
@@ -2042,10 +2088,10 @@ dump_ddt_object(ddt_t *ddt, ddt_type_t type, ddt_class_t class)
if (error == ENOENT)
return;
- ASSERT(error == 0);
+ ASSERT0(error);
error = ddt_object_count(ddt, type, class, &count);
- ASSERT(error == 0);
+ ASSERT0(error);
if (count == 0)
return;
@@ -2568,7 +2614,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
(u_longlong_t)BP_GET_PSIZE(bp),
(u_longlong_t)BP_GET_FILL(bp),
(u_longlong_t)BP_GET_LOGICAL_BIRTH(bp),
- (u_longlong_t)BP_GET_BIRTH(bp));
+ (u_longlong_t)BP_GET_PHYSICAL_BIRTH(bp));
if (bp_freed)
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), " %s", "FREE");
@@ -2582,19 +2628,17 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
}
}
-static void
+static u_longlong_t
print_indirect(spa_t *spa, blkptr_t *bp, const zbookmark_phys_t *zb,
const dnode_phys_t *dnp)
{
char blkbuf[BP_SPRINTF_LEN];
+ u_longlong_t offset;
int l;
- if (!BP_IS_EMBEDDED(bp)) {
- ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type);
- ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level);
- }
+ offset = (u_longlong_t)blkid2offset(dnp, bp, zb);
- (void) printf("%16llx ", (u_longlong_t)blkid2offset(dnp, bp, zb));
+ (void) printf("%16llx ", offset);
ASSERT(zb->zb_level >= 0);
@@ -2609,19 +2653,38 @@ print_indirect(spa_t *spa, blkptr_t *bp, const zbookmark_phys_t *zb,
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp, B_FALSE);
if (dump_opt['Z'] && BP_GET_COMPRESS(bp) == ZIO_COMPRESS_ZSTD)
snprintf_zstd_header(spa, blkbuf, sizeof (blkbuf), bp);
- (void) printf("%s\n", blkbuf);
+ (void) printf("%s", blkbuf);
+
+ if (!BP_IS_EMBEDDED(bp)) {
+ if (BP_GET_TYPE(bp) != dnp->dn_type) {
+ (void) printf(" (ERROR: Block pointer type "
+ "(%llu) does not match dnode type (%hhu))",
+ BP_GET_TYPE(bp), dnp->dn_type);
+ corruption_found = B_TRUE;
+ }
+ if (BP_GET_LEVEL(bp) != zb->zb_level) {
+ (void) printf(" (ERROR: Block pointer level "
+ "(%llu) does not match bookmark level (%lld))",
+ BP_GET_LEVEL(bp), (longlong_t)zb->zb_level);
+ corruption_found = B_TRUE;
+ }
+ }
+ (void) printf("\n");
+
+ return (offset);
}
static int
visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
blkptr_t *bp, const zbookmark_phys_t *zb)
{
+ u_longlong_t offset;
int err = 0;
- if (BP_GET_LOGICAL_BIRTH(bp) == 0)
+ if (BP_GET_BIRTH(bp) == 0)
return (0);
- print_indirect(spa, bp, zb, dnp);
+ offset = print_indirect(spa, bp, zb, dnp);
if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) {
arc_flags_t flags = ARC_FLAG_WAIT;
@@ -2651,8 +2714,15 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
break;
fill += BP_GET_FILL(cbp);
}
- if (!err)
- ASSERT3U(fill, ==, BP_GET_FILL(bp));
+ if (!err) {
+ if (fill != BP_GET_FILL(bp)) {
+ (void) printf("%16llx: Block pointer "
+ "fill (%llu) does not match calculated "
+ "value (%llu)\n", offset, BP_GET_FILL(bp),
+ (u_longlong_t)fill);
+ corruption_found = B_TRUE;
+ }
+ }
arc_buf_destroy(buf, &buf);
}
@@ -2806,7 +2876,7 @@ dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
- if (BP_GET_LOGICAL_BIRTH(bp) != 0) {
+ if (BP_GET_BIRTH(bp) != 0) {
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("\t%s\n", blkbuf);
}
@@ -2847,7 +2917,7 @@ dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
- ASSERT(BP_GET_LOGICAL_BIRTH(bp) != 0);
+ ASSERT(BP_GET_BIRTH(bp) != 0);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp, bp_freed);
(void) printf("\t%s\n", blkbuf);
return (0);
@@ -2908,6 +2978,7 @@ dump_full_bpobj(bpobj_t *bpo, const char *name, int indent)
(void) printf("ERROR %u while trying to open "
"subobj id %llu\n",
error, (u_longlong_t)subobj);
+ corruption_found = B_TRUE;
continue;
}
dump_full_bpobj(&subbpo, "subobj", indent + 1);
@@ -3087,6 +3158,7 @@ bpobj_count_refd(bpobj_t *bpo)
(void) printf("ERROR %u while trying to open "
"subobj id %llu\n",
error, (u_longlong_t)subobj);
+ corruption_found = B_TRUE;
continue;
}
bpobj_count_refd(&subbpo);
@@ -3108,7 +3180,7 @@ dsl_deadlist_entry_count_refd(void *arg, dsl_deadlist_entry_t *dle)
static int
dsl_deadlist_entry_dump(void *arg, dsl_deadlist_entry_t *dle)
{
- ASSERT(arg == NULL);
+ ASSERT0P(arg);
if (dump_opt['d'] >= 5) {
char buf[128];
(void) snprintf(buf, sizeof (buf),
@@ -3346,7 +3418,7 @@ open_objset(const char *path, const void *tag, objset_t **osp)
uint64_t sa_attrs = 0;
uint64_t version = 0;
- VERIFY3P(sa_os, ==, NULL);
+ VERIFY0P(sa_os);
/*
* We can't own an objset if it's redacted. Therefore, we do this
@@ -3519,8 +3591,8 @@ dump_uidgid(objset_t *os, uint64_t uid, uint64_t gid)
uint64_t fuid_obj;
/* first find the fuid object. It lives in the master node */
- VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
- 8, 1, &fuid_obj) == 0);
+ VERIFY0(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
+ 8, 1, &fuid_obj));
zfs_fuid_avl_tree_create(&idx_tree, &domain_tree);
(void) zfs_fuid_table_load(os, fuid_obj,
&idx_tree, &domain_tree);
@@ -5921,11 +5993,11 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
* entry back to the block pointer before we claim it.
*/
if (v == DDT_PHYS_FLAT) {
- ASSERT3U(BP_GET_BIRTH(bp), ==,
+ ASSERT3U(BP_GET_PHYSICAL_BIRTH(bp), ==,
ddt_phys_birth(dde->dde_phys, v));
tempbp = *bp;
ddt_bp_fill(dde->dde_phys, v, &tempbp,
- BP_GET_BIRTH(bp));
+ BP_GET_PHYSICAL_BIRTH(bp));
bp = &tempbp;
}
@@ -6151,7 +6223,7 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
if (zb->zb_level == ZB_DNODE_LEVEL)
return (0);
- if (dump_opt['b'] >= 5 && BP_GET_LOGICAL_BIRTH(bp) > 0) {
+ if (dump_opt['b'] >= 5 && BP_GET_BIRTH(bp) > 0) {
char blkbuf[BP_SPRINTF_LEN];
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("objset %llu object %llu "
@@ -6322,8 +6394,9 @@ zdb_claim_removing(spa_t *spa, zdb_cb_t *zcb)
ASSERT0(zfs_range_tree_space(svr->svr_allocd_segs));
- zfs_range_tree_t *allocs = zfs_range_tree_create(NULL, ZFS_RANGE_SEG64,
- NULL, 0, 0);
+ zfs_range_tree_t *allocs = zfs_range_tree_create_flags(
+ NULL, ZFS_RANGE_SEG64, NULL, 0, 0,
+ 0, "zdb_claim_removing:allocs");
for (uint64_t msi = 0; msi < vd->vdev_ms_count; msi++) {
metaslab_t *msp = vd->vdev_ms[msi];
@@ -6750,6 +6823,7 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
spa->spa_normal_class->mc_ops = &zdb_metaslab_ops;
spa->spa_log_class->mc_ops = &zdb_metaslab_ops;
spa->spa_embedded_log_class->mc_ops = &zdb_metaslab_ops;
+ spa->spa_special_embedded_log_class->mc_ops = &zdb_metaslab_ops;
zcb->zcb_vd_obsolete_counts =
umem_zalloc(rvd->vdev_children * sizeof (uint32_t *),
@@ -6887,7 +6961,9 @@ zdb_leak_fini(spa_t *spa, zdb_cb_t *zcb)
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
ASSERT3P(msp->ms_group, ==, (msp->ms_group->mg_class ==
- spa_embedded_log_class(spa)) ?
+ spa_embedded_log_class(spa) ||
+ msp->ms_group->mg_class ==
+ spa_special_embedded_log_class(spa)) ?
vd->vdev_log_mg : vd->vdev_mg);
/*
@@ -7011,7 +7087,7 @@ deleted_livelists_count_blocks(spa_t *spa, zdb_cb_t *zbc)
static void
dump_livelist_cb(dsl_deadlist_t *ll, void *arg)
{
- ASSERT3P(arg, ==, NULL);
+ ASSERT0P(arg);
global_feature_count[SPA_FEATURE_LIVELIST]++;
dump_blkptr_list(ll, "Deleted Livelist");
dsl_deadlist_iterate(ll, sublivelist_verify_lightweight, NULL);
@@ -7121,6 +7197,8 @@ dump_block_stats(spa_t *spa)
zcb->zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
zcb->zcb_totalasize +=
metaslab_class_get_alloc(spa_embedded_log_class(spa));
+ zcb->zcb_totalasize +=
+ metaslab_class_get_alloc(spa_special_embedded_log_class(spa));
zcb->zcb_start = zcb->zcb_lastprint = gethrtime();
err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, zcb);
@@ -7169,6 +7247,7 @@ dump_block_stats(spa_t *spa)
total_alloc = norm_alloc +
metaslab_class_get_alloc(spa_log_class(spa)) +
metaslab_class_get_alloc(spa_embedded_log_class(spa)) +
+ metaslab_class_get_alloc(spa_special_embedded_log_class(spa)) +
metaslab_class_get_alloc(spa_special_class(spa)) +
metaslab_class_get_alloc(spa_dedup_class(spa)) +
get_unflushed_alloc_space(spa);
@@ -7252,6 +7331,18 @@ dump_block_stats(spa_t *spa)
100.0 * alloc / space);
}
+ if (spa_special_embedded_log_class(spa)->mc_allocator[0].mca_rotor
+ != NULL) {
+ uint64_t alloc = metaslab_class_get_alloc(
+ spa_special_embedded_log_class(spa));
+ uint64_t space = metaslab_class_get_space(
+ spa_special_embedded_log_class(spa));
+
+ (void) printf("\t%-16s %14llu used: %5.2f%%\n",
+ "Special embedded log", (u_longlong_t)alloc,
+ 100.0 * alloc / space);
+ }
+
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
if (zcb->zcb_embedded_blocks[i] == 0)
continue;
@@ -7706,7 +7797,8 @@ zdb_set_skip_mmp(char *target)
* applies to the new_path parameter if allocated.
*/
static char *
-import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
+import_checkpointed_state(char *target, nvlist_t *cfg, boolean_t target_is_spa,
+ char **new_path)
{
int error = 0;
char *poolname, *bogus_name = NULL;
@@ -7714,11 +7806,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
/* If the target is not a pool, the extract the pool name */
char *path_start = strchr(target, '/');
- if (path_start != NULL) {
+ if (target_is_spa || path_start == NULL) {
+ poolname = target;
+ } else {
size_t poolname_len = path_start - target;
poolname = strndup(target, poolname_len);
- } else {
- poolname = target;
}
if (cfg == NULL) {
@@ -7749,10 +7841,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
"with error %d\n", bogus_name, error);
}
- if (new_path != NULL && path_start != NULL) {
- if (asprintf(new_path, "%s%s", bogus_name, path_start) == -1) {
+ if (new_path != NULL && !target_is_spa) {
+ if (asprintf(new_path, "%s%s", bogus_name,
+ path_start != NULL ? path_start : "") == -1) {
free(bogus_name);
- if (path_start != NULL)
+ if (!target_is_spa && path_start != NULL)
free(poolname);
return (NULL);
}
@@ -7891,7 +7984,7 @@ verify_checkpoint_vdev_spacemaps(spa_t *checkpoint, spa_t *current)
for (uint64_t c = ckpoint_rvd->vdev_children;
c < current_rvd->vdev_children; c++) {
vdev_t *current_vd = current_rvd->vdev_child[c];
- VERIFY3P(current_vd->vdev_checkpoint_sm, ==, NULL);
+ VERIFY0P(current_vd->vdev_checkpoint_sm);
}
}
@@ -7981,7 +8074,7 @@ verify_checkpoint_blocks(spa_t *spa)
* name) so we can do verification on it against the current state
* of the pool.
*/
- checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL,
+ checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL, B_TRUE,
NULL);
ASSERT(strcmp(spa->spa_name, checkpoint_pool) != 0);
@@ -8451,8 +8544,9 @@ dump_zpool(spa_t *spa)
if (dump_opt['d'] || dump_opt['i']) {
spa_feature_t f;
- mos_refd_objs = zfs_range_tree_create(NULL, ZFS_RANGE_SEG64,
- NULL, 0, 0);
+ mos_refd_objs = zfs_range_tree_create_flags(
+ NULL, ZFS_RANGE_SEG64, NULL, 0, 0,
+ 0, "dump_zpool:mos_refd_objs");
dump_objset(dp->dp_meta_objset);
if (dump_opt['d'] >= 3) {
@@ -8588,9 +8682,9 @@ zdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
}
static void
-zdb_dump_gbh(void *buf, int flags)
+zdb_dump_gbh(void *buf, uint64_t size, int flags)
{
- zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
+ zdb_dump_indirect((blkptr_t *)buf, gbh_nblkptrs(size), flags);
}
static void
@@ -8780,7 +8874,6 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
(void) buf;
uint64_t orig_lsize = lsize;
boolean_t tryzle = ((getenv("ZDB_NO_ZLE") == NULL));
- boolean_t found = B_FALSE;
/*
* We don't know how the data was compressed, so just try
* every decompress function at every inflated blocksize.
@@ -8823,20 +8916,19 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
for (cfuncp = cfuncs; *cfuncp; cfuncp++) {
if (try_decompress_block(pabd, lsize, psize, flags,
*cfuncp, lbuf, lbuf2)) {
- found = B_TRUE;
+ tryzle = B_FALSE;
break;
}
}
if (*cfuncp != 0)
break;
}
- if (!found && tryzle) {
+ if (tryzle) {
for (lsize = orig_lsize; lsize <= maxlsize;
lsize += SPA_MINBLOCKSIZE) {
if (try_decompress_block(pabd, lsize, psize, flags,
ZIO_COMPRESS_ZLE, lbuf, lbuf2)) {
*cfuncp = ZIO_COMPRESS_ZLE;
- found = B_TRUE;
break;
}
}
@@ -9073,7 +9165,7 @@ zdb_read_block(char *thing, spa_t *spa)
zdb_dump_indirect((blkptr_t *)buf,
orig_lsize / sizeof (blkptr_t), flags);
else if (flags & ZDB_FLAG_GBH)
- zdb_dump_gbh(buf, flags);
+ zdb_dump_gbh(buf, lsize, flags);
else
zdb_dump_block(thing, buf, lsize, flags);
@@ -9120,7 +9212,7 @@ zdb_read_block(char *thing, spa_t *spa)
ck_zio->io_offset =
DVA_GET_OFFSET(&bp->blk_dva[0]);
ck_zio->io_bp = bp;
- zio_checksum_compute(ck_zio, ck, pabd, lsize);
+ zio_checksum_compute(ck_zio, ck, pabd, psize);
printf(
"%12s\t"
"cksum=%016llx:%016llx:%016llx:%016llx\n",
@@ -9313,6 +9405,8 @@ main(int argc, char **argv)
{"all-reconstruction", no_argument, NULL, 'Y'},
{"livelist", no_argument, NULL, 'y'},
{"zstd-headers", no_argument, NULL, 'Z'},
+ {"allocated-map", no_argument, NULL,
+ ALLOCATED_OPT},
{0, 0, 0, 0}
};
@@ -9343,6 +9437,7 @@ main(int argc, char **argv)
case 'u':
case 'y':
case 'Z':
+ case ALLOCATED_OPT:
dump_opt[c]++;
dump_all = 0;
break;
@@ -9377,9 +9472,11 @@ main(int argc, char **argv)
while (*optarg != '\0') { *optarg++ = '*'; }
break;
case 'o':
- error = set_global_var(optarg);
+ dump_opt[c]++;
+ dump_all = 0;
+ error = handle_tunable_option(optarg, B_FALSE);
if (error != 0)
- usage();
+ zdb_exit(1);
break;
case 'p':
if (searchdirs == NULL) {
@@ -9545,6 +9642,12 @@ main(int argc, char **argv)
error = 0;
goto fini;
}
+ if (dump_opt['o'])
+ /*
+ * Avoid blasting tunable options off the top of the
+ * screen.
+ */
+ zdb_exit(1);
usage();
}
@@ -9605,7 +9708,7 @@ main(int argc, char **argv)
} else if (objset_str && !zdb_numeric(objset_str + 1) &&
dump_opt['N']) {
printf("Supply a numeric objset ID with -N\n");
- error = 1;
+ error = 2;
goto fini;
}
} else {
@@ -9697,7 +9800,7 @@ main(int argc, char **argv)
char *checkpoint_target = NULL;
if (dump_opt['k']) {
checkpoint_pool = import_checkpointed_state(target, cfg,
- &checkpoint_target);
+ target_is_spa, &checkpoint_target);
if (checkpoint_target != NULL)
target = checkpoint_target;
@@ -9714,7 +9817,7 @@ main(int argc, char **argv)
if (error == 0) {
if (dump_opt['k'] && (target_is_spa || dump_opt['R'])) {
ASSERT(checkpoint_pool != NULL);
- ASSERT(checkpoint_target == NULL);
+ ASSERT0P(checkpoint_target);
error = spa_open(checkpoint_pool, &spa, FTAG);
if (error != 0) {
@@ -9907,5 +10010,8 @@ fini:
if (kernel_init_done)
kernel_fini();
+ if (corruption_found && error == 0)
+ error = 3;
+
return (error);
}