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