zdb: show BRT statistics and dump its contents
Same idea as the dedup stats, but for block cloning. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Kay Pedersen <mail@mkwg.de> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Rob Norris <robn@despairlabs.com> Closes #15541
This commit is contained in:
parent
d702f86eaf
commit
e96675a7b1
|
@ -34,6 +34,7 @@
|
||||||
* Copyright (c) 2021 Allan Jude
|
* Copyright (c) 2021 Allan Jude
|
||||||
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
|
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
|
||||||
* Copyright (c) 2023, Klara Inc.
|
* Copyright (c) 2023, Klara Inc.
|
||||||
|
* Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -80,6 +81,7 @@
|
||||||
#include <sys/dsl_scan.h>
|
#include <sys/dsl_scan.h>
|
||||||
#include <sys/btree.h>
|
#include <sys/btree.h>
|
||||||
#include <sys/brt.h>
|
#include <sys/brt.h>
|
||||||
|
#include <sys/brt_impl.h>
|
||||||
#include <zfs_comutil.h>
|
#include <zfs_comutil.h>
|
||||||
#include <sys/zstd/zstd.h>
|
#include <sys/zstd/zstd.h>
|
||||||
|
|
||||||
|
@ -899,6 +901,8 @@ usage(void)
|
||||||
"don't print label contents\n");
|
"don't print label contents\n");
|
||||||
(void) fprintf(stderr, " -t --txg=INTEGER "
|
(void) fprintf(stderr, " -t --txg=INTEGER "
|
||||||
"highest txg to use when searching for uberblocks\n");
|
"highest txg to use when searching for uberblocks\n");
|
||||||
|
(void) fprintf(stderr, " -T --brt-stats "
|
||||||
|
"BRT statistics\n");
|
||||||
(void) fprintf(stderr, " -u --uberblock "
|
(void) fprintf(stderr, " -u --uberblock "
|
||||||
"uberblock\n");
|
"uberblock\n");
|
||||||
(void) fprintf(stderr, " -U --cachefile=PATH "
|
(void) fprintf(stderr, " -U --cachefile=PATH "
|
||||||
|
@ -999,6 +1003,15 @@ zdb_nicenum(uint64_t num, char *buf, size_t buflen)
|
||||||
nicenum(num, buf, 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 char histo_stars[] = "****************************************";
|
||||||
static const uint64_t histo_width = sizeof (histo_stars) - 1;
|
static const uint64_t histo_width = sizeof (histo_stars) - 1;
|
||||||
|
|
||||||
|
@ -2081,6 +2094,76 @@ dump_all_ddts(spa_t *spa)
|
||||||
dump_dedup_ratio(&dds_total);
|
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 = za.za_first_integer;
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
|
dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
|
||||||
{
|
{
|
||||||
|
@ -8093,6 +8176,9 @@ dump_zpool(spa_t *spa)
|
||||||
if (dump_opt['D'])
|
if (dump_opt['D'])
|
||||||
dump_all_ddts(spa);
|
dump_all_ddts(spa);
|
||||||
|
|
||||||
|
if (dump_opt['T'])
|
||||||
|
dump_brt(spa);
|
||||||
|
|
||||||
if (dump_opt['d'] > 2 || dump_opt['m'])
|
if (dump_opt['d'] > 2 || dump_opt['m'])
|
||||||
dump_metaslabs(spa);
|
dump_metaslabs(spa);
|
||||||
if (dump_opt['M'])
|
if (dump_opt['M'])
|
||||||
|
@ -8879,6 +8965,7 @@ main(int argc, char **argv)
|
||||||
{"io-stats", no_argument, NULL, 's'},
|
{"io-stats", no_argument, NULL, 's'},
|
||||||
{"simulate-dedup", no_argument, NULL, 'S'},
|
{"simulate-dedup", no_argument, NULL, 'S'},
|
||||||
{"txg", required_argument, NULL, 't'},
|
{"txg", required_argument, NULL, 't'},
|
||||||
|
{"brt-stats", no_argument, NULL, 'T'},
|
||||||
{"uberblock", no_argument, NULL, 'u'},
|
{"uberblock", no_argument, NULL, 'u'},
|
||||||
{"cachefile", required_argument, NULL, 'U'},
|
{"cachefile", required_argument, NULL, 'U'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
@ -8892,7 +8979,7 @@ main(int argc, char **argv)
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((c = getopt_long(argc, 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) {
|
long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
|
@ -8914,6 +9001,7 @@ main(int argc, char **argv)
|
||||||
case 'R':
|
case 'R':
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
|
case 'T':
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'y':
|
case 'y':
|
||||||
case 'Z':
|
case 'Z':
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
.\" Copyright (c) 2017 Lawrence Livermore National Security, LLC.
|
.\" Copyright (c) 2017 Lawrence Livermore National Security, LLC.
|
||||||
.\" Copyright (c) 2017 Intel Corporation.
|
.\" Copyright (c) 2017 Intel Corporation.
|
||||||
.\"
|
.\"
|
||||||
.Dd June 27, 2023
|
.Dd November 18, 2023
|
||||||
.Dt ZDB 8
|
.Dt ZDB 8
|
||||||
.Os
|
.Os
|
||||||
.
|
.
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
.Nd display ZFS storage pool debugging and consistency information
|
.Nd display ZFS storage pool debugging and consistency information
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl AbcdDFGhikLMNPsvXYy
|
.Op Fl AbcdDFGhikLMNPsTvXYy
|
||||||
.Op Fl e Oo Fl V Oc Oo Fl p Ar path Oc Ns …
|
.Op Fl e Oo Fl V Oc Oo Fl p Ar path Oc Ns …
|
||||||
.Op Fl I Ar inflight-I/O-ops
|
.Op Fl I Ar inflight-I/O-ops
|
||||||
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns …
|
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns …
|
||||||
|
@ -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
|
Simulate the effects of deduplication, constructing a DDT and then display
|
||||||
that DDT as with
|
that DDT as with
|
||||||
.Fl DD .
|
.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
|
.It Fl u , -uberblock
|
||||||
Display the current uberblock.
|
Display the current uberblock.
|
||||||
.El
|
.El
|
||||||
|
|
|
@ -58,7 +58,7 @@ set -A args "create" "add" "destroy" "import fakepool" \
|
||||||
"setvprop" "blah blah" "-%" "--?" "-*" "-=" \
|
"setvprop" "blah blah" "-%" "--?" "-*" "-=" \
|
||||||
"-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \
|
"-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \
|
||||||
"-t" "-w" "-z" "-E" "-H" "-I" "-J" \
|
"-t" "-w" "-z" "-E" "-H" "-I" "-J" \
|
||||||
"-Q" "-R" "-T" "-W"
|
"-Q" "-R" "-W"
|
||||||
|
|
||||||
log_assert "Execute zdb using invalid parameters."
|
log_assert "Execute zdb using invalid parameters."
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue