]> git.proxmox.com Git - mirror_zfs.git/commitdiff
zdb: show BRT statistics and dump its contents
authorRob Norris <robn@despairlabs.com>
Sat, 18 Nov 2023 10:33:45 +0000 (21:33 +1100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 27 Nov 2023 21:35:07 +0000 (13:35 -0800)
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

cmd/zdb/zdb.c
man/man8/zdb.8
tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh

index 18221c4b92d2cca1f9f7960b8d6c9b5ba4a6b238..e8726915cc8fdff461befbd045bb66288cd84372 100644 (file)
@@ -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>
@@ -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>
 
@@ -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          "
@@ -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;
 
@@ -2081,6 +2094,76 @@ 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 = 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
 dump_dtl_seg(void *arg, uint64_t start, uint64_t size)
 {
@@ -8108,6 +8191,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'])
@@ -8894,6 +8980,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'},
@@ -8907,7 +8994,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':
@@ -8929,6 +9016,7 @@ main(int argc, char **argv)
                case 'R':
                case 's':
                case 'S':
+               case 'T':
                case 'u':
                case 'y':
                case 'Z':
index 52c8e452fa7cb06d9b103de33d069a07a8fe2700..d7f66d917ac78929bb4073fa25ccb556bf511648 100644 (file)
@@ -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
 .
@@ -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 …
@@ -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
index 168e7c18c3a30d43cc2321b8e09e1fba35c8943f..688d488ceb62fc9a1d39e20095dfff9d4efa104f 100755 (executable)
@@ -58,7 +58,7 @@ set -A args "create" "add" "destroy" "import fakepool" \
     "setvprop" "blah blah" "-%" "--?" "-*" "-=" \
     "-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \
     "-t" "-w" "-z" "-E" "-H" "-I" "-J" \
-    "-Q" "-R" "-T" "-W"
+    "-Q" "-R" "-W"
 
 log_assert "Execute zdb using invalid parameters."