Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/lib/libzfsbootenv/lzbe_device.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
* Store device name to zpool label bootenv area.
25
* This call will set bootenv version to VB_NVLIST, if bootenv currently
26
* does contain other version, then old data will be replaced.
27
*/
28
int
29
lzbe_set_boot_device(const char *pool, lzbe_flags_t flag, const char *device)
30
{
31
libzfs_handle_t *hdl;
32
zpool_handle_t *zphdl;
33
nvlist_t *nv;
34
char *descriptor;
35
uint64_t version;
36
int rv = -1;
37
38
if (pool == NULL || *pool == '\0')
39
return (rv);
40
41
if ((hdl = libzfs_init()) == NULL)
42
return (rv);
43
44
zphdl = zpool_open(hdl, pool);
45
if (zphdl == NULL) {
46
libzfs_fini(hdl);
47
return (rv);
48
}
49
50
switch (flag) {
51
case lzbe_add:
52
rv = zpool_get_bootenv(zphdl, &nv);
53
if (rv == 0) {
54
/*
55
* We got the nvlist, check for version.
56
* if version is missing or is not VB_NVLIST,
57
* create new list.
58
*/
59
rv = nvlist_lookup_uint64(nv, BOOTENV_VERSION,
60
&version);
61
if (rv == 0 && version == VB_NVLIST)
62
break;
63
64
/* Drop this nvlist */
65
fnvlist_free(nv);
66
}
67
zfs_fallthrough;
68
case lzbe_replace:
69
nv = fnvlist_alloc();
70
break;
71
default:
72
return (rv);
73
}
74
75
/* version is mandatory */
76
fnvlist_add_uint64(nv, BOOTENV_VERSION, VB_NVLIST);
77
78
rv = 0;
79
/*
80
* If device name is empty, remove boot device configuration.
81
*/
82
if ((device == NULL || *device == '\0')) {
83
if (nvlist_exists(nv, OS_BOOTONCE))
84
fnvlist_remove(nv, OS_BOOTONCE);
85
} else {
86
/*
87
* Use device name directly if it does start with
88
* prefix "zfs:". Otherwise, add prefix and suffix.
89
*/
90
if (strncmp(device, "zfs:", 4) == 0) {
91
fnvlist_add_string(nv, OS_BOOTONCE, device);
92
} else {
93
if (asprintf(&descriptor, "zfs:%s:", device) > 0) {
94
fnvlist_add_string(nv, OS_BOOTONCE, descriptor);
95
free(descriptor);
96
} else
97
rv = ENOMEM;
98
}
99
}
100
if (rv == 0)
101
rv = zpool_set_bootenv(zphdl, nv);
102
if (rv != 0)
103
fprintf(stderr, "%s\n", libzfs_error_description(hdl));
104
105
fnvlist_free(nv);
106
zpool_close(zphdl);
107
libzfs_fini(hdl);
108
return (rv);
109
}
110
111
/*
112
* Return boot device name from bootenv, if set.
113
*/
114
int
115
lzbe_get_boot_device(const char *pool, char **device)
116
{
117
libzfs_handle_t *hdl;
118
zpool_handle_t *zphdl;
119
nvlist_t *nv;
120
const char *val;
121
int rv = -1;
122
123
if (pool == NULL || *pool == '\0' || device == NULL)
124
return (rv);
125
126
if ((hdl = libzfs_init()) == NULL)
127
return (rv);
128
129
zphdl = zpool_open(hdl, pool);
130
if (zphdl == NULL) {
131
libzfs_fini(hdl);
132
return (rv);
133
}
134
135
rv = zpool_get_bootenv(zphdl, &nv);
136
if (rv == 0) {
137
rv = nvlist_lookup_string(nv, OS_BOOTONCE, &val);
138
if (rv == 0) {
139
/*
140
* zfs device descriptor is in form of "zfs:dataset:",
141
* we only do need dataset name.
142
*/
143
if (strncmp(val, "zfs:", 4) == 0) {
144
char *tmp = strdup(val + 4);
145
if (tmp != NULL) {
146
size_t len = strlen(tmp);
147
148
if (tmp[len - 1] == ':')
149
tmp[len - 1] = '\0';
150
*device = tmp;
151
} else {
152
rv = ENOMEM;
153
}
154
} else {
155
rv = EINVAL;
156
}
157
}
158
nvlist_free(nv);
159
}
160
161
zpool_close(zphdl);
162
libzfs_fini(hdl);
163
return (rv);
164
}
165
166