summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2017-04-13 09:40:56 -0700
committerGitHub <[email protected]>2017-04-13 09:40:56 -0700
commita44e7faa6c63998a4c058901a5c587706abe56ab (patch)
tree5aba7be7e4df4c6ba227d37f1d94ffac182eb50e
parente550644f0cdd5c3f312e8fc92846b8b1fc4290f2 (diff)
OpenZFS 6410 - teach zdb to perform object lookups by path
Authored by: Yuri Pankov <[email protected]> Reviewed by: Pavel Zakharov <[email protected]> Reviewed by: Matthew Ahrens <[email protected]> Reviewed by: Will Andrews <[email protected]> Approved by: Dan McDonald <[email protected]> Ported-by: Brian Behlendorf <[email protected]> Porting Notes: - Replaced zdb.8 with upstream mdoc zdb.1m version. Updated to include Linux specific features: -V verbatium imports and improved label printing (-u, and -l). - Minor changes to `zdb -h` output to honor 80 character limit. OpenZFS-issue: https://www.illumos.org/issues/6410 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/ed61ec1 Closes #6006
-rw-r--r--cmd/zdb/zdb.c325
-rw-r--r--man/man8/zdb.8837
2 files changed, 562 insertions, 600 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index b58b709e7..13d0bcf0e 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -22,8 +22,10 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
- * Copyright (c) 2015, 2017, Intel Corporation.
+ * Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Nexenta Systems, Inc.
+ * Copyright (c) 2017 Lawrence Livermore National Security, LLC.
+ * Copyright (c) 2015, 2017, Intel Corporation.
*/
#include <stdio.h>
@@ -122,19 +124,22 @@ static void
usage(void)
{
(void) fprintf(stderr,
- "Usage: %s [-CmMdibcsDvhLXFPAG] [-t txg] [-e [-p path...]] "
- "[-U config] [-I inflight I/Os] [-x dumpdir] [-o var=value] "
- "poolname [object...]\n"
- " %s [-divPA] [-e -p path...] [-U config] dataset "
- "[object...]\n"
- " %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
- "poolname [vdev [metaslab...]]\n"
- " %s -R [-A] [-e [-p path...]] poolname "
- "vdev:offset:size[:flags]\n"
- " %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
- " %s -l [-Aqu] device\n"
- " %s -C [-A] [-U config]\n\n",
- cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
+ "Usage:\t%s [-AbcdDFGhiLMPsvVX] [-e [-p <path> ...]] "
+ "[-I <inflight I/Os>]\n"
+ "\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
+ "\t\t[<poolname> [<object> ...]]\n"
+ "\t%s [-AdiPv] [-e [-p <path> ...]] [-U <cache>] <dataset> "
+ "[<object> ...]\n"
+ "\t%s -C [-A] [-U <cache>]\n"
+ "\t%s -l [-Aqu] <device>\n"
+ "\t%s -m [-AFLPX] [-e [-p <path> ...]] [-t <txg>] [-U <cache>]\n"
+ "\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
+ "\t%s -O <dataset> <path>\n"
+ "\t%s -R [-A] [-e [-p <path> ...]] [-U <cache>]\n"
+ "\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
+ "\t%s -S [-AP] [-e [-p <path> ...]] [-U <cache>] <poolname>\n\n",
+ cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
+ cmdname);
(void) fprintf(stderr, " Dataset name must include at least one "
"separator character '/' or '@'\n");
@@ -143,52 +148,56 @@ usage(void)
(void) fprintf(stderr, " If object numbers are specified, only "
"those objects are dumped\n\n");
(void) fprintf(stderr, " Options to control amount of output:\n");
- (void) fprintf(stderr, " -d dataset(s)\n");
- (void) fprintf(stderr, " -i intent logs\n");
- (void) fprintf(stderr, " -C config (or cachefile if alone)\n");
- (void) fprintf(stderr, " -h pool history\n");
(void) fprintf(stderr, " -b block statistics\n");
- (void) fprintf(stderr, " -m metaslabs\n");
- (void) fprintf(stderr, " -M metaslab groups\n");
(void) fprintf(stderr, " -c checksum all metadata (twice for "
"all data) blocks\n");
- (void) fprintf(stderr, " -s report stats on zdb's I/O\n");
+ (void) fprintf(stderr, " -C config (or cachefile if alone)\n");
+ (void) fprintf(stderr, " -d dataset(s)\n");
(void) fprintf(stderr, " -D dedup statistics\n");
- (void) fprintf(stderr, " -S simulate dedup to measure effect\n");
- (void) fprintf(stderr, " -v verbose (applies to all others)\n");
+ (void) fprintf(stderr, " -h pool history\n");
+ (void) fprintf(stderr, " -i intent logs\n");
(void) fprintf(stderr, " -l read label contents\n");
(void) fprintf(stderr, " -L disable leak tracking (do not "
"load spacemaps)\n");
+ (void) fprintf(stderr, " -m metaslabs\n");
+ (void) fprintf(stderr, " -M metaslab groups\n");
+ (void) fprintf(stderr, " -O perform object lookups by path\n");
(void) fprintf(stderr, " -R read and display block from a "
- "device\n\n");
+ "device\n");
+ (void) fprintf(stderr, " -s report stats on zdb's I/O\n");
+ (void) fprintf(stderr, " -S simulate dedup to measure effect\n");
+ (void) fprintf(stderr, " -v verbose (applies to all "
+ "others)\n\n");
(void) fprintf(stderr, " Below options are intended for use "
"with other options:\n");
(void) fprintf(stderr, " -A ignore assertions (-A), enable "
"panic recovery (-AA) or both (-AAA)\n");
- (void) fprintf(stderr, " -F attempt automatic rewind within "
- "safe range of transaction groups\n");
- (void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
- "cachefile\n");
- (void) fprintf(stderr, " -X attempt extreme rewind (does not "
- "work with dataset)\n");
(void) fprintf(stderr, " -e pool is exported/destroyed/"
"has altroot/not in a cachefile\n");
- (void) fprintf(stderr, " -p <path> -- use one or more with "
- "-e to specify path to vdev dir\n");
- (void) fprintf(stderr, " -x <dumpdir> -- "
- "dump all read blocks into specified directory\n");
- (void) fprintf(stderr, " -P print numbers in parsable form\n");
- (void) fprintf(stderr, " -t <txg> -- highest txg to use when "
- "searching for uberblocks\n");
- (void) fprintf(stderr, " -I <number of inflight I/Os> -- "
- "specify the maximum number of "
- "checksumming I/Os [default is 200]\n");
+ (void) fprintf(stderr, " -F attempt automatic rewind within "
+ "safe range of transaction groups\n");
(void) fprintf(stderr, " -G dump zfs_dbgmsg buffer before "
"exiting\n");
+ (void) fprintf(stderr, " -I <number of inflight I/Os> -- "
+ "specify the maximum number of\n "
+ "checksumming I/Os [default is 200]\n");
(void) fprintf(stderr, " -o <variable>=<value> set global "
- "variable to an unsigned 32-bit integer value\n");
+ "variable to an unsigned 32-bit integer\n");
+ (void) fprintf(stderr, " -p <path> -- use one or more with "
+ "-e to specify path to vdev dir\n");
+ (void) fprintf(stderr, " -P print numbers in parseable form\n");
(void) fprintf(stderr, " -q don't print label contents\n");
+ (void) fprintf(stderr, " -t <txg> -- highest txg to use when "
+ "searching for uberblocks\n");
(void) fprintf(stderr, " -u uberblock\n");
+ (void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
+ "cachefile\n");
+ (void) fprintf(stderr, " -x <dumpdir> -- "
+ "dump all read blocks into specified directory\n");
+ (void) fprintf(stderr, " -X attempt extreme rewind (does not "
+ "work with dataset)\n");
+ (void) fprintf(stderr, " -V verbatim import (as if it had been "
+ "loaded at boot)\n\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");
@@ -1607,8 +1616,55 @@ dump_deadlist(dsl_deadlist_t *dl)
static avl_tree_t idx_tree;
static avl_tree_t domain_tree;
static boolean_t fuid_table_loaded;
-static boolean_t sa_loaded;
-sa_attr_type_t *sa_attr_table;
+static objset_t *sa_os = NULL;
+static sa_attr_type_t *sa_attr_table = NULL;
+
+static int
+open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
+{
+ int err;
+ uint64_t sa_attrs = 0;
+ uint64_t version = 0;
+
+ VERIFY3P(sa_os, ==, NULL);
+ err = dmu_objset_own(path, type, B_TRUE, tag, osp);
+ if (err != 0) {
+ (void) fprintf(stderr, "failed to own dataset '%s': %s\n", path,
+ strerror(err));
+ return (err);
+ }
+
+ if (dmu_objset_type(*osp) == DMU_OST_ZFS) {
+ (void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
+ 8, 1, &version);
+ if (version >= ZPL_VERSION_SA) {
+ (void) zap_lookup(*osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
+ 8, 1, &sa_attrs);
+ }
+ err = sa_setup(*osp, sa_attrs, zfs_attr_table, ZPL_END,
+ &sa_attr_table);
+ if (err != 0) {
+ (void) fprintf(stderr, "sa_setup failed: %s\n",
+ strerror(err));
+ dmu_objset_disown(*osp, tag);
+ *osp = NULL;
+ }
+ }
+ sa_os = *osp;
+
+ return (0);
+}
+
+static void
+close_objset(objset_t *os, void *tag)
+{
+ VERIFY3P(os, ==, sa_os);
+ if (os->os_sa != NULL)
+ sa_tear_down(os);
+ dmu_objset_disown(os, tag);
+ sa_attr_table = NULL;
+ sa_os = NULL;
+}
static void
fuid_table_destroy(void)
@@ -1735,25 +1791,7 @@ dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
int idx = 0;
int error;
- if (!sa_loaded) {
- uint64_t sa_attrs = 0;
- uint64_t version;
-
- VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
- 8, 1, &version) == 0);
- if (version >= ZPL_VERSION_SA) {
- VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
- 8, 1, &sa_attrs) == 0);
- }
- if ((error = sa_setup(os, sa_attrs, zfs_attr_table,
- ZPL_END, &sa_attr_table)) != 0) {
- (void) printf("sa_setup failed errno %d, can't "
- "display znode contents\n", error);
- return;
- }
- sa_loaded = B_TRUE;
- }
-
+ VERIFY3P(os, ==, sa_os);
if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) {
(void) printf("Failed to get handle for SA znode\n");
return;
@@ -2499,6 +2537,108 @@ dump_label_uberblocks(label_t *label, uint64_t ashift, int label_num)
}
}
+static char curpath[PATH_MAX];
+
+/*
+ * Iterate through the path components, recursively passing
+ * current one's obj and remaining path until we find the obj
+ * for the last one.
+ */
+static int
+dump_path_impl(objset_t *os, uint64_t obj, char *name)
+{
+ int err;
+ int header = 1;
+ uint64_t child_obj;
+ char *s;
+ dmu_buf_t *db;
+ dmu_object_info_t doi;
+
+ if ((s = strchr(name, '/')) != NULL)
+ *s = '\0';
+ err = zap_lookup(os, obj, name, 8, 1, &child_obj);
+
+ (void) strlcat(curpath, name, sizeof (curpath));
+
+ if (err != 0) {
+ (void) fprintf(stderr, "failed to lookup %s: %s\n",
+ curpath, strerror(err));
+ return (err);
+ }
+
+ child_obj = ZFS_DIRENT_OBJ(child_obj);
+ err = sa_buf_hold(os, child_obj, FTAG, &db);
+ if (err != 0) {
+ (void) fprintf(stderr,
+ "failed to get SA dbuf for obj %llu: %s\n",
+ (u_longlong_t)child_obj, strerror(err));
+ return (EINVAL);
+ }
+ dmu_object_info_from_db(db, &doi);
+ sa_buf_rele(db, FTAG);
+
+ if (doi.doi_bonus_type != DMU_OT_SA &&
+ doi.doi_bonus_type != DMU_OT_ZNODE) {
+ (void) fprintf(stderr, "invalid bonus type %d for obj %llu\n",
+ doi.doi_bonus_type, (u_longlong_t)child_obj);
+ return (EINVAL);
+ }
+
+ if (dump_opt['v'] > 6) {
+ (void) printf("obj=%llu %s type=%d bonustype=%d\n",
+ (u_longlong_t)child_obj, curpath, doi.doi_type,
+ doi.doi_bonus_type);
+ }
+
+ (void) strlcat(curpath, "/", sizeof (curpath));
+
+ switch (doi.doi_type) {
+ case DMU_OT_DIRECTORY_CONTENTS:
+ if (s != NULL && *(s + 1) != '\0')
+ return (dump_path_impl(os, child_obj, s + 1));
+ /*FALLTHROUGH*/
+ case DMU_OT_PLAIN_FILE_CONTENTS:
+ dump_object(os, child_obj, dump_opt['v'], &header);
+ return (0);
+ default:
+ (void) fprintf(stderr, "object %llu has non-file/directory "
+ "type %d\n", (u_longlong_t)obj, doi.doi_type);
+ break;
+ }
+
+ return (EINVAL);
+}
+
+/*
+ * Dump the blocks for the object specified by path inside the dataset.
+ */
+static int
+dump_path(char *ds, char *path)
+{
+ int err;
+ objset_t *os;
+ uint64_t root_obj;
+
+ err = open_objset(ds, DMU_OST_ZFS, FTAG, &os);
+ if (err != 0)
+ return (err);
+
+ err = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, &root_obj);
+ if (err != 0) {
+ (void) fprintf(stderr, "can't lookup root znode: %s\n",
+ strerror(err));
+ dmu_objset_disown(os, FTAG);
+ return (EINVAL);
+ }
+
+ (void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds);
+
+ err = dump_path_impl(os, root_obj, path);
+
+ close_objset(os, FTAG);
+ return (err);
+}
+
static int
dump_label(const char *dev)
{
@@ -2677,11 +2817,9 @@ dump_one_dir(const char *dsname, void *arg)
objset_t *os;
spa_feature_t f;
- error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
- if (error) {
- (void) printf("Could not open %s, error %d\n", dsname, error);
+ error = open_objset(dsname, DMU_OST_ANY, FTAG, &os);
+ if (error != 0)
return (0);
- }
for (f = 0; f < SPA_FEATURES; f++) {
if (!dmu_objset_ds(os)->ds_feature_inuse[f])
@@ -2692,9 +2830,8 @@ dump_one_dir(const char *dsname, void *arg)
}
dump_dir(os);
- dmu_objset_disown(os, FTAG);
+ close_objset(os, FTAG);
fuid_table_destroy();
- sa_loaded = B_FALSE;
return (0);
}
@@ -4077,38 +4214,37 @@ main(int argc, char **argv)
spa_config_path = spa_config_path_env;
while ((c = getopt(argc, argv,
- "bcdhilmMI:suCDRSAFLXx:evp:t:U:PVGoq")) != -1) {
+ "AbcCdDeFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
switch (c) {
case 'b':
case 'c':
+ case 'C':
case 'd':
+ case 'D':
+ case 'G':
case 'h':
case 'i':
case 'l':
case 'm':
- case 's':
- case 'u':
- case 'C':
- case 'D':
case 'M':
+ case 'O':
case 'R':
+ case 's':
case 'S':
- case 'G':
+ case 'u':
dump_opt[c]++;
dump_all = 0;
break;
case 'A':
+ case 'e':
case 'F':
case 'L':
- case 'X':
- case 'e':
case 'P':
case 'q':
+ case 'X':
dump_opt[c]++;
break;
- case 'V':
- flags |= ZFS_IMPORT_VERBATIM;
- break;
+ /* NB: Sort single match options below. */
case 'I':
max_inflight = strtoull(optarg, NULL, 0);
if (max_inflight == 0) {
@@ -4118,6 +4254,11 @@ main(int argc, char **argv)
usage();
}
break;
+ case 'o':
+ error = set_global_var(optarg);
+ if (error != 0)
+ usage();
+ break;
case 'p':
if (searchdirs == NULL) {
searchdirs = umem_alloc(sizeof (char *),
@@ -4147,14 +4288,12 @@ main(int argc, char **argv)
case 'v':
verbose++;
break;
+ case 'V':
+ flags |= ZFS_IMPORT_VERBATIM;
+ break;
case 'x':
vn_dumpdir = optarg;
break;
- case 'o':
- error = set_global_var(optarg);
- if (error != 0)
- usage();
- break;
default:
usage();
break;
@@ -4196,7 +4335,7 @@ main(int argc, char **argv)
verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) {
- if (dump_all && !strchr("elAFLRSXP", c))
+ if (dump_all && strchr("AeFlLOPRSX", c) == NULL)
dump_opt[c] = 1;
if (dump_opt[c])
dump_opt[c] += verbose;
@@ -4221,6 +4360,13 @@ main(int argc, char **argv)
if (dump_opt['l'])
return (dump_label(argv[0]));
+ if (dump_opt['O']) {
+ if (argc != 2)
+ usage();
+ dump_opt['v'] = verbose + 3;
+ return (dump_path(argv[0], argv[1]));
+ }
+
if (dump_opt['X'] || dump_opt['F'])
rewind = ZPOOL_DO_REWIND |
(dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
@@ -4285,8 +4431,7 @@ main(int argc, char **argv)
}
}
} else {
- error = dmu_objset_own(target, DMU_OST_ANY,
- B_TRUE, FTAG, &os);
+ error = open_objset(target, DMU_OST_ANY, FTAG, &os);
}
}
nvlist_free(policy);
@@ -4329,10 +4474,12 @@ main(int argc, char **argv)
zdb_read_block(argv[i], spa);
}
- (os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG);
+ if (os != NULL)
+ close_objset(os, FTAG);
+ else
+ spa_close(spa, FTAG);
fuid_table_destroy();
- sa_loaded = B_FALSE;
dump_debug_buffer();
diff --git a/man/man8/zdb.8 b/man/man8/zdb.8
index 667f6b171..83e7fba14 100644
--- a/man/man8/zdb.8
+++ b/man/man8/zdb.8
@@ -1,4 +1,3 @@
-'\" t
.\"
.\" This file and its contents are supplied under the terms of the
.\" Common Development and Distribution License ("CDDL"), version 1.0.
@@ -12,556 +11,378 @@
.\"
.\" Copyright 2012, Richard Lowe.
.\" Copyright (c) 2012, 2016 by Delphix. All rights reserved.
-.\" Copyright 2016 Nexenta Systems, Inc.
+.\" Copyright 2017 Nexenta Systems, Inc.
+.\" Copyright (c) 2017 Lawrence Livermore National Security, LLC.
+.\" Copyright (c) 2017 Intel Corporation.
.\"
-.TH "ZDB" "8" "April 9, 2016" "" ""
-
-.SH "NAME"
-\fBzdb\fR - Display zpool debugging and consistency information
-
-.SH "SYNOPSIS"
-\fBzdb\fR [-CumdibcsDvhLMXFPAG] [-e [-p \fIpath\fR...]] [-t \fItxg\fR]
- [-U \fIcache\fR] [-I \fIinflight I/Os\fR] [-x \fIdumpdir\fR]
- [-o \fIvar\fR=\fIvalue\fR] ... [\fIpoolname\fR [\fIobject\fR ...]]
-
-.P
-\fBzdb\fR [-divPA] [-e [-p \fIpath\fR...]] [-U \fIcache\fR]
- \fIdataset\fR [\fIobject\fR ...]
-
-.P
-\fBzdb\fR -m [-MLXFPA] [-t \fItxg\fR] [-e [-p \fIpath\fR...]] [-U \fIcache\fR]
- \fIpoolname\fR [\fIvdev\fR [\fImetaslab\fR ...]]
-
-.P
-\fBzdb\fR -R [-A] [-e [-p \fIpath\fR...]] [-U \fIcache\fR] \fIpoolname\fR
- \fIvdev\fR:\fIoffset\fR:\fIsize\fR[:\fIflags\fR]
-
-.P
-\fBzdb\fR -S [-AP] [-e [-p \fIpath\fR...]] [-U \fIcache\fR] \fIpoolname\fR
-
-.P
-\fBzdb\fR -l [-Aqu] \fIdevice\fR
-
-.P
-\fBzdb\fR -C [-A] [-U \fIcache\fR]
-
-.SH "DESCRIPTION"
-The \fBzdb\fR utility displays information about a ZFS pool useful for
-debugging and performs some amount of consistency checking. It is a not a
-general purpose tool and options (and facilities) may change. This is neither
-a fsck(8) nor an fsdb(8) utility.
-
-.P
+.Dd April 11, 2017
+.Dt ZDB 8 SMM
+.Os Linux
+.Sh NAME
+.Nm zdb
+.Nd display zpool debugging and consistency information
+.Sh SYNOPSIS
+.Nm
+.Op Fl AbcdDFGhiLMPsvVX
+.Op Fl e Op Fl p Ar path ...
+.Op Fl I Ar inflight I/Os
+.Oo Fl o Ar var Ns = Ns Ar value Oc Ns ...
+.Op Fl t Ar txg
+.Op Fl U Ar cache
+.Op Fl x Ar dumpdir
+.Op Ar poolname Op Ar object ...
+.Nm
+.Op Fl AdiPv
+.Op Fl e Op Fl p Ar path ...
+.Op Fl U Ar cache
+.Ar dataset Op Ar object ...
+.Nm
+.Fl C
+.Op Fl A
+.Op Fl U Ar cache
+.Nm
+.Fl l
+.Op Fl Aqu
+.Ar device
+.Nm
+.Fl m
+.Op Fl AFLPVX
+.Op Fl t Ar txg
+.Op Fl e Op Fl p Ar path ...
+.Op Fl U Ar cache
+.Ar poolname Op Ar vdev Op Ar metaslab ...
+.Nm
+.Fl O
+.Ar dataset path
+.Nm
+.Fl R
+.Op Fl A
+.Op Fl e Op Fl p Ar path ...
+.Op Fl U Ar cache
+.Ar poolname vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op : Ns Ar flags
+.Nm
+.Fl S
+.Op Fl AP
+.Op Fl e Op Fl p Ar path ...
+.Op Fl U Ar cache
+.Ar poolname
+.Sh DESCRIPTION
+The
+.Nm
+utility displays information about a ZFS pool useful for debugging and performs
+some amount of consistency checking.
+It is a not a general purpose tool and options
+.Pq and facilities
+may change.
+This is neither a
+.Xr fsck 1M
+nor an
+.Xr fsdb 1M
+utility.
+.Pp
The output of this command in general reflects the on-disk structure of a ZFS
-pool, and is inherently unstable. The precise output of most invocations is
-not documented, a knowledge of ZFS internals is assumed.
-
-.P
-If the \fIdataset\fR argument does not contain any \fB/\fR or \fB@\fR
-characters, it is interpreted as a pool name. The root dataset can be
-specified as \fIpool\fB/\fR (pool name followed by a slash).
-
-.P
+pool, and is inherently unstable.
+The precise output of most invocations is not documented, a knowledge of ZFS
+internals is assumed.
+.Pp
+If the
+.Ar dataset
+argument does not contain any
+.Qq Sy /
+or
+.Qq Sy @
+characters, it is interpreted as a pool name.
+The root dataset can be specified as
+.Ar pool Ns /
+.Pq pool name followed by a slash .
+.Pp
When operating on an imported and active pool it is possible, though unlikely,
that zdb may interpret inconsistent pool data and behave erratically.
-
-.SH "OPTIONS"
+.Sh OPTIONS
Display options:
-
-.sp
-.ne 2
-.na
-\fB-b\fR
-.ad
-.sp .6
-.RS 4n
-Display statistics regarding the number, size (logical, physical and
-allocated) and deduplication of blocks.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-c\fR
-.ad
-.sp .6
-.RS 4n
+.Bl -tag -width Ds
+.It Fl b
+Display statistics regarding the number, size
+.Pq logical, physical and allocated
+and deduplication of blocks.
+.It Fl c
Verify the checksum of all metadata blocks while printing block statistics
-(see \fB-b\fR).
-.sp
+.Po see
+.Fl b
+.Pc .
+.Pp
If specified multiple times, verify the checksums of all blocks.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-C\fR
-.ad
-.sp .6
-.RS 4n
-Display information about the configuration. If specified with no other
-options, instead display information about the cache file
-(\fB/etc/zfs/zpool.cache\fR). To specify the cache file to display, see
-\fB-U\fR.
-.P
-If specified multiple times, and a pool name is also specified display both
-the cached configuration and the on-disk configuration. If specified multiple
-times with \fB-e\fR also display the configuration that would be used were the
-pool to be imported.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-d\fR
-.ad
-.sp .6
-.RS 4n
-Display information about datasets. Specified once, displays basic dataset
-information: ID, create transaction, size, and object count.
-.sp
+.It Fl C
+Display information about the configuration.
+If specified with no other options, instead display information about the cache
+file
+.Pq Pa /etc/zfs/zpool.cache .
+To specify the cache file to display, see
+.Fl U .
+.Pp
+If specified multiple times, and a pool name is also specified display both the
+cached configuration and the on-disk configuration.
+If specified multiple times with
+.Fl e
+also display the configuration that would be used were the pool to be imported.
+.It Fl d
+Display information about datasets.
+Specified once, displays basic dataset information: ID, create transaction,
+size, and object count.
+.Pp
If specified multiple times provides greater and greater verbosity.
-.sp
-If object IDs are specified, display information about those specific objects only.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-D\fR
-.ad
-.sp .6
-.RS 4n
-Display deduplication statistics, including the deduplication ratio (dedup),
-compression ratio (compress), inflation due to the zfs copies property
-(copies), and an overall effective ratio (dedup * compress / copies).
-.sp
-If specified twice, display a histogram of deduplication statistics, showing
-the allocated (physically present on disk) and referenced (logically
-referenced in the pool) block counts and sizes by reference count.
-.sp
-If specified a third time, display the statistics independently for each deduplication table.
-.sp
-If specified a fourth time, dump the contents of the deduplication tables describing duplicate blocks.
-.sp
-If specified a fifth time, also dump the contents of the deduplication tables describing unique blocks.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-h\fR
-.ad
-.sp .6
-.RS 4n
-Display pool history similar to \fBzpool history\fR, but include internal
-changes, transaction, and dataset information.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-i\fR
-.ad
-.sp .6
-.RS 4n
-Display information about intent log (ZIL) entries relating to each
-dataset. If specified multiple times, display counts of each intent log
-transaction type.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-l\fR \fIdevice\fR
-.ad
-.sp .6
-.RS 4n
-Read the vdev labels from the specified device and dump the unique
-configuration nvlist(s). \fBzdb -l\fR will return 1 if an error occured, 2 if
-no configuration nvlist could be unpacked (errors or not), and 0 otherwise.
-Specify multiple times to increase verbosity.
-.P
-If the \fB-u\fR option is also specified, also display the uberblocks on this
-device. Specify multiple times to increase verbosity.
-.P
-If the \fB-q\fR option is also specified, don't dump the configurations or the
-uberblocks.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-L\fR
-.ad
-.sp .6
-.RS 4n
-Disable leak tracing and the loading of space maps. By default, \fBzdb\fR
+.Pp
+If object IDs are specified, display information about those specific objects
+only.
+.It Fl D
+Display deduplication statistics, including the deduplication ratio
+.Pq Sy dedup ,
+compression ratio
+.Pq Sy compress ,
+inflation due to the zfs copies property
+.Pq Sy copies ,
+and an overall effective ratio
+.Pq Sy dedup No * Sy compress No / Sy copies .
+.It Fl DD
+Display a histogram of deduplication statistics, showing the allocated
+.Pq physically present on disk
+and referenced
+.Pq logically referenced in the pool
+block counts and sizes by reference count.
+.It Fl DDD
+Display the statistics independently for each deduplication table.
+.It Fl DDDD
+Dump the contents of the deduplication tables describing duplicate blocks.
+.It Fl DDDDD
+Also dump the contents of the deduplication tables describing unique blocks.
+.It Fl h
+Display pool history similar to
+.Nm zpool Cm history ,
+but include internal changes, transaction, and dataset information.
+.It Fl i
+Display information about intent log
+.Pq ZIL
+entries relating to each dataset.
+If specified multiple times, display counts of each intent log transaction type.
+.It Fl l Ar device
+Read the vdev labels from the specified device.
+.Nm Fl l
+will return 0 if valid label was found, 1 if error occurred, and 2 if no valid
+labels were found. Each unique configuration is displayed only once.
+.It Fl ll Ar device
+In addition display label space usage stats.
+.It Fl lll Ar device
+Display every configuration, unique or not.
+.Pp
+If the
+.Fl q
+option is also specified, don't print the labels.
+.Pp
+If the
+.Fl u
+option is also specified, also display the uberblocks on this device. Specify
+multiple times to increase verbosity.
+.It Fl L
+Disable leak tracing and the loading of space maps.
+By default,
+.Nm
verifies that all non-free blocks are referenced, which can be very expensive.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-m\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl m
Display the offset, spacemap, and free space of each metaslab.
-When specified twice, also display information about the on-disk free
-space histogram associated with each metaslab. When specified three time,
-display the maximum contiguous free space, the in-core free space histogram,
-and the percentage of free space in each space map. When specified
-four times display every spacemap record.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-M\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl mm
+Also display information about the on-disk free space histogram associated with
+each metaslab.
+.It Fl mmm
+Display the maximum contiguous free space, the in-core free space histogram, and
+the percentage of free space in each space map.
+.It Fl mmmm
+Display every spacemap record.
+.It Fl M
Display the offset, spacemap, and free space of each metaslab.
-When specified twice, also display information about the maximum contiguous
-free space and the percentage of free space in each space map. When specified
-three times display every spacemap record.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-R\fR \fIpoolname\fR \fIvdev\fR:\fIoffset\fR:\fIsize\fR[:\fIflags\fR]
-.ad
-.sp .6
-.RS 4n
-Read and display a block from the specified device. By default the block is
-displayed as a hex dump, but see the description of the \'r\' flag, below.
-.sp
-The block is specified in terms of a colon-separated tuple \fIvdev\fR (an
-integer vdev identifier) \fIoffset\fR (the offset within the vdev) \fIsize\fR
-(the size of the block to read) and, optionally, \fIflags\fR (a set of flags,
-described below).
-
-.sp
-.ne 2
-.na
-\fBb\fR \fIoffset\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl MM
+Also display information about the maximum contiguous free space and the
+percentage of free space in each space map.
+.It Fl MMM
+Display every spacemap record.
+.It Fl O Ar dataset path
+Look up the specified
+.Ar path
+inside of the
+.Ar dataset
+and display its metadata and indirect blocks.
+Specified
+.Ar path
+must be relative to the root of
+.Ar dataset .
+This option can be combined with
+.Fl v
+for increasing verbosity.
+.It Fl R Ar poolname vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op : Ns Ar flags
+Read and display a block from the specified device.
+By default the block is displayed as a hex dump, but see the description of the
+.Sy r
+flag, below.
+.Pp
+The block is specified in terms of a colon-separated tuple
+.Ar vdev
+.Pq an integer vdev identifier
+.Ar offset
+.Pq the offset within the vdev
+.Ar size
+.Pq the size of the block to read
+and, optionally,
+.Ar flags
+.Pq a set of flags, described below .
+.Pp
+.Bl -tag -compact -width "b offset"
+.It Sy b Ar offset
Print block pointer
-.RE
-
-.sp
-.ne 2
-.na
-\fBd\fR
-.ad
-.sp .6
-.RS 4n
+.It Sy d
Decompress the block
-.RE
-
-.sp
-.ne 2
-.na
-\fBe\fR
-.ad
-.sp .6
-.RS 4n
+.It Sy e
Byte swap the block
-.RE
-
-.sp
-.ne 2
-.na
-\fBg\fR
-.ad
-.sp .6
-.RS 4n
+.It Sy g
Dump gang block header
-.RE
-
-.sp
-.ne 2
-.na
-\fBi\fR
-.ad
-.sp .6
-.RS 4n
+.It Sy i
Dump indirect block
-.RE
-
-.sp
-.ne 2
-.na
-\fBr\fR
-.ad
-.sp .6
-.RS 4n
+.It Sy r
Dump raw uninterpreted block data
-.RE
-.RE
-
-.sp
-.ne 2
-.na
-\fB-s\fR
-.ad
-.sp .6
-.RS 4n
-Report statistics on \fBzdb\fR\'s I/O. Display operation counts, bandwidth,
-and error counts of I/O to the pool from \fBzdb\fR.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-S\fR
-.ad
-.sp .6
-.RS 4n
+.El
+.It Fl s
+Report statistics on
+.Nm zdb
+I/O.
+Display operation counts, bandwidth, and error counts of I/O to the pool from
+.Nm .
+.It Fl S
Simulate the effects of deduplication, constructing a DDT and then display
-that DDT as with \fB-DD\fR.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-u\fR
-.ad
-.sp .6
-.RS 4n
+that DDT as with
+.Fl DD .
+.It Fl u
Display the current uberblock.
-.RE
-
-.P
+.El
+.Pp
Other options:
-
-.sp
-.ne 2
-.na
-\fB-A\fR
-.ad
-.sp .6
-.RS 4n
+.Bl -tag -width Ds
+.It Fl A
Do not abort should any assertion fail.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-AA\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl AA
Enable panic recovery, certain errors which would otherwise be fatal are
demoted to warnings.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-AAA\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl AAA
Do not abort if asserts fail and also enable panic recovery.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-e\fR [-p \fIpath\fR]...
-.ad
-.sp .6
-.RS 4n
-Operate on an exported pool, not present in \fB/etc/zfs/zpool.cache\fR. The
-\fB-p\fR flag specifies the path under which devices are to be searched.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-x\fR \fIdumpdir\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl e Op Fl p Ar path ...
+Operate on an exported pool, not present in
+.Pa /etc/zfs/zpool.cache .
+The
+.Fl p
+flag specifies the path under which devices are to be searched.
+.It Fl x Ar dumpdir
All blocks accessed will be copied to files in the specified directory.
The blocks will be placed in sparse files whose name is the same as
-that of the file or device read. zdb can be then run on the generated files.
-Note that the \fB-bbc\fR flags are sufficient to access (and thus copy)
+that of the file or device read.
+.Nm
+can be then run on the generated files.
+Note that the
+.Fl bbc
+flags are sufficient to access
+.Pq and thus copy
all metadata on the pool.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-F\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl F
Attempt to make an unreadable pool readable by trying progressively older
transactions.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-G\fR
-.ad
-.sp .6
-.RS 4n
-Dump the contents of the zfs_dbgmsg buffer before exiting zdb. zfs_dbgmsg is
-a buffer used by ZFS to dump advanced debug information.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-I \fIinflight I/Os\fR \fR
-.ad
-.sp .6
-.RS 4n
-Limit the number of outstanding checksum I/Os to the specified value. The
-default value is 200. This option affects the performance of the \fB-c\fR
+.It Fl G
+Dump the contents of the zfs_dbgmsg buffer before exiting
+.Nm .
+zfs_dbgmsg is a buffer used by ZFS to dump advanced debug information.
+.It Fl I Ar inflight I/Os
+Limit the number of outstanding checksum I/Os to the specified value.
+The default value is 200.
+This option affects the performance of the
+.Fl c
option.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-o \fIvar\fR=\fIvalue\fR ... \fR
-.ad
-.sp .6
-.RS 4n
-Set the given global libzpool variable to the provided value. The value must
-be an unsigned 32-bit integer. Currently only little-endian systems are
-supported to avoid accidentally setting the high 32 bits of 64-bit variables.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-P\fR
-.ad
-.sp .6
-.RS 4n
+.It Fl o Ar var Ns = Ns Ar value ...
+Set the given global libzpool variable to the provided value.
+The value must be an unsigned 32-bit integer.
+Currently only little-endian systems are supported to avoid accidentally setting
+the high 32 bits of 64-bit variables.
+.It Fl P
Print numbers in an unscaled form more amenable to parsing, eg. 1000000 rather
than 1M.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-t\fR \fItransaction\fR
-.ad
-.sp .6
-.RS 4n
-Specify the highest transaction to use when searching for uberblocks. See also
-the \fB-u\fR and \fB-l\fR options for a means to see the available uberblocks
-and their associated transaction numbers.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-U\fR \fIcachefile\fR
-.ad
-.sp .6
-.RS 4n
-Use a cache file other than \fB/etc/zfs/zpool.cache\fR.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-v\fR
-.ad
-.sp .6
-.RS 4n
-Enable verbosity. Specify multiple times for increased verbosity.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-X\fR
-.ad
-.sp .6
-.RS 4n
-Attempt \'extreme\' transaction rewind, that is attempt the same recovery as
-\fB-F\fR but read transactions otherwise deemed too old.
-.RE
-
-.sp
-.ne 2
-.na
-\fB-V\fR
-.ad
-.sp .6
-.RS 4n
-Attempt a verbatim import. This mimics the behavior of the kernel when loading
-a pool from a cachefile.
-.RE
-
-.P
+.It Fl t Ar transaction
+Specify the highest transaction to use when searching for uberblocks.
+See also the
+.Fl u
+and
+.Fl l
+options for a means to see the available uberblocks and their associated
+transaction numbers.
+.It Fl U Ar cachefile
+Use a cache file other than
+.Pa /etc/zfs/zpool.cache .
+.It Fl v
+Enable verbosity.
+Specify multiple times for increased verbosity.
+.It Fl V
+Attempt a verbatim import. This mimics the behavior of the kernel when
+loading a pool from a cachefile.
+.It Fl X
+Attempt
+.Qq extreme
+transaction rewind, that is attempt the same recovery as
+.Fl F
+but read transactions otherwise deemed too old.
+.El
+.Pp
Specifying a display option more than once enables verbosity for only that
option, with more occurrences enabling more verbosity.
-.P
+.Pp
If no options are specified, all information about the named pool will be
displayed at default verbosity.
-
-.SH "EXAMPLES"
-.LP
-\fBExample 1 \fRDisplay the configuration of imported pool 'rpool'
-.sp
-.in +2
-.nf
+.Sh EXAMPLES
+.Bl -tag -width Ds
+.It Xo
+.Sy Example 1
+Display the configuration of imported pool
+.Pa rpool
+.Xc
+.Bd -literal
# zdb -C rpool
MOS Configuration:
version: 28
name: 'rpool'
...
-.fi
-.in -2
-.sp
-
-.LP
-\fBExample 2 \fRDisplay basic dataset information about 'rpool'
-.sp
-.in +2
-.nf
+.Ed
+.It Xo
+.Sy Example 2
+Display basic dataset information about
+.Pa rpool
+.Xc
+.Bd -literal
# zdb -d rpool
Dataset mos [META], ID 0, cr_txg 4, 26.9M, 1051 objects
Dataset rpool/swap [ZVOL], ID 59, cr_txg 356, 486M, 2 objects
...
-.fi
-.in -2
-.sp
-
-.LP
-\fBExample 3 \fRDisplay basic information about object 0
-in 'rpool/export/home'
-.sp
-.in +2
-.nf
+.Ed
+.It Xo
+.Sy Example 3
+Display basic information about object 0 in
+.Pa rpool/export/home
+.Xc
+.Bd -literal
# zdb -d rpool/export/home 0
Dataset rpool/export/home [ZPL], ID 137, cr_txg 1546, 32K, 8 objects
Object lvl iblk dblk dsize lsize %full type
0 7 16K 16K 15.0K 16K 25.00 DMU dnode
-.fi
-.in -2
-.sp
-
-.LP
-\fBExample 4 \fRDisplay the predicted effect of enabling deduplication on 'rpool'
-.sp
-.in +2
-.nf
+.Ed
+.It Xo
+.Sy Example 4
+Display the predicted effect of enabling deduplication on
+.Pa rpool
+.Xc
+.Bd -literal
# zdb -S rpool
Simulated DDT histogram:
@@ -573,14 +394,8 @@ refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE
2 35.0K 1.33G 699M 699M 74.7K 2.79G 1.45G 1.45G
...
dedup = 1.11, compress = 1.80, copies = 1.00, dedup * compress / copies = 2.00
-.fi
-.in -2
-.sp
-
-.SH "ENVIRONMENT VARIABLES"
-.TP
-.B "SPA_CONFIG_PATH"
-Override the default \fBspa_config_path\fR (\fI/etc/zfs/zpool.cache\fR) setting. If \fB-U\fR flag is specified it will override this environment variable settings once again.
-
-.SH "SEE ALSO"
-zfs(8), zpool(8)
+.Ed
+.El
+.Sh SEE ALSO
+.Xr zfs 8 ,
+.Xr zpool 8