From d9794577604d6a724623fc3a4bf2b5de1d599441 Mon Sep 17 00:00:00 2001 From: Garth Snyder Date: Thu, 5 Mar 2026 15:33:03 -0800 Subject: [PATCH] zstream: consolidate shared code zstream currently contains three identical copies of dump_record(), which appear to all be drawn from libzfs_sendrecv.c. The original is marked internal. This PR adds zstream_util.[hc] and puts the shared code there along with a couple of other items in common. No functional changes. Reviewed-by: Brian Behlendorf Signed-off-by: Garth Snyder Closes #18284 --- cmd/zstream/Makefile.am | 4 +- cmd/zstream/zstream.h | 3 - cmd/zstream/zstream_decompress.c | 26 +------- cmd/zstream/zstream_dump.c | 13 +--- cmd/zstream/zstream_recompress.c | 26 +------- cmd/zstream/zstream_redup.c | 54 +--------------- cmd/zstream/zstream_util.c | 106 +++++++++++++++++++++++++++++++ cmd/zstream/zstream_util.h | 60 +++++++++++++++++ 8 files changed, 173 insertions(+), 119 deletions(-) create mode 100644 cmd/zstream/zstream_util.c create mode 100644 cmd/zstream/zstream_util.h diff --git a/cmd/zstream/Makefile.am b/cmd/zstream/Makefile.am index 1ccf67a6c..576b1ba2c 100644 --- a/cmd/zstream/Makefile.am +++ b/cmd/zstream/Makefile.am @@ -11,7 +11,9 @@ zstream_SOURCES = \ %D%/zstream_dump.c \ %D%/zstream_recompress.c \ %D%/zstream_redup.c \ - %D%/zstream_token.c + %D%/zstream_token.c \ + %D%/zstream_util.c \ + %D%/zstream_util.h zstream_LDADD = \ libzfs.la \ diff --git a/cmd/zstream/zstream.h b/cmd/zstream/zstream.h index 889b6e753..fb46e5462 100644 --- a/cmd/zstream/zstream.h +++ b/cmd/zstream/zstream.h @@ -25,9 +25,6 @@ extern "C" { #endif -extern void *safe_calloc(size_t n); -extern int sfread(void *buf, size_t size, FILE *fp); -extern void *safe_malloc(size_t size); extern int zstream_do_redup(int, char *[]); extern int zstream_do_dump(int, char *[]); extern int zstream_do_decompress(int argc, char *argv[]); diff --git a/cmd/zstream/zstream_decompress.c b/cmd/zstream/zstream_decompress.c index 40bb1ece8..a9dbe3079 100644 --- a/cmd/zstream/zstream_decompress.c +++ b/cmd/zstream/zstream_decompress.c @@ -37,31 +37,7 @@ #include #include "zfs_fletcher.h" #include "zstream.h" - -static int -dump_record(dmu_replay_record_t *drr, void *payload, int payload_len, - zio_cksum_t *zc, int outfd) -{ - assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum) - == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} +#include "zstream_util.h" int zstream_do_decompress(int argc, char *argv[]) diff --git a/cmd/zstream/zstream_dump.c b/cmd/zstream/zstream_dump.c index 78949d4d0..6ccc57204 100644 --- a/cmd/zstream/zstream_dump.c +++ b/cmd/zstream/zstream_dump.c @@ -44,6 +44,7 @@ #include #include #include "zstream.h" +#include "zstream_util.h" /* * If dump mode is enabled, the number of bytes to print per line @@ -60,18 +61,6 @@ static FILE *send_stream = 0; static boolean_t do_byteswap = B_FALSE; static boolean_t do_cksum = B_TRUE; -void * -safe_malloc(size_t size) -{ - void *rv = malloc(size); - if (rv == NULL) { - (void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n", - size); - abort(); - } - return (rv); -} - /* * ssread - send stream read. * diff --git a/cmd/zstream/zstream_recompress.c b/cmd/zstream/zstream_recompress.c index 174265ece..5092b534a 100644 --- a/cmd/zstream/zstream_recompress.c +++ b/cmd/zstream/zstream_recompress.c @@ -37,31 +37,7 @@ #include #include "zfs_fletcher.h" #include "zstream.h" - -static int -dump_record(dmu_replay_record_t *drr, void *payload, int payload_len, - zio_cksum_t *zc, int outfd) -{ - assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum) - == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} +#include "zstream_util.h" int zstream_do_recompress(int argc, char *argv[]) diff --git a/cmd/zstream/zstream_redup.c b/cmd/zstream/zstream_redup.c index c1cb6d4d3..59bccd7b1 100644 --- a/cmd/zstream/zstream_redup.c +++ b/cmd/zstream/zstream_redup.c @@ -37,6 +37,7 @@ #include #include "zfs_fletcher.h" #include "zstream.h" +#include "zstream_util.h" #define MAX_RDT_PHYSMEM_PERCENT 20 @@ -57,34 +58,6 @@ typedef struct redup_table { int numhashbits; } redup_table_t; -void * -safe_calloc(size_t n) -{ - void *rv = calloc(1, n); - if (rv == NULL) { - fprintf(stderr, - "Error: could not allocate %u bytes of memory\n", - (int)n); - exit(1); - } - return (rv); -} - -/* - * Safe version of fread(), exits on error. - */ -int -sfread(void *buf, size_t size, FILE *fp) -{ - int rv = fread(buf, size, 1, fp); - if (rv == 0 && ferror(fp)) { - (void) fprintf(stderr, "Error while reading file: %s\n", - strerror(errno)); - exit(1); - } - return (rv); -} - /* * Safe version of pread(), exits on error. */ @@ -104,31 +77,6 @@ spread(int fd, void *buf, size_t count, off_t offset) } } -static int -dump_record(dmu_replay_record_t *drr, void *payload, int payload_len, - zio_cksum_t *zc, int outfd) -{ - assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum) - == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} - static void rdt_insert(redup_table_t *rdt, uint64_t guid, uint64_t object, uint64_t offset, uint64_t stream_offset) diff --git a/cmd/zstream/zstream_util.c b/cmd/zstream/zstream_util.c new file mode 100644 index 000000000..b44175284 --- /dev/null +++ b/cmd/zstream/zstream_util.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2012 Pawel Jakub Dawidek . + * All rights reserved + * Copyright (c) 2013 Steven Hartland. All rights reserved. + * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2016 Igor Kozhukhov + * Copyright (c) 2018, loli10K . All rights reserved. + * Copyright (c) 2019 Datto Inc. + * Copyright (c) 2024, Klara, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "zstream_util.h" + +/* + * From libzfs_sendrecv.c + */ +int +dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len, + zio_cksum_t *zc, int outfd) +{ + ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), + ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); + fletcher_4_incremental_native(drr, + offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); + if (drr->drr_type != DRR_BEGIN) { + ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. + drr_checksum.drr_checksum)); + drr->drr_u.drr_checksum.drr_checksum = *zc; + } + fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, + sizeof (zio_cksum_t), zc); + if (write(outfd, drr, sizeof (*drr)) == -1) + return (errno); + if (payload_len != 0) { + fletcher_4_incremental_native(payload, payload_len, zc); + if (write(outfd, payload, payload_len) == -1) + return (errno); + } + return (0); +} + +void * +safe_malloc(size_t size) +{ + void *rv = malloc(size); + if (rv == NULL) { + (void) fprintf(stderr, "Error: failed to allocate %zu bytes\n", + size); + exit(1); + } + return (rv); +} + +void * +safe_calloc(size_t size) +{ + void *rv = calloc(1, size); + if (rv == NULL) { + (void) fprintf(stderr, + "Error: failed to allocate %zu bytes\n", size); + exit(1); + } + return (rv); +} + +/* + * Safe version of fread(), exits on error. + */ +int +sfread(void *buf, size_t size, FILE *fp) +{ + int rv = fread(buf, size, 1, fp); + if (rv == 0 && ferror(fp)) { + (void) fprintf(stderr, "Error while reading file: %s\n", + strerror(errno)); + exit(1); + } + return (rv); +} diff --git a/cmd/zstream/zstream_util.h b/cmd/zstream/zstream_util.h new file mode 100644 index 000000000..50600fdd1 --- /dev/null +++ b/cmd/zstream/zstream_util.h @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2026 by Garth Snyder. All rights reserved. + */ + +#ifndef _ZSTREAM_UTIL_H +#define _ZSTREAM_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + * The safe_ versions of the functions below terminate the process if the + * operation doesn't succeed instead of returning an error. + */ +extern void * +safe_malloc(size_t size); + +extern void * +safe_calloc(size_t n); + +extern int +sfread(void *buf, size_t size, FILE *fp); + +/* + * 1) Update checksum with the record header up to drr_checksum. + * 2) Update checksum field in the record header. + * 3) Update checksum with the checksum field in the record header. + * 4) Update checksum with the contents of the payload. + * 5) Write header and payload to fd. + */ +extern int +dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len, + zio_cksum_t *zc, int outfd); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZSTREAM_UTIL_H */