1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011 by Delphix. All rights reserved.
25 * Copyright (c) 2013 Martin Matuska <[email protected]>. All rights reserved.
26 */
27
28
29 #include <sys/zfs_context.h>
30 #include <sys/fm/fs/zfs.h>
31 #include <sys/spa_impl.h>
32 #include <sys/zio.h>
33 #include <sys/zio_checksum.h>
34 #include <sys/dmu.h>
35 #include <sys/dmu_tx.h>
36 #include <sys/zap.h>
37 #include <sys/zil.h>
38 #include <sys/ddt.h>
39 #include <sys/vdev_impl.h>
40 #include <sys/vdev_os.h>
41 #include <sys/vdev_removal.h>
42 #include <sys/vdev_indirect_mapping.h>
43 #include <sys/vdev_indirect_births.h>
44 #include <sys/metaslab.h>
45 #include <sys/metaslab_impl.h>
46 #include <sys/uberblock_impl.h>
47 #include <sys/txg.h>
48 #include <sys/avl.h>
49 #include <sys/bpobj.h>
50 #include <sys/dmu_traverse.h>
51 #include <sys/dmu_objset.h>
52 #include <sys/unique.h>
53 #include <sys/dsl_pool.h>
54 #include <sys/dsl_dataset.h>
55 #include <sys/dsl_dir.h>
56 #include <sys/dsl_prop.h>
57 #include <sys/dsl_synctask.h>
58 #include <sys/fs/zfs.h>
59 #include <sys/arc.h>
60 #include <sys/callb.h>
61 #include <sys/spa_boot.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 VERIFY(nvlist_lookup_uint64(configs[i], ZPOOL_CONFIG_POOL_TXG,
99 &txg) == 0);
100 if (txg > best_txg) {
101 best_txg = txg;
102 best_cfg = configs[i];
103 }
104 }
105
106 nchildren = 1;
107 nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN, &nchildren);
108 holes = NULL;
109 nvlist_lookup_uint64_array(best_cfg, ZPOOL_CONFIG_HOLE_ARRAY,
110 &holes, &nholes);
111
112 tops = kmem_zalloc(nchildren * sizeof (void *), KM_SLEEP);
113 for (i = 0; i < nchildren; i++) {
114 if (i >= count)
115 break;
116 if (configs[i] == NULL)
117 continue;
118 VERIFY(nvlist_lookup_nvlist(configs[i], ZPOOL_CONFIG_VDEV_TREE,
119 &nvtop) == 0);
120 nvlist_dup(nvtop, &tops[i], KM_SLEEP);
121 }
122 for (i = 0; holes != NULL && i < nholes; i++) {
123 if (i >= nchildren)
124 continue;
125 if (tops[holes[i]] != NULL)
126 continue;
127 nvlist_alloc(&tops[holes[i]], NV_UNIQUE_NAME, KM_SLEEP);
128 VERIFY(nvlist_add_string(tops[holes[i]], ZPOOL_CONFIG_TYPE,
129 VDEV_TYPE_HOLE) == 0);
130 VERIFY(nvlist_add_uint64(tops[holes[i]], ZPOOL_CONFIG_ID,
131 holes[i]) == 0);
132 VERIFY(nvlist_add_uint64(tops[holes[i]], ZPOOL_CONFIG_GUID,
133 0) == 0);
134 }
135 for (i = 0; i < nchildren; i++) {
136 if (tops[i] != NULL)
137 continue;
138 nvlist_alloc(&tops[i], NV_UNIQUE_NAME, KM_SLEEP);
139 VERIFY(nvlist_add_string(tops[i], ZPOOL_CONFIG_TYPE,
140 VDEV_TYPE_MISSING) == 0);
141 VERIFY(nvlist_add_uint64(tops[i], ZPOOL_CONFIG_ID,
142 i) == 0);
143 VERIFY(nvlist_add_uint64(tops[i], ZPOOL_CONFIG_GUID,
144 0) == 0);
145 }
146
147 /*
148 * Create pool config based on the best vdev config.
149 */
150 nvlist_dup(best_cfg, &config, KM_SLEEP);
151
152 /*
153 * Put this pool's top-level vdevs into a root vdev.
154 */
155 VERIFY(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
156 &pgid) == 0);
157 VERIFY(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, KM_SLEEP) == 0);
158 VERIFY(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
159 VDEV_TYPE_ROOT) == 0);
160 VERIFY(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) == 0);
161 VERIFY(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, pgid) == 0);
162 VERIFY(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
163 tops, nchildren) == 0);
164
165 /*
166 * Replace the existing vdev_tree with the new root vdev in
167 * this pool's configuration (remove the old, add the new).
168 */
169 VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot) == 0);
170
171 /*
172 * Drop vdev config elements that should not be present at pool level.
173 */
174 nvlist_remove(config, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64);
175 nvlist_remove(config, ZPOOL_CONFIG_TOP_GUID, DATA_TYPE_UINT64);
176
177 for (i = 0; i < count; i++)
178 nvlist_free(configs[i]);
179 kmem_free(configs, count * sizeof (void *));
180 for (i = 0; i < nchildren; i++)
181 nvlist_free(tops[i]);
182 kmem_free(tops, nchildren * sizeof (void *));
183 nvlist_free(nvroot);
184 return (config);
185 }
186
187 int
spa_import_rootpool(const char * name,bool checkpointrewind)188 spa_import_rootpool(const char *name, bool checkpointrewind)
189 {
190 spa_t *spa;
191 vdev_t *rvd;
192 nvlist_t *config, *nvtop;
193 uint64_t txg;
194 char *pname;
195 int error;
196
197 /*
198 * Read the label from the boot device and generate a configuration.
199 */
200 config = spa_generate_rootconf(name);
201
202 mutex_enter(&spa_namespace_lock);
203 if (config != NULL) {
204 VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
205 &pname) == 0 && strcmp(name, pname) == 0);
206 VERIFY(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, &txg)
207 == 0);
208
209 if ((spa = spa_lookup(pname)) != NULL) {
210 /*
211 * The pool could already be imported,
212 * e.g., after reboot -r.
213 */
214 if (spa->spa_state == POOL_STATE_ACTIVE) {
215 mutex_exit(&spa_namespace_lock);
216 nvlist_free(config);
217 return (0);
218 }
219
220 /*
221 * Remove the existing root pool from the namespace so
222 * that we can replace it with the correct config
223 * we just read in.
224 */
225 spa_remove(spa);
226 }
227 spa = spa_add(pname, config, NULL);
228
229 /*
230 * Set spa_ubsync.ub_version as it can be used in vdev_alloc()
231 * via spa_version().
232 */
233 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
234 &spa->spa_ubsync.ub_version) != 0)
235 spa->spa_ubsync.ub_version = SPA_VERSION_INITIAL;
236 } else if ((spa = spa_lookup(name)) == NULL) {
237 mutex_exit(&spa_namespace_lock);
238 nvlist_free(config);
239 cmn_err(CE_NOTE, "Cannot find the pool label for '%s'",
240 name);
241 return (EIO);
242 } else {
243 VERIFY(nvlist_dup(spa->spa_config, &config, KM_SLEEP) == 0);
244 }
245 spa->spa_is_root = B_TRUE;
246 spa->spa_import_flags = ZFS_IMPORT_VERBATIM;
247 if (checkpointrewind) {
248 spa->spa_import_flags |= ZFS_IMPORT_CHECKPOINT;
249 }
250
251 /*
252 * Build up a vdev tree based on the boot device's label config.
253 */
254 VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
255 &nvtop) == 0);
256 spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
257 error = spa_config_parse(spa, &rvd, nvtop, NULL, 0,
258 VDEV_ALLOC_ROOTPOOL);
259 spa_config_exit(spa, SCL_ALL, FTAG);
260 if (error) {
261 mutex_exit(&spa_namespace_lock);
262 nvlist_free(config);
263 cmn_err(CE_NOTE, "Can not parse the config for pool '%s'",
264 pname);
265 return (error);
266 }
267
268 spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
269 vdev_free(rvd);
270 spa_config_exit(spa, SCL_ALL, FTAG);
271 mutex_exit(&spa_namespace_lock);
272
273 nvlist_free(config);
274 return (0);
275 }
276
277 const char *
spa_history_zone(void)278 spa_history_zone(void)
279 {
280 return ("freebsd");
281 }
282