1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * CDDL HEADER START 4 * 5 * This file and its contents are supplied under the terms of the Common 6 * Development and Distribution License ("CDDL"), version 1.0. You may only use 7 * this file in accordance with the terms of version 1.0 of the CDDL. 8 * 9 * A full copy of the text of the CDDL should have accompanied this source. A 10 * copy of the CDDL is also available via the Internet at 11 * http://www.illumos.org/license/CDDL. 12 * 13 * CDDL HEADER END 14 */ 15 16 /* 17 * Copyright (c) 2026 by Garth Snyder. All rights reserved. 18 */ 19 20 #ifndef _ZSTREAM_CHAIN_H 21 #define _ZSTREAM_CHAIN_H 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 #include <stddef.h> 28 #include <stdint.h> 29 #include <sys/zfs_ioctl.h> 30 31 /* 32 * A chain is a linear series of steps that process packets of data. It's 33 * designed to modularize common functionality, reduce code duplication, and 34 * separate processing structure from implementation. 35 * 36 * Some terms: 37 * 38 * **STEP** - A chain_step_t struct that represents a packet-processing 39 * module and any arguments or context that it needs. Chain modules 40 * generally define a function named serial_* that produces a chain_step_t 41 * that can be incorporated directly into a chain. 42 * 43 * **CHAIN** - An array of chain_step_t's. It's just data, so you can create 44 * the array however you like. But normally you'd just declare the whole 45 * thing: 46 * 47 * zstream_chain_t dump_chain = { 48 * serial_read_stream(infile), 49 * serial_validate_fletcher4(), 50 * serial_byteswap(BS_INCOMING), 51 * serial_validate_records(), 52 * serial_dump_records(&dump_args), 53 * serial_null_output(), 54 * chain_terminator() 55 * } 56 * 57 * Or more succinctly: 58 * 59 * zstream_chain_t dump_chain = { 60 * STANDARD_INPUT_STACK(infile), 61 * serial_dump_records(&dump_args), 62 * NULL_OUTPUT_STACK() 63 * }; 64 * 65 * Chains must be terminated by a step of type CS_TERMINATE. 66 * 67 * **ITEMS** - The data packets that flow through a chain. Each step accepts 68 * items of one size and emits items of another size, which may be smaller, 69 * larger, or the same size. Items will generally be structs that start with 70 * a drr_packet_t (defined in zstream_io.h) and may include additional 71 * module-specific fields. 72 * 73 * **PROCESSING FUNCTION** - Each step names a processing function that does 74 * the actual work of transforming an input buffer into an output buffer. 75 * The transformation happens in place, in a single buffer provided by the 76 * chain. 77 * 78 * The processing function should return a disposition_t, normally D_OK. A 79 * function can return D_DROP to remove an item from the stream entirely. It 80 * can also return D_EOF to indicate that no more data will be forthcoming. 81 * However, only the first step in the chain should ever return D_EOF. 82 * 83 * Functions are called with a NULL packet pointer when the end of the 84 * stream passes by them. 85 * 86 * **CONTEXT** - An arbitrary void * that the chain passes along to the 87 * processing function as an argument. 88 * 89 * **CHAIN ATTRIBUTES** - A global set of flags available to all steps. 90 */ 91 92 #define CA_BYTESWAPPED (1ULL << 0) /* ca_attrs */ 93 #define CA_BIG_ENDIAN_INPUT (1ULL << 1) 94 #define CA_LITTLE_ENDIAN_INPUT (1ULL << 2) 95 96 #define CA_VERBOSE (1ULL << 0) /* ca_command_opts */ 97 #define CA_VERY_VERBOSE (1ULL << 1) 98 #define CA_DUMP_DATA (1ULL << 2) 99 #define CA_IGNORE_CKSUMS (1ULL << 3) 100 #define CA_DO_NOT_VALIDATE (1ULL << 4) 101 #define CA_FORBID_DEDUP (1ULL << 5) 102 #define CA_REQUIRE_DEDUP (1ULL << 6) 103 #define CA_REQUIRE_NATIVE_ENDIAN (1ULL << 7) 104 #define CA_BYTESWAP_ON_OUTPUT (1ULL << 8) 105 #define CA_BIG_ENDIAN_OUT (1ULL << 9) 106 #define CA_LITTLE_ENDIAN_OUT (1ULL << 10) 107 #define CA_OPPOSITE_ENDIAN_OUT (1ULL << 11) 108 109 #define OPTION_ENABLED(option) (!!(chain_attrs->ca_command_opts & (option))) 110 #define STREAM_HAS_FEATURE(feat) (!!(chain_attrs->ca_feature_flags & (feat))) 111 #define ATTR_IS_SET(attr) (!!(chain_attrs->ca_attrs & (attr))) 112 113 #define ENABLE_OPTION(attrs, opt) ((attrs)->ca_command_opts |= (opt)) 114 #define SET_ATTR(attr) (chain_attrs->ca_attrs |= (attr)) 115 116 typedef struct { 117 uint64_t rs_num_records; 118 uint64_t rs_total_header_bytes; 119 uint64_t rs_total_payload_bytes; 120 } record_stats_t; 121 122 /* 123 * Chain attribute flags that describe the stream. Statistics are maintained 124 * by the zstream_io modules. 125 */ 126 typedef struct { 127 uint64_t ca_feature_flags; /* From drr_versioninfo */ 128 uint64_t ca_attrs; /* Discovered attributes */ 129 uint64_t ca_command_opts; /* Command line options */ 130 record_stats_t ca_totals_in; 131 record_stats_t ca_totals_out; 132 record_stats_t ca_stats_in[DRR_NUMTYPES]; 133 record_stats_t ca_stats_out[DRR_NUMTYPES]; 134 } chain_attrs_t; 135 136 typedef enum { CS_SERIAL, CS_TERMINATE } step_type_t; 137 typedef enum { D_OK, D_EOF, D_DROP } disposition_t; 138 139 typedef disposition_t 140 zc_serial_process_f(void *item, void *context); 141 142 typedef struct chain_step 143 { 144 step_type_t cs_type; 145 size_t cs_in_size; 146 size_t cs_out_size; 147 void *cs_context; 148 struct { 149 zc_serial_process_f *process; 150 } cs_serial; 151 } chain_step_t; 152 153 typedef chain_step_t zstream_chain_t[]; 154 155 /* 156 * Chain attributes accessible to any step on the chain. In theory this 157 * could cause a race condition between reading and setting, but all 158 * attributes are typically set by the time the first record has been read. 159 * Ergo, nobody else will be executing while that first chain_read() runs. 160 */ 161 extern chain_attrs_t *chain_attrs; 162 163 /* 164 * Execute a chain. Returns once execution is complete. You can pass NULL 165 * for the attrs if you're not interested in preserving them after the chain 166 * has run. 167 */ 168 void 169 zstream_chain_exec(zstream_chain_t chain, chain_attrs_t *attrs); 170 171 chain_step_t 172 serial_null_step(void); 173 174 chain_step_t 175 chain_terminator(void); 176 177 #ifdef __cplusplus 178 } 179 #endif 180 181 #endif /* _ZSTREAM_CHAIN_H */ 182