Skip to content

Commit

Permalink
zdb: show BRT statistics and dump its contents
Browse files Browse the repository at this point in the history
Same idea as the dedup stats, but for block cloning.

Signed-off-by: Rob Norris <robn@despairlabs.com>
  • Loading branch information
robn committed Nov 18, 2023
1 parent 9c2c255 commit 297d89b
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 3 deletions.
93 changes: 92 additions & 1 deletion cmd/zdb/zdb.c
Expand Up @@ -34,6 +34,7 @@
* Copyright (c) 2021 Allan Jude
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
* Copyright (c) 2023, Klara Inc.
* Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
*/

#include <stdio.h>
Expand Down Expand Up @@ -80,6 +81,7 @@
#include <sys/dsl_scan.h>
#include <sys/btree.h>
#include <sys/brt.h>
#include <sys/brt_impl.h>
#include <zfs_comutil.h>
#include <sys/zstd/zstd.h>

Expand Down Expand Up @@ -899,6 +901,8 @@ usage(void)
"don't print label contents\n");
(void) fprintf(stderr, " -t --txg=INTEGER "
"highest txg to use when searching for uberblocks\n");
(void) fprintf(stderr, " -T --brt-stats "
"BRT statistics\n");
(void) fprintf(stderr, " -u --uberblock "
"uberblock\n");
(void) fprintf(stderr, " -U --cachefile=PATH "
Expand Down Expand Up @@ -999,6 +1003,15 @@ zdb_nicenum(uint64_t num, char *buf, size_t buflen)
nicenum(num, buf, buflen);
}

static void
zdb_nicebytes(uint64_t bytes, char *buf, size_t buflen)
{
if (dump_opt['P'])
(void) snprintf(buf, buflen, "%llu", (longlong_t)bytes);
else
zfs_nicebytes(bytes, buf, buflen);
}

static const char histo_stars[] = "****************************************";
static const uint64_t histo_width = sizeof (histo_stars) - 1;

Expand Down Expand Up @@ -2081,6 +2094,79 @@ dump_all_ddts(spa_t *spa)
dump_dedup_ratio(&dds_total);
}

static void
dump_brt(spa_t *spa)
{
if (!spa_feature_is_enabled(spa, SPA_FEATURE_BLOCK_CLONING)) {
printf("BRT: unsupported on this pool\n");
return;
}

if (!spa_feature_is_active(spa, SPA_FEATURE_BLOCK_CLONING)) {
printf("BRT: empty\n");
return;
}

brt_t *brt = spa->spa_brt;
VERIFY(brt);

char count[32], used[32], saved[32];
zdb_nicebytes(brt_get_used(spa), used, sizeof (used));
zdb_nicebytes(brt_get_saved(spa), saved, sizeof (saved));
uint64_t ratio = brt_get_ratio(spa);
printf("BRT: used %s; saved %s; ratio %llu.%02llux\n", used, saved,
(u_longlong_t)(ratio / 100), (u_longlong_t)(ratio % 100));

if (dump_opt['T'] < 2)
return;

for (uint64_t vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
brt_vdev_t *brtvd = &brt->brt_vdevs[vdevid];
if (brtvd == NULL)
continue;

if (!brtvd->bv_initiated) {
printf("BRT: vdev %lu: empty\n", vdevid);
continue;
}

zdb_nicenum(brtvd->bv_totalcount, count, sizeof (count));
zdb_nicebytes(brtvd->bv_usedspace, used, sizeof (used));
zdb_nicebytes(brtvd->bv_savedspace, saved, sizeof (saved));
printf("BRT: vdev %lu: refcnt %s; used %s; saved %s\n",
vdevid, count, used, saved);
}

if (dump_opt['T'] < 3)
return;

char dva[64];
printf("\n%-16s %-10s\n", "DVA", "REFCNT");

for (uint64_t vdevid = 0; vdevid < brt->brt_nvdevs; vdevid++) {
brt_vdev_t *brtvd = &brt->brt_vdevs[vdevid];
if (brtvd == NULL || !brtvd->bv_initiated)
continue;

zap_cursor_t zc;
zap_attribute_t za;
for (zap_cursor_init(&zc, brt->brt_mos, brtvd->bv_mos_entries);
zap_cursor_retrieve(&zc, &za) == 0;
zap_cursor_advance(&zc)) {
uint64_t offset = *(uint64_t *)za.za_name;
uint64_t refcnt;
VERIFY0(zap_lookup_uint64(brt->brt_mos,
brtvd->bv_mos_entries, &offset, BRT_KEY_WORDS, 1,
sizeof (refcnt), &refcnt));

snprintf(dva, sizeof (dva), "%lu:%llx", vdevid,
(u_longlong_t)offset);
printf("%-16s %-10llu\n", dva, (u_longlong_t)refcnt);
}
zap_cursor_fini(&zc);
}
}

static void
dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
{
Expand Down Expand Up @@ -8108,6 +8194,9 @@ dump_zpool(spa_t *spa)
if (dump_opt['D'])
dump_all_ddts(spa);

if (dump_opt['T'])
dump_brt(spa);

if (dump_opt['d'] > 2 || dump_opt['m'])
dump_metaslabs(spa);
if (dump_opt['M'])
Expand Down Expand Up @@ -8894,6 +8983,7 @@ main(int argc, char **argv)
{"io-stats", no_argument, NULL, 's'},
{"simulate-dedup", no_argument, NULL, 'S'},
{"txg", required_argument, NULL, 't'},
{"brt-stats", no_argument, NULL, 'T'},
{"uberblock", no_argument, NULL, 'u'},
{"cachefile", required_argument, NULL, 'U'},
{"verbose", no_argument, NULL, 'v'},
Expand All @@ -8907,7 +8997,7 @@ main(int argc, char **argv)
};

while ((c = getopt_long(argc, argv,
"AbBcCdDeEFGhiI:kK:lLmMNo:Op:PqrRsSt:uU:vVx:XYyZ",
"AbBcCdDeEFGhiI:kK:lLmMNo:Op:PqrRsSt:TuU:vVx:XYyZ",
long_options, NULL)) != -1) {
switch (c) {
case 'b':
Expand All @@ -8929,6 +9019,7 @@ main(int argc, char **argv)
case 'R':
case 's':
case 'S':
case 'T':
case 'u':
case 'y':
case 'Z':
Expand Down
11 changes: 9 additions & 2 deletions man/man8/zdb.8
Expand Up @@ -14,7 +14,7 @@
.\" Copyright (c) 2017 Lawrence Livermore National Security, LLC.
.\" Copyright (c) 2017 Intel Corporation.
.\"
.Dd June 27, 2023
.Dd November 18, 2023
.Dt ZDB 8
.Os
.
Expand All @@ -23,7 +23,7 @@
.Nd display ZFS storage pool debugging and consistency information
.Sh SYNOPSIS
.Nm
.Op Fl AbcdDFGhikLMNPsvXYy
.Op Fl AbcdDFGhikLMNPsTvXYy
.Op Fl e Oo Fl V Oc Oo Fl p Ar path Oc Ns
.Op Fl I Ar inflight-I/O-ops
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns
Expand Down Expand Up @@ -403,6 +403,13 @@ Display operation counts, bandwidth, and error counts of I/O to the pool from
Simulate the effects of deduplication, constructing a DDT and then display
that DDT as with
.Fl DD .
.It Fl T , -brt-stats
Display block reference table (BRT) statistics, including the size of uniques
blocks cloned, the space saving as a result of cloning, and the saving ratio.
.It Fl TT
Display the per-vdev BRT statistics, including total references.
.It Fl TTT
Dump the contents of the block reference tables.
.It Fl u , -uberblock
Display the current uberblock.
.El
Expand Down

0 comments on commit 297d89b

Please sign in to comment.