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 <mm@FreeBSD.org>. 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 * 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 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 * 278 spa_history_zone(void) 279 { 280 return ("freebsd"); 281 } 282