MFV r258972:
4373 add block contents print to zstreamdump illumos/illumos-gate@994fb6b8a9 MFC after: 2 weeks
This commit is contained in:
commit
f86b34932a
@ -18,10 +18,11 @@
|
|||||||
.\" information: Portions Copyright [yyyy] [name of copyright owner]
|
.\" information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
|
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
.\" Copyright (c) 2013, Delphix. All Rights Reserved.
|
||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd November 26, 2011
|
.Dd December 31, 2013
|
||||||
.Dt ZSTREAMDUMP 8
|
.Dt ZSTREAMDUMP 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -30,6 +31,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl C
|
.Op Fl C
|
||||||
|
.Op Fl d
|
||||||
.Op Fl v
|
.Op Fl v
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
@ -43,6 +45,8 @@ The following options are supported:
|
|||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl C
|
.It Fl C
|
||||||
Suppress the validation of checksums.
|
Suppress the validation of checksums.
|
||||||
|
.It Fl d
|
||||||
|
Dump contents of blocks modified, implies verbose.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Verbose. Dump all headers, not only begin and end headers.
|
Verbose. Dump all headers, not only begin and end headers.
|
||||||
.El
|
.El
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <libnvpair.h>
|
#include <libnvpair.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -34,6 +39,16 @@
|
|||||||
#include <sys/zfs_ioctl.h>
|
#include <sys/zfs_ioctl.h>
|
||||||
#include <zfs_fletcher.h>
|
#include <zfs_fletcher.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If dump mode is enabled, the number of bytes to print per line
|
||||||
|
*/
|
||||||
|
#define BYTES_PER_LINE 16
|
||||||
|
/*
|
||||||
|
* If dump mode is enabled, the number of bytes to group together, separated
|
||||||
|
* by newlines or spaces
|
||||||
|
*/
|
||||||
|
#define DUMP_GROUPING 4
|
||||||
|
|
||||||
uint64_t drr_record_count[DRR_NUMTYPES];
|
uint64_t drr_record_count[DRR_NUMTYPES];
|
||||||
uint64_t total_write_size = 0;
|
uint64_t total_write_size = 0;
|
||||||
uint64_t total_stream_len = 0;
|
uint64_t total_stream_len = 0;
|
||||||
@ -45,9 +60,11 @@ boolean_t do_cksum = B_TRUE;
|
|||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] < file\n");
|
(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n");
|
||||||
(void) fprintf(stderr, "\t -v -- verbose\n");
|
(void) fprintf(stderr, "\t -v -- verbose\n");
|
||||||
(void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
|
(void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
|
||||||
|
(void) fprintf(stderr, "\t -d -- dump contents of blocks modified, "
|
||||||
|
"implies verbose\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +92,70 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
|
|||||||
return (outlen);
|
return (outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print part of a block in ASCII characters
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_ascii_block(char *subbuf, int length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';
|
||||||
|
if (i != 0 && i % DUMP_GROUPING == 0) {
|
||||||
|
(void) printf(" ");
|
||||||
|
}
|
||||||
|
(void) printf("%c", char_print);
|
||||||
|
}
|
||||||
|
(void) printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_block - Dump the contents of a modified block to STDOUT
|
||||||
|
*
|
||||||
|
* Assume that buf has capacity evenly divisible by BYTES_PER_LINE
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
print_block(char *buf, int length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/*
|
||||||
|
* Start printing ASCII characters at a constant offset, after
|
||||||
|
* the hex prints. Leave 3 characters per byte on a line (2 digit
|
||||||
|
* hex number plus 1 space) plus spaces between characters and
|
||||||
|
* groupings
|
||||||
|
*/
|
||||||
|
int ascii_start = BYTES_PER_LINE * 3 +
|
||||||
|
BYTES_PER_LINE / DUMP_GROUPING + 2;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i += BYTES_PER_LINE) {
|
||||||
|
int j;
|
||||||
|
int this_line_length = MIN(BYTES_PER_LINE, length - i);
|
||||||
|
int print_offset = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < this_line_length; j++) {
|
||||||
|
int buf_offset = i + j;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Separate every DUMP_GROUPING bytes by a space.
|
||||||
|
*/
|
||||||
|
if (buf_offset % DUMP_GROUPING == 0) {
|
||||||
|
print_offset += printf(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print the two-digit hex value for this byte.
|
||||||
|
*/
|
||||||
|
unsigned char hex_print = buf[buf_offset];
|
||||||
|
print_offset += printf("%02x ", hex_print);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) printf("%*s", ascii_start - print_offset, " ");
|
||||||
|
|
||||||
|
print_ascii_block(buf + i, this_line_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -92,11 +173,17 @@ main(int argc, char *argv[])
|
|||||||
char c;
|
char c;
|
||||||
boolean_t verbose = B_FALSE;
|
boolean_t verbose = B_FALSE;
|
||||||
boolean_t first = B_TRUE;
|
boolean_t first = B_TRUE;
|
||||||
|
/*
|
||||||
|
* dump flag controls whether the contents of any modified data blocks
|
||||||
|
* are printed to the console during processing of the stream. Warning:
|
||||||
|
* for large streams, this can obviously lead to massive prints.
|
||||||
|
*/
|
||||||
|
boolean_t dump = B_FALSE;
|
||||||
int err;
|
int err;
|
||||||
zio_cksum_t zc = { 0 };
|
zio_cksum_t zc = { 0 };
|
||||||
zio_cksum_t pcksum = { 0 };
|
zio_cksum_t pcksum = { 0 };
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, ":vC")) != -1) {
|
while ((c = getopt(argc, argv, ":vCd")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
do_cksum = B_FALSE;
|
do_cksum = B_FALSE;
|
||||||
@ -104,6 +191,10 @@ main(int argc, char *argv[])
|
|||||||
case 'v':
|
case 'v':
|
||||||
verbose = B_TRUE;
|
verbose = B_TRUE;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
dump = B_TRUE;
|
||||||
|
verbose = B_TRUE;
|
||||||
|
break;
|
||||||
case ':':
|
case ':':
|
||||||
(void) fprintf(stderr,
|
(void) fprintf(stderr,
|
||||||
"missing argument for '%c' option\n", optopt);
|
"missing argument for '%c' option\n", optopt);
|
||||||
@ -128,6 +219,10 @@ main(int argc, char *argv[])
|
|||||||
pcksum = zc;
|
pcksum = zc;
|
||||||
while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
|
while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is the first DMU record being processed, check for
|
||||||
|
* the magic bytes and figure out the endian-ness based on them.
|
||||||
|
*/
|
||||||
if (first) {
|
if (first) {
|
||||||
if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
|
if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
|
||||||
do_byteswap = B_TRUE;
|
do_byteswap = B_TRUE;
|
||||||
@ -209,7 +304,7 @@ main(int argc, char *argv[])
|
|||||||
nvlist_t *nv;
|
nvlist_t *nv;
|
||||||
int sz = drr->drr_payloadlen;
|
int sz = drr->drr_payloadlen;
|
||||||
|
|
||||||
if (sz > 1<<20) {
|
if (sz > INITIAL_BUFLEN) {
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = malloc(sz);
|
buf = malloc(sz);
|
||||||
}
|
}
|
||||||
@ -283,6 +378,10 @@ main(int argc, char *argv[])
|
|||||||
if (drro->drr_bonuslen > 0) {
|
if (drro->drr_bonuslen > 0) {
|
||||||
(void) ssread(buf, P2ROUNDUP(drro->drr_bonuslen,
|
(void) ssread(buf, P2ROUNDUP(drro->drr_bonuslen,
|
||||||
8), &zc);
|
8), &zc);
|
||||||
|
if (dump) {
|
||||||
|
print_block(buf,
|
||||||
|
P2ROUNDUP(drro->drr_bonuslen, 8));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -312,6 +411,10 @@ main(int argc, char *argv[])
|
|||||||
drrw->drr_key.ddk_prop =
|
drrw->drr_key.ddk_prop =
|
||||||
BSWAP_64(drrw->drr_key.ddk_prop);
|
BSWAP_64(drrw->drr_key.ddk_prop);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* If this is verbose and/or dump output,
|
||||||
|
* print info on the modified block
|
||||||
|
*/
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
(void) printf("WRITE object = %llu type = %u "
|
(void) printf("WRITE object = %llu type = %u "
|
||||||
"checksum type = %u\n"
|
"checksum type = %u\n"
|
||||||
@ -324,7 +427,16 @@ main(int argc, char *argv[])
|
|||||||
(u_longlong_t)drrw->drr_length,
|
(u_longlong_t)drrw->drr_length,
|
||||||
(u_longlong_t)drrw->drr_key.ddk_prop);
|
(u_longlong_t)drrw->drr_key.ddk_prop);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Read the contents of the block in from STDIN to buf
|
||||||
|
*/
|
||||||
(void) ssread(buf, drrw->drr_length, &zc);
|
(void) ssread(buf, drrw->drr_length, &zc);
|
||||||
|
/*
|
||||||
|
* If in dump mode
|
||||||
|
*/
|
||||||
|
if (dump) {
|
||||||
|
print_block(buf, drrw->drr_length);
|
||||||
|
}
|
||||||
total_write_size += drrw->drr_length;
|
total_write_size += drrw->drr_length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -390,6 +502,9 @@ main(int argc, char *argv[])
|
|||||||
drrs->drr_length);
|
drrs->drr_length);
|
||||||
}
|
}
|
||||||
(void) ssread(buf, drrs->drr_length, &zc);
|
(void) ssread(buf, drrs->drr_length, &zc);
|
||||||
|
if (dump) {
|
||||||
|
print_block(buf, drrs->drr_length);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pcksum = zc;
|
pcksum = zc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user