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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
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 <mm@FreeBSD.org>. All rights reserved.
29 #include <sys/zfs_context.h>
30 #include <sys/fm/fs/zfs.h>
31 #include <sys/spa_impl.h>
33 #include <sys/zio_checksum.h>
35 #include <sys/dmu_tx.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>
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>
60 #include <sys/callb.h>
61 #include <sys/zfs_ioctl.h>
62 #include <sys/dsl_scan.h>
63 #include <sys/dmu_send.h>
64 #include <sys/dsl_destroy.h>
65 #include <sys/dsl_userhold.h>
66 #include <sys/zfeature.h>
69 #include <sys/callb.h>
73 #include "zfs_comutil.h"
76 spa_generate_rootconf(const char *name
)
78 nvlist_t
**configs
, **tops
;
80 nvlist_t
*best_cfg
, *nvtop
, *nvroot
;
89 if (vdev_geom_read_pool_label(name
, &configs
, &count
) != 0)
92 ASSERT3U(count
, !=, 0);
94 for (i
= 0; i
< count
; i
++) {
97 if (configs
[i
] == NULL
)
99 txg
= fnvlist_lookup_uint64(configs
[i
], ZPOOL_CONFIG_POOL_TXG
);
100 if (txg
> best_txg
) {
102 best_cfg
= configs
[i
];
107 nvlist_lookup_uint64(best_cfg
, ZPOOL_CONFIG_VDEV_CHILDREN
, &nchildren
);
109 nvlist_lookup_uint64_array(best_cfg
, ZPOOL_CONFIG_HOLE_ARRAY
,
112 tops
= kmem_zalloc(nchildren
* sizeof (void *), KM_SLEEP
);
113 for (i
= 0; i
< nchildren
; i
++) {
116 if (configs
[i
] == NULL
)
118 nvtop
= fnvlist_lookup_nvlist(configs
[i
],
119 ZPOOL_CONFIG_VDEV_TREE
);
120 tops
[i
] = fnvlist_dup(nvtop
);
122 for (i
= 0; holes
!= NULL
&& i
< nholes
; i
++) {
125 if (tops
[holes
[i
]] != NULL
)
127 tops
[holes
[i
]] = fnvlist_alloc();
128 fnvlist_add_string(tops
[holes
[i
]], ZPOOL_CONFIG_TYPE
,
130 fnvlist_add_uint64(tops
[holes
[i
]], ZPOOL_CONFIG_ID
, holes
[i
]);
131 fnvlist_add_uint64(tops
[holes
[i
]], ZPOOL_CONFIG_GUID
, 0);
133 for (i
= 0; i
< nchildren
; i
++) {
136 tops
[i
] = fnvlist_alloc();
137 fnvlist_add_string(tops
[i
], ZPOOL_CONFIG_TYPE
,
139 fnvlist_add_uint64(tops
[i
], ZPOOL_CONFIG_ID
, i
);
140 fnvlist_add_uint64(tops
[i
], ZPOOL_CONFIG_GUID
, 0);
144 * Create pool config based on the best vdev config.
146 config
= fnvlist_dup(best_cfg
);
149 * Put this pool's top-level vdevs into a root vdev.
151 pgid
= fnvlist_lookup_uint64(config
, ZPOOL_CONFIG_POOL_GUID
);
152 nvroot
= fnvlist_alloc();
153 fnvlist_add_string(nvroot
, ZPOOL_CONFIG_TYPE
, VDEV_TYPE_ROOT
);
154 fnvlist_add_uint64(nvroot
, ZPOOL_CONFIG_ID
, 0ULL);
155 fnvlist_add_uint64(nvroot
, ZPOOL_CONFIG_GUID
, pgid
);
156 fnvlist_add_nvlist_array(nvroot
, ZPOOL_CONFIG_CHILDREN
,
157 (const nvlist_t
* const *)tops
, nchildren
);
160 * Replace the existing vdev_tree with the new root vdev in
161 * this pool's configuration (remove the old, add the new).
163 fnvlist_add_nvlist(config
, ZPOOL_CONFIG_VDEV_TREE
, nvroot
);
166 * Drop vdev config elements that should not be present at pool level.
168 fnvlist_remove(config
, ZPOOL_CONFIG_GUID
);
169 fnvlist_remove(config
, ZPOOL_CONFIG_TOP_GUID
);
171 for (i
= 0; i
< count
; i
++)
172 fnvlist_free(configs
[i
]);
173 kmem_free(configs
, count
* sizeof (void *));
174 for (i
= 0; i
< nchildren
; i
++)
175 fnvlist_free(tops
[i
]);
176 kmem_free(tops
, nchildren
* sizeof (void *));
177 fnvlist_free(nvroot
);
182 spa_import_rootpool(const char *name
, bool checkpointrewind
)
186 nvlist_t
*config
, *nvtop
;
191 * Read the label from the boot device and generate a configuration.
193 config
= spa_generate_rootconf(name
);
195 mutex_enter(&spa_namespace_lock
);
196 if (config
!= NULL
) {
197 pname
= fnvlist_lookup_string(config
, ZPOOL_CONFIG_POOL_NAME
);
198 VERIFY0(strcmp(name
, pname
));
200 if ((spa
= spa_lookup(pname
)) != NULL
) {
202 * The pool could already be imported,
203 * e.g., after reboot -r.
205 if (spa
->spa_state
== POOL_STATE_ACTIVE
) {
206 mutex_exit(&spa_namespace_lock
);
207 fnvlist_free(config
);
212 * Remove the existing root pool from the namespace so
213 * that we can replace it with the correct config
218 spa
= spa_add(pname
, config
, NULL
);
221 * Set spa_ubsync.ub_version as it can be used in vdev_alloc()
224 if (nvlist_lookup_uint64(config
, ZPOOL_CONFIG_VERSION
,
225 &spa
->spa_ubsync
.ub_version
) != 0)
226 spa
->spa_ubsync
.ub_version
= SPA_VERSION_INITIAL
;
227 } else if ((spa
= spa_lookup(name
)) == NULL
) {
228 mutex_exit(&spa_namespace_lock
);
229 fnvlist_free(config
);
230 cmn_err(CE_NOTE
, "Cannot find the pool label for '%s'",
234 config
= fnvlist_dup(spa
->spa_config
);
236 spa
->spa_is_root
= B_TRUE
;
237 spa
->spa_import_flags
= ZFS_IMPORT_VERBATIM
;
238 if (checkpointrewind
) {
239 spa
->spa_import_flags
|= ZFS_IMPORT_CHECKPOINT
;
243 * Build up a vdev tree based on the boot device's label config.
245 nvtop
= fnvlist_lookup_nvlist(config
, ZPOOL_CONFIG_VDEV_TREE
);
246 spa_config_enter(spa
, SCL_ALL
, FTAG
, RW_WRITER
);
247 error
= spa_config_parse(spa
, &rvd
, nvtop
, NULL
, 0,
248 VDEV_ALLOC_ROOTPOOL
);
249 spa_config_exit(spa
, SCL_ALL
, FTAG
);
251 mutex_exit(&spa_namespace_lock
);
252 fnvlist_free(config
);
253 cmn_err(CE_NOTE
, "Can not parse the config for pool '%s'",
258 spa_config_enter(spa
, SCL_ALL
, FTAG
, RW_WRITER
);
260 spa_config_exit(spa
, SCL_ALL
, FTAG
);
261 mutex_exit(&spa_namespace_lock
);
263 fnvlist_free(config
);
268 spa_history_zone(void)
274 spa_import_os(spa_t
*spa
)
280 spa_export_os(spa_t
*spa
)
286 spa_activate_os(spa_t
*spa
)
292 spa_deactivate_os(spa_t
*spa
)