Skip to content

Commit cfec5b1

Browse files
Max Grossmanbehlendorf
authored andcommitted
Illumos 4373 - add block contents print to zstreamdump
4373 add block contents print to zstreamdump Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Approved by: Dan McDonald <danmcd@nexenta.com> References: https://www.illumos.org/issues/4373 illumos/illumos-gate@994fb6b Ported by: Brian Behlendorf <behlendorf1@llnl.gov>
1 parent a0c9a17 commit cfec5b1

File tree

1 file changed

+120
-5
lines changed

1 file changed

+120
-5
lines changed

cmd/zstreamdump/zstreamdump.c

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
* Portions Copyright 2012 Martin Matuska <martin@matuska.org>
2727
*/
2828

29+
/*
30+
* Copyright (c) 2013 by Delphix. All rights reserved.
31+
*/
32+
33+
#include <ctype.h>
2934
#include <libnvpair.h>
3035
#include <stdio.h>
3136
#include <stdlib.h>
@@ -36,6 +41,16 @@
3641
#include <sys/zfs_ioctl.h>
3742
#include <zfs_fletcher.h>
3843

44+
/*
45+
* If dump mode is enabled, the number of bytes to print per line
46+
*/
47+
#define BYTES_PER_LINE 16
48+
/*
49+
* If dump mode is enabled, the number of bytes to group together, separated
50+
* by newlines or spaces
51+
*/
52+
#define DUMP_GROUPING 4
53+
3954
uint64_t total_write_size = 0;
4055
uint64_t total_stream_len = 0;
4156
FILE *send_stream = 0;
@@ -46,9 +61,11 @@ boolean_t do_cksum = B_TRUE;
4661
static void
4762
usage(void)
4863
{
49-
(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] < file\n");
64+
(void) fprintf(stderr, "usage: zstreamdump [-v] [-C] [-d] < file\n");
5065
(void) fprintf(stderr, "\t -v -- verbose\n");
5166
(void) fprintf(stderr, "\t -C -- suppress checksum verification\n");
67+
(void) fprintf(stderr, "\t -d -- dump contents of blocks modified, "
68+
"implies verbose\n");
5269
exit(1);
5370
}
5471

@@ -76,6 +93,70 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
7693
return (outlen);
7794
}
7895

96+
/*
97+
* Print part of a block in ASCII characters
98+
*/
99+
static void
100+
print_ascii_block(char *subbuf, int length)
101+
{
102+
int i;
103+
104+
for (i = 0; i < length; i++) {
105+
char char_print = isprint(subbuf[i]) ? subbuf[i] : '.';
106+
if (i != 0 && i % DUMP_GROUPING == 0) {
107+
(void) printf(" ");
108+
}
109+
(void) printf("%c", char_print);
110+
}
111+
(void) printf("\n");
112+
}
113+
114+
/*
115+
* print_block - Dump the contents of a modified block to STDOUT
116+
*
117+
* Assume that buf has capacity evenly divisible by BYTES_PER_LINE
118+
*/
119+
static void
120+
print_block(char *buf, int length)
121+
{
122+
int i;
123+
/*
124+
* Start printing ASCII characters at a constant offset, after
125+
* the hex prints. Leave 3 characters per byte on a line (2 digit
126+
* hex number plus 1 space) plus spaces between characters and
127+
* groupings
128+
*/
129+
int ascii_start = BYTES_PER_LINE * 3 +
130+
BYTES_PER_LINE / DUMP_GROUPING + 2;
131+
132+
for (i = 0; i < length; i += BYTES_PER_LINE) {
133+
int j;
134+
int this_line_length = MIN(BYTES_PER_LINE, length - i);
135+
int print_offset = 0;
136+
137+
for (j = 0; j < this_line_length; j++) {
138+
int buf_offset = i + j;
139+
140+
/*
141+
* Separate every DUMP_GROUPING bytes by a space.
142+
*/
143+
if (buf_offset % DUMP_GROUPING == 0) {
144+
print_offset += printf(" ");
145+
}
146+
147+
/*
148+
* Print the two-digit hex value for this byte.
149+
*/
150+
unsigned char hex_print = buf[buf_offset];
151+
print_offset += printf("%02x ", hex_print);
152+
}
153+
154+
(void) printf("%*s", ascii_start - print_offset, " ");
155+
156+
print_ascii_block(buf + i, this_line_length);
157+
}
158+
}
159+
79160
int
80161
main(int argc, char *argv[])
81162
{
@@ -96,18 +177,28 @@ main(int argc, char *argv[])
96177
char c;
97178
boolean_t verbose = B_FALSE;
98179
boolean_t first = B_TRUE;
180+
/*
181+
* dump flag controls whether the contents of any modified data blocks
182+
* are printed to the console during processing of the stream. Warning:
183+
* for large streams, this can obviously lead to massive prints.
184+
*/
185+
boolean_t dump = B_FALSE;
99186
int err;
100187
zio_cksum_t zc = { { 0 } };
101188
zio_cksum_t pcksum = { { 0 } };
102189

103-
while ((c = getopt(argc, argv, ":vC")) != -1) {
190+
while ((c = getopt(argc, argv, ":vCd")) != -1) {
104191
switch (c) {
105192
case 'C':
106193
do_cksum = B_FALSE;
107194
break;
108195
case 'v':
109196
verbose = B_TRUE;
110197
break;
198+
case 'd':
199+
dump = B_TRUE;
200+
verbose = B_TRUE;
201+
break;
111202
case ':':
112203
(void) fprintf(stderr,
113204
"missing argument for '%c' option\n", optopt);
@@ -131,6 +222,10 @@ main(int argc, char *argv[])
131222
send_stream = stdin;
132223
while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
133224

225+
/*
226+
* If this is the first DMU record being processed, check for
227+
* the magic bytes and figure out the endian-ness based on them.
228+
*/
134229
if (first) {
135230
if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
136231
do_byteswap = B_TRUE;
@@ -213,7 +308,7 @@ main(int argc, char *argv[])
213308
nvlist_t *nv;
214309
int sz = drr->drr_payloadlen;
215310

216-
if (sz > 1<<20) {
311+
if (sz > INITIAL_BUFLEN) {
217312
free(buf);
218313
buf = malloc(sz);
219314
}
@@ -289,8 +384,12 @@ main(int argc, char *argv[])
289384
drro->drr_bonuslen);
290385
}
291386
if (drro->drr_bonuslen > 0) {
292-
(void) ssread(buf,
293-
P2ROUNDUP(drro->drr_bonuslen, 8), &zc);
387+
(void) ssread(buf, P2ROUNDUP(drro->drr_bonuslen,
388+
8), &zc);
389+
if (dump) {
390+
print_block(buf,
391+
P2ROUNDUP(drro->drr_bonuslen, 8));
392+
}
294393
}
295394
break;
296395

@@ -320,6 +419,10 @@ main(int argc, char *argv[])
320419
drrw->drr_key.ddk_prop =
321420
BSWAP_64(drrw->drr_key.ddk_prop);
322421
}
422+
/*
423+
* If this is verbose and/or dump output,
424+
* print info on the modified block
425+
*/
323426
if (verbose) {
324427
(void) printf("WRITE object = %llu type = %u "
325428
"checksum type = %u\n"
@@ -332,7 +435,16 @@ main(int argc, char *argv[])
332435
(u_longlong_t)drrw->drr_length,
333436
(u_longlong_t)drrw->drr_key.ddk_prop);
334437
}
438+
/*
439+
* Read the contents of the block in from STDIN to buf
440+
*/
335441
(void) ssread(buf, drrw->drr_length, &zc);
442+
/*
443+
* If in dump mode
444+
*/
445+
if (dump) {
446+
print_block(buf, drrw->drr_length);
447+
}
336448
total_write_size += drrw->drr_length;
337449
break;
338450

@@ -399,6 +511,9 @@ main(int argc, char *argv[])
399511
(long long unsigned int)drrs->drr_length);
400512
}
401513
(void) ssread(buf, drrs->drr_length, &zc);
514+
if (dump) {
515+
print_block(buf, drrs->drr_length);
516+
}
402517
break;
403518
case DRR_WRITE_EMBEDDED:
404519
if (do_byteswap) {

0 commit comments

Comments
 (0)