Skip to content

Commit 37f8a88

Browse files
ahrensbehlendorf
authored andcommitted
Illumos 5746 - more checksumming in zfs send
5746 more checksumming in zfs send Reviewed by: Christopher Siden <[email protected]> Reviewed by: George Wilson <[email protected]> Reviewed by: Bayard Bell <[email protected]> Approved by: Albert Lee <[email protected]> References: https://www.illumos.org/issues/5746 illumos/illumos-gate@98110f0 #905 Porting notes: - Minor conflicts due to: - 2024041 - 044baf0 - 88904bb - Fix ISO C90 warnings (-Werror=declaration-after-statement) - arc_buf_t *abuf; - dmu_buf_t *bonus; - zio_cksum_t cksum_orig; - zio_cksum_t *cksump; - Fix format '%llx' format specifier warning - Align message in zstreamdump safe_malloc() with upstream Ported-by: kernelOfTruth [email protected] Signed-off-by: Brian Behlendorf <[email protected]> Closes #3611
1 parent 43b4935 commit 37f8a88

File tree

6 files changed

+445
-307
lines changed

6 files changed

+445
-307
lines changed

cmd/zstreamdump/zstreamdump.c

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*/
2828

2929
/*
30-
* Copyright (c) 2013 by Delphix. All rights reserved.
30+
* Copyright (c) 2013, 2014 by Delphix. All rights reserved.
3131
*/
3232

3333
#include <ctype.h>
@@ -36,6 +36,7 @@
3636
#include <stdlib.h>
3737
#include <strings.h>
3838
#include <unistd.h>
39+
#include <stddef.h>
3940

4041
#include <sys/dmu.h>
4142
#include <sys/zfs_ioctl.h>
@@ -73,8 +74,8 @@ safe_malloc(size_t size)
7374
{
7475
void *rv = malloc(size);
7576
if (rv == NULL) {
76-
(void) fprintf(stderr, "ERROR; failed to allocate %u bytes\n",
77-
(unsigned)size);
77+
(void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n",
78+
size);
7879
abort();
7980
}
8081
return (rv);
@@ -85,7 +86,6 @@ safe_malloc(size_t size)
8586
*
8687
* Read while computing incremental checksum
8788
*/
88-
8989
static size_t
9090
ssread(void *buf, size_t len, zio_cksum_t *cksum)
9191
{
@@ -94,7 +94,7 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
9494
if ((outlen = fread(buf, len, 1, send_stream)) == 0)
9595
return (0);
9696

97-
if (do_cksum && cksum) {
97+
if (do_cksum) {
9898
if (do_byteswap)
9999
fletcher_4_incremental_byteswap(buf, len, cksum);
100100
else
@@ -104,6 +104,34 @@ ssread(void *buf, size_t len, zio_cksum_t *cksum)
104104
return (outlen);
105105
}
106106

107+
static size_t
108+
read_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)
109+
{
110+
ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
111+
==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
112+
size_t r = ssread(drr, sizeof (*drr) - sizeof (zio_cksum_t), cksum);
113+
if (r == 0)
114+
return (0);
115+
zio_cksum_t saved_cksum = *cksum;
116+
r = ssread(&drr->drr_u.drr_checksum.drr_checksum,
117+
sizeof (zio_cksum_t), cksum);
118+
if (r == 0)
119+
return (0);
120+
if (!ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.drr_checksum.drr_checksum) &&
121+
!ZIO_CHECKSUM_EQUAL(saved_cksum,
122+
drr->drr_u.drr_checksum.drr_checksum)) {
123+
fprintf(stderr, "invalid checksum\n");
124+
(void) printf("Incorrect checksum in record header.\n");
125+
(void) printf("Expected checksum = %llx/%llx/%llx/%llx\n",
126+
(longlong_t)saved_cksum.zc_word[0],
127+
(longlong_t)saved_cksum.zc_word[1],
128+
(longlong_t)saved_cksum.zc_word[2],
129+
(longlong_t)saved_cksum.zc_word[3]);
130+
exit(1);
131+
}
132+
return (sizeof (*drr));
133+
}
134+
107135
/*
108136
* Print part of a block in ASCII characters
109137
*/
@@ -135,7 +163,7 @@ print_block(char *buf, int length)
135163
* Start printing ASCII characters at a constant offset, after
136164
* the hex prints. Leave 3 characters per byte on a line (2 digit
137165
* hex number plus 1 space) plus spaces between characters and
138-
* groupings
166+
* groupings.
139167
*/
140168
int ascii_start = BYTES_PER_LINE * 3 +
141169
BYTES_PER_LINE / DUMP_GROUPING + 2;
@@ -185,8 +213,10 @@ main(int argc, char *argv[])
185213
struct drr_free *drrf = &thedrr.drr_u.drr_free;
186214
struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
187215
struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
216+
struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;
188217
char c;
189218
boolean_t verbose = B_FALSE;
219+
boolean_t very_verbose = B_FALSE;
190220
boolean_t first = B_TRUE;
191221
/*
192222
* dump flag controls whether the contents of any modified data blocks
@@ -204,11 +234,14 @@ main(int argc, char *argv[])
204234
do_cksum = B_FALSE;
205235
break;
206236
case 'v':
237+
if (verbose)
238+
very_verbose = B_TRUE;
207239
verbose = B_TRUE;
208240
break;
209241
case 'd':
210242
dump = B_TRUE;
211243
verbose = B_TRUE;
244+
very_verbose = B_TRUE;
212245
break;
213246
case ':':
214247
(void) fprintf(stderr,
@@ -231,7 +264,7 @@ main(int argc, char *argv[])
231264
}
232265

233266
send_stream = stdin;
234-
while (ssread(drr, sizeof (dmu_replay_record_t), &zc)) {
267+
while (read_hdr(drr, &zc)) {
235268

236269
/*
237270
* If this is the first DMU record being processed, check for
@@ -437,7 +470,7 @@ main(int argc, char *argv[])
437470
if (verbose) {
438471
(void) printf("WRITE object = %llu type = %u "
439472
"checksum type = %u\n"
440-
"offset = %llu length = %llu "
473+
" offset = %llu length = %llu "
441474
"props = %llx\n",
442475
(u_longlong_t)drrw->drr_object,
443476
drrw->drr_type,
@@ -481,9 +514,9 @@ main(int argc, char *argv[])
481514
if (verbose) {
482515
(void) printf("WRITE_BYREF object = %llu "
483516
"checksum type = %u props = %llx\n"
484-
"offset = %llu length = %llu\n"
517+
" offset = %llu length = %llu\n"
485518
"toguid = %llx refguid = %llx\n"
486-
"refobject = %llu refoffset = %llu\n",
519+
" refobject = %llu refoffset = %llu\n",
487520
(u_longlong_t)drrwbr->drr_object,
488521
drrwbr->drr_checksumtype,
489522
(u_longlong_t)drrwbr->drr_key.ddk_prop,
@@ -544,7 +577,7 @@ main(int argc, char *argv[])
544577
if (verbose) {
545578
(void) printf("WRITE_EMBEDDED object = %llu "
546579
"offset = %llu length = %llu\n"
547-
"toguid = %llx comp = %u etype = %u "
580+
" toguid = %llx comp = %u etype = %u "
548581
"lsize = %u psize = %u\n",
549582
(u_longlong_t)drrwe->drr_object,
550583
(u_longlong_t)drrwe->drr_offset,
@@ -562,6 +595,13 @@ main(int argc, char *argv[])
562595
/* should never be reached */
563596
exit(1);
564597
}
598+
if (drr->drr_type != DRR_BEGIN && very_verbose) {
599+
(void) printf(" checksum = %llx/%llx/%llx/%llx\n",
600+
(longlong_t)drrc->drr_checksum.zc_word[0],
601+
(longlong_t)drrc->drr_checksum.zc_word[1],
602+
(longlong_t)drrc->drr_checksum.zc_word[2],
603+
(longlong_t)drrc->drr_checksum.zc_word[3]);
604+
}
565605
pcksum = zc;
566606
}
567607
free(buf);

include/sys/spa.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,19 @@ _NOTE(CONSTCOND) } while (0)
446446
((zc1).zc_word[2] - (zc2).zc_word[2]) | \
447447
((zc1).zc_word[3] - (zc2).zc_word[3])))
448448

449+
#define ZIO_CHECKSUM_IS_ZERO(zc) \
450+
(0 == ((zc)->zc_word[0] | (zc)->zc_word[1] | \
451+
(zc)->zc_word[2] | (zc)->zc_word[3]))
452+
453+
#define ZIO_CHECKSUM_BSWAP(zcp) \
454+
{ \
455+
(zcp)->zc_word[0] = BSWAP_64((zcp)->zc_word[0]); \
456+
(zcp)->zc_word[1] = BSWAP_64((zcp)->zc_word[1]); \
457+
(zcp)->zc_word[2] = BSWAP_64((zcp)->zc_word[2]); \
458+
(zcp)->zc_word[3] = BSWAP_64((zcp)->zc_word[3]); \
459+
}
460+
461+
449462
#define DVA_IS_VALID(dva) (DVA_GET_ASIZE(dva) != 0)
450463

451464
#define ZIO_SET_CHECKSUM(zcp, w0, w1, w2, w3) \

include/sys/zfs_ioctl.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*/
2121
/*
2222
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23-
* Copyright (c) 2013 by Delphix. All rights reserved.
23+
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
2424
*/
2525

2626
#ifndef _SYS_ZFS_IOCTL_H
@@ -237,6 +237,22 @@ typedef struct dmu_replay_record {
237237
uint32_t drr_psize; /* compr. (real) size of payload */
238238
/* (possibly compressed) content follows */
239239
} drr_write_embedded;
240+
241+
/*
242+
* Nore: drr_checksum is overlaid with all record types
243+
* except DRR_BEGIN. Therefore its (non-pad) members
244+
* must not overlap with members from the other structs.
245+
* We accomplish this by putting its members at the very
246+
* end of the struct.
247+
*/
248+
struct drr_checksum {
249+
uint64_t drr_pad[34];
250+
/*
251+
* fletcher-4 checksum of everything preceding the
252+
* checksum.
253+
*/
254+
zio_cksum_t drr_checksum;
255+
} drr_checksum;
240256
} drr_u;
241257
} dmu_replay_record_t;
242258

include/sys/zio_checksum.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121
/*
2222
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23+
* Copyright (c) 2014 by Delphix. All rights reserved.
2324
*/
2425

2526
#ifndef _SYS_ZIO_CHECKSUM_H
@@ -34,13 +35,13 @@ extern "C" {
3435
/*
3536
* Signature for checksum functions.
3637
*/
37-
typedef void zio_checksum_t(const void *data, uint64_t size, zio_cksum_t *zcp);
38+
typedef void zio_checksum_func_t(const void *, uint64_t, zio_cksum_t *);
3839

3940
/*
4041
* Information about each checksum function.
4142
*/
4243
typedef const struct zio_checksum_info {
43-
zio_checksum_t *ci_func[2]; /* checksum function for each byteorder */
44+
zio_checksum_func_t *ci_func[2]; /* checksum function per byteorder */
4445
int ci_correctable; /* number of correctable bits */
4546
int ci_eck; /* uses zio embedded checksum? */
4647
int ci_dedup; /* strong enough for dedup? */
@@ -61,7 +62,7 @@ extern zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS];
6162
/*
6263
* Checksum routines.
6364
*/
64-
extern zio_checksum_t zio_checksum_SHA256;
65+
extern zio_checksum_func_t zio_checksum_SHA256;
6566

6667
extern void zio_checksum_compute(zio_t *zio, enum zio_checksum checksum,
6768
void *data, uint64_t size);

0 commit comments

Comments
 (0)