8067 zdb should be able to dump literal embedded block pointer
illumos/illumos-gate@4923c69fdd
4923c69fdd
https://www.illumos.org/issues/8067
Add an option to zdb to print a literal embedded block pointer supplied on the
command line:
zdb -E [-A] word0:word1:...:word15
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Yuri Pankov <yuri.pankov@gmail.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Matthew Ahrens <mahrens@delphix.com>
This commit is contained in:
parent
84e46b3cbd
commit
33f8e79f6a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor-sys/illumos/dist/; revision=322235
@ -61,6 +61,7 @@
|
|||||||
#include <sys/ddt.h>
|
#include <sys/ddt.h>
|
||||||
#include <sys/zfeature.h>
|
#include <sys/zfeature.h>
|
||||||
#include <sys/abd.h>
|
#include <sys/abd.h>
|
||||||
|
#include <sys/blkptr.h>
|
||||||
#include <zfs_comutil.h>
|
#include <zfs_comutil.h>
|
||||||
#undef verify
|
#undef verify
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
@ -134,10 +135,11 @@ usage(void)
|
|||||||
"\t%s -O <dataset> <path>\n"
|
"\t%s -O <dataset> <path>\n"
|
||||||
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
|
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
|
||||||
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\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>] "
|
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
|
||||||
"<poolname>\n\n",
|
"<poolname>\n\n",
|
||||||
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
|
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
|
||||||
cmdname);
|
cmdname, cmdname);
|
||||||
|
|
||||||
(void) fprintf(stderr, " Dataset name must include at least one "
|
(void) fprintf(stderr, " Dataset name must include at least one "
|
||||||
"separator character '/' or '@'\n");
|
"separator character '/' or '@'\n");
|
||||||
@ -152,6 +154,8 @@ usage(void)
|
|||||||
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
|
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
|
||||||
(void) fprintf(stderr, " -d dataset(s)\n");
|
(void) fprintf(stderr, " -d dataset(s)\n");
|
||||||
(void) fprintf(stderr, " -D dedup statistics\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, " -h pool history\n");
|
||||||
(void) fprintf(stderr, " -i intent logs\n");
|
(void) fprintf(stderr, " -i intent logs\n");
|
||||||
(void) fprintf(stderr, " -l read label contents\n");
|
(void) fprintf(stderr, " -l read label contents\n");
|
||||||
@ -3625,6 +3629,33 @@ zdb_read_block(char *thing, spa_t *spa)
|
|||||||
free(dup);
|
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
|
static boolean_t
|
||||||
pool_match(nvlist_t *cfg, char *tgt)
|
pool_match(nvlist_t *cfg, char *tgt)
|
||||||
{
|
{
|
||||||
@ -3743,13 +3774,14 @@ main(int argc, char **argv)
|
|||||||
spa_config_path = spa_config_path_env;
|
spa_config_path = spa_config_path_env;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv,
|
while ((c = getopt(argc, argv,
|
||||||
"AbcCdDeFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
|
"AbcCdDeEFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'C':
|
case 'C':
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'D':
|
case 'D':
|
||||||
|
case 'E':
|
||||||
case 'G':
|
case 'G':
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'i':
|
case 'i':
|
||||||
@ -3813,6 +3845,12 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
spa_config_path = optarg;
|
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;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
@ -3860,7 +3898,7 @@ main(int argc, char **argv)
|
|||||||
verbose = MAX(verbose, 1);
|
verbose = MAX(verbose, 1);
|
||||||
|
|
||||||
for (c = 0; c < 256; c++) {
|
for (c = 0; c < 256; c++) {
|
||||||
if (dump_all && strchr("AeFlLOPRSX", c) == NULL)
|
if (dump_all && strchr("AeEFlLOPRSX", c) == NULL)
|
||||||
dump_opt[c] = 1;
|
dump_opt[c] = 1;
|
||||||
if (dump_opt[c])
|
if (dump_opt[c])
|
||||||
dump_opt[c] += verbose;
|
dump_opt[c] += verbose;
|
||||||
@ -3874,6 +3912,14 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (argc < 2 && dump_opt['R'])
|
if (argc < 2 && dump_opt['R'])
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
if (dump_opt['E']) {
|
||||||
|
if (argc != 1)
|
||||||
|
usage();
|
||||||
|
zdb_embedded_block(argv[0]);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
if (!dump_opt['e'] && dump_opt['C']) {
|
if (!dump_opt['e'] && dump_opt['C']) {
|
||||||
dump_cachefile(spa_config_path);
|
dump_cachefile(spa_config_path);
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
.\"
|
.\"
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright 2012, Richard Lowe.
|
.\" 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.
|
.\" Copyright 2017 Nexenta Systems, Inc.
|
||||||
.\"
|
.\"
|
||||||
.Dd January 14, 2017
|
.Dd April 14, 2017
|
||||||
.Dt ZDB 1M
|
.Dt ZDB 1M
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -39,6 +39,10 @@
|
|||||||
.Op Fl A
|
.Op Fl A
|
||||||
.Op Fl U Ar cache
|
.Op Fl U Ar cache
|
||||||
.Nm
|
.Nm
|
||||||
|
.Fl E
|
||||||
|
.Op Fl A
|
||||||
|
.Ar word0 Ns : Ns Ar word1 Ns :...: Ns Ar word15
|
||||||
|
.Nm
|
||||||
.Fl l
|
.Fl l
|
||||||
.Op Fl Aqu
|
.Op Fl Aqu
|
||||||
.Ar device
|
.Ar device
|
||||||
@ -153,6 +157,10 @@ Display the statistics independently for each deduplication table.
|
|||||||
Dump the contents of the deduplication tables describing duplicate blocks.
|
Dump the contents of the deduplication tables describing duplicate blocks.
|
||||||
.It Fl DDDDD
|
.It Fl DDDDD
|
||||||
Also dump the contents of the deduplication tables describing unique blocks.
|
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
|
.It Fl h
|
||||||
Display pool history similar to
|
Display pool history similar to
|
||||||
.Nm zpool Cm history ,
|
.Nm zpool Cm history ,
|
||||||
|
@ -117,3 +117,36 @@ decode_embedded_bp_compressed(const blkptr_t *bp, void *buf)
|
|||||||
buf8[i] = BF64_GET(w, (i % sizeof (w)) * NBBY, NBBY);
|
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);
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ extern "C" {
|
|||||||
void encode_embedded_bp_compressed(blkptr_t *, void *,
|
void encode_embedded_bp_compressed(blkptr_t *, void *,
|
||||||
enum zio_compress, int, int);
|
enum zio_compress, int, int);
|
||||||
void decode_embedded_bp_compressed(const blkptr_t *, void *);
|
void decode_embedded_bp_compressed(const blkptr_t *, void *);
|
||||||
|
int decode_embedded_bp(const blkptr_t *, void *, int);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user