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