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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2011 by Delphix. All rights reserved.
26 * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
27 */
28
29
30 #include <sys/zfs_context.h>
31 #include <sys/fm/fs/zfs.h>
32 #include <sys/spa_impl.h>
33 #include <sys/zio.h>
34 #include <sys/zio_checksum.h>
35 #include <sys/dmu.h>
36 #include <sys/dmu_tx.h>
37 #include <sys/zap.h>
38 #include <sys/zil.h>
39 #include <sys/ddt.h>
40 #include <sys/vdev_impl.h>
41 #include <sys/vdev_os.h>
42 #include <sys/vdev_removal.h>
43 #include <sys/vdev_indirect_mapping.h>
44 #include <sys/vdev_indirect_births.h>
45 #include <sys/metaslab.h>
46 #include <sys/metaslab_impl.h>
47 #include <sys/uberblock_impl.h>
48 #include <sys/txg.h>
49 #include <sys/avl.h>
50 #include <sys/bpobj.h>
51 #include <sys/dmu_traverse.h>
52 #include <sys/dmu_objset.h>
53 #include <sys/unique.h>
54 #include <sys/dsl_pool.h>
55 #include <sys/dsl_dataset.h>
56 #include <sys/dsl_dir.h>
57 #include <sys/dsl_prop.h>
58 #include <sys/dsl_synctask.h>
59 #include <sys/fs/zfs.h>
60 #include <sys/arc.h>
61 #include <sys/callb.h>
62 #include <sys/zfs_ioctl.h>
63 #include <sys/dsl_scan.h>
64 #include <sys/dmu_send.h>
65 #include <sys/dsl_destroy.h>
66 #include <sys/dsl_userhold.h>
67 #include <sys/zfeature.h>
68 #include <sys/zvol.h>
69 #include <sys/abd.h>
70 #include <sys/callb.h>
71 #include <sys/zone.h>
72
73 #include "zfs_prop.h"
74 #include "zfs_comutil.h"
75
76 static nvlist_t *
spa_generate_rootconf(const char * name)77 spa_generate_rootconf(const char *name)
78 {
79 nvlist_t **configs, **tops;
80 nvlist_t *config;
81 nvlist_t *best_cfg, *nvtop, *nvroot;
82 uint64_t *holes;
83 uint64_t best_txg;
84 uint64_t nchildren;
85 uint64_t pgid;
86 uint64_t count;
87 uint64_t i;
88 uint_t nholes;
89
90 if (vdev_geom_read_pool_label(name, &configs, &count) != 0)
91 return (NULL);
92
93 ASSERT3U(count, !=, 0);
94 best_txg = 0;
95 for (i = 0; i < count; i++) {
96 uint64_t txg;
97
98 if (configs[i] == NULL)
99 continue;
100 txg = fnvlist_lookup_uint64(configs[i], ZPOOL_CONFIG_POOL_TXG);
101 if (txg > best_txg) {
102 best_txg = txg;
103 best_cfg = configs[i];
104 }
105 }
106
107 nchildren = 1;
108 nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN, &nchildren);
109 holes = NULL;
110 nvlist_lookup_uint64_array(best_cfg, ZPOOL_CONFIG_HOLE_ARRAY,
111 &holes, &nholes);
112
113 tops = kmem_zalloc(nchildren * sizeof (void *), KM_SLEEP);
114 for (i = 0; i < nchildren; i++) {
115 if (i >= count)
116 break;
117 if (configs[i] == NULL)
118 continue;
119 nvtop = fnvlist_lookup_nvlist(configs[i],
120 ZPOOL_CONFIG_VDEV_TREE);
121 tops[i] = fnvlist_dup(nvtop);
122 }
123 for (i = 0; holes != NULL && i < nholes; i++) {
124 if (i >= nchildren)
125 continue;
126 if (tops[holes[i]] != NULL)
127 continue;
128 tops[holes[i]] = fnvlist_alloc();
129 fnvlist_add_string(tops[holes[i]], ZPOOL_CONFIG_TYPE,
130 VDEV_TYPE_HOLE);
131 fnvlist_add_uint64(tops[holes[i]], ZPOOL_CONFIG_ID, holes[i]);
132 fnvlist_add_uint64(tops[holes[i]], ZPOOL_CONFIG_GUID, 0);
133 }
134 for (i = 0; i < nchildren; i++) {
135 if (tops[i] != NULL)
136 continue;
137 tops[i] = fnvlist_alloc();
138 fnvlist_add_string(tops[i], ZPOOL_CONFIG_TYPE,
139 VDEV_TYPE_MISSING);
140 fnvlist_add_uint64(tops[i], ZPOOL_CONFIG_ID, i);
141 fnvlist_add_uint64(tops[i], ZPOOL_CONFIG_GUID, 0);
142 }
143
144 /*
145 * Create pool config based on the best vdev config.
146 */
147 config = fnvlist_dup(best_cfg);
148
149 /*
150 * Put this pool's top-level vdevs into a root vdev.
151 */
152 pgid = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID);
153 nvroot = fnvlist_alloc();
154 fnvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT);
155 fnvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL);
156 fnvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, pgid);
157 fnvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
158 (const nvlist_t * const *)tops, nchildren);
159
160 /*
161 * Replace the existing vdev_tree with the new root vdev in
162 * this pool's configuration (remove the old, add the new).
163 */
164 fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot);
165
166 /*
167 * Drop vdev config elements that should not be present at pool level.
168 */
169 fnvlist_remove(config, ZPOOL_CONFIG_GUID);
170 fnvlist_remove(config, ZPOOL_CONFIG_TOP_GUID);
171
172 for (i = 0; i < count; i++)
173 fnvlist_free(configs[i]);
174 kmem_free(configs, count * sizeof (void *));
175 for (i = 0; i < nchildren; i++)
176 fnvlist_free(tops[i]);
177 kmem_free(tops, nchildren * sizeof (void *));
178 fnvlist_free(nvroot);
179 return (config);
180 }
181
182 int
spa_import_rootpool(const char * name,bool checkpointrewind)183 spa_import_rootpool(const char *name, bool checkpointrewind)
184 {
185 spa_t *spa;
186 vdev_t *rvd;
187 nvlist_t *config, *nvtop;
188 const char *pname;
189 int error;
190
191 /*
192 * Read the label from the boot device and generate a configuration.
193 */
194 config = spa_generate_rootconf(name);
195
196 mutex_enter(&spa_namespace_lock);
197 if (config != NULL) {
198 pname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
199 VERIFY0(strcmp(name, pname));
200
201 if ((spa = spa_lookup(pname)) != NULL) {
202 /*
203 * The pool could already be imported,
204 * e.g., after reboot -r.
205 */
206 if (spa->spa_state == POOL_STATE_ACTIVE) {
207 mutex_exit(&spa_namespace_lock);
208 fnvlist_free(config);
209 return (0);
210 }
211
212 /*
213 * Remove the existing root pool from the namespace so
214 * that we can replace it with the correct config
215 * we just read in.
216 */
217 spa_remove(spa);
218 }
219 spa = spa_add(pname, config, NULL);
220
221 /*
222 * Set spa_ubsync.ub_version as it can be used in vdev_alloc()
223 * via spa_version().
224 */
225 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
226 &spa->spa_ubsync.ub_version) != 0)
227 spa->spa_ubsync.ub_version = SPA_VERSION_INITIAL;
228 } else if ((spa = spa_lookup(name)) == NULL) {
229 mutex_exit(&spa_namespace_lock);
230 fnvlist_free(config);
231 cmn_err(CE_NOTE, "Cannot find the pool label for '%s'",
232 name);
233 return (EIO);
234 } else {
235 config = fnvlist_dup(spa->spa_config);
236 }
237 spa->spa_is_root = B_TRUE;
238 spa->spa_import_flags = ZFS_IMPORT_VERBATIM;
239 if (checkpointrewind) {
240 spa->spa_import_flags |= ZFS_IMPORT_CHECKPOINT;
241 }
242
243 /*
244 * Build up a vdev tree based on the boot device's label config.
245 */
246 nvtop = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
247 spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
248 error = spa_config_parse(spa, &rvd, nvtop, NULL, 0,
249 VDEV_ALLOC_ROOTPOOL);
250 spa_config_exit(spa, SCL_ALL, FTAG);
251 if (error) {
252 mutex_exit(&spa_namespace_lock);
253 fnvlist_free(config);
254 cmn_err(CE_NOTE, "Can not parse the config for pool '%s'",
255 name);
256 return (error);
257 }
258
259 spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
260 vdev_free(rvd);
261 spa_config_exit(spa, SCL_ALL, FTAG);
262 mutex_exit(&spa_namespace_lock);
263
264 fnvlist_free(config);
265 return (0);
266 }
267
268 const char *
spa_history_zone(void)269 spa_history_zone(void)
270 {
271 return ("freebsd");
272 }
273
274 void
spa_import_os(spa_t * spa)275 spa_import_os(spa_t *spa)
276 {
277 (void) spa;
278 }
279
280 void
spa_export_os(spa_t * spa)281 spa_export_os(spa_t *spa)
282 {
283 (void) spa;
284 }
285
286 void
spa_activate_os(spa_t * spa)287 spa_activate_os(spa_t *spa)
288 {
289 (void) spa;
290 }
291
292 void
spa_deactivate_os(spa_t * spa)293 spa_deactivate_os(spa_t *spa)
294 {
295 (void) spa;
296 }
297