// SPDX-License-Identifier: CDDL-1.0 /* * 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 * https://opensource.org/license/CDDL-1.0. */ /* * Copyright (c) 2026 by Garth Snyder. All rights reserved. */ #ifndef _ZSTREAM_FLETCHER4_H #define _ZSTREAM_FLETCHER4_H #ifdef __cplusplus extern "C" { #endif #include #include #include "zstream_io.h" /* * zstream_chain module for calculating, validating, and inscribing * Fletcher4 checksums. * * Checksums are calculated for the entire stream between a DRR_BEGIN record * and its corresponding DRR_END, so the final checksum assembly must be * performed as a serial step. However, we can pre-calculate the checksums * for individual payloads in parallel. * * The normal sequence is a parallel_calc_fletcher4() step followed by a * serial_validate_fletcher4() or serial_add_fletcher4() step. * * Fletcher4 is just addition, so it's quite fast on its own. However, not * parallelizing these calculations reduces aggregate throughput because of * [Amdahl's Law](https://en.wikipedia.org/wiki/Amdahl%27s_law). Briefly * stated: nonparallelizable work limits the total speedup obtainable * through parallelization, often to a nonintuitive degree. Here, the effect * is magnified because parallelizable work such as recompression lies * beyond a Fletcher4 bottleneck. */ /* * DRR_END records normally do have end-record checksums. However, records * emitted by send_conclusion_record() in libzfs_sendrecv.c have the * checksum set to zero. zfs receive ignores those checksums. DRR_END * records also have an internal checksum that applies to the stream-to-date * since the most recent DRR_BEGIN. * * Ideally, null zstream transformations should be idempotent. E.g., a * zstream redup that does not redup anything should yield a stream that is * identical to the original stream. So, it's helpful to emulate zfs send's * checksumming practices just to minimize spurious differences between * input and output streams. * * The IS_CONCLUSION macro recognizes the records generated by * send_conclusion_record() so that they can be treated specially. */ #define IS_CONCLUSION(drr, type) \ ((type) == DRR_END && \ (drr)->drr_u.drr_end.drr_toguid == 0 && \ ZIO_CHECKSUM_IS_ZERO(&(drr)->drr_u.drr_checksum.drr_checksum)) /* * Maximum number of checksum operations in one chain */ #define MAX_FLETCHER_4 8 typedef struct { drr_packet_t dp_base; zio_cksum_t dp_fletcher4_payload; zio_cksum_t *dp_fletcher4_overflow; } drr_fletcher4_t; chain_step_t parallel_calc_fletcher4(void); chain_step_t serial_validate_fletcher4(void); chain_step_t serial_add_fletcher4(void); #ifdef __cplusplus } #endif #endif /* _ZSTREAM_FLETCHER4_H */