1*e2df9bb4SMartin Matuska /* 2*e2df9bb4SMartin Matuska * CDDL HEADER START 3*e2df9bb4SMartin Matuska * 4*e2df9bb4SMartin Matuska * The contents of this file are subject to the terms of the 5*e2df9bb4SMartin Matuska * Common Development and Distribution License (the "License"). 6*e2df9bb4SMartin Matuska * You may not use this file except in compliance with the License. 7*e2df9bb4SMartin Matuska * 8*e2df9bb4SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*e2df9bb4SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10*e2df9bb4SMartin Matuska * See the License for the specific language governing permissions 11*e2df9bb4SMartin Matuska * and limitations under the License. 12*e2df9bb4SMartin Matuska * 13*e2df9bb4SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each 14*e2df9bb4SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*e2df9bb4SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the 16*e2df9bb4SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying 17*e2df9bb4SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner] 18*e2df9bb4SMartin Matuska * 19*e2df9bb4SMartin Matuska * CDDL HEADER END 20*e2df9bb4SMartin Matuska */ 21*e2df9bb4SMartin Matuska 22*e2df9bb4SMartin Matuska /* 23*e2df9bb4SMartin Matuska * Copyright (c) 2024, Klara Inc. 24*e2df9bb4SMartin Matuska */ 25*e2df9bb4SMartin Matuska 26*e2df9bb4SMartin Matuska #include <sys/fs/zfs.h> 27*e2df9bb4SMartin Matuska #include <sys/types.h> 28*e2df9bb4SMartin Matuska #include <sys/sysmacros.h> 29*e2df9bb4SMartin Matuska #include <sys/string.h> 30*e2df9bb4SMartin Matuska #include <sys/debug.h> 31*e2df9bb4SMartin Matuska #include "zfs_valstr.h" 32*e2df9bb4SMartin Matuska 33*e2df9bb4SMartin Matuska /* 34*e2df9bb4SMartin Matuska * Each bit in a bitfield has three possible string representations: 35*e2df9bb4SMartin Matuska * - single char 36*e2df9bb4SMartin Matuska * - two-char pair 37*e2df9bb4SMartin Matuska * - full name 38*e2df9bb4SMartin Matuska */ 39*e2df9bb4SMartin Matuska typedef struct { 40*e2df9bb4SMartin Matuska const char vb_bit; 41*e2df9bb4SMartin Matuska const char vb_pair[2]; 42*e2df9bb4SMartin Matuska const char *vb_name; 43*e2df9bb4SMartin Matuska } valstr_bit_t; 44*e2df9bb4SMartin Matuska 45*e2df9bb4SMartin Matuska /* 46*e2df9bb4SMartin Matuska * Emits a character for each bit in `bits`, up to the number of elements 47*e2df9bb4SMartin Matuska * in the table. Set bits get the character in vb_bit, clear bits get a 48*e2df9bb4SMartin Matuska * space. This results in all strings having the same width, for easier 49*e2df9bb4SMartin Matuska * visual comparison. 50*e2df9bb4SMartin Matuska */ 51*e2df9bb4SMartin Matuska static size_t 52*e2df9bb4SMartin Matuska valstr_bitfield_bits(const valstr_bit_t *table, const size_t nelems, 53*e2df9bb4SMartin Matuska uint64_t bits, char *out, size_t outlen) 54*e2df9bb4SMartin Matuska { 55*e2df9bb4SMartin Matuska ASSERT(out); 56*e2df9bb4SMartin Matuska size_t n = 0; 57*e2df9bb4SMartin Matuska for (int b = 0; b < nelems; b++) { 58*e2df9bb4SMartin Matuska if (n == outlen) 59*e2df9bb4SMartin Matuska break; 60*e2df9bb4SMartin Matuska uint64_t mask = (1ULL << b); 61*e2df9bb4SMartin Matuska out[n++] = (bits & mask) ? table[b].vb_bit : ' '; 62*e2df9bb4SMartin Matuska } 63*e2df9bb4SMartin Matuska if (n < outlen) 64*e2df9bb4SMartin Matuska out[n++] = '\0'; 65*e2df9bb4SMartin Matuska return (n); 66*e2df9bb4SMartin Matuska } 67*e2df9bb4SMartin Matuska 68*e2df9bb4SMartin Matuska /* 69*e2df9bb4SMartin Matuska * Emits a two-char pair for each bit set in `bits`, taken from vb_pair, and 70*e2df9bb4SMartin Matuska * separated by a `|` character. This gives a concise representation of the 71*e2df9bb4SMartin Matuska * whole value. 72*e2df9bb4SMartin Matuska */ 73*e2df9bb4SMartin Matuska static size_t 74*e2df9bb4SMartin Matuska valstr_bitfield_pairs(const valstr_bit_t *table, const size_t nelems, 75*e2df9bb4SMartin Matuska uint64_t bits, char *out, size_t outlen) 76*e2df9bb4SMartin Matuska { 77*e2df9bb4SMartin Matuska ASSERT(out); 78*e2df9bb4SMartin Matuska size_t n = 0; 79*e2df9bb4SMartin Matuska for (int b = 0; b < nelems; b++) { 80*e2df9bb4SMartin Matuska ASSERT3U(n, <=, outlen); 81*e2df9bb4SMartin Matuska if (n == outlen) 82*e2df9bb4SMartin Matuska break; 83*e2df9bb4SMartin Matuska uint64_t mask = (1ULL << b); 84*e2df9bb4SMartin Matuska if (bits & mask) { 85*e2df9bb4SMartin Matuska size_t len = (n > 0) ? 3 : 2; 86*e2df9bb4SMartin Matuska if (n > outlen-len) 87*e2df9bb4SMartin Matuska break; 88*e2df9bb4SMartin Matuska if (n > 0) 89*e2df9bb4SMartin Matuska out[n++] = '|'; 90*e2df9bb4SMartin Matuska out[n++] = table[b].vb_pair[0]; 91*e2df9bb4SMartin Matuska out[n++] = table[b].vb_pair[1]; 92*e2df9bb4SMartin Matuska } 93*e2df9bb4SMartin Matuska } 94*e2df9bb4SMartin Matuska if (n < outlen) 95*e2df9bb4SMartin Matuska out[n++] = '\0'; 96*e2df9bb4SMartin Matuska return (n); 97*e2df9bb4SMartin Matuska } 98*e2df9bb4SMartin Matuska 99*e2df9bb4SMartin Matuska /* 100*e2df9bb4SMartin Matuska * Emits the full name for each bit set in `bits`, taken from vb_name, and 101*e2df9bb4SMartin Matuska * separated by a space. This unambiguously shows the entire set of bits, but 102*e2df9bb4SMartin Matuska * can get very long. 103*e2df9bb4SMartin Matuska */ 104*e2df9bb4SMartin Matuska static size_t 105*e2df9bb4SMartin Matuska valstr_bitfield_str(const valstr_bit_t *table, const size_t nelems, 106*e2df9bb4SMartin Matuska uint64_t bits, char *out, size_t outlen) 107*e2df9bb4SMartin Matuska { 108*e2df9bb4SMartin Matuska ASSERT(out); 109*e2df9bb4SMartin Matuska size_t n = 0; 110*e2df9bb4SMartin Matuska for (int b = 0; b < nelems; b++) { 111*e2df9bb4SMartin Matuska ASSERT3U(n, <=, outlen); 112*e2df9bb4SMartin Matuska if (n == outlen) 113*e2df9bb4SMartin Matuska break; 114*e2df9bb4SMartin Matuska uint64_t mask = (1ULL << b); 115*e2df9bb4SMartin Matuska if (bits & mask) { 116*e2df9bb4SMartin Matuska size_t len = strlen(table[b].vb_name); 117*e2df9bb4SMartin Matuska if (n > 0) 118*e2df9bb4SMartin Matuska len++; 119*e2df9bb4SMartin Matuska if (n > outlen-len) 120*e2df9bb4SMartin Matuska break; 121*e2df9bb4SMartin Matuska if (n > 0) { 122*e2df9bb4SMartin Matuska out[n++] = ' '; 123*e2df9bb4SMartin Matuska len--; 124*e2df9bb4SMartin Matuska } 125*e2df9bb4SMartin Matuska memcpy(&out[n], table[b].vb_name, len); 126*e2df9bb4SMartin Matuska n += len; 127*e2df9bb4SMartin Matuska } 128*e2df9bb4SMartin Matuska } 129*e2df9bb4SMartin Matuska if (n < outlen) 130*e2df9bb4SMartin Matuska out[n++] = '\0'; 131*e2df9bb4SMartin Matuska return (n); 132*e2df9bb4SMartin Matuska } 133*e2df9bb4SMartin Matuska 134*e2df9bb4SMartin Matuska /* 135*e2df9bb4SMartin Matuska * Emits the name of the given enum value in the table. 136*e2df9bb4SMartin Matuska */ 137*e2df9bb4SMartin Matuska static size_t 138*e2df9bb4SMartin Matuska valstr_enum_str(const char **table, const size_t nelems, 139*e2df9bb4SMartin Matuska int v, char *out, size_t outlen) 140*e2df9bb4SMartin Matuska { 141*e2df9bb4SMartin Matuska ASSERT(out); 142*e2df9bb4SMartin Matuska ASSERT3U(v, <, nelems); 143*e2df9bb4SMartin Matuska if (v >= nelems) 144*e2df9bb4SMartin Matuska return (0); 145*e2df9bb4SMartin Matuska return (MIN(strlcpy(out, table[v], outlen), outlen)); 146*e2df9bb4SMartin Matuska } 147*e2df9bb4SMartin Matuska 148*e2df9bb4SMartin Matuska /* 149*e2df9bb4SMartin Matuska * These macros create the string tables for the given name, and implement 150*e2df9bb4SMartin Matuska * the public functions described in zfs_valstr.h. 151*e2df9bb4SMartin Matuska */ 152*e2df9bb4SMartin Matuska #define _VALSTR_BITFIELD_IMPL(name, ...) \ 153*e2df9bb4SMartin Matuska static const valstr_bit_t valstr_ ## name ## _table[] = { __VA_ARGS__ };\ 154*e2df9bb4SMartin Matuska size_t \ 155*e2df9bb4SMartin Matuska zfs_valstr_ ## name ## _bits(uint64_t bits, char *out, size_t outlen) \ 156*e2df9bb4SMartin Matuska { \ 157*e2df9bb4SMartin Matuska return (valstr_bitfield_bits(valstr_ ## name ## _table, \ 158*e2df9bb4SMartin Matuska ARRAY_SIZE(valstr_ ## name ## _table), bits, out, outlen)); \ 159*e2df9bb4SMartin Matuska } \ 160*e2df9bb4SMartin Matuska \ 161*e2df9bb4SMartin Matuska size_t \ 162*e2df9bb4SMartin Matuska zfs_valstr_ ## name ## _pairs(uint64_t bits, char *out, size_t outlen) \ 163*e2df9bb4SMartin Matuska { \ 164*e2df9bb4SMartin Matuska return (valstr_bitfield_pairs(valstr_ ## name ## _table, \ 165*e2df9bb4SMartin Matuska ARRAY_SIZE(valstr_ ## name ## _table), bits, out, outlen)); \ 166*e2df9bb4SMartin Matuska } \ 167*e2df9bb4SMartin Matuska \ 168*e2df9bb4SMartin Matuska size_t \ 169*e2df9bb4SMartin Matuska zfs_valstr_ ## name(uint64_t bits, char *out, size_t outlen) \ 170*e2df9bb4SMartin Matuska { \ 171*e2df9bb4SMartin Matuska return (valstr_bitfield_str(valstr_ ## name ## _table, \ 172*e2df9bb4SMartin Matuska ARRAY_SIZE(valstr_ ## name ## _table), bits, out, outlen)); \ 173*e2df9bb4SMartin Matuska } \ 174*e2df9bb4SMartin Matuska 175*e2df9bb4SMartin Matuska #define _VALSTR_ENUM_IMPL(name, ...) \ 176*e2df9bb4SMartin Matuska static const char *valstr_ ## name ## _table[] = { __VA_ARGS__ }; \ 177*e2df9bb4SMartin Matuska size_t \ 178*e2df9bb4SMartin Matuska zfs_valstr_ ## name(int v, char *out, size_t outlen) \ 179*e2df9bb4SMartin Matuska { \ 180*e2df9bb4SMartin Matuska return (valstr_enum_str(valstr_ ## name ## _table, \ 181*e2df9bb4SMartin Matuska ARRAY_SIZE(valstr_ ## name ## _table), v, out, outlen)); \ 182*e2df9bb4SMartin Matuska } \ 183*e2df9bb4SMartin Matuska 184*e2df9bb4SMartin Matuska 185*e2df9bb4SMartin Matuska /* String tables */ 186*e2df9bb4SMartin Matuska 187*e2df9bb4SMartin Matuska /* ZIO flags: zio_flag_t, typically zio->io_flags */ 188*e2df9bb4SMartin Matuska /* BEGIN CSTYLED */ 189*e2df9bb4SMartin Matuska _VALSTR_BITFIELD_IMPL(zio_flag, 190*e2df9bb4SMartin Matuska { '.', "DA", "DONT_AGGREGATE" }, 191*e2df9bb4SMartin Matuska { '.', "RP", "IO_REPAIR" }, 192*e2df9bb4SMartin Matuska { '.', "SH", "SELF_HEAL" }, 193*e2df9bb4SMartin Matuska { '.', "RS", "RESILVER" }, 194*e2df9bb4SMartin Matuska { '.', "SC", "SCRUB" }, 195*e2df9bb4SMartin Matuska { '.', "ST", "SCAN_THREAD" }, 196*e2df9bb4SMartin Matuska { '.', "PH", "PHYSICAL" }, 197*e2df9bb4SMartin Matuska { '.', "CF", "CANFAIL" }, 198*e2df9bb4SMartin Matuska { '.', "SP", "SPECULATIVE" }, 199*e2df9bb4SMartin Matuska { '.', "CW", "CONFIG_WRITER" }, 200*e2df9bb4SMartin Matuska { '.', "DR", "DONT_RETRY" }, 201*e2df9bb4SMartin Matuska { '?', "??", "[UNUSED 11]" }, 202*e2df9bb4SMartin Matuska { '.', "ND", "NODATA" }, 203*e2df9bb4SMartin Matuska { '.', "ID", "INDUCE_DAMAGE" }, 204*e2df9bb4SMartin Matuska { '.', "AL", "IO_ALLOCATING" }, 205*e2df9bb4SMartin Matuska { '.', "RE", "IO_RETRY" }, 206*e2df9bb4SMartin Matuska { '.', "PR", "PROBE" }, 207*e2df9bb4SMartin Matuska { '.', "TH", "TRYHARD" }, 208*e2df9bb4SMartin Matuska { '.', "OP", "OPTIONAL" }, 209*e2df9bb4SMartin Matuska { '.', "DQ", "DONT_QUEUE" }, 210*e2df9bb4SMartin Matuska { '.', "DP", "DONT_PROPAGATE" }, 211*e2df9bb4SMartin Matuska { '.', "BY", "IO_BYPASS" }, 212*e2df9bb4SMartin Matuska { '.', "RW", "IO_REWRITE" }, 213*e2df9bb4SMartin Matuska { '.', "CM", "RAW_COMPRESS" }, 214*e2df9bb4SMartin Matuska { '.', "EN", "RAW_ENCRYPT" }, 215*e2df9bb4SMartin Matuska { '.', "GG", "GANG_CHILD" }, 216*e2df9bb4SMartin Matuska { '.', "DD", "DDT_CHILD" }, 217*e2df9bb4SMartin Matuska { '.', "GF", "GODFATHER" }, 218*e2df9bb4SMartin Matuska { '.', "NP", "NOPWRITE" }, 219*e2df9bb4SMartin Matuska { '.', "EX", "REEXECUTED" }, 220*e2df9bb4SMartin Matuska { '.', "DG", "DELEGATED" }, 221*e2df9bb4SMartin Matuska ) 222*e2df9bb4SMartin Matuska /* END CSTYLED */ 223*e2df9bb4SMartin Matuska 224*e2df9bb4SMartin Matuska /* 225*e2df9bb4SMartin Matuska * ZIO pipeline stage(s): enum zio_stage, typically zio->io_stage or 226*e2df9bb4SMartin Matuska * zio->io_pipeline. 227*e2df9bb4SMartin Matuska */ 228*e2df9bb4SMartin Matuska /* BEGIN CSTYLED */ 229*e2df9bb4SMartin Matuska _VALSTR_BITFIELD_IMPL(zio_stage, 230*e2df9bb4SMartin Matuska { 'O', "O ", "OPEN" }, 231*e2df9bb4SMartin Matuska { 'I', "RI", "READ_BP_INIT" }, 232*e2df9bb4SMartin Matuska { 'I', "WI", "WRITE_BP_INIT" }, 233*e2df9bb4SMartin Matuska { 'I', "FI", "FREE_BP_INIT" }, 234*e2df9bb4SMartin Matuska { 'A', "IA", "ISSUE_ASYNC" }, 235*e2df9bb4SMartin Matuska { 'W', "WC", "WRITE_COMPRESS" }, 236*e2df9bb4SMartin Matuska { 'E', "EN", "ENCRYPT" }, 237*e2df9bb4SMartin Matuska { 'C', "CG", "CHECKSUM_GENERATE" }, 238*e2df9bb4SMartin Matuska { 'N', "NW", "NOP_WRITE" }, 239*e2df9bb4SMartin Matuska { 'B', "BF", "BRT_FREE" }, 240*e2df9bb4SMartin Matuska { 'd', "dS", "DDT_READ_START" }, 241*e2df9bb4SMartin Matuska { 'd', "dD", "DDT_READ_DONE" }, 242*e2df9bb4SMartin Matuska { 'd', "dW", "DDT_WRITE" }, 243*e2df9bb4SMartin Matuska { 'd', "dF", "DDT_FREE" }, 244*e2df9bb4SMartin Matuska { 'G', "GA", "GANG_ASSEMBLE" }, 245*e2df9bb4SMartin Matuska { 'G', "GI", "GANG_ISSUE" }, 246*e2df9bb4SMartin Matuska { 'D', "DT", "DVA_THROTTLE" }, 247*e2df9bb4SMartin Matuska { 'D', "DA", "DVA_ALLOCATE" }, 248*e2df9bb4SMartin Matuska { 'D', "DF", "DVA_FREE" }, 249*e2df9bb4SMartin Matuska { 'D', "DC", "DVA_CLAIM" }, 250*e2df9bb4SMartin Matuska { 'R', "R ", "READY" }, 251*e2df9bb4SMartin Matuska { 'V', "VS", "VDEV_IO_START" }, 252*e2df9bb4SMartin Matuska { 'V', "VD", "VDEV_IO_DONE" }, 253*e2df9bb4SMartin Matuska { 'V', "VA", "VDEV_IO_ASSESS" }, 254*e2df9bb4SMartin Matuska { 'C', "CV", "CHECKSUM_VERIFY" }, 255*e2df9bb4SMartin Matuska { 'X', "X ", "DONE" }, 256*e2df9bb4SMartin Matuska ) 257*e2df9bb4SMartin Matuska /* END CSTYLED */ 258*e2df9bb4SMartin Matuska 259*e2df9bb4SMartin Matuska /* ZIO priority: zio_priority_t, typically zio->io_priority */ 260*e2df9bb4SMartin Matuska /* BEGIN CSTYLED */ 261*e2df9bb4SMartin Matuska _VALSTR_ENUM_IMPL(zio_priority, 262*e2df9bb4SMartin Matuska "SYNC_READ", 263*e2df9bb4SMartin Matuska "SYNC_WRITE", 264*e2df9bb4SMartin Matuska "ASYNC_READ", 265*e2df9bb4SMartin Matuska "ASYNC_WRITE", 266*e2df9bb4SMartin Matuska "SCRUB", 267*e2df9bb4SMartin Matuska "REMOVAL", 268*e2df9bb4SMartin Matuska "INITIALIZING", 269*e2df9bb4SMartin Matuska "TRIM", 270*e2df9bb4SMartin Matuska "REBUILD", 271*e2df9bb4SMartin Matuska "[NUM_QUEUEABLE]", 272*e2df9bb4SMartin Matuska "NOW", 273*e2df9bb4SMartin Matuska ) 274*e2df9bb4SMartin Matuska /* END CSTYLED */ 275*e2df9bb4SMartin Matuska 276*e2df9bb4SMartin Matuska #undef _VALSTR_BITFIELD_IMPL 277*e2df9bb4SMartin Matuska #undef _VALSTR_ENUM_IMPL 278