1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5fa9e4066Sahrens * Common Development and Distribution License, Version 1.0 only 6fa9e4066Sahrens * (the "License"). You may not use this file except in compliance 7fa9e4066Sahrens * with the License. 8fa9e4066Sahrens * 9fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 11fa9e4066Sahrens * See the License for the specific language governing permissions 12fa9e4066Sahrens * and limitations under the License. 13fa9e4066Sahrens * 14fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 17fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19fa9e4066Sahrens * 20fa9e4066Sahrens * CDDL HEADER END 21fa9e4066Sahrens */ 22fa9e4066Sahrens /* 23fa9e4066Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24fa9e4066Sahrens * Use is subject to license terms. 25fa9e4066Sahrens */ 26fa9e4066Sahrens 27fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28fa9e4066Sahrens 29fa9e4066Sahrens /* 30fa9e4066Sahrens * Pool import support functions. 31fa9e4066Sahrens * 32fa9e4066Sahrens * To import a pool, we rely on reading the configuration information from the 33fa9e4066Sahrens * ZFS label of each device. If we successfully read the label, then we 34fa9e4066Sahrens * organize the configuration information in the following hierarchy: 35fa9e4066Sahrens * 36fa9e4066Sahrens * pool guid -> toplevel vdev guid -> label txg 37fa9e4066Sahrens * 38fa9e4066Sahrens * Duplicate entries matching this same tuple will be discarded. Once we have 39fa9e4066Sahrens * examined every device, we pick the best label txg config for each toplevel 40fa9e4066Sahrens * vdev. We then arrange these toplevel vdevs into a complete pool config, and 41fa9e4066Sahrens * update any paths that have changed. Finally, we attempt to import the pool 42fa9e4066Sahrens * using our derived config, and record the results. 43fa9e4066Sahrens */ 44fa9e4066Sahrens 45fa9e4066Sahrens #include <devid.h> 46fa9e4066Sahrens #include <dirent.h> 47fa9e4066Sahrens #include <errno.h> 48fa9e4066Sahrens #include <libintl.h> 49fa9e4066Sahrens #include <stdlib.h> 50fa9e4066Sahrens #include <string.h> 51fa9e4066Sahrens #include <sys/stat.h> 52fa9e4066Sahrens #include <unistd.h> 53fa9e4066Sahrens #include <fcntl.h> 54fa9e4066Sahrens 55fa9e4066Sahrens #include <sys/vdev_impl.h> 56fa9e4066Sahrens 57fa9e4066Sahrens #include "libzfs.h" 58fa9e4066Sahrens #include "libzfs_impl.h" 59fa9e4066Sahrens 60fa9e4066Sahrens /* 61fa9e4066Sahrens * Intermediate structures used to gather configuration information. 62fa9e4066Sahrens */ 63fa9e4066Sahrens typedef struct config_entry { 64fa9e4066Sahrens uint64_t ce_txg; 65fa9e4066Sahrens nvlist_t *ce_config; 66fa9e4066Sahrens struct config_entry *ce_next; 67fa9e4066Sahrens } config_entry_t; 68fa9e4066Sahrens 69fa9e4066Sahrens typedef struct vdev_entry { 70fa9e4066Sahrens uint64_t ve_guid; 71fa9e4066Sahrens config_entry_t *ve_configs; 72fa9e4066Sahrens struct vdev_entry *ve_next; 73fa9e4066Sahrens } vdev_entry_t; 74fa9e4066Sahrens 75fa9e4066Sahrens typedef struct pool_entry { 76fa9e4066Sahrens uint64_t pe_guid; 77fa9e4066Sahrens vdev_entry_t *pe_vdevs; 78fa9e4066Sahrens struct pool_entry *pe_next; 79fa9e4066Sahrens } pool_entry_t; 80fa9e4066Sahrens 81fa9e4066Sahrens typedef struct name_entry { 82fa9e4066Sahrens const char *ne_name; 83fa9e4066Sahrens uint64_t ne_guid; 84fa9e4066Sahrens struct name_entry *ne_next; 85fa9e4066Sahrens } name_entry_t; 86fa9e4066Sahrens 87fa9e4066Sahrens typedef struct pool_list { 88fa9e4066Sahrens pool_entry_t *pools; 89fa9e4066Sahrens name_entry_t *names; 90fa9e4066Sahrens } pool_list_t; 91fa9e4066Sahrens 92fa9e4066Sahrens static char * 93fa9e4066Sahrens get_devid(const char *path) 94fa9e4066Sahrens { 95fa9e4066Sahrens int fd; 96fa9e4066Sahrens ddi_devid_t devid; 97fa9e4066Sahrens char *minor, *ret; 98fa9e4066Sahrens 99fa9e4066Sahrens if ((fd = open(path, O_RDONLY)) < 0) 100fa9e4066Sahrens return (NULL); 101fa9e4066Sahrens 102fa9e4066Sahrens minor = NULL; 103fa9e4066Sahrens ret = NULL; 104fa9e4066Sahrens if (devid_get(fd, &devid) == 0) { 105fa9e4066Sahrens if (devid_get_minor_name(fd, &minor) == 0) 106fa9e4066Sahrens ret = devid_str_encode(devid, minor); 107fa9e4066Sahrens if (minor != NULL) 108fa9e4066Sahrens devid_str_free(minor); 109fa9e4066Sahrens devid_free(devid); 110fa9e4066Sahrens } 111fa9e4066Sahrens 112fa9e4066Sahrens return (ret); 113fa9e4066Sahrens } 114fa9e4066Sahrens 115fa9e4066Sahrens 116fa9e4066Sahrens /* 117fa9e4066Sahrens * Go through and fix up any path and/or devid information for the given vdev 118fa9e4066Sahrens * configuration. 119fa9e4066Sahrens */ 120fa9e4066Sahrens static void 121fa9e4066Sahrens fix_paths(nvlist_t *nv, name_entry_t *names) 122fa9e4066Sahrens { 123fa9e4066Sahrens nvlist_t **child; 124fa9e4066Sahrens uint_t c, children; 125fa9e4066Sahrens uint64_t guid; 126fa9e4066Sahrens name_entry_t *ne; 127fa9e4066Sahrens char *devid; 128fa9e4066Sahrens 129fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 130fa9e4066Sahrens &child, &children) == 0) { 131fa9e4066Sahrens for (c = 0; c < children; c++) 132fa9e4066Sahrens fix_paths(child[c], names); 133fa9e4066Sahrens return; 134fa9e4066Sahrens } 135fa9e4066Sahrens 136fa9e4066Sahrens /* 137fa9e4066Sahrens * This is a leaf (file or disk) vdev. In either case, go through 138fa9e4066Sahrens * the name list and see if we find a matching guid. If so, replace 139fa9e4066Sahrens * the path and see if we can calculate a new devid. 140fa9e4066Sahrens */ 141fa9e4066Sahrens verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0); 142fa9e4066Sahrens 143fa9e4066Sahrens for (ne = names; ne != NULL; ne = ne->ne_next) 144fa9e4066Sahrens if (ne->ne_guid == guid) 145fa9e4066Sahrens break; 146fa9e4066Sahrens 147fa9e4066Sahrens if (ne == NULL) 148fa9e4066Sahrens return; 149fa9e4066Sahrens 150fa9e4066Sahrens verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, ne->ne_name) == 0); 151fa9e4066Sahrens 152fa9e4066Sahrens if ((devid = get_devid(ne->ne_name)) == NULL) { 153fa9e4066Sahrens (void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID); 154fa9e4066Sahrens } else { 155fa9e4066Sahrens verify(nvlist_add_string(nv, ZPOOL_CONFIG_DEVID, devid) == 0); 156fa9e4066Sahrens devid_str_free(devid); 157fa9e4066Sahrens } 158fa9e4066Sahrens } 159fa9e4066Sahrens 160fa9e4066Sahrens /* 161fa9e4066Sahrens * Add the given configuration to the list of known devices. 162fa9e4066Sahrens */ 163fa9e4066Sahrens static void 164fa9e4066Sahrens add_config(pool_list_t *pl, const char *path, nvlist_t *config) 165fa9e4066Sahrens { 166fa9e4066Sahrens uint64_t pool_guid, vdev_guid, top_guid, txg; 167fa9e4066Sahrens pool_entry_t *pe; 168fa9e4066Sahrens vdev_entry_t *ve; 169fa9e4066Sahrens config_entry_t *ce; 170fa9e4066Sahrens name_entry_t *ne; 171fa9e4066Sahrens 172fa9e4066Sahrens /* 173fa9e4066Sahrens * If we have a valid config but cannot read any of these fields, then 174fa9e4066Sahrens * it means we have a half-initialized label. In vdev_label_init() 175fa9e4066Sahrens * we write a label with txg == 0 so that we can identify the device 176fa9e4066Sahrens * in case the user refers to the same disk later on. If we fail to 177fa9e4066Sahrens * create the pool, we'll be left with a label in this state 178fa9e4066Sahrens * which should not be considered part of a valid pool. 179fa9e4066Sahrens */ 180fa9e4066Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 181fa9e4066Sahrens &pool_guid) != 0 || 182fa9e4066Sahrens nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, 183fa9e4066Sahrens &vdev_guid) != 0 || 184fa9e4066Sahrens nvlist_lookup_uint64(config, ZPOOL_CONFIG_TOP_GUID, 185fa9e4066Sahrens &top_guid) != 0 || 186fa9e4066Sahrens nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, 187fa9e4066Sahrens &txg) != 0 || txg == 0) { 188fa9e4066Sahrens nvlist_free(config); 189fa9e4066Sahrens return; 190fa9e4066Sahrens } 191fa9e4066Sahrens 192fa9e4066Sahrens /* 193fa9e4066Sahrens * First, see if we know about this pool. If not, then add it to the 194fa9e4066Sahrens * list of known pools. 195fa9e4066Sahrens */ 196fa9e4066Sahrens for (pe = pl->pools; pe != NULL; pe = pe->pe_next) { 197fa9e4066Sahrens if (pe->pe_guid == pool_guid) 198fa9e4066Sahrens break; 199fa9e4066Sahrens } 200fa9e4066Sahrens 201fa9e4066Sahrens if (pe == NULL) { 202fa9e4066Sahrens pe = zfs_malloc(sizeof (pool_entry_t)); 203fa9e4066Sahrens pe->pe_guid = pool_guid; 204fa9e4066Sahrens pe->pe_next = pl->pools; 205fa9e4066Sahrens pl->pools = pe; 206fa9e4066Sahrens } 207fa9e4066Sahrens 208fa9e4066Sahrens /* 209fa9e4066Sahrens * Second, see if we know about this toplevel vdev. Add it if its 210fa9e4066Sahrens * missing. 211fa9e4066Sahrens */ 212fa9e4066Sahrens for (ve = pe->pe_vdevs; ve != NULL; ve = ve->ve_next) { 213fa9e4066Sahrens if (ve->ve_guid == top_guid) 214fa9e4066Sahrens break; 215fa9e4066Sahrens } 216fa9e4066Sahrens 217fa9e4066Sahrens if (ve == NULL) { 218fa9e4066Sahrens ve = zfs_malloc(sizeof (vdev_entry_t)); 219fa9e4066Sahrens ve->ve_guid = top_guid; 220fa9e4066Sahrens ve->ve_next = pe->pe_vdevs; 221fa9e4066Sahrens pe->pe_vdevs = ve; 222fa9e4066Sahrens } 223fa9e4066Sahrens 224fa9e4066Sahrens /* 225fa9e4066Sahrens * Third, see if we have a config with a matching transaction group. If 226fa9e4066Sahrens * so, then we do nothing. Otherwise, add it to the list of known 227fa9e4066Sahrens * configs. 228fa9e4066Sahrens */ 229fa9e4066Sahrens for (ce = ve->ve_configs; ce != NULL; ce = ce->ce_next) { 230fa9e4066Sahrens if (ce->ce_txg == txg) 231fa9e4066Sahrens break; 232fa9e4066Sahrens } 233fa9e4066Sahrens 234fa9e4066Sahrens if (ce == NULL) { 235fa9e4066Sahrens ce = zfs_malloc(sizeof (config_entry_t)); 236fa9e4066Sahrens ce->ce_txg = txg; 237fa9e4066Sahrens ce->ce_config = config; 238fa9e4066Sahrens ce->ce_next = ve->ve_configs; 239fa9e4066Sahrens ve->ve_configs = ce; 240fa9e4066Sahrens } else { 241fa9e4066Sahrens nvlist_free(config); 242fa9e4066Sahrens } 243fa9e4066Sahrens 244fa9e4066Sahrens /* 245fa9e4066Sahrens * At this point we've successfully added our config to the list of 246fa9e4066Sahrens * known configs. The last thing to do is add the vdev guid -> path 247fa9e4066Sahrens * mappings so that we can fix up the configuration as necessary before 248fa9e4066Sahrens * doing the import. 249fa9e4066Sahrens */ 250fa9e4066Sahrens ne = zfs_malloc(sizeof (name_entry_t)); 251fa9e4066Sahrens 252fa9e4066Sahrens ne->ne_name = zfs_strdup(path); 253fa9e4066Sahrens ne->ne_guid = vdev_guid; 254fa9e4066Sahrens ne->ne_next = pl->names; 255fa9e4066Sahrens pl->names = ne; 256fa9e4066Sahrens } 257fa9e4066Sahrens 258fa9e4066Sahrens /* 259fa9e4066Sahrens * Convert our list of pools into the definitive set of configurations. We 260fa9e4066Sahrens * start by picking the best config for each toplevel vdev. Once that's done, 261fa9e4066Sahrens * we assemble the toplevel vdevs into a full config for the pool. We make a 262fa9e4066Sahrens * pass to fix up any incorrect paths, and then add it to the main list to 263fa9e4066Sahrens * return to the user. 264fa9e4066Sahrens */ 265fa9e4066Sahrens static nvlist_t * 266fa9e4066Sahrens get_configs(pool_list_t *pl) 267fa9e4066Sahrens { 268fa9e4066Sahrens pool_entry_t *pe, *penext; 269fa9e4066Sahrens vdev_entry_t *ve, *venext; 270fa9e4066Sahrens config_entry_t *ce, *cenext; 271fa9e4066Sahrens nvlist_t *ret, *config, *tmp, *nvtop, *nvroot; 272fa9e4066Sahrens int config_seen; 273fa9e4066Sahrens uint64_t best_txg; 274fa9e4066Sahrens char *name; 275fa9e4066Sahrens zfs_cmd_t zc = { 0 }; 276fa9e4066Sahrens uint64_t guid; 277fa9e4066Sahrens char *packed; 278fa9e4066Sahrens size_t len; 279fa9e4066Sahrens int err; 280fa9e4066Sahrens 281fa9e4066Sahrens verify(nvlist_alloc(&ret, 0, 0) == 0); 282fa9e4066Sahrens 283fa9e4066Sahrens for (pe = pl->pools; pe != NULL; pe = penext) { 284fa9e4066Sahrens uint_t c; 285fa9e4066Sahrens uint_t children = 0; 286fa9e4066Sahrens uint64_t id; 287fa9e4066Sahrens nvlist_t **child = NULL; 288fa9e4066Sahrens 289fa9e4066Sahrens penext = pe->pe_next; 290fa9e4066Sahrens 291fa9e4066Sahrens verify(nvlist_alloc(&config, NV_UNIQUE_NAME, 0) == 0); 292fa9e4066Sahrens config_seen = FALSE; 293fa9e4066Sahrens 294fa9e4066Sahrens /* 295fa9e4066Sahrens * Iterate over all toplevel vdevs. Grab the pool configuration 296fa9e4066Sahrens * from the first one we find, and then go through the rest and 297fa9e4066Sahrens * add them as necessary to the 'vdevs' member of the config. 298fa9e4066Sahrens */ 299fa9e4066Sahrens for (ve = pe->pe_vdevs; ve != NULL; ve = venext) { 300fa9e4066Sahrens venext = ve->ve_next; 301fa9e4066Sahrens 302fa9e4066Sahrens /* 303fa9e4066Sahrens * Determine the best configuration for this vdev by 304fa9e4066Sahrens * selecting the config with the latest transaction 305fa9e4066Sahrens * group. 306fa9e4066Sahrens */ 307fa9e4066Sahrens best_txg = 0; 308fa9e4066Sahrens for (ce = ve->ve_configs; ce != NULL; 309fa9e4066Sahrens ce = ce->ce_next) { 310fa9e4066Sahrens 311fa9e4066Sahrens if (ce->ce_txg > best_txg) 312fa9e4066Sahrens tmp = ce->ce_config; 313fa9e4066Sahrens } 314fa9e4066Sahrens 315fa9e4066Sahrens if (!config_seen) { 316fa9e4066Sahrens /* 317fa9e4066Sahrens * Copy the relevant pieces of data to the pool 318fa9e4066Sahrens * configuration: 319fa9e4066Sahrens * 320fa9e4066Sahrens * pool guid 321fa9e4066Sahrens * name 322fa9e4066Sahrens * pool state 323fa9e4066Sahrens */ 324fa9e4066Sahrens uint64_t state; 325fa9e4066Sahrens 326fa9e4066Sahrens verify(nvlist_lookup_uint64(tmp, 327fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 328fa9e4066Sahrens verify(nvlist_add_uint64(config, 329fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, guid) == 0); 330fa9e4066Sahrens verify(nvlist_lookup_string(tmp, 331fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 332fa9e4066Sahrens verify(nvlist_add_string(config, 333fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, name) == 0); 334fa9e4066Sahrens verify(nvlist_lookup_uint64(tmp, 335fa9e4066Sahrens ZPOOL_CONFIG_POOL_STATE, &state) == 0); 336fa9e4066Sahrens verify(nvlist_add_uint64(config, 337fa9e4066Sahrens ZPOOL_CONFIG_POOL_STATE, state) == 0); 338fa9e4066Sahrens 339fa9e4066Sahrens config_seen = TRUE; 340fa9e4066Sahrens } 341fa9e4066Sahrens 342fa9e4066Sahrens /* 343fa9e4066Sahrens * Add this top-level vdev to the child array. 344fa9e4066Sahrens */ 345fa9e4066Sahrens verify(nvlist_lookup_nvlist(tmp, 346fa9e4066Sahrens ZPOOL_CONFIG_VDEV_TREE, &nvtop) == 0); 347fa9e4066Sahrens verify(nvlist_lookup_uint64(nvtop, ZPOOL_CONFIG_ID, 348fa9e4066Sahrens &id) == 0); 349fa9e4066Sahrens if (id >= children) { 350fa9e4066Sahrens nvlist_t **newchild; 351fa9e4066Sahrens 352fa9e4066Sahrens newchild = zfs_malloc((id + 1) * 353fa9e4066Sahrens sizeof (nvlist_t *)); 354fa9e4066Sahrens 355fa9e4066Sahrens for (c = 0; c < children; c++) 356fa9e4066Sahrens newchild[c] = child[c]; 357fa9e4066Sahrens 358fa9e4066Sahrens free(child); 359fa9e4066Sahrens child = newchild; 360fa9e4066Sahrens children = id + 1; 361fa9e4066Sahrens } 362fa9e4066Sahrens verify(nvlist_dup(nvtop, &child[id], 0) == 0); 363fa9e4066Sahrens 364fa9e4066Sahrens /* 365fa9e4066Sahrens * Go through and free all config information. 366fa9e4066Sahrens */ 367fa9e4066Sahrens for (ce = ve->ve_configs; ce != NULL; ce = cenext) { 368fa9e4066Sahrens cenext = ce->ce_next; 369fa9e4066Sahrens 370fa9e4066Sahrens nvlist_free(ce->ce_config); 371fa9e4066Sahrens free(ce); 372fa9e4066Sahrens } 373fa9e4066Sahrens 374fa9e4066Sahrens /* 375fa9e4066Sahrens * Free this vdev entry, since it has now been merged 376fa9e4066Sahrens * into the main config. 377fa9e4066Sahrens */ 378fa9e4066Sahrens free(ve); 379fa9e4066Sahrens } 380fa9e4066Sahrens 381fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 382fa9e4066Sahrens &guid) == 0); 383fa9e4066Sahrens 384fa9e4066Sahrens /* 385fa9e4066Sahrens * Look for any missing top-level vdevs. If this is the case, 386fa9e4066Sahrens * create a faked up 'missing' vdev as a placeholder. We cannot 387fa9e4066Sahrens * simply compress the child array, because the kernel performs 388fa9e4066Sahrens * certain checks to make sure the vdev IDs match their location 389fa9e4066Sahrens * in the configuration. 390fa9e4066Sahrens */ 391fa9e4066Sahrens for (c = 0; c < children; c++) 392fa9e4066Sahrens if (child[c] == NULL) { 393fa9e4066Sahrens nvlist_t *missing; 394fa9e4066Sahrens verify(nvlist_alloc(&missing, NV_UNIQUE_NAME, 395fa9e4066Sahrens 0) == 0); 396fa9e4066Sahrens verify(nvlist_add_string(missing, 397fa9e4066Sahrens ZPOOL_CONFIG_TYPE, VDEV_TYPE_MISSING) == 0); 398fa9e4066Sahrens verify(nvlist_add_uint64(missing, 399fa9e4066Sahrens ZPOOL_CONFIG_ID, c) == 0); 400fa9e4066Sahrens verify(nvlist_add_uint64(missing, 401fa9e4066Sahrens ZPOOL_CONFIG_GUID, 0ULL) == 0); 402fa9e4066Sahrens child[c] = missing; 403fa9e4066Sahrens } 404fa9e4066Sahrens 405fa9e4066Sahrens /* 406fa9e4066Sahrens * Put all of this pool's top-level vdevs into a root vdev. 407fa9e4066Sahrens */ 408fa9e4066Sahrens verify(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) == 0); 409fa9e4066Sahrens verify(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, 410fa9e4066Sahrens VDEV_TYPE_ROOT) == 0); 411fa9e4066Sahrens verify(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) == 0); 412fa9e4066Sahrens verify(nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, guid) == 0); 413fa9e4066Sahrens verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 414fa9e4066Sahrens child, children) == 0); 415fa9e4066Sahrens 416fa9e4066Sahrens for (c = 0; c < children; c++) 417fa9e4066Sahrens nvlist_free(child[c]); 418fa9e4066Sahrens free(child); 419fa9e4066Sahrens 420fa9e4066Sahrens /* 421fa9e4066Sahrens * Go through and fix up any paths and/or devids based on our 422fa9e4066Sahrens * known list of vdev GUID -> path mappings. 423fa9e4066Sahrens */ 424fa9e4066Sahrens fix_paths(nvroot, pl->names); 425fa9e4066Sahrens 426fa9e4066Sahrens /* 427fa9e4066Sahrens * Add the root vdev to this pool's configuration. 428fa9e4066Sahrens */ 429fa9e4066Sahrens verify(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 430fa9e4066Sahrens nvroot) == 0); 431fa9e4066Sahrens nvlist_free(nvroot); 432fa9e4066Sahrens 433fa9e4066Sahrens /* 434fa9e4066Sahrens * Free this pool entry. 435fa9e4066Sahrens */ 436fa9e4066Sahrens free(pe); 437fa9e4066Sahrens 438fa9e4066Sahrens /* 439fa9e4066Sahrens * Determine if this pool is currently active, in which case we 440fa9e4066Sahrens * can't actually import it. 441fa9e4066Sahrens */ 442fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 443fa9e4066Sahrens &name) == 0); 444fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 445fa9e4066Sahrens &guid) == 0); 446fa9e4066Sahrens 447fa9e4066Sahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 448fa9e4066Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_GUID, &zc) == 0 && 449fa9e4066Sahrens guid == zc.zc_pool_guid) { 450fa9e4066Sahrens nvlist_free(config); 451fa9e4066Sahrens continue; 452fa9e4066Sahrens } 453fa9e4066Sahrens 454fa9e4066Sahrens /* 455fa9e4066Sahrens * Try to do the import in order to get vdev state. 456fa9e4066Sahrens */ 457fa9e4066Sahrens if ((err = nvlist_size(config, &len, NV_ENCODE_NATIVE)) != 0) 458fa9e4066Sahrens zfs_baderror(err); 459fa9e4066Sahrens 460fa9e4066Sahrens packed = zfs_malloc(len); 461fa9e4066Sahrens 462fa9e4066Sahrens if ((err = nvlist_pack(config, &packed, &len, 463fa9e4066Sahrens NV_ENCODE_NATIVE, 0)) != 0) 464fa9e4066Sahrens zfs_baderror(err); 465fa9e4066Sahrens 466fa9e4066Sahrens nvlist_free(config); 467fa9e4066Sahrens config = NULL; 468fa9e4066Sahrens 469fa9e4066Sahrens zc.zc_config_src_size = len; 470fa9e4066Sahrens zc.zc_config_src = (uint64_t)(uintptr_t)packed; 471fa9e4066Sahrens 472fa9e4066Sahrens zc.zc_config_dst_size = 2 * len; 473fa9e4066Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 474fa9e4066Sahrens zfs_malloc(zc.zc_config_dst_size); 475fa9e4066Sahrens 476fa9e4066Sahrens while ((err = ioctl(zfs_fd, ZFS_IOC_POOL_TRYIMPORT, 477fa9e4066Sahrens &zc)) != 0 && errno == ENOMEM) { 478fa9e4066Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 479fa9e4066Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 480fa9e4066Sahrens zfs_malloc(zc.zc_config_dst_size); 481fa9e4066Sahrens } 482fa9e4066Sahrens 483fa9e4066Sahrens free(packed); 484fa9e4066Sahrens 485fa9e4066Sahrens if (err) 486fa9e4066Sahrens zfs_baderror(errno); 487fa9e4066Sahrens 488fa9e4066Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 489fa9e4066Sahrens zc.zc_config_dst_size, &config, 0) == 0); 490fa9e4066Sahrens 491fa9e4066Sahrens set_pool_health(config); 492fa9e4066Sahrens 493fa9e4066Sahrens /* 494fa9e4066Sahrens * Add this pool to the list of configs. 495fa9e4066Sahrens */ 496fa9e4066Sahrens verify(nvlist_add_nvlist(ret, name, config) == 0); 497fa9e4066Sahrens 498fa9e4066Sahrens nvlist_free(config); 499fa9e4066Sahrens 500fa9e4066Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 501fa9e4066Sahrens } 502fa9e4066Sahrens 503fa9e4066Sahrens return (ret); 504fa9e4066Sahrens } 505fa9e4066Sahrens 506fa9e4066Sahrens /* 507fa9e4066Sahrens * Return the offset of the given label. 508fa9e4066Sahrens */ 509fa9e4066Sahrens static uint64_t 510fa9e4066Sahrens label_offset(size_t size, int l) 511fa9e4066Sahrens { 512fa9e4066Sahrens return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? 513fa9e4066Sahrens 0 : size - VDEV_LABELS * sizeof (vdev_label_t))); 514fa9e4066Sahrens } 515fa9e4066Sahrens 516fa9e4066Sahrens /* 517fa9e4066Sahrens * Given a file descriptor, read the label information and return an nvlist 518fa9e4066Sahrens * describing the configuration, if there is one. 519fa9e4066Sahrens */ 520fa9e4066Sahrens nvlist_t * 521fa9e4066Sahrens zpool_read_label(int fd) 522fa9e4066Sahrens { 523fa9e4066Sahrens struct stat64 statbuf; 524fa9e4066Sahrens int l; 525fa9e4066Sahrens vdev_label_t *label; 526fa9e4066Sahrens nvlist_t *config; 527fa9e4066Sahrens uint64_t version, state, txg; 528fa9e4066Sahrens 529fa9e4066Sahrens if (fstat64(fd, &statbuf) == -1) 530fa9e4066Sahrens return (NULL); 531fa9e4066Sahrens 532fa9e4066Sahrens label = zfs_malloc(sizeof (vdev_label_t)); 533fa9e4066Sahrens 534fa9e4066Sahrens for (l = 0; l < VDEV_LABELS; l++) { 535fa9e4066Sahrens if (pread(fd, label, sizeof (vdev_label_t), 536fa9e4066Sahrens label_offset(statbuf.st_size, l)) != sizeof (vdev_label_t)) 537fa9e4066Sahrens continue; 538fa9e4066Sahrens 539fa9e4066Sahrens if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, 540fa9e4066Sahrens sizeof (label->vl_vdev_phys.vp_nvlist), &config, 0) != 0) 541fa9e4066Sahrens continue; 542fa9e4066Sahrens 543fa9e4066Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 544fa9e4066Sahrens &version) != 0 || version != UBERBLOCK_VERSION) { 545fa9e4066Sahrens nvlist_free(config); 546fa9e4066Sahrens continue; 547fa9e4066Sahrens } 548fa9e4066Sahrens 549fa9e4066Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 550fa9e4066Sahrens &state) != 0 || state > POOL_STATE_EXPORTED) { 551fa9e4066Sahrens nvlist_free(config); 552fa9e4066Sahrens continue; 553fa9e4066Sahrens } 554fa9e4066Sahrens 555fa9e4066Sahrens if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, 556fa9e4066Sahrens &txg) != 0 || txg == 0) { 557fa9e4066Sahrens nvlist_free(config); 558fa9e4066Sahrens continue; 559fa9e4066Sahrens } 560fa9e4066Sahrens 561fa9e4066Sahrens free(label); 562fa9e4066Sahrens return (config); 563fa9e4066Sahrens } 564fa9e4066Sahrens 565fa9e4066Sahrens free(label); 566fa9e4066Sahrens return (NULL); 567fa9e4066Sahrens } 568fa9e4066Sahrens 569fa9e4066Sahrens /* 570fa9e4066Sahrens * Given a list of directories to search, find all pools stored on disk. This 571fa9e4066Sahrens * includes partial pools which are not available to import. If no args are 572fa9e4066Sahrens * given (argc is 0), then the default directory (/dev/dsk) is searched. 573fa9e4066Sahrens */ 574fa9e4066Sahrens nvlist_t * 575fa9e4066Sahrens zpool_find_import(int argc, char **argv) 576fa9e4066Sahrens { 577fa9e4066Sahrens int i; 578fa9e4066Sahrens DIR *dirp; 579fa9e4066Sahrens struct dirent64 *dp; 580fa9e4066Sahrens char path[MAXPATHLEN]; 581fa9e4066Sahrens struct stat64 statbuf; 582fa9e4066Sahrens nvlist_t *ret, *config; 583fa9e4066Sahrens static char *default_dir = "/dev/dsk"; 584fa9e4066Sahrens int fd; 585fa9e4066Sahrens pool_list_t pools = { 0 }; 586fa9e4066Sahrens 587fa9e4066Sahrens if (argc == 0) { 588fa9e4066Sahrens argc = 1; 589fa9e4066Sahrens argv = &default_dir; 590fa9e4066Sahrens } 591fa9e4066Sahrens 592fa9e4066Sahrens /* 593fa9e4066Sahrens * Go through and read the label configuration information from every 594fa9e4066Sahrens * possible device, organizing the information according to pool GUID 595fa9e4066Sahrens * and toplevel GUID. 596fa9e4066Sahrens */ 597fa9e4066Sahrens for (i = 0; i < argc; i++) { 598fa9e4066Sahrens if (argv[i][0] != '/') { 599fa9e4066Sahrens zfs_error(dgettext(TEXT_DOMAIN, 600fa9e4066Sahrens "cannot open '%s': must be an absolute path"), 601fa9e4066Sahrens argv[i]); 602fa9e4066Sahrens return (NULL); 603fa9e4066Sahrens } 604fa9e4066Sahrens 605fa9e4066Sahrens if ((dirp = opendir(argv[i])) == NULL) { 606fa9e4066Sahrens zfs_error(dgettext(TEXT_DOMAIN, 607fa9e4066Sahrens "cannot open '%s': %s"), argv[i], 608fa9e4066Sahrens strerror(errno)); 609fa9e4066Sahrens return (NULL); 610fa9e4066Sahrens } 611fa9e4066Sahrens 612fa9e4066Sahrens /* 613fa9e4066Sahrens * This is not MT-safe, but we have no MT consumers of libzfs 614fa9e4066Sahrens */ 615fa9e4066Sahrens while ((dp = readdir64(dirp)) != NULL) { 616fa9e4066Sahrens 617fa9e4066Sahrens (void) snprintf(path, sizeof (path), "%s/%s", 618fa9e4066Sahrens argv[i], dp->d_name); 619fa9e4066Sahrens 620fa9e4066Sahrens if (stat64(path, &statbuf) != 0) 621fa9e4066Sahrens continue; 622fa9e4066Sahrens 623fa9e4066Sahrens /* 624fa9e4066Sahrens * Ignore directories (which includes "." and ".."). 625fa9e4066Sahrens */ 626fa9e4066Sahrens if (S_ISDIR(statbuf.st_mode)) 627fa9e4066Sahrens continue; 628fa9e4066Sahrens 629fa9e4066Sahrens if ((fd = open64(path, O_RDONLY)) < 0) 630fa9e4066Sahrens continue; 631fa9e4066Sahrens 632fa9e4066Sahrens config = zpool_read_label(fd); 633fa9e4066Sahrens 634fa9e4066Sahrens (void) close(fd); 635fa9e4066Sahrens 636fa9e4066Sahrens if (config != NULL) 637fa9e4066Sahrens add_config(&pools, path, config); 638fa9e4066Sahrens } 639fa9e4066Sahrens } 640fa9e4066Sahrens 641fa9e4066Sahrens ret = get_configs(&pools); 642fa9e4066Sahrens 643fa9e4066Sahrens return (ret); 644fa9e4066Sahrens } 645fa9e4066Sahrens 646fa9e4066Sahrens int 647fa9e4066Sahrens find_guid(nvlist_t *nv, uint64_t guid) 648fa9e4066Sahrens { 649fa9e4066Sahrens uint64_t tmp; 650fa9e4066Sahrens nvlist_t **child; 651fa9e4066Sahrens uint_t c, children; 652fa9e4066Sahrens 653fa9e4066Sahrens verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &tmp) == 0); 654fa9e4066Sahrens if (tmp == guid) 655fa9e4066Sahrens return (TRUE); 656fa9e4066Sahrens 657fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 658fa9e4066Sahrens &child, &children) == 0) { 659fa9e4066Sahrens for (c = 0; c < children; c++) 660fa9e4066Sahrens if (find_guid(child[c], guid)) 661fa9e4066Sahrens return (TRUE); 662fa9e4066Sahrens } 663fa9e4066Sahrens 664fa9e4066Sahrens return (FALSE); 665fa9e4066Sahrens } 666fa9e4066Sahrens 667fa9e4066Sahrens /* 668fa9e4066Sahrens * Determines if the pool is in use. If so, it returns TRUE and the state of 669fa9e4066Sahrens * the pool as well as the name of the pool. Both strings are allocated and 670fa9e4066Sahrens * must be freed by the caller. 671fa9e4066Sahrens */ 672fa9e4066Sahrens int 673fa9e4066Sahrens zpool_in_use(int fd, char **statestr, char **namestr) 674fa9e4066Sahrens { 675fa9e4066Sahrens nvlist_t *config; 676fa9e4066Sahrens uint64_t state; 677fa9e4066Sahrens char *name; 678fa9e4066Sahrens int ret; 679fa9e4066Sahrens zfs_cmd_t zc = { 0 }; 680fa9e4066Sahrens uint64_t guid, vdev_guid; 681fa9e4066Sahrens zpool_handle_t *zhp; 682fa9e4066Sahrens nvlist_t *pool_config; 683fa9e4066Sahrens 684fa9e4066Sahrens if ((config = zpool_read_label(fd)) == NULL) 685fa9e4066Sahrens return (FALSE); 686fa9e4066Sahrens 687fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 688fa9e4066Sahrens &name) == 0); 689fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 690fa9e4066Sahrens &state) == 0); 691fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 692fa9e4066Sahrens &guid) == 0); 693fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, 694fa9e4066Sahrens &vdev_guid) == 0); 695fa9e4066Sahrens 696fa9e4066Sahrens switch (state) { 697fa9e4066Sahrens case POOL_STATE_EXPORTED: 698fa9e4066Sahrens *statestr = zfs_strdup(dgettext(TEXT_DOMAIN, "exported")); 699fa9e4066Sahrens *namestr = zfs_strdup(name); 700fa9e4066Sahrens ret = TRUE; 701fa9e4066Sahrens break; 702fa9e4066Sahrens 703fa9e4066Sahrens case POOL_STATE_ACTIVE: 704fa9e4066Sahrens /* 705fa9e4066Sahrens * For an active pool, we have to determine if it's really part 706fa9e4066Sahrens * of an active pool (in which case the pool will exist and the 707fa9e4066Sahrens * guid will be the same), or whether it's part of an active 708fa9e4066Sahrens * pool that was disconnected without being explicitly exported. 709fa9e4066Sahrens * 710fa9e4066Sahrens * We use the direct ioctl() first to avoid triggering an error 711fa9e4066Sahrens * message if the pool cannot be opened. 712fa9e4066Sahrens */ 713fa9e4066Sahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 714fa9e4066Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_GUID, &zc) == 0 && 715fa9e4066Sahrens guid == zc.zc_pool_guid) { 716fa9e4066Sahrens /* 717fa9e4066Sahrens * Because the device may have been removed while 718fa9e4066Sahrens * offlined, we only report it as active if the vdev is 719fa9e4066Sahrens * still present in the config. Otherwise, pretend like 720fa9e4066Sahrens * it's not in use. 721fa9e4066Sahrens */ 722fa9e4066Sahrens if ((zhp = zpool_open_canfail(name)) != NULL && 723*088e9d47Seschrock (pool_config = zpool_get_config(zhp, NULL)) 724*088e9d47Seschrock != NULL) { 725fa9e4066Sahrens nvlist_t *nvroot; 726fa9e4066Sahrens 727fa9e4066Sahrens verify(nvlist_lookup_nvlist(pool_config, 728fa9e4066Sahrens ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 729fa9e4066Sahrens if (find_guid(nvroot, vdev_guid)) { 730fa9e4066Sahrens *statestr = zfs_strdup( 731fa9e4066Sahrens dgettext(TEXT_DOMAIN, "active")); 732fa9e4066Sahrens *namestr = zfs_strdup(name); 733fa9e4066Sahrens ret = TRUE; 734fa9e4066Sahrens } else { 735fa9e4066Sahrens ret = FALSE; 736fa9e4066Sahrens } 737fa9e4066Sahrens } else { 738fa9e4066Sahrens ret = FALSE; 739fa9e4066Sahrens } 740fa9e4066Sahrens } else { 741fa9e4066Sahrens *statestr = zfs_strdup(dgettext(TEXT_DOMAIN, 742fa9e4066Sahrens "potentially active")); 743fa9e4066Sahrens *namestr = zfs_strdup(name); 744fa9e4066Sahrens ret = TRUE; 745fa9e4066Sahrens } 746fa9e4066Sahrens break; 747fa9e4066Sahrens 748fa9e4066Sahrens default: 749fa9e4066Sahrens ret = FALSE; 750fa9e4066Sahrens } 751fa9e4066Sahrens 752fa9e4066Sahrens nvlist_free(config); 753fa9e4066Sahrens return (ret); 754fa9e4066Sahrens } 755