Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/lib/libzfsbootenv/lzbe_pair.c
48378 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* This file and its contents are supplied under the terms of the
4
* Common Development and Distribution License ("CDDL"), version 1.0.
5
* You may only use this file in accordance with the terms of version
6
* 1.0 of the CDDL.
7
*
8
* A full copy of the text of the CDDL should have accompanied this
9
* source. A copy of the CDDL is also available via the Internet at
10
* http://www.illumos.org/license/CDDL.
11
*/
12
/*
13
* Copyright 2020 Toomas Soome <[email protected]>
14
*/
15
16
#include <sys/types.h>
17
#include <string.h>
18
#include <libzfs.h>
19
#include <libzfsbootenv.h>
20
#include <sys/zfs_bootenv.h>
21
#include <sys/vdev_impl.h>
22
23
/*
24
* Get or create nvlist. If key is not NULL, get nvlist from bootenv,
25
* otherwise return bootenv.
26
*/
27
int
28
lzbe_nvlist_get(const char *pool, const char *key, void **ptr)
29
{
30
libzfs_handle_t *hdl;
31
zpool_handle_t *zphdl;
32
nvlist_t *nv;
33
int rv = -1;
34
35
if (pool == NULL || *pool == '\0')
36
return (rv);
37
38
if ((hdl = libzfs_init()) == NULL) {
39
return (rv);
40
}
41
42
zphdl = zpool_open(hdl, pool);
43
if (zphdl == NULL) {
44
libzfs_fini(hdl);
45
return (rv);
46
}
47
48
rv = zpool_get_bootenv(zphdl, &nv);
49
if (rv == 0) {
50
nvlist_t *nvl, *dup;
51
52
if (key != NULL) {
53
rv = nvlist_lookup_nvlist(nv, key, &nvl);
54
if (rv == 0) {
55
rv = nvlist_dup(nvl, &dup, 0);
56
nvlist_free(nv);
57
if (rv == 0)
58
nv = dup;
59
else
60
nv = NULL;
61
} else {
62
nvlist_free(nv);
63
rv = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
64
}
65
}
66
*ptr = nv;
67
}
68
69
zpool_close(zphdl);
70
libzfs_fini(hdl);
71
return (rv);
72
}
73
74
int
75
lzbe_nvlist_set(const char *pool, const char *key, void *ptr)
76
{
77
libzfs_handle_t *hdl;
78
zpool_handle_t *zphdl;
79
nvlist_t *nv;
80
uint64_t version;
81
int rv = -1;
82
83
if (pool == NULL || *pool == '\0')
84
return (rv);
85
86
if ((hdl = libzfs_init()) == NULL) {
87
return (rv);
88
}
89
90
zphdl = zpool_open(hdl, pool);
91
if (zphdl == NULL) {
92
libzfs_fini(hdl);
93
return (rv);
94
}
95
96
if (key != NULL) {
97
rv = zpool_get_bootenv(zphdl, &nv);
98
if (rv == 0) {
99
/*
100
* We got the nvlist, check for version.
101
* if version is missing or is not VB_NVLIST,
102
* create new list.
103
*/
104
rv = nvlist_lookup_uint64(nv, BOOTENV_VERSION,
105
&version);
106
if (rv != 0 || version != VB_NVLIST) {
107
/* Drop this nvlist */
108
fnvlist_free(nv);
109
/* Create and prepare new nvlist */
110
nv = fnvlist_alloc();
111
fnvlist_add_uint64(nv, BOOTENV_VERSION,
112
VB_NVLIST);
113
}
114
rv = nvlist_add_nvlist(nv, key, ptr);
115
if (rv == 0)
116
rv = zpool_set_bootenv(zphdl, nv);
117
nvlist_free(nv);
118
}
119
} else {
120
rv = zpool_set_bootenv(zphdl, ptr);
121
}
122
123
zpool_close(zphdl);
124
libzfs_fini(hdl);
125
return (rv);
126
}
127
128
/*
129
* free nvlist we got via lzbe_nvlist_get()
130
*/
131
void
132
lzbe_nvlist_free(void *ptr)
133
{
134
nvlist_free(ptr);
135
}
136
137
static const char *typenames[] = {
138
"DATA_TYPE_UNKNOWN",
139
"DATA_TYPE_BOOLEAN",
140
"DATA_TYPE_BYTE",
141
"DATA_TYPE_INT16",
142
"DATA_TYPE_UINT16",
143
"DATA_TYPE_INT32",
144
"DATA_TYPE_UINT32",
145
"DATA_TYPE_INT64",
146
"DATA_TYPE_UINT64",
147
"DATA_TYPE_STRING",
148
"DATA_TYPE_BYTE_ARRAY",
149
"DATA_TYPE_INT16_ARRAY",
150
"DATA_TYPE_UINT16_ARRAY",
151
"DATA_TYPE_INT32_ARRAY",
152
"DATA_TYPE_UINT32_ARRAY",
153
"DATA_TYPE_INT64_ARRAY",
154
"DATA_TYPE_UINT64_ARRAY",
155
"DATA_TYPE_STRING_ARRAY",
156
"DATA_TYPE_HRTIME",
157
"DATA_TYPE_NVLIST",
158
"DATA_TYPE_NVLIST_ARRAY",
159
"DATA_TYPE_BOOLEAN_VALUE",
160
"DATA_TYPE_INT8",
161
"DATA_TYPE_UINT8",
162
"DATA_TYPE_BOOLEAN_ARRAY",
163
"DATA_TYPE_INT8_ARRAY",
164
"DATA_TYPE_UINT8_ARRAY"
165
};
166
167
static int
168
nvpair_type_from_name(const char *name)
169
{
170
unsigned i;
171
172
for (i = 0; i < ARRAY_SIZE(typenames); i++) {
173
if (strcmp(name, typenames[i]) == 0)
174
return (i);
175
}
176
return (0);
177
}
178
179
/*
180
* Add pair defined by key, type and value into nvlist.
181
*/
182
int
183
lzbe_add_pair(void *ptr, const char *key, const char *type, void *value,
184
size_t size)
185
{
186
nvlist_t *nv = ptr;
187
data_type_t dt;
188
int rv = 0;
189
190
if (ptr == NULL || key == NULL || value == NULL)
191
return (rv);
192
193
if (type == NULL)
194
type = "DATA_TYPE_STRING";
195
dt = nvpair_type_from_name(type);
196
if (dt == DATA_TYPE_UNKNOWN)
197
return (EINVAL);
198
199
switch (dt) {
200
case DATA_TYPE_BYTE:
201
if (size != sizeof (uint8_t)) {
202
rv = EINVAL;
203
break;
204
}
205
rv = nvlist_add_byte(nv, key, *(uint8_t *)value);
206
break;
207
208
case DATA_TYPE_INT16:
209
if (size != sizeof (int16_t)) {
210
rv = EINVAL;
211
break;
212
}
213
rv = nvlist_add_int16(nv, key, *(int16_t *)value);
214
break;
215
216
case DATA_TYPE_UINT16:
217
if (size != sizeof (uint16_t)) {
218
rv = EINVAL;
219
break;
220
}
221
rv = nvlist_add_uint16(nv, key, *(uint16_t *)value);
222
break;
223
224
case DATA_TYPE_INT32:
225
if (size != sizeof (int32_t)) {
226
rv = EINVAL;
227
break;
228
}
229
rv = nvlist_add_int32(nv, key, *(int32_t *)value);
230
break;
231
232
case DATA_TYPE_UINT32:
233
if (size != sizeof (uint32_t)) {
234
rv = EINVAL;
235
break;
236
}
237
rv = nvlist_add_uint32(nv, key, *(uint32_t *)value);
238
break;
239
240
case DATA_TYPE_INT64:
241
if (size != sizeof (int64_t)) {
242
rv = EINVAL;
243
break;
244
}
245
rv = nvlist_add_int64(nv, key, *(int64_t *)value);
246
break;
247
248
case DATA_TYPE_UINT64:
249
if (size != sizeof (uint64_t)) {
250
rv = EINVAL;
251
break;
252
}
253
rv = nvlist_add_uint64(nv, key, *(uint64_t *)value);
254
break;
255
256
case DATA_TYPE_STRING:
257
rv = nvlist_add_string(nv, key, value);
258
break;
259
260
case DATA_TYPE_BYTE_ARRAY:
261
rv = nvlist_add_byte_array(nv, key, value, size);
262
break;
263
264
case DATA_TYPE_INT16_ARRAY:
265
rv = nvlist_add_int16_array(nv, key, value, size);
266
break;
267
268
case DATA_TYPE_UINT16_ARRAY:
269
rv = nvlist_add_uint16_array(nv, key, value, size);
270
break;
271
272
case DATA_TYPE_INT32_ARRAY:
273
rv = nvlist_add_int32_array(nv, key, value, size);
274
break;
275
276
case DATA_TYPE_UINT32_ARRAY:
277
rv = nvlist_add_uint32_array(nv, key, value, size);
278
break;
279
280
case DATA_TYPE_INT64_ARRAY:
281
rv = nvlist_add_int64_array(nv, key, value, size);
282
break;
283
284
case DATA_TYPE_UINT64_ARRAY:
285
rv = nvlist_add_uint64_array(nv, key, value, size);
286
break;
287
288
case DATA_TYPE_STRING_ARRAY:
289
rv = nvlist_add_string_array(nv, key, value, size);
290
break;
291
292
case DATA_TYPE_NVLIST:
293
rv = nvlist_add_nvlist(nv, key, (nvlist_t *)value);
294
break;
295
296
case DATA_TYPE_NVLIST_ARRAY:
297
rv = nvlist_add_nvlist_array(nv, key, (const nvlist_t **)value,
298
size);
299
break;
300
301
case DATA_TYPE_BOOLEAN_VALUE:
302
if (size != sizeof (boolean_t)) {
303
rv = EINVAL;
304
break;
305
}
306
rv = nvlist_add_boolean_value(nv, key, *(boolean_t *)value);
307
break;
308
309
case DATA_TYPE_INT8:
310
if (size != sizeof (int8_t)) {
311
rv = EINVAL;
312
break;
313
}
314
rv = nvlist_add_int8(nv, key, *(int8_t *)value);
315
break;
316
317
case DATA_TYPE_UINT8:
318
if (size != sizeof (uint8_t)) {
319
rv = EINVAL;
320
break;
321
}
322
rv = nvlist_add_uint8(nv, key, *(uint8_t *)value);
323
break;
324
325
case DATA_TYPE_BOOLEAN_ARRAY:
326
rv = nvlist_add_boolean_array(nv, key, value, size);
327
break;
328
329
case DATA_TYPE_INT8_ARRAY:
330
rv = nvlist_add_int8_array(nv, key, value, size);
331
break;
332
333
case DATA_TYPE_UINT8_ARRAY:
334
rv = nvlist_add_uint8_array(nv, key, value, size);
335
break;
336
337
default:
338
return (ENOTSUP);
339
}
340
341
return (rv);
342
}
343
344
int
345
lzbe_remove_pair(void *ptr, const char *key)
346
{
347
348
return (nvlist_remove_all(ptr, key));
349
}
350
351