summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2017-08-08 11:10:37 +0000
committerAndriy Gapon <avg@FreeBSD.org>2017-08-08 11:10:37 +0000
commit33f8e79f6a68598a652e28932876c7f6c00f60b0 (patch)
treee55603bc114b5cb00b7197671f368756f7c81552
parent84e46b3cbdb5f2f8f47d246b282eb568420aae25 (diff)
Notes
-rw-r--r--cmd/zdb/zdb.c52
-rw-r--r--man/man1m/zdb.1m12
-rw-r--r--uts/common/fs/zfs/blkptr.c33
-rw-r--r--uts/common/fs/zfs/sys/blkptr.h1
4 files changed, 93 insertions, 5 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 81dd94c37cf3..bd2aa652df87 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -61,6 +61,7 @@
#include <sys/ddt.h>
#include <sys/zfeature.h>
#include <sys/abd.h>
+#include <sys/blkptr.h>
#include <zfs_comutil.h>
#undef verify
#include <libzfs.h>
@@ -134,10 +135,11 @@ usage(void)
"\t%s -O <dataset> <path>\n"
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
+ "\t%s -E [-A] word0:word1:...:word15\n"
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
"<poolname>\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
- cmdname);
+ cmdname, cmdname);
(void) fprintf(stderr, " Dataset name must include at least one "
"separator character '/' or '@'\n");
@@ -152,6 +154,8 @@ usage(void)
(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, " -E decode and display block from an "
+ "embedded block pointer\n");
(void) fprintf(stderr, " -h pool history\n");
(void) fprintf(stderr, " -i intent logs\n");
(void) fprintf(stderr, " -l read label contents\n");
@@ -3625,6 +3629,33 @@ out:
free(dup);
}
+static void
+zdb_embedded_block(char *thing)
+{
+ blkptr_t bp = { 0 };
+ unsigned long long *words = (void *)&bp;
+ char buf[SPA_MAXBLOCKSIZE];
+ int err;
+
+ err = sscanf(thing, "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx:"
+ "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx",
+ words + 0, words + 1, words + 2, words + 3,
+ words + 4, words + 5, words + 6, words + 7,
+ words + 8, words + 9, words + 10, words + 11,
+ words + 12, words + 13, words + 14, words + 15);
+ if (err != 16) {
+ (void) printf("invalid input format\n");
+ exit(1);
+ }
+ ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE);
+ err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp));
+ if (err != 0) {
+ (void) printf("decode failed: %u\n", err);
+ exit(1);
+ }
+ zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0);
+}
+
static boolean_t
pool_match(nvlist_t *cfg, char *tgt)
{
@@ -3743,13 +3774,14 @@ main(int argc, char **argv)
spa_config_path = spa_config_path_env;
while ((c = getopt(argc, argv,
- "AbcCdDeFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
+ "AbcCdDeEFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
switch (c) {
case 'b':
case 'c':
case 'C':
case 'd':
case 'D':
+ case 'E':
case 'G':
case 'h':
case 'i':
@@ -3813,6 +3845,12 @@ main(int argc, char **argv)
break;
case 'U':
spa_config_path = optarg;
+ if (spa_config_path[0] != '/') {
+ (void) fprintf(stderr,
+ "cachefile must be an absolute path "
+ "(i.e. start with a slash)\n");
+ usage();
+ }
break;
case 'v':
verbose++;
@@ -3860,7 +3898,7 @@ main(int argc, char **argv)
verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) {
- if (dump_all && strchr("AeFlLOPRSX", c) == NULL)
+ if (dump_all && strchr("AeEFlLOPRSX", c) == NULL)
dump_opt[c] = 1;
if (dump_opt[c])
dump_opt[c] += verbose;
@@ -3874,6 +3912,14 @@ main(int argc, char **argv)
if (argc < 2 && dump_opt['R'])
usage();
+
+ if (dump_opt['E']) {
+ if (argc != 1)
+ usage();
+ zdb_embedded_block(argv[0]);
+ return (0);
+ }
+
if (argc < 1) {
if (!dump_opt['e'] && dump_opt['C']) {
dump_cachefile(spa_config_path);
diff --git a/man/man1m/zdb.1m b/man/man1m/zdb.1m
index 1bd47bbfa40e..f341df4e202a 100644
--- a/man/man1m/zdb.1m
+++ b/man/man1m/zdb.1m
@@ -10,10 +10,10 @@
.\"
.\"
.\" Copyright 2012, Richard Lowe.
-.\" Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+.\" Copyright (c) 2012, 2017 by Delphix. All rights reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\"
-.Dd January 14, 2017
+.Dd April 14, 2017
.Dt ZDB 1M
.Os
.Sh NAME
@@ -39,6 +39,10 @@
.Op Fl A
.Op Fl U Ar cache
.Nm
+.Fl E
+.Op Fl A
+.Ar word0 Ns : Ns Ar word1 Ns :...: Ns Ar word15
+.Nm
.Fl l
.Op Fl Aqu
.Ar device
@@ -153,6 +157,10 @@ Display the statistics independently for each deduplication table.
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 E Ar word0 Ns : Ns Ar word1 Ns :...: Ns Ar word15
+Decode and display block from an embedded block pointer specified by the
+.Ar word
+arguments.
.It Fl h
Display pool history similar to
.Nm zpool Cm history ,
diff --git a/uts/common/fs/zfs/blkptr.c b/uts/common/fs/zfs/blkptr.c
index ff93ff445691..d7a7fdb0e1b1 100644
--- a/uts/common/fs/zfs/blkptr.c
+++ b/uts/common/fs/zfs/blkptr.c
@@ -117,3 +117,36 @@ decode_embedded_bp_compressed(const blkptr_t *bp, void *buf)
buf8[i] = BF64_GET(w, (i % sizeof (w)) * NBBY, NBBY);
}
}
+
+/*
+ * Fill in the buffer with the (decompressed) payload of the embedded
+ * blkptr_t. Takes into account compression and byteorder (the payload is
+ * treated as a stream of bytes).
+ * Return 0 on success, or ENOSPC if it won't fit in the buffer.
+ */
+int
+decode_embedded_bp(const blkptr_t *bp, void *buf, int buflen)
+{
+ int lsize, psize;
+
+ ASSERT(BP_IS_EMBEDDED(bp));
+
+ lsize = BPE_GET_LSIZE(bp);
+ psize = BPE_GET_PSIZE(bp);
+
+ if (lsize > buflen)
+ return (ENOSPC);
+ ASSERT3U(lsize, ==, buflen);
+
+ if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF) {
+ uint8_t dstbuf[BPE_PAYLOAD_SIZE];
+ decode_embedded_bp_compressed(bp, dstbuf);
+ VERIFY0(zio_decompress_data_buf(BP_GET_COMPRESS(bp),
+ dstbuf, buf, psize, buflen));
+ } else {
+ ASSERT3U(lsize, ==, psize);
+ decode_embedded_bp_compressed(bp, buf);
+ }
+
+ return (0);
+}
diff --git a/uts/common/fs/zfs/sys/blkptr.h b/uts/common/fs/zfs/sys/blkptr.h
index b720482a73fe..77b1b827ac37 100644
--- a/uts/common/fs/zfs/sys/blkptr.h
+++ b/uts/common/fs/zfs/sys/blkptr.h
@@ -30,6 +30,7 @@ extern "C" {
void encode_embedded_bp_compressed(blkptr_t *, void *,
enum zio_compress, int, int);
void decode_embedded_bp_compressed(const blkptr_t *, void *);
+int decode_embedded_bp(const blkptr_t *, void *, int);
#ifdef __cplusplus
}