1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6*eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7*eda14cbcSMatt Macy * 8*eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10*eda14cbcSMatt Macy * See the License for the specific language governing permissions 11*eda14cbcSMatt Macy * and limitations under the License. 12*eda14cbcSMatt Macy * 13*eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14*eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16*eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17*eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18*eda14cbcSMatt Macy * 19*eda14cbcSMatt Macy * CDDL HEADER END 20*eda14cbcSMatt Macy */ 21*eda14cbcSMatt Macy /* 22*eda14cbcSMatt Macy * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 23*eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24*eda14cbcSMatt Macy * Copyright (c) 2012, 2018 by Delphix. All rights reserved. 25*eda14cbcSMatt Macy * Copyright 2015 RackTop Systems. 26*eda14cbcSMatt Macy * Copyright (c) 2016, Intel Corporation. 27*eda14cbcSMatt Macy */ 28*eda14cbcSMatt Macy 29*eda14cbcSMatt Macy /* 30*eda14cbcSMatt Macy * Pool import support functions. 31*eda14cbcSMatt Macy * 32*eda14cbcSMatt Macy * Used by zpool, ztest, zdb, and zhack to locate importable configs. Since 33*eda14cbcSMatt Macy * these commands are expected to run in the global zone, we can assume 34*eda14cbcSMatt Macy * that the devices are all readable when called. 35*eda14cbcSMatt Macy * 36*eda14cbcSMatt Macy * To import a pool, we rely on reading the configuration information from the 37*eda14cbcSMatt Macy * ZFS label of each device. If we successfully read the label, then we 38*eda14cbcSMatt Macy * organize the configuration information in the following hierarchy: 39*eda14cbcSMatt Macy * 40*eda14cbcSMatt Macy * pool guid -> toplevel vdev guid -> label txg 41*eda14cbcSMatt Macy * 42*eda14cbcSMatt Macy * Duplicate entries matching this same tuple will be discarded. Once we have 43*eda14cbcSMatt Macy * examined every device, we pick the best label txg config for each toplevel 44*eda14cbcSMatt Macy * vdev. We then arrange these toplevel vdevs into a complete pool config, and 45*eda14cbcSMatt Macy * update any paths that have changed. Finally, we attempt to import the pool 46*eda14cbcSMatt Macy * using our derived config, and record the results. 47*eda14cbcSMatt Macy */ 48*eda14cbcSMatt Macy 49*eda14cbcSMatt Macy #include <ctype.h> 50*eda14cbcSMatt Macy #include <dirent.h> 51*eda14cbcSMatt Macy #include <errno.h> 52*eda14cbcSMatt Macy #include <libintl.h> 53*eda14cbcSMatt Macy #include <libgen.h> 54*eda14cbcSMatt Macy #include <stddef.h> 55*eda14cbcSMatt Macy #include <stdlib.h> 56*eda14cbcSMatt Macy #include <string.h> 57*eda14cbcSMatt Macy #include <sys/stat.h> 58*eda14cbcSMatt Macy #include <unistd.h> 59*eda14cbcSMatt Macy #include <fcntl.h> 60*eda14cbcSMatt Macy #include <sys/dktp/fdisk.h> 61*eda14cbcSMatt Macy #include <sys/vdev_impl.h> 62*eda14cbcSMatt Macy #include <sys/fs/zfs.h> 63*eda14cbcSMatt Macy #include <sys/vdev_impl.h> 64*eda14cbcSMatt Macy 65*eda14cbcSMatt Macy #include <thread_pool.h> 66*eda14cbcSMatt Macy #include <libzutil.h> 67*eda14cbcSMatt Macy #include <libnvpair.h> 68*eda14cbcSMatt Macy 69*eda14cbcSMatt Macy #include "zutil_import.h" 70*eda14cbcSMatt Macy 71*eda14cbcSMatt Macy /*PRINTFLIKE2*/ 72*eda14cbcSMatt Macy static void 73*eda14cbcSMatt Macy zutil_error_aux(libpc_handle_t *hdl, const char *fmt, ...) 74*eda14cbcSMatt Macy { 75*eda14cbcSMatt Macy va_list ap; 76*eda14cbcSMatt Macy 77*eda14cbcSMatt Macy va_start(ap, fmt); 78*eda14cbcSMatt Macy 79*eda14cbcSMatt Macy (void) vsnprintf(hdl->lpc_desc, sizeof (hdl->lpc_desc), fmt, ap); 80*eda14cbcSMatt Macy hdl->lpc_desc_active = B_TRUE; 81*eda14cbcSMatt Macy 82*eda14cbcSMatt Macy va_end(ap); 83*eda14cbcSMatt Macy } 84*eda14cbcSMatt Macy 85*eda14cbcSMatt Macy static void 86*eda14cbcSMatt Macy zutil_verror(libpc_handle_t *hdl, const char *error, const char *fmt, 87*eda14cbcSMatt Macy va_list ap) 88*eda14cbcSMatt Macy { 89*eda14cbcSMatt Macy char action[1024]; 90*eda14cbcSMatt Macy 91*eda14cbcSMatt Macy (void) vsnprintf(action, sizeof (action), fmt, ap); 92*eda14cbcSMatt Macy 93*eda14cbcSMatt Macy if (hdl->lpc_desc_active) 94*eda14cbcSMatt Macy hdl->lpc_desc_active = B_FALSE; 95*eda14cbcSMatt Macy else 96*eda14cbcSMatt Macy hdl->lpc_desc[0] = '\0'; 97*eda14cbcSMatt Macy 98*eda14cbcSMatt Macy if (hdl->lpc_printerr) { 99*eda14cbcSMatt Macy if (hdl->lpc_desc[0] != '\0') 100*eda14cbcSMatt Macy error = hdl->lpc_desc; 101*eda14cbcSMatt Macy 102*eda14cbcSMatt Macy (void) fprintf(stderr, "%s: %s\n", action, error); 103*eda14cbcSMatt Macy } 104*eda14cbcSMatt Macy } 105*eda14cbcSMatt Macy 106*eda14cbcSMatt Macy /*PRINTFLIKE3*/ 107*eda14cbcSMatt Macy static int 108*eda14cbcSMatt Macy zutil_error_fmt(libpc_handle_t *hdl, const char *error, const char *fmt, ...) 109*eda14cbcSMatt Macy { 110*eda14cbcSMatt Macy va_list ap; 111*eda14cbcSMatt Macy 112*eda14cbcSMatt Macy va_start(ap, fmt); 113*eda14cbcSMatt Macy 114*eda14cbcSMatt Macy zutil_verror(hdl, error, fmt, ap); 115*eda14cbcSMatt Macy 116*eda14cbcSMatt Macy va_end(ap); 117*eda14cbcSMatt Macy 118*eda14cbcSMatt Macy return (-1); 119*eda14cbcSMatt Macy } 120*eda14cbcSMatt Macy 121*eda14cbcSMatt Macy static int 122*eda14cbcSMatt Macy zutil_error(libpc_handle_t *hdl, const char *error, const char *msg) 123*eda14cbcSMatt Macy { 124*eda14cbcSMatt Macy return (zutil_error_fmt(hdl, error, "%s", msg)); 125*eda14cbcSMatt Macy } 126*eda14cbcSMatt Macy 127*eda14cbcSMatt Macy static int 128*eda14cbcSMatt Macy zutil_no_memory(libpc_handle_t *hdl) 129*eda14cbcSMatt Macy { 130*eda14cbcSMatt Macy zutil_error(hdl, EZFS_NOMEM, "internal error"); 131*eda14cbcSMatt Macy exit(1); 132*eda14cbcSMatt Macy } 133*eda14cbcSMatt Macy 134*eda14cbcSMatt Macy void * 135*eda14cbcSMatt Macy zutil_alloc(libpc_handle_t *hdl, size_t size) 136*eda14cbcSMatt Macy { 137*eda14cbcSMatt Macy void *data; 138*eda14cbcSMatt Macy 139*eda14cbcSMatt Macy if ((data = calloc(1, size)) == NULL) 140*eda14cbcSMatt Macy (void) zutil_no_memory(hdl); 141*eda14cbcSMatt Macy 142*eda14cbcSMatt Macy return (data); 143*eda14cbcSMatt Macy } 144*eda14cbcSMatt Macy 145*eda14cbcSMatt Macy char * 146*eda14cbcSMatt Macy zutil_strdup(libpc_handle_t *hdl, const char *str) 147*eda14cbcSMatt Macy { 148*eda14cbcSMatt Macy char *ret; 149*eda14cbcSMatt Macy 150*eda14cbcSMatt Macy if ((ret = strdup(str)) == NULL) 151*eda14cbcSMatt Macy (void) zutil_no_memory(hdl); 152*eda14cbcSMatt Macy 153*eda14cbcSMatt Macy return (ret); 154*eda14cbcSMatt Macy } 155*eda14cbcSMatt Macy 156*eda14cbcSMatt Macy /* 157*eda14cbcSMatt Macy * Intermediate structures used to gather configuration information. 158*eda14cbcSMatt Macy */ 159*eda14cbcSMatt Macy typedef struct config_entry { 160*eda14cbcSMatt Macy uint64_t ce_txg; 161*eda14cbcSMatt Macy nvlist_t *ce_config; 162*eda14cbcSMatt Macy struct config_entry *ce_next; 163*eda14cbcSMatt Macy } config_entry_t; 164*eda14cbcSMatt Macy 165*eda14cbcSMatt Macy typedef struct vdev_entry { 166*eda14cbcSMatt Macy uint64_t ve_guid; 167*eda14cbcSMatt Macy config_entry_t *ve_configs; 168*eda14cbcSMatt Macy struct vdev_entry *ve_next; 169*eda14cbcSMatt Macy } vdev_entry_t; 170*eda14cbcSMatt Macy 171*eda14cbcSMatt Macy typedef struct pool_entry { 172*eda14cbcSMatt Macy uint64_t pe_guid; 173*eda14cbcSMatt Macy vdev_entry_t *pe_vdevs; 174*eda14cbcSMatt Macy struct pool_entry *pe_next; 175*eda14cbcSMatt Macy } pool_entry_t; 176*eda14cbcSMatt Macy 177*eda14cbcSMatt Macy typedef struct name_entry { 178*eda14cbcSMatt Macy char *ne_name; 179*eda14cbcSMatt Macy uint64_t ne_guid; 180*eda14cbcSMatt Macy uint64_t ne_order; 181*eda14cbcSMatt Macy uint64_t ne_num_labels; 182*eda14cbcSMatt Macy struct name_entry *ne_next; 183*eda14cbcSMatt Macy } name_entry_t; 184*eda14cbcSMatt Macy 185*eda14cbcSMatt Macy typedef struct pool_list { 186*eda14cbcSMatt Macy pool_entry_t *pools; 187*eda14cbcSMatt Macy name_entry_t *names; 188*eda14cbcSMatt Macy } pool_list_t; 189*eda14cbcSMatt Macy 190*eda14cbcSMatt Macy /* 191*eda14cbcSMatt Macy * Go through and fix up any path and/or devid information for the given vdev 192*eda14cbcSMatt Macy * configuration. 193*eda14cbcSMatt Macy */ 194*eda14cbcSMatt Macy static int 195*eda14cbcSMatt Macy fix_paths(libpc_handle_t *hdl, nvlist_t *nv, name_entry_t *names) 196*eda14cbcSMatt Macy { 197*eda14cbcSMatt Macy nvlist_t **child; 198*eda14cbcSMatt Macy uint_t c, children; 199*eda14cbcSMatt Macy uint64_t guid; 200*eda14cbcSMatt Macy name_entry_t *ne, *best; 201*eda14cbcSMatt Macy char *path; 202*eda14cbcSMatt Macy 203*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 204*eda14cbcSMatt Macy &child, &children) == 0) { 205*eda14cbcSMatt Macy for (c = 0; c < children; c++) 206*eda14cbcSMatt Macy if (fix_paths(hdl, child[c], names) != 0) 207*eda14cbcSMatt Macy return (-1); 208*eda14cbcSMatt Macy return (0); 209*eda14cbcSMatt Macy } 210*eda14cbcSMatt Macy 211*eda14cbcSMatt Macy /* 212*eda14cbcSMatt Macy * This is a leaf (file or disk) vdev. In either case, go through 213*eda14cbcSMatt Macy * the name list and see if we find a matching guid. If so, replace 214*eda14cbcSMatt Macy * the path and see if we can calculate a new devid. 215*eda14cbcSMatt Macy * 216*eda14cbcSMatt Macy * There may be multiple names associated with a particular guid, in 217*eda14cbcSMatt Macy * which case we have overlapping partitions or multiple paths to the 218*eda14cbcSMatt Macy * same disk. In this case we prefer to use the path name which 219*eda14cbcSMatt Macy * matches the ZPOOL_CONFIG_PATH. If no matching entry is found we 220*eda14cbcSMatt Macy * use the lowest order device which corresponds to the first match 221*eda14cbcSMatt Macy * while traversing the ZPOOL_IMPORT_PATH search path. 222*eda14cbcSMatt Macy */ 223*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0); 224*eda14cbcSMatt Macy if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0) 225*eda14cbcSMatt Macy path = NULL; 226*eda14cbcSMatt Macy 227*eda14cbcSMatt Macy best = NULL; 228*eda14cbcSMatt Macy for (ne = names; ne != NULL; ne = ne->ne_next) { 229*eda14cbcSMatt Macy if (ne->ne_guid == guid) { 230*eda14cbcSMatt Macy if (path == NULL) { 231*eda14cbcSMatt Macy best = ne; 232*eda14cbcSMatt Macy break; 233*eda14cbcSMatt Macy } 234*eda14cbcSMatt Macy 235*eda14cbcSMatt Macy if ((strlen(path) == strlen(ne->ne_name)) && 236*eda14cbcSMatt Macy strncmp(path, ne->ne_name, strlen(path)) == 0) { 237*eda14cbcSMatt Macy best = ne; 238*eda14cbcSMatt Macy break; 239*eda14cbcSMatt Macy } 240*eda14cbcSMatt Macy 241*eda14cbcSMatt Macy if (best == NULL) { 242*eda14cbcSMatt Macy best = ne; 243*eda14cbcSMatt Macy continue; 244*eda14cbcSMatt Macy } 245*eda14cbcSMatt Macy 246*eda14cbcSMatt Macy /* Prefer paths with move vdev labels. */ 247*eda14cbcSMatt Macy if (ne->ne_num_labels > best->ne_num_labels) { 248*eda14cbcSMatt Macy best = ne; 249*eda14cbcSMatt Macy continue; 250*eda14cbcSMatt Macy } 251*eda14cbcSMatt Macy 252*eda14cbcSMatt Macy /* Prefer paths earlier in the search order. */ 253*eda14cbcSMatt Macy if (ne->ne_num_labels == best->ne_num_labels && 254*eda14cbcSMatt Macy ne->ne_order < best->ne_order) { 255*eda14cbcSMatt Macy best = ne; 256*eda14cbcSMatt Macy continue; 257*eda14cbcSMatt Macy } 258*eda14cbcSMatt Macy } 259*eda14cbcSMatt Macy } 260*eda14cbcSMatt Macy 261*eda14cbcSMatt Macy if (best == NULL) 262*eda14cbcSMatt Macy return (0); 263*eda14cbcSMatt Macy 264*eda14cbcSMatt Macy if (nvlist_add_string(nv, ZPOOL_CONFIG_PATH, best->ne_name) != 0) 265*eda14cbcSMatt Macy return (-1); 266*eda14cbcSMatt Macy 267*eda14cbcSMatt Macy update_vdev_config_dev_strs(nv); 268*eda14cbcSMatt Macy 269*eda14cbcSMatt Macy return (0); 270*eda14cbcSMatt Macy } 271*eda14cbcSMatt Macy 272*eda14cbcSMatt Macy /* 273*eda14cbcSMatt Macy * Add the given configuration to the list of known devices. 274*eda14cbcSMatt Macy */ 275*eda14cbcSMatt Macy static int 276*eda14cbcSMatt Macy add_config(libpc_handle_t *hdl, pool_list_t *pl, const char *path, 277*eda14cbcSMatt Macy int order, int num_labels, nvlist_t *config) 278*eda14cbcSMatt Macy { 279*eda14cbcSMatt Macy uint64_t pool_guid, vdev_guid, top_guid, txg, state; 280*eda14cbcSMatt Macy pool_entry_t *pe; 281*eda14cbcSMatt Macy vdev_entry_t *ve; 282*eda14cbcSMatt Macy config_entry_t *ce; 283*eda14cbcSMatt Macy name_entry_t *ne; 284*eda14cbcSMatt Macy 285*eda14cbcSMatt Macy /* 286*eda14cbcSMatt Macy * If this is a hot spare not currently in use or level 2 cache 287*eda14cbcSMatt Macy * device, add it to the list of names to translate, but don't do 288*eda14cbcSMatt Macy * anything else. 289*eda14cbcSMatt Macy */ 290*eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 291*eda14cbcSMatt Macy &state) == 0 && 292*eda14cbcSMatt Macy (state == POOL_STATE_SPARE || state == POOL_STATE_L2CACHE) && 293*eda14cbcSMatt Macy nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, &vdev_guid) == 0) { 294*eda14cbcSMatt Macy if ((ne = zutil_alloc(hdl, sizeof (name_entry_t))) == NULL) 295*eda14cbcSMatt Macy return (-1); 296*eda14cbcSMatt Macy 297*eda14cbcSMatt Macy if ((ne->ne_name = zutil_strdup(hdl, path)) == NULL) { 298*eda14cbcSMatt Macy free(ne); 299*eda14cbcSMatt Macy return (-1); 300*eda14cbcSMatt Macy } 301*eda14cbcSMatt Macy ne->ne_guid = vdev_guid; 302*eda14cbcSMatt Macy ne->ne_order = order; 303*eda14cbcSMatt Macy ne->ne_num_labels = num_labels; 304*eda14cbcSMatt Macy ne->ne_next = pl->names; 305*eda14cbcSMatt Macy pl->names = ne; 306*eda14cbcSMatt Macy 307*eda14cbcSMatt Macy return (0); 308*eda14cbcSMatt Macy } 309*eda14cbcSMatt Macy 310*eda14cbcSMatt Macy /* 311*eda14cbcSMatt Macy * If we have a valid config but cannot read any of these fields, then 312*eda14cbcSMatt Macy * it means we have a half-initialized label. In vdev_label_init() 313*eda14cbcSMatt Macy * we write a label with txg == 0 so that we can identify the device 314*eda14cbcSMatt Macy * in case the user refers to the same disk later on. If we fail to 315*eda14cbcSMatt Macy * create the pool, we'll be left with a label in this state 316*eda14cbcSMatt Macy * which should not be considered part of a valid pool. 317*eda14cbcSMatt Macy */ 318*eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 319*eda14cbcSMatt Macy &pool_guid) != 0 || 320*eda14cbcSMatt Macy nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, 321*eda14cbcSMatt Macy &vdev_guid) != 0 || 322*eda14cbcSMatt Macy nvlist_lookup_uint64(config, ZPOOL_CONFIG_TOP_GUID, 323*eda14cbcSMatt Macy &top_guid) != 0 || 324*eda14cbcSMatt Macy nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, 325*eda14cbcSMatt Macy &txg) != 0 || txg == 0) { 326*eda14cbcSMatt Macy return (0); 327*eda14cbcSMatt Macy } 328*eda14cbcSMatt Macy 329*eda14cbcSMatt Macy /* 330*eda14cbcSMatt Macy * First, see if we know about this pool. If not, then add it to the 331*eda14cbcSMatt Macy * list of known pools. 332*eda14cbcSMatt Macy */ 333*eda14cbcSMatt Macy for (pe = pl->pools; pe != NULL; pe = pe->pe_next) { 334*eda14cbcSMatt Macy if (pe->pe_guid == pool_guid) 335*eda14cbcSMatt Macy break; 336*eda14cbcSMatt Macy } 337*eda14cbcSMatt Macy 338*eda14cbcSMatt Macy if (pe == NULL) { 339*eda14cbcSMatt Macy if ((pe = zutil_alloc(hdl, sizeof (pool_entry_t))) == NULL) { 340*eda14cbcSMatt Macy return (-1); 341*eda14cbcSMatt Macy } 342*eda14cbcSMatt Macy pe->pe_guid = pool_guid; 343*eda14cbcSMatt Macy pe->pe_next = pl->pools; 344*eda14cbcSMatt Macy pl->pools = pe; 345*eda14cbcSMatt Macy } 346*eda14cbcSMatt Macy 347*eda14cbcSMatt Macy /* 348*eda14cbcSMatt Macy * Second, see if we know about this toplevel vdev. Add it if its 349*eda14cbcSMatt Macy * missing. 350*eda14cbcSMatt Macy */ 351*eda14cbcSMatt Macy for (ve = pe->pe_vdevs; ve != NULL; ve = ve->ve_next) { 352*eda14cbcSMatt Macy if (ve->ve_guid == top_guid) 353*eda14cbcSMatt Macy break; 354*eda14cbcSMatt Macy } 355*eda14cbcSMatt Macy 356*eda14cbcSMatt Macy if (ve == NULL) { 357*eda14cbcSMatt Macy if ((ve = zutil_alloc(hdl, sizeof (vdev_entry_t))) == NULL) { 358*eda14cbcSMatt Macy return (-1); 359*eda14cbcSMatt Macy } 360*eda14cbcSMatt Macy ve->ve_guid = top_guid; 361*eda14cbcSMatt Macy ve->ve_next = pe->pe_vdevs; 362*eda14cbcSMatt Macy pe->pe_vdevs = ve; 363*eda14cbcSMatt Macy } 364*eda14cbcSMatt Macy 365*eda14cbcSMatt Macy /* 366*eda14cbcSMatt Macy * Third, see if we have a config with a matching transaction group. If 367*eda14cbcSMatt Macy * so, then we do nothing. Otherwise, add it to the list of known 368*eda14cbcSMatt Macy * configs. 369*eda14cbcSMatt Macy */ 370*eda14cbcSMatt Macy for (ce = ve->ve_configs; ce != NULL; ce = ce->ce_next) { 371*eda14cbcSMatt Macy if (ce->ce_txg == txg) 372*eda14cbcSMatt Macy break; 373*eda14cbcSMatt Macy } 374*eda14cbcSMatt Macy 375*eda14cbcSMatt Macy if (ce == NULL) { 376*eda14cbcSMatt Macy if ((ce = zutil_alloc(hdl, sizeof (config_entry_t))) == NULL) { 377*eda14cbcSMatt Macy return (-1); 378*eda14cbcSMatt Macy } 379*eda14cbcSMatt Macy ce->ce_txg = txg; 380*eda14cbcSMatt Macy ce->ce_config = fnvlist_dup(config); 381*eda14cbcSMatt Macy ce->ce_next = ve->ve_configs; 382*eda14cbcSMatt Macy ve->ve_configs = ce; 383*eda14cbcSMatt Macy } 384*eda14cbcSMatt Macy 385*eda14cbcSMatt Macy /* 386*eda14cbcSMatt Macy * At this point we've successfully added our config to the list of 387*eda14cbcSMatt Macy * known configs. The last thing to do is add the vdev guid -> path 388*eda14cbcSMatt Macy * mappings so that we can fix up the configuration as necessary before 389*eda14cbcSMatt Macy * doing the import. 390*eda14cbcSMatt Macy */ 391*eda14cbcSMatt Macy if ((ne = zutil_alloc(hdl, sizeof (name_entry_t))) == NULL) 392*eda14cbcSMatt Macy return (-1); 393*eda14cbcSMatt Macy 394*eda14cbcSMatt Macy if ((ne->ne_name = zutil_strdup(hdl, path)) == NULL) { 395*eda14cbcSMatt Macy free(ne); 396*eda14cbcSMatt Macy return (-1); 397*eda14cbcSMatt Macy } 398*eda14cbcSMatt Macy 399*eda14cbcSMatt Macy ne->ne_guid = vdev_guid; 400*eda14cbcSMatt Macy ne->ne_order = order; 401*eda14cbcSMatt Macy ne->ne_num_labels = num_labels; 402*eda14cbcSMatt Macy ne->ne_next = pl->names; 403*eda14cbcSMatt Macy pl->names = ne; 404*eda14cbcSMatt Macy 405*eda14cbcSMatt Macy return (0); 406*eda14cbcSMatt Macy } 407*eda14cbcSMatt Macy 408*eda14cbcSMatt Macy static int 409*eda14cbcSMatt Macy zutil_pool_active(libpc_handle_t *hdl, const char *name, uint64_t guid, 410*eda14cbcSMatt Macy boolean_t *isactive) 411*eda14cbcSMatt Macy { 412*eda14cbcSMatt Macy ASSERT(hdl->lpc_ops->pco_pool_active != NULL); 413*eda14cbcSMatt Macy 414*eda14cbcSMatt Macy int error = hdl->lpc_ops->pco_pool_active(hdl->lpc_lib_handle, name, 415*eda14cbcSMatt Macy guid, isactive); 416*eda14cbcSMatt Macy 417*eda14cbcSMatt Macy return (error); 418*eda14cbcSMatt Macy } 419*eda14cbcSMatt Macy 420*eda14cbcSMatt Macy static nvlist_t * 421*eda14cbcSMatt Macy zutil_refresh_config(libpc_handle_t *hdl, nvlist_t *tryconfig) 422*eda14cbcSMatt Macy { 423*eda14cbcSMatt Macy ASSERT(hdl->lpc_ops->pco_refresh_config != NULL); 424*eda14cbcSMatt Macy 425*eda14cbcSMatt Macy return (hdl->lpc_ops->pco_refresh_config(hdl->lpc_lib_handle, 426*eda14cbcSMatt Macy tryconfig)); 427*eda14cbcSMatt Macy } 428*eda14cbcSMatt Macy 429*eda14cbcSMatt Macy /* 430*eda14cbcSMatt Macy * Determine if the vdev id is a hole in the namespace. 431*eda14cbcSMatt Macy */ 432*eda14cbcSMatt Macy static boolean_t 433*eda14cbcSMatt Macy vdev_is_hole(uint64_t *hole_array, uint_t holes, uint_t id) 434*eda14cbcSMatt Macy { 435*eda14cbcSMatt Macy int c; 436*eda14cbcSMatt Macy 437*eda14cbcSMatt Macy for (c = 0; c < holes; c++) { 438*eda14cbcSMatt Macy 439*eda14cbcSMatt Macy /* Top-level is a hole */ 440*eda14cbcSMatt Macy if (hole_array[c] == id) 441*eda14cbcSMatt Macy return (B_TRUE); 442*eda14cbcSMatt Macy } 443*eda14cbcSMatt Macy return (B_FALSE); 444*eda14cbcSMatt Macy } 445*eda14cbcSMatt Macy 446*eda14cbcSMatt Macy /* 447*eda14cbcSMatt Macy * Convert our list of pools into the definitive set of configurations. We 448*eda14cbcSMatt Macy * start by picking the best config for each toplevel vdev. Once that's done, 449*eda14cbcSMatt Macy * we assemble the toplevel vdevs into a full config for the pool. We make a 450*eda14cbcSMatt Macy * pass to fix up any incorrect paths, and then add it to the main list to 451*eda14cbcSMatt Macy * return to the user. 452*eda14cbcSMatt Macy */ 453*eda14cbcSMatt Macy static nvlist_t * 454*eda14cbcSMatt Macy get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, 455*eda14cbcSMatt Macy nvlist_t *policy) 456*eda14cbcSMatt Macy { 457*eda14cbcSMatt Macy pool_entry_t *pe; 458*eda14cbcSMatt Macy vdev_entry_t *ve; 459*eda14cbcSMatt Macy config_entry_t *ce; 460*eda14cbcSMatt Macy nvlist_t *ret = NULL, *config = NULL, *tmp = NULL, *nvtop, *nvroot; 461*eda14cbcSMatt Macy nvlist_t **spares, **l2cache; 462*eda14cbcSMatt Macy uint_t i, nspares, nl2cache; 463*eda14cbcSMatt Macy boolean_t config_seen; 464*eda14cbcSMatt Macy uint64_t best_txg; 465*eda14cbcSMatt Macy char *name, *hostname = NULL; 466*eda14cbcSMatt Macy uint64_t guid; 467*eda14cbcSMatt Macy uint_t children = 0; 468*eda14cbcSMatt Macy nvlist_t **child = NULL; 469*eda14cbcSMatt Macy uint_t holes; 470*eda14cbcSMatt Macy uint64_t *hole_array, max_id; 471*eda14cbcSMatt Macy uint_t c; 472*eda14cbcSMatt Macy boolean_t isactive; 473*eda14cbcSMatt Macy uint64_t hostid; 474*eda14cbcSMatt Macy nvlist_t *nvl; 475*eda14cbcSMatt Macy boolean_t valid_top_config = B_FALSE; 476*eda14cbcSMatt Macy 477*eda14cbcSMatt Macy if (nvlist_alloc(&ret, 0, 0) != 0) 478*eda14cbcSMatt Macy goto nomem; 479*eda14cbcSMatt Macy 480*eda14cbcSMatt Macy for (pe = pl->pools; pe != NULL; pe = pe->pe_next) { 481*eda14cbcSMatt Macy uint64_t id, max_txg = 0; 482*eda14cbcSMatt Macy 483*eda14cbcSMatt Macy if (nvlist_alloc(&config, NV_UNIQUE_NAME, 0) != 0) 484*eda14cbcSMatt Macy goto nomem; 485*eda14cbcSMatt Macy config_seen = B_FALSE; 486*eda14cbcSMatt Macy 487*eda14cbcSMatt Macy /* 488*eda14cbcSMatt Macy * Iterate over all toplevel vdevs. Grab the pool configuration 489*eda14cbcSMatt Macy * from the first one we find, and then go through the rest and 490*eda14cbcSMatt Macy * add them as necessary to the 'vdevs' member of the config. 491*eda14cbcSMatt Macy */ 492*eda14cbcSMatt Macy for (ve = pe->pe_vdevs; ve != NULL; ve = ve->ve_next) { 493*eda14cbcSMatt Macy 494*eda14cbcSMatt Macy /* 495*eda14cbcSMatt Macy * Determine the best configuration for this vdev by 496*eda14cbcSMatt Macy * selecting the config with the latest transaction 497*eda14cbcSMatt Macy * group. 498*eda14cbcSMatt Macy */ 499*eda14cbcSMatt Macy best_txg = 0; 500*eda14cbcSMatt Macy for (ce = ve->ve_configs; ce != NULL; 501*eda14cbcSMatt Macy ce = ce->ce_next) { 502*eda14cbcSMatt Macy 503*eda14cbcSMatt Macy if (ce->ce_txg > best_txg) { 504*eda14cbcSMatt Macy tmp = ce->ce_config; 505*eda14cbcSMatt Macy best_txg = ce->ce_txg; 506*eda14cbcSMatt Macy } 507*eda14cbcSMatt Macy } 508*eda14cbcSMatt Macy 509*eda14cbcSMatt Macy /* 510*eda14cbcSMatt Macy * We rely on the fact that the max txg for the 511*eda14cbcSMatt Macy * pool will contain the most up-to-date information 512*eda14cbcSMatt Macy * about the valid top-levels in the vdev namespace. 513*eda14cbcSMatt Macy */ 514*eda14cbcSMatt Macy if (best_txg > max_txg) { 515*eda14cbcSMatt Macy (void) nvlist_remove(config, 516*eda14cbcSMatt Macy ZPOOL_CONFIG_VDEV_CHILDREN, 517*eda14cbcSMatt Macy DATA_TYPE_UINT64); 518*eda14cbcSMatt Macy (void) nvlist_remove(config, 519*eda14cbcSMatt Macy ZPOOL_CONFIG_HOLE_ARRAY, 520*eda14cbcSMatt Macy DATA_TYPE_UINT64_ARRAY); 521*eda14cbcSMatt Macy 522*eda14cbcSMatt Macy max_txg = best_txg; 523*eda14cbcSMatt Macy hole_array = NULL; 524*eda14cbcSMatt Macy holes = 0; 525*eda14cbcSMatt Macy max_id = 0; 526*eda14cbcSMatt Macy valid_top_config = B_FALSE; 527*eda14cbcSMatt Macy 528*eda14cbcSMatt Macy if (nvlist_lookup_uint64(tmp, 529*eda14cbcSMatt Macy ZPOOL_CONFIG_VDEV_CHILDREN, &max_id) == 0) { 530*eda14cbcSMatt Macy verify(nvlist_add_uint64(config, 531*eda14cbcSMatt Macy ZPOOL_CONFIG_VDEV_CHILDREN, 532*eda14cbcSMatt Macy max_id) == 0); 533*eda14cbcSMatt Macy valid_top_config = B_TRUE; 534*eda14cbcSMatt Macy } 535*eda14cbcSMatt Macy 536*eda14cbcSMatt Macy if (nvlist_lookup_uint64_array(tmp, 537*eda14cbcSMatt Macy ZPOOL_CONFIG_HOLE_ARRAY, &hole_array, 538*eda14cbcSMatt Macy &holes) == 0) { 539*eda14cbcSMatt Macy verify(nvlist_add_uint64_array(config, 540*eda14cbcSMatt Macy ZPOOL_CONFIG_HOLE_ARRAY, 541*eda14cbcSMatt Macy hole_array, holes) == 0); 542*eda14cbcSMatt Macy } 543*eda14cbcSMatt Macy } 544*eda14cbcSMatt Macy 545*eda14cbcSMatt Macy if (!config_seen) { 546*eda14cbcSMatt Macy /* 547*eda14cbcSMatt Macy * Copy the relevant pieces of data to the pool 548*eda14cbcSMatt Macy * configuration: 549*eda14cbcSMatt Macy * 550*eda14cbcSMatt Macy * version 551*eda14cbcSMatt Macy * pool guid 552*eda14cbcSMatt Macy * name 553*eda14cbcSMatt Macy * comment (if available) 554*eda14cbcSMatt Macy * pool state 555*eda14cbcSMatt Macy * hostid (if available) 556*eda14cbcSMatt Macy * hostname (if available) 557*eda14cbcSMatt Macy */ 558*eda14cbcSMatt Macy uint64_t state, version; 559*eda14cbcSMatt Macy char *comment = NULL; 560*eda14cbcSMatt Macy 561*eda14cbcSMatt Macy version = fnvlist_lookup_uint64(tmp, 562*eda14cbcSMatt Macy ZPOOL_CONFIG_VERSION); 563*eda14cbcSMatt Macy fnvlist_add_uint64(config, 564*eda14cbcSMatt Macy ZPOOL_CONFIG_VERSION, version); 565*eda14cbcSMatt Macy guid = fnvlist_lookup_uint64(tmp, 566*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_GUID); 567*eda14cbcSMatt Macy fnvlist_add_uint64(config, 568*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_GUID, guid); 569*eda14cbcSMatt Macy name = fnvlist_lookup_string(tmp, 570*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_NAME); 571*eda14cbcSMatt Macy fnvlist_add_string(config, 572*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_NAME, name); 573*eda14cbcSMatt Macy 574*eda14cbcSMatt Macy if (nvlist_lookup_string(tmp, 575*eda14cbcSMatt Macy ZPOOL_CONFIG_COMMENT, &comment) == 0) 576*eda14cbcSMatt Macy fnvlist_add_string(config, 577*eda14cbcSMatt Macy ZPOOL_CONFIG_COMMENT, comment); 578*eda14cbcSMatt Macy 579*eda14cbcSMatt Macy state = fnvlist_lookup_uint64(tmp, 580*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_STATE); 581*eda14cbcSMatt Macy fnvlist_add_uint64(config, 582*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_STATE, state); 583*eda14cbcSMatt Macy 584*eda14cbcSMatt Macy hostid = 0; 585*eda14cbcSMatt Macy if (nvlist_lookup_uint64(tmp, 586*eda14cbcSMatt Macy ZPOOL_CONFIG_HOSTID, &hostid) == 0) { 587*eda14cbcSMatt Macy fnvlist_add_uint64(config, 588*eda14cbcSMatt Macy ZPOOL_CONFIG_HOSTID, hostid); 589*eda14cbcSMatt Macy hostname = fnvlist_lookup_string(tmp, 590*eda14cbcSMatt Macy ZPOOL_CONFIG_HOSTNAME); 591*eda14cbcSMatt Macy fnvlist_add_string(config, 592*eda14cbcSMatt Macy ZPOOL_CONFIG_HOSTNAME, hostname); 593*eda14cbcSMatt Macy } 594*eda14cbcSMatt Macy 595*eda14cbcSMatt Macy config_seen = B_TRUE; 596*eda14cbcSMatt Macy } 597*eda14cbcSMatt Macy 598*eda14cbcSMatt Macy /* 599*eda14cbcSMatt Macy * Add this top-level vdev to the child array. 600*eda14cbcSMatt Macy */ 601*eda14cbcSMatt Macy verify(nvlist_lookup_nvlist(tmp, 602*eda14cbcSMatt Macy ZPOOL_CONFIG_VDEV_TREE, &nvtop) == 0); 603*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(nvtop, ZPOOL_CONFIG_ID, 604*eda14cbcSMatt Macy &id) == 0); 605*eda14cbcSMatt Macy 606*eda14cbcSMatt Macy if (id >= children) { 607*eda14cbcSMatt Macy nvlist_t **newchild; 608*eda14cbcSMatt Macy 609*eda14cbcSMatt Macy newchild = zutil_alloc(hdl, (id + 1) * 610*eda14cbcSMatt Macy sizeof (nvlist_t *)); 611*eda14cbcSMatt Macy if (newchild == NULL) 612*eda14cbcSMatt Macy goto nomem; 613*eda14cbcSMatt Macy 614*eda14cbcSMatt Macy for (c = 0; c < children; c++) 615*eda14cbcSMatt Macy newchild[c] = child[c]; 616*eda14cbcSMatt Macy 617*eda14cbcSMatt Macy free(child); 618*eda14cbcSMatt Macy child = newchild; 619*eda14cbcSMatt Macy children = id + 1; 620*eda14cbcSMatt Macy } 621*eda14cbcSMatt Macy if (nvlist_dup(nvtop, &child[id], 0) != 0) 622*eda14cbcSMatt Macy goto nomem; 623*eda14cbcSMatt Macy 624*eda14cbcSMatt Macy } 625*eda14cbcSMatt Macy 626*eda14cbcSMatt Macy /* 627*eda14cbcSMatt Macy * If we have information about all the top-levels then 628*eda14cbcSMatt Macy * clean up the nvlist which we've constructed. This 629*eda14cbcSMatt Macy * means removing any extraneous devices that are 630*eda14cbcSMatt Macy * beyond the valid range or adding devices to the end 631*eda14cbcSMatt Macy * of our array which appear to be missing. 632*eda14cbcSMatt Macy */ 633*eda14cbcSMatt Macy if (valid_top_config) { 634*eda14cbcSMatt Macy if (max_id < children) { 635*eda14cbcSMatt Macy for (c = max_id; c < children; c++) 636*eda14cbcSMatt Macy nvlist_free(child[c]); 637*eda14cbcSMatt Macy children = max_id; 638*eda14cbcSMatt Macy } else if (max_id > children) { 639*eda14cbcSMatt Macy nvlist_t **newchild; 640*eda14cbcSMatt Macy 641*eda14cbcSMatt Macy newchild = zutil_alloc(hdl, (max_id) * 642*eda14cbcSMatt Macy sizeof (nvlist_t *)); 643*eda14cbcSMatt Macy if (newchild == NULL) 644*eda14cbcSMatt Macy goto nomem; 645*eda14cbcSMatt Macy 646*eda14cbcSMatt Macy for (c = 0; c < children; c++) 647*eda14cbcSMatt Macy newchild[c] = child[c]; 648*eda14cbcSMatt Macy 649*eda14cbcSMatt Macy free(child); 650*eda14cbcSMatt Macy child = newchild; 651*eda14cbcSMatt Macy children = max_id; 652*eda14cbcSMatt Macy } 653*eda14cbcSMatt Macy } 654*eda14cbcSMatt Macy 655*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 656*eda14cbcSMatt Macy &guid) == 0); 657*eda14cbcSMatt Macy 658*eda14cbcSMatt Macy /* 659*eda14cbcSMatt Macy * The vdev namespace may contain holes as a result of 660*eda14cbcSMatt Macy * device removal. We must add them back into the vdev 661*eda14cbcSMatt Macy * tree before we process any missing devices. 662*eda14cbcSMatt Macy */ 663*eda14cbcSMatt Macy if (holes > 0) { 664*eda14cbcSMatt Macy ASSERT(valid_top_config); 665*eda14cbcSMatt Macy 666*eda14cbcSMatt Macy for (c = 0; c < children; c++) { 667*eda14cbcSMatt Macy nvlist_t *holey; 668*eda14cbcSMatt Macy 669*eda14cbcSMatt Macy if (child[c] != NULL || 670*eda14cbcSMatt Macy !vdev_is_hole(hole_array, holes, c)) 671*eda14cbcSMatt Macy continue; 672*eda14cbcSMatt Macy 673*eda14cbcSMatt Macy if (nvlist_alloc(&holey, NV_UNIQUE_NAME, 674*eda14cbcSMatt Macy 0) != 0) 675*eda14cbcSMatt Macy goto nomem; 676*eda14cbcSMatt Macy 677*eda14cbcSMatt Macy /* 678*eda14cbcSMatt Macy * Holes in the namespace are treated as 679*eda14cbcSMatt Macy * "hole" top-level vdevs and have a 680*eda14cbcSMatt Macy * special flag set on them. 681*eda14cbcSMatt Macy */ 682*eda14cbcSMatt Macy if (nvlist_add_string(holey, 683*eda14cbcSMatt Macy ZPOOL_CONFIG_TYPE, 684*eda14cbcSMatt Macy VDEV_TYPE_HOLE) != 0 || 685*eda14cbcSMatt Macy nvlist_add_uint64(holey, 686*eda14cbcSMatt Macy ZPOOL_CONFIG_ID, c) != 0 || 687*eda14cbcSMatt Macy nvlist_add_uint64(holey, 688*eda14cbcSMatt Macy ZPOOL_CONFIG_GUID, 0ULL) != 0) { 689*eda14cbcSMatt Macy nvlist_free(holey); 690*eda14cbcSMatt Macy goto nomem; 691*eda14cbcSMatt Macy } 692*eda14cbcSMatt Macy child[c] = holey; 693*eda14cbcSMatt Macy } 694*eda14cbcSMatt Macy } 695*eda14cbcSMatt Macy 696*eda14cbcSMatt Macy /* 697*eda14cbcSMatt Macy * Look for any missing top-level vdevs. If this is the case, 698*eda14cbcSMatt Macy * create a faked up 'missing' vdev as a placeholder. We cannot 699*eda14cbcSMatt Macy * simply compress the child array, because the kernel performs 700*eda14cbcSMatt Macy * certain checks to make sure the vdev IDs match their location 701*eda14cbcSMatt Macy * in the configuration. 702*eda14cbcSMatt Macy */ 703*eda14cbcSMatt Macy for (c = 0; c < children; c++) { 704*eda14cbcSMatt Macy if (child[c] == NULL) { 705*eda14cbcSMatt Macy nvlist_t *missing; 706*eda14cbcSMatt Macy if (nvlist_alloc(&missing, NV_UNIQUE_NAME, 707*eda14cbcSMatt Macy 0) != 0) 708*eda14cbcSMatt Macy goto nomem; 709*eda14cbcSMatt Macy if (nvlist_add_string(missing, 710*eda14cbcSMatt Macy ZPOOL_CONFIG_TYPE, 711*eda14cbcSMatt Macy VDEV_TYPE_MISSING) != 0 || 712*eda14cbcSMatt Macy nvlist_add_uint64(missing, 713*eda14cbcSMatt Macy ZPOOL_CONFIG_ID, c) != 0 || 714*eda14cbcSMatt Macy nvlist_add_uint64(missing, 715*eda14cbcSMatt Macy ZPOOL_CONFIG_GUID, 0ULL) != 0) { 716*eda14cbcSMatt Macy nvlist_free(missing); 717*eda14cbcSMatt Macy goto nomem; 718*eda14cbcSMatt Macy } 719*eda14cbcSMatt Macy child[c] = missing; 720*eda14cbcSMatt Macy } 721*eda14cbcSMatt Macy } 722*eda14cbcSMatt Macy 723*eda14cbcSMatt Macy /* 724*eda14cbcSMatt Macy * Put all of this pool's top-level vdevs into a root vdev. 725*eda14cbcSMatt Macy */ 726*eda14cbcSMatt Macy if (nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) != 0) 727*eda14cbcSMatt Macy goto nomem; 728*eda14cbcSMatt Macy if (nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, 729*eda14cbcSMatt Macy VDEV_TYPE_ROOT) != 0 || 730*eda14cbcSMatt Macy nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) != 0 || 731*eda14cbcSMatt Macy nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, guid) != 0 || 732*eda14cbcSMatt Macy nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 733*eda14cbcSMatt Macy child, children) != 0) { 734*eda14cbcSMatt Macy nvlist_free(nvroot); 735*eda14cbcSMatt Macy goto nomem; 736*eda14cbcSMatt Macy } 737*eda14cbcSMatt Macy 738*eda14cbcSMatt Macy for (c = 0; c < children; c++) 739*eda14cbcSMatt Macy nvlist_free(child[c]); 740*eda14cbcSMatt Macy free(child); 741*eda14cbcSMatt Macy children = 0; 742*eda14cbcSMatt Macy child = NULL; 743*eda14cbcSMatt Macy 744*eda14cbcSMatt Macy /* 745*eda14cbcSMatt Macy * Go through and fix up any paths and/or devids based on our 746*eda14cbcSMatt Macy * known list of vdev GUID -> path mappings. 747*eda14cbcSMatt Macy */ 748*eda14cbcSMatt Macy if (fix_paths(hdl, nvroot, pl->names) != 0) { 749*eda14cbcSMatt Macy nvlist_free(nvroot); 750*eda14cbcSMatt Macy goto nomem; 751*eda14cbcSMatt Macy } 752*eda14cbcSMatt Macy 753*eda14cbcSMatt Macy /* 754*eda14cbcSMatt Macy * Add the root vdev to this pool's configuration. 755*eda14cbcSMatt Macy */ 756*eda14cbcSMatt Macy if (nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 757*eda14cbcSMatt Macy nvroot) != 0) { 758*eda14cbcSMatt Macy nvlist_free(nvroot); 759*eda14cbcSMatt Macy goto nomem; 760*eda14cbcSMatt Macy } 761*eda14cbcSMatt Macy nvlist_free(nvroot); 762*eda14cbcSMatt Macy 763*eda14cbcSMatt Macy /* 764*eda14cbcSMatt Macy * zdb uses this path to report on active pools that were 765*eda14cbcSMatt Macy * imported or created using -R. 766*eda14cbcSMatt Macy */ 767*eda14cbcSMatt Macy if (active_ok) 768*eda14cbcSMatt Macy goto add_pool; 769*eda14cbcSMatt Macy 770*eda14cbcSMatt Macy /* 771*eda14cbcSMatt Macy * Determine if this pool is currently active, in which case we 772*eda14cbcSMatt Macy * can't actually import it. 773*eda14cbcSMatt Macy */ 774*eda14cbcSMatt Macy verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 775*eda14cbcSMatt Macy &name) == 0); 776*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 777*eda14cbcSMatt Macy &guid) == 0); 778*eda14cbcSMatt Macy 779*eda14cbcSMatt Macy if (zutil_pool_active(hdl, name, guid, &isactive) != 0) 780*eda14cbcSMatt Macy goto error; 781*eda14cbcSMatt Macy 782*eda14cbcSMatt Macy if (isactive) { 783*eda14cbcSMatt Macy nvlist_free(config); 784*eda14cbcSMatt Macy config = NULL; 785*eda14cbcSMatt Macy continue; 786*eda14cbcSMatt Macy } 787*eda14cbcSMatt Macy 788*eda14cbcSMatt Macy if (policy != NULL) { 789*eda14cbcSMatt Macy if (nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 790*eda14cbcSMatt Macy policy) != 0) 791*eda14cbcSMatt Macy goto nomem; 792*eda14cbcSMatt Macy } 793*eda14cbcSMatt Macy 794*eda14cbcSMatt Macy if ((nvl = zutil_refresh_config(hdl, config)) == NULL) { 795*eda14cbcSMatt Macy nvlist_free(config); 796*eda14cbcSMatt Macy config = NULL; 797*eda14cbcSMatt Macy continue; 798*eda14cbcSMatt Macy } 799*eda14cbcSMatt Macy 800*eda14cbcSMatt Macy nvlist_free(config); 801*eda14cbcSMatt Macy config = nvl; 802*eda14cbcSMatt Macy 803*eda14cbcSMatt Macy /* 804*eda14cbcSMatt Macy * Go through and update the paths for spares, now that we have 805*eda14cbcSMatt Macy * them. 806*eda14cbcSMatt Macy */ 807*eda14cbcSMatt Macy verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 808*eda14cbcSMatt Macy &nvroot) == 0); 809*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 810*eda14cbcSMatt Macy &spares, &nspares) == 0) { 811*eda14cbcSMatt Macy for (i = 0; i < nspares; i++) { 812*eda14cbcSMatt Macy if (fix_paths(hdl, spares[i], pl->names) != 0) 813*eda14cbcSMatt Macy goto nomem; 814*eda14cbcSMatt Macy } 815*eda14cbcSMatt Macy } 816*eda14cbcSMatt Macy 817*eda14cbcSMatt Macy /* 818*eda14cbcSMatt Macy * Update the paths for l2cache devices. 819*eda14cbcSMatt Macy */ 820*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 821*eda14cbcSMatt Macy &l2cache, &nl2cache) == 0) { 822*eda14cbcSMatt Macy for (i = 0; i < nl2cache; i++) { 823*eda14cbcSMatt Macy if (fix_paths(hdl, l2cache[i], pl->names) != 0) 824*eda14cbcSMatt Macy goto nomem; 825*eda14cbcSMatt Macy } 826*eda14cbcSMatt Macy } 827*eda14cbcSMatt Macy 828*eda14cbcSMatt Macy /* 829*eda14cbcSMatt Macy * Restore the original information read from the actual label. 830*eda14cbcSMatt Macy */ 831*eda14cbcSMatt Macy (void) nvlist_remove(config, ZPOOL_CONFIG_HOSTID, 832*eda14cbcSMatt Macy DATA_TYPE_UINT64); 833*eda14cbcSMatt Macy (void) nvlist_remove(config, ZPOOL_CONFIG_HOSTNAME, 834*eda14cbcSMatt Macy DATA_TYPE_STRING); 835*eda14cbcSMatt Macy if (hostid != 0) { 836*eda14cbcSMatt Macy verify(nvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID, 837*eda14cbcSMatt Macy hostid) == 0); 838*eda14cbcSMatt Macy verify(nvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME, 839*eda14cbcSMatt Macy hostname) == 0); 840*eda14cbcSMatt Macy } 841*eda14cbcSMatt Macy 842*eda14cbcSMatt Macy add_pool: 843*eda14cbcSMatt Macy /* 844*eda14cbcSMatt Macy * Add this pool to the list of configs. 845*eda14cbcSMatt Macy */ 846*eda14cbcSMatt Macy verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 847*eda14cbcSMatt Macy &name) == 0); 848*eda14cbcSMatt Macy 849*eda14cbcSMatt Macy if (nvlist_add_nvlist(ret, name, config) != 0) 850*eda14cbcSMatt Macy goto nomem; 851*eda14cbcSMatt Macy 852*eda14cbcSMatt Macy nvlist_free(config); 853*eda14cbcSMatt Macy config = NULL; 854*eda14cbcSMatt Macy } 855*eda14cbcSMatt Macy 856*eda14cbcSMatt Macy return (ret); 857*eda14cbcSMatt Macy 858*eda14cbcSMatt Macy nomem: 859*eda14cbcSMatt Macy (void) zutil_no_memory(hdl); 860*eda14cbcSMatt Macy error: 861*eda14cbcSMatt Macy nvlist_free(config); 862*eda14cbcSMatt Macy nvlist_free(ret); 863*eda14cbcSMatt Macy for (c = 0; c < children; c++) 864*eda14cbcSMatt Macy nvlist_free(child[c]); 865*eda14cbcSMatt Macy free(child); 866*eda14cbcSMatt Macy 867*eda14cbcSMatt Macy return (NULL); 868*eda14cbcSMatt Macy } 869*eda14cbcSMatt Macy 870*eda14cbcSMatt Macy /* 871*eda14cbcSMatt Macy * Return the offset of the given label. 872*eda14cbcSMatt Macy */ 873*eda14cbcSMatt Macy static uint64_t 874*eda14cbcSMatt Macy label_offset(uint64_t size, int l) 875*eda14cbcSMatt Macy { 876*eda14cbcSMatt Macy ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0); 877*eda14cbcSMatt Macy return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? 878*eda14cbcSMatt Macy 0 : size - VDEV_LABELS * sizeof (vdev_label_t))); 879*eda14cbcSMatt Macy } 880*eda14cbcSMatt Macy 881*eda14cbcSMatt Macy /* 882*eda14cbcSMatt Macy * Given a file descriptor, read the label information and return an nvlist 883*eda14cbcSMatt Macy * describing the configuration, if there is one. The number of valid 884*eda14cbcSMatt Macy * labels found will be returned in num_labels when non-NULL. 885*eda14cbcSMatt Macy */ 886*eda14cbcSMatt Macy int 887*eda14cbcSMatt Macy zpool_read_label(int fd, nvlist_t **config, int *num_labels) 888*eda14cbcSMatt Macy { 889*eda14cbcSMatt Macy struct stat64 statbuf; 890*eda14cbcSMatt Macy int l, count = 0; 891*eda14cbcSMatt Macy vdev_label_t *label; 892*eda14cbcSMatt Macy nvlist_t *expected_config = NULL; 893*eda14cbcSMatt Macy uint64_t expected_guid = 0, size; 894*eda14cbcSMatt Macy int error; 895*eda14cbcSMatt Macy 896*eda14cbcSMatt Macy *config = NULL; 897*eda14cbcSMatt Macy 898*eda14cbcSMatt Macy if (fstat64_blk(fd, &statbuf) == -1) 899*eda14cbcSMatt Macy return (0); 900*eda14cbcSMatt Macy size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); 901*eda14cbcSMatt Macy 902*eda14cbcSMatt Macy error = posix_memalign((void **)&label, PAGESIZE, sizeof (*label)); 903*eda14cbcSMatt Macy if (error) 904*eda14cbcSMatt Macy return (-1); 905*eda14cbcSMatt Macy 906*eda14cbcSMatt Macy for (l = 0; l < VDEV_LABELS; l++) { 907*eda14cbcSMatt Macy uint64_t state, guid, txg; 908*eda14cbcSMatt Macy 909*eda14cbcSMatt Macy if (pread64(fd, label, sizeof (vdev_label_t), 910*eda14cbcSMatt Macy label_offset(size, l)) != sizeof (vdev_label_t)) 911*eda14cbcSMatt Macy continue; 912*eda14cbcSMatt Macy 913*eda14cbcSMatt Macy if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, 914*eda14cbcSMatt Macy sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0) 915*eda14cbcSMatt Macy continue; 916*eda14cbcSMatt Macy 917*eda14cbcSMatt Macy if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_GUID, 918*eda14cbcSMatt Macy &guid) != 0 || guid == 0) { 919*eda14cbcSMatt Macy nvlist_free(*config); 920*eda14cbcSMatt Macy continue; 921*eda14cbcSMatt Macy } 922*eda14cbcSMatt Macy 923*eda14cbcSMatt Macy if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE, 924*eda14cbcSMatt Macy &state) != 0 || state > POOL_STATE_L2CACHE) { 925*eda14cbcSMatt Macy nvlist_free(*config); 926*eda14cbcSMatt Macy continue; 927*eda14cbcSMatt Macy } 928*eda14cbcSMatt Macy 929*eda14cbcSMatt Macy if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE && 930*eda14cbcSMatt Macy (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG, 931*eda14cbcSMatt Macy &txg) != 0 || txg == 0)) { 932*eda14cbcSMatt Macy nvlist_free(*config); 933*eda14cbcSMatt Macy continue; 934*eda14cbcSMatt Macy } 935*eda14cbcSMatt Macy 936*eda14cbcSMatt Macy if (expected_guid) { 937*eda14cbcSMatt Macy if (expected_guid == guid) 938*eda14cbcSMatt Macy count++; 939*eda14cbcSMatt Macy 940*eda14cbcSMatt Macy nvlist_free(*config); 941*eda14cbcSMatt Macy } else { 942*eda14cbcSMatt Macy expected_config = *config; 943*eda14cbcSMatt Macy expected_guid = guid; 944*eda14cbcSMatt Macy count++; 945*eda14cbcSMatt Macy } 946*eda14cbcSMatt Macy } 947*eda14cbcSMatt Macy 948*eda14cbcSMatt Macy if (num_labels != NULL) 949*eda14cbcSMatt Macy *num_labels = count; 950*eda14cbcSMatt Macy 951*eda14cbcSMatt Macy free(label); 952*eda14cbcSMatt Macy *config = expected_config; 953*eda14cbcSMatt Macy 954*eda14cbcSMatt Macy return (0); 955*eda14cbcSMatt Macy } 956*eda14cbcSMatt Macy 957*eda14cbcSMatt Macy /* 958*eda14cbcSMatt Macy * Sorted by full path and then vdev guid to allow for multiple entries with 959*eda14cbcSMatt Macy * the same full path name. This is required because it's possible to 960*eda14cbcSMatt Macy * have multiple block devices with labels that refer to the same 961*eda14cbcSMatt Macy * ZPOOL_CONFIG_PATH yet have different vdev guids. In this case both 962*eda14cbcSMatt Macy * entries need to be added to the cache. Scenarios where this can occur 963*eda14cbcSMatt Macy * include overwritten pool labels, devices which are visible from multiple 964*eda14cbcSMatt Macy * hosts and multipath devices. 965*eda14cbcSMatt Macy */ 966*eda14cbcSMatt Macy int 967*eda14cbcSMatt Macy slice_cache_compare(const void *arg1, const void *arg2) 968*eda14cbcSMatt Macy { 969*eda14cbcSMatt Macy const char *nm1 = ((rdsk_node_t *)arg1)->rn_name; 970*eda14cbcSMatt Macy const char *nm2 = ((rdsk_node_t *)arg2)->rn_name; 971*eda14cbcSMatt Macy uint64_t guid1 = ((rdsk_node_t *)arg1)->rn_vdev_guid; 972*eda14cbcSMatt Macy uint64_t guid2 = ((rdsk_node_t *)arg2)->rn_vdev_guid; 973*eda14cbcSMatt Macy int rv; 974*eda14cbcSMatt Macy 975*eda14cbcSMatt Macy rv = TREE_ISIGN(strcmp(nm1, nm2)); 976*eda14cbcSMatt Macy if (rv) 977*eda14cbcSMatt Macy return (rv); 978*eda14cbcSMatt Macy 979*eda14cbcSMatt Macy return (TREE_CMP(guid1, guid2)); 980*eda14cbcSMatt Macy } 981*eda14cbcSMatt Macy 982*eda14cbcSMatt Macy static int 983*eda14cbcSMatt Macy label_paths_impl(libpc_handle_t *hdl, nvlist_t *nvroot, uint64_t pool_guid, 984*eda14cbcSMatt Macy uint64_t vdev_guid, char **path, char **devid) 985*eda14cbcSMatt Macy { 986*eda14cbcSMatt Macy nvlist_t **child; 987*eda14cbcSMatt Macy uint_t c, children; 988*eda14cbcSMatt Macy uint64_t guid; 989*eda14cbcSMatt Macy char *val; 990*eda14cbcSMatt Macy int error; 991*eda14cbcSMatt Macy 992*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 993*eda14cbcSMatt Macy &child, &children) == 0) { 994*eda14cbcSMatt Macy for (c = 0; c < children; c++) { 995*eda14cbcSMatt Macy error = label_paths_impl(hdl, child[c], 996*eda14cbcSMatt Macy pool_guid, vdev_guid, path, devid); 997*eda14cbcSMatt Macy if (error) 998*eda14cbcSMatt Macy return (error); 999*eda14cbcSMatt Macy } 1000*eda14cbcSMatt Macy return (0); 1001*eda14cbcSMatt Macy } 1002*eda14cbcSMatt Macy 1003*eda14cbcSMatt Macy if (nvroot == NULL) 1004*eda14cbcSMatt Macy return (0); 1005*eda14cbcSMatt Macy 1006*eda14cbcSMatt Macy error = nvlist_lookup_uint64(nvroot, ZPOOL_CONFIG_GUID, &guid); 1007*eda14cbcSMatt Macy if ((error != 0) || (guid != vdev_guid)) 1008*eda14cbcSMatt Macy return (0); 1009*eda14cbcSMatt Macy 1010*eda14cbcSMatt Macy error = nvlist_lookup_string(nvroot, ZPOOL_CONFIG_PATH, &val); 1011*eda14cbcSMatt Macy if (error == 0) 1012*eda14cbcSMatt Macy *path = val; 1013*eda14cbcSMatt Macy 1014*eda14cbcSMatt Macy error = nvlist_lookup_string(nvroot, ZPOOL_CONFIG_DEVID, &val); 1015*eda14cbcSMatt Macy if (error == 0) 1016*eda14cbcSMatt Macy *devid = val; 1017*eda14cbcSMatt Macy 1018*eda14cbcSMatt Macy return (0); 1019*eda14cbcSMatt Macy } 1020*eda14cbcSMatt Macy 1021*eda14cbcSMatt Macy /* 1022*eda14cbcSMatt Macy * Given a disk label fetch the ZPOOL_CONFIG_PATH and ZPOOL_CONFIG_DEVID 1023*eda14cbcSMatt Macy * and store these strings as config_path and devid_path respectively. 1024*eda14cbcSMatt Macy * The returned pointers are only valid as long as label remains valid. 1025*eda14cbcSMatt Macy */ 1026*eda14cbcSMatt Macy int 1027*eda14cbcSMatt Macy label_paths(libpc_handle_t *hdl, nvlist_t *label, char **path, char **devid) 1028*eda14cbcSMatt Macy { 1029*eda14cbcSMatt Macy nvlist_t *nvroot; 1030*eda14cbcSMatt Macy uint64_t pool_guid; 1031*eda14cbcSMatt Macy uint64_t vdev_guid; 1032*eda14cbcSMatt Macy 1033*eda14cbcSMatt Macy *path = NULL; 1034*eda14cbcSMatt Macy *devid = NULL; 1035*eda14cbcSMatt Macy 1036*eda14cbcSMatt Macy if (nvlist_lookup_nvlist(label, ZPOOL_CONFIG_VDEV_TREE, &nvroot) || 1037*eda14cbcSMatt Macy nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid) || 1038*eda14cbcSMatt Macy nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid)) 1039*eda14cbcSMatt Macy return (ENOENT); 1040*eda14cbcSMatt Macy 1041*eda14cbcSMatt Macy return (label_paths_impl(hdl, nvroot, pool_guid, vdev_guid, path, 1042*eda14cbcSMatt Macy devid)); 1043*eda14cbcSMatt Macy } 1044*eda14cbcSMatt Macy 1045*eda14cbcSMatt Macy static void 1046*eda14cbcSMatt Macy zpool_find_import_scan_add_slice(libpc_handle_t *hdl, pthread_mutex_t *lock, 1047*eda14cbcSMatt Macy avl_tree_t *cache, const char *path, const char *name, int order) 1048*eda14cbcSMatt Macy { 1049*eda14cbcSMatt Macy avl_index_t where; 1050*eda14cbcSMatt Macy rdsk_node_t *slice; 1051*eda14cbcSMatt Macy 1052*eda14cbcSMatt Macy slice = zutil_alloc(hdl, sizeof (rdsk_node_t)); 1053*eda14cbcSMatt Macy if (asprintf(&slice->rn_name, "%s/%s", path, name) == -1) { 1054*eda14cbcSMatt Macy free(slice); 1055*eda14cbcSMatt Macy return; 1056*eda14cbcSMatt Macy } 1057*eda14cbcSMatt Macy slice->rn_vdev_guid = 0; 1058*eda14cbcSMatt Macy slice->rn_lock = lock; 1059*eda14cbcSMatt Macy slice->rn_avl = cache; 1060*eda14cbcSMatt Macy slice->rn_hdl = hdl; 1061*eda14cbcSMatt Macy slice->rn_order = order + IMPORT_ORDER_SCAN_OFFSET; 1062*eda14cbcSMatt Macy slice->rn_labelpaths = B_FALSE; 1063*eda14cbcSMatt Macy 1064*eda14cbcSMatt Macy pthread_mutex_lock(lock); 1065*eda14cbcSMatt Macy if (avl_find(cache, slice, &where)) { 1066*eda14cbcSMatt Macy free(slice->rn_name); 1067*eda14cbcSMatt Macy free(slice); 1068*eda14cbcSMatt Macy } else { 1069*eda14cbcSMatt Macy avl_insert(cache, slice, where); 1070*eda14cbcSMatt Macy } 1071*eda14cbcSMatt Macy pthread_mutex_unlock(lock); 1072*eda14cbcSMatt Macy } 1073*eda14cbcSMatt Macy 1074*eda14cbcSMatt Macy static int 1075*eda14cbcSMatt Macy zpool_find_import_scan_dir(libpc_handle_t *hdl, pthread_mutex_t *lock, 1076*eda14cbcSMatt Macy avl_tree_t *cache, const char *dir, int order) 1077*eda14cbcSMatt Macy { 1078*eda14cbcSMatt Macy int error; 1079*eda14cbcSMatt Macy char path[MAXPATHLEN]; 1080*eda14cbcSMatt Macy struct dirent64 *dp; 1081*eda14cbcSMatt Macy DIR *dirp; 1082*eda14cbcSMatt Macy 1083*eda14cbcSMatt Macy if (realpath(dir, path) == NULL) { 1084*eda14cbcSMatt Macy error = errno; 1085*eda14cbcSMatt Macy if (error == ENOENT) 1086*eda14cbcSMatt Macy return (0); 1087*eda14cbcSMatt Macy 1088*eda14cbcSMatt Macy zutil_error_aux(hdl, strerror(error)); 1089*eda14cbcSMatt Macy (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext( 1090*eda14cbcSMatt Macy TEXT_DOMAIN, "cannot resolve path '%s'"), dir); 1091*eda14cbcSMatt Macy return (error); 1092*eda14cbcSMatt Macy } 1093*eda14cbcSMatt Macy 1094*eda14cbcSMatt Macy dirp = opendir(path); 1095*eda14cbcSMatt Macy if (dirp == NULL) { 1096*eda14cbcSMatt Macy error = errno; 1097*eda14cbcSMatt Macy zutil_error_aux(hdl, strerror(error)); 1098*eda14cbcSMatt Macy (void) zutil_error_fmt(hdl, EZFS_BADPATH, 1099*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); 1100*eda14cbcSMatt Macy return (error); 1101*eda14cbcSMatt Macy } 1102*eda14cbcSMatt Macy 1103*eda14cbcSMatt Macy while ((dp = readdir64(dirp)) != NULL) { 1104*eda14cbcSMatt Macy const char *name = dp->d_name; 1105*eda14cbcSMatt Macy if (name[0] == '.' && 1106*eda14cbcSMatt Macy (name[1] == 0 || (name[1] == '.' && name[2] == 0))) 1107*eda14cbcSMatt Macy continue; 1108*eda14cbcSMatt Macy 1109*eda14cbcSMatt Macy zpool_find_import_scan_add_slice(hdl, lock, cache, path, name, 1110*eda14cbcSMatt Macy order); 1111*eda14cbcSMatt Macy } 1112*eda14cbcSMatt Macy 1113*eda14cbcSMatt Macy (void) closedir(dirp); 1114*eda14cbcSMatt Macy return (0); 1115*eda14cbcSMatt Macy } 1116*eda14cbcSMatt Macy 1117*eda14cbcSMatt Macy static int 1118*eda14cbcSMatt Macy zpool_find_import_scan_path(libpc_handle_t *hdl, pthread_mutex_t *lock, 1119*eda14cbcSMatt Macy avl_tree_t *cache, const char *dir, int order) 1120*eda14cbcSMatt Macy { 1121*eda14cbcSMatt Macy int error = 0; 1122*eda14cbcSMatt Macy char path[MAXPATHLEN]; 1123*eda14cbcSMatt Macy char *d, *b; 1124*eda14cbcSMatt Macy char *dpath, *name; 1125*eda14cbcSMatt Macy 1126*eda14cbcSMatt Macy /* 1127*eda14cbcSMatt Macy * Separate the directory part and last part of the 1128*eda14cbcSMatt Macy * path. We do this so that we can get the realpath of 1129*eda14cbcSMatt Macy * the directory. We don't get the realpath on the 1130*eda14cbcSMatt Macy * whole path because if it's a symlink, we want the 1131*eda14cbcSMatt Macy * path of the symlink not where it points to. 1132*eda14cbcSMatt Macy */ 1133*eda14cbcSMatt Macy d = zutil_strdup(hdl, dir); 1134*eda14cbcSMatt Macy b = zutil_strdup(hdl, dir); 1135*eda14cbcSMatt Macy dpath = dirname(d); 1136*eda14cbcSMatt Macy name = basename(b); 1137*eda14cbcSMatt Macy 1138*eda14cbcSMatt Macy if (realpath(dpath, path) == NULL) { 1139*eda14cbcSMatt Macy error = errno; 1140*eda14cbcSMatt Macy if (error == ENOENT) { 1141*eda14cbcSMatt Macy error = 0; 1142*eda14cbcSMatt Macy goto out; 1143*eda14cbcSMatt Macy } 1144*eda14cbcSMatt Macy 1145*eda14cbcSMatt Macy zutil_error_aux(hdl, strerror(error)); 1146*eda14cbcSMatt Macy (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext( 1147*eda14cbcSMatt Macy TEXT_DOMAIN, "cannot resolve path '%s'"), dir); 1148*eda14cbcSMatt Macy goto out; 1149*eda14cbcSMatt Macy } 1150*eda14cbcSMatt Macy 1151*eda14cbcSMatt Macy zpool_find_import_scan_add_slice(hdl, lock, cache, path, name, order); 1152*eda14cbcSMatt Macy 1153*eda14cbcSMatt Macy out: 1154*eda14cbcSMatt Macy free(b); 1155*eda14cbcSMatt Macy free(d); 1156*eda14cbcSMatt Macy return (error); 1157*eda14cbcSMatt Macy } 1158*eda14cbcSMatt Macy 1159*eda14cbcSMatt Macy /* 1160*eda14cbcSMatt Macy * Scan a list of directories for zfs devices. 1161*eda14cbcSMatt Macy */ 1162*eda14cbcSMatt Macy static int 1163*eda14cbcSMatt Macy zpool_find_import_scan(libpc_handle_t *hdl, pthread_mutex_t *lock, 1164*eda14cbcSMatt Macy avl_tree_t **slice_cache, const char * const *dir, size_t dirs) 1165*eda14cbcSMatt Macy { 1166*eda14cbcSMatt Macy avl_tree_t *cache; 1167*eda14cbcSMatt Macy rdsk_node_t *slice; 1168*eda14cbcSMatt Macy void *cookie; 1169*eda14cbcSMatt Macy int i, error; 1170*eda14cbcSMatt Macy 1171*eda14cbcSMatt Macy *slice_cache = NULL; 1172*eda14cbcSMatt Macy cache = zutil_alloc(hdl, sizeof (avl_tree_t)); 1173*eda14cbcSMatt Macy avl_create(cache, slice_cache_compare, sizeof (rdsk_node_t), 1174*eda14cbcSMatt Macy offsetof(rdsk_node_t, rn_node)); 1175*eda14cbcSMatt Macy 1176*eda14cbcSMatt Macy for (i = 0; i < dirs; i++) { 1177*eda14cbcSMatt Macy struct stat sbuf; 1178*eda14cbcSMatt Macy 1179*eda14cbcSMatt Macy if (stat(dir[i], &sbuf) != 0) { 1180*eda14cbcSMatt Macy error = errno; 1181*eda14cbcSMatt Macy if (error == ENOENT) 1182*eda14cbcSMatt Macy continue; 1183*eda14cbcSMatt Macy 1184*eda14cbcSMatt Macy zutil_error_aux(hdl, strerror(error)); 1185*eda14cbcSMatt Macy (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext( 1186*eda14cbcSMatt Macy TEXT_DOMAIN, "cannot resolve path '%s'"), dir[i]); 1187*eda14cbcSMatt Macy goto error; 1188*eda14cbcSMatt Macy } 1189*eda14cbcSMatt Macy 1190*eda14cbcSMatt Macy /* 1191*eda14cbcSMatt Macy * If dir[i] is a directory, we walk through it and add all 1192*eda14cbcSMatt Macy * the entries to the cache. If it's not a directory, we just 1193*eda14cbcSMatt Macy * add it to the cache. 1194*eda14cbcSMatt Macy */ 1195*eda14cbcSMatt Macy if (S_ISDIR(sbuf.st_mode)) { 1196*eda14cbcSMatt Macy if ((error = zpool_find_import_scan_dir(hdl, lock, 1197*eda14cbcSMatt Macy cache, dir[i], i)) != 0) 1198*eda14cbcSMatt Macy goto error; 1199*eda14cbcSMatt Macy } else { 1200*eda14cbcSMatt Macy if ((error = zpool_find_import_scan_path(hdl, lock, 1201*eda14cbcSMatt Macy cache, dir[i], i)) != 0) 1202*eda14cbcSMatt Macy goto error; 1203*eda14cbcSMatt Macy } 1204*eda14cbcSMatt Macy } 1205*eda14cbcSMatt Macy 1206*eda14cbcSMatt Macy *slice_cache = cache; 1207*eda14cbcSMatt Macy return (0); 1208*eda14cbcSMatt Macy 1209*eda14cbcSMatt Macy error: 1210*eda14cbcSMatt Macy cookie = NULL; 1211*eda14cbcSMatt Macy while ((slice = avl_destroy_nodes(cache, &cookie)) != NULL) { 1212*eda14cbcSMatt Macy free(slice->rn_name); 1213*eda14cbcSMatt Macy free(slice); 1214*eda14cbcSMatt Macy } 1215*eda14cbcSMatt Macy free(cache); 1216*eda14cbcSMatt Macy 1217*eda14cbcSMatt Macy return (error); 1218*eda14cbcSMatt Macy } 1219*eda14cbcSMatt Macy 1220*eda14cbcSMatt Macy /* 1221*eda14cbcSMatt Macy * Given a list of directories to search, find all pools stored on disk. This 1222*eda14cbcSMatt Macy * includes partial pools which are not available to import. If no args are 1223*eda14cbcSMatt Macy * given (argc is 0), then the default directory (/dev/dsk) is searched. 1224*eda14cbcSMatt Macy * poolname or guid (but not both) are provided by the caller when trying 1225*eda14cbcSMatt Macy * to import a specific pool. 1226*eda14cbcSMatt Macy */ 1227*eda14cbcSMatt Macy static nvlist_t * 1228*eda14cbcSMatt Macy zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg) 1229*eda14cbcSMatt Macy { 1230*eda14cbcSMatt Macy nvlist_t *ret = NULL; 1231*eda14cbcSMatt Macy pool_list_t pools = { 0 }; 1232*eda14cbcSMatt Macy pool_entry_t *pe, *penext; 1233*eda14cbcSMatt Macy vdev_entry_t *ve, *venext; 1234*eda14cbcSMatt Macy config_entry_t *ce, *cenext; 1235*eda14cbcSMatt Macy name_entry_t *ne, *nenext; 1236*eda14cbcSMatt Macy pthread_mutex_t lock; 1237*eda14cbcSMatt Macy avl_tree_t *cache; 1238*eda14cbcSMatt Macy rdsk_node_t *slice; 1239*eda14cbcSMatt Macy void *cookie; 1240*eda14cbcSMatt Macy tpool_t *t; 1241*eda14cbcSMatt Macy 1242*eda14cbcSMatt Macy verify(iarg->poolname == NULL || iarg->guid == 0); 1243*eda14cbcSMatt Macy pthread_mutex_init(&lock, NULL); 1244*eda14cbcSMatt Macy 1245*eda14cbcSMatt Macy /* 1246*eda14cbcSMatt Macy * Locate pool member vdevs by blkid or by directory scanning. 1247*eda14cbcSMatt Macy * On success a newly allocated AVL tree which is populated with an 1248*eda14cbcSMatt Macy * entry for each discovered vdev will be returned in the cache. 1249*eda14cbcSMatt Macy * It's the caller's responsibility to consume and destroy this tree. 1250*eda14cbcSMatt Macy */ 1251*eda14cbcSMatt Macy if (iarg->scan || iarg->paths != 0) { 1252*eda14cbcSMatt Macy size_t dirs = iarg->paths; 1253*eda14cbcSMatt Macy const char * const *dir = (const char * const *)iarg->path; 1254*eda14cbcSMatt Macy 1255*eda14cbcSMatt Macy if (dirs == 0) 1256*eda14cbcSMatt Macy dir = zpool_default_search_paths(&dirs); 1257*eda14cbcSMatt Macy 1258*eda14cbcSMatt Macy if (zpool_find_import_scan(hdl, &lock, &cache, dir, dirs) != 0) 1259*eda14cbcSMatt Macy return (NULL); 1260*eda14cbcSMatt Macy } else { 1261*eda14cbcSMatt Macy if (zpool_find_import_blkid(hdl, &lock, &cache) != 0) 1262*eda14cbcSMatt Macy return (NULL); 1263*eda14cbcSMatt Macy } 1264*eda14cbcSMatt Macy 1265*eda14cbcSMatt Macy /* 1266*eda14cbcSMatt Macy * Create a thread pool to parallelize the process of reading and 1267*eda14cbcSMatt Macy * validating labels, a large number of threads can be used due to 1268*eda14cbcSMatt Macy * minimal contention. 1269*eda14cbcSMatt Macy */ 1270*eda14cbcSMatt Macy t = tpool_create(1, 2 * sysconf(_SC_NPROCESSORS_ONLN), 0, NULL); 1271*eda14cbcSMatt Macy for (slice = avl_first(cache); slice; 1272*eda14cbcSMatt Macy (slice = avl_walk(cache, slice, AVL_AFTER))) 1273*eda14cbcSMatt Macy (void) tpool_dispatch(t, zpool_open_func, slice); 1274*eda14cbcSMatt Macy 1275*eda14cbcSMatt Macy tpool_wait(t); 1276*eda14cbcSMatt Macy tpool_destroy(t); 1277*eda14cbcSMatt Macy 1278*eda14cbcSMatt Macy /* 1279*eda14cbcSMatt Macy * Process the cache, filtering out any entries which are not 1280*eda14cbcSMatt Macy * for the specified pool then adding matching label configs. 1281*eda14cbcSMatt Macy */ 1282*eda14cbcSMatt Macy cookie = NULL; 1283*eda14cbcSMatt Macy while ((slice = avl_destroy_nodes(cache, &cookie)) != NULL) { 1284*eda14cbcSMatt Macy if (slice->rn_config != NULL) { 1285*eda14cbcSMatt Macy nvlist_t *config = slice->rn_config; 1286*eda14cbcSMatt Macy boolean_t matched = B_TRUE; 1287*eda14cbcSMatt Macy boolean_t aux = B_FALSE; 1288*eda14cbcSMatt Macy int fd; 1289*eda14cbcSMatt Macy 1290*eda14cbcSMatt Macy /* 1291*eda14cbcSMatt Macy * Check if it's a spare or l2cache device. If it is, 1292*eda14cbcSMatt Macy * we need to skip the name and guid check since they 1293*eda14cbcSMatt Macy * don't exist on aux device label. 1294*eda14cbcSMatt Macy */ 1295*eda14cbcSMatt Macy if (iarg->poolname != NULL || iarg->guid != 0) { 1296*eda14cbcSMatt Macy uint64_t state; 1297*eda14cbcSMatt Macy aux = nvlist_lookup_uint64(config, 1298*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_STATE, &state) == 0 && 1299*eda14cbcSMatt Macy (state == POOL_STATE_SPARE || 1300*eda14cbcSMatt Macy state == POOL_STATE_L2CACHE); 1301*eda14cbcSMatt Macy } 1302*eda14cbcSMatt Macy 1303*eda14cbcSMatt Macy if (iarg->poolname != NULL && !aux) { 1304*eda14cbcSMatt Macy char *pname; 1305*eda14cbcSMatt Macy 1306*eda14cbcSMatt Macy matched = nvlist_lookup_string(config, 1307*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_NAME, &pname) == 0 && 1308*eda14cbcSMatt Macy strcmp(iarg->poolname, pname) == 0; 1309*eda14cbcSMatt Macy } else if (iarg->guid != 0 && !aux) { 1310*eda14cbcSMatt Macy uint64_t this_guid; 1311*eda14cbcSMatt Macy 1312*eda14cbcSMatt Macy matched = nvlist_lookup_uint64(config, 1313*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_GUID, &this_guid) == 0 && 1314*eda14cbcSMatt Macy iarg->guid == this_guid; 1315*eda14cbcSMatt Macy } 1316*eda14cbcSMatt Macy if (matched) { 1317*eda14cbcSMatt Macy /* 1318*eda14cbcSMatt Macy * Verify all remaining entries can be opened 1319*eda14cbcSMatt Macy * exclusively. This will prune all underlying 1320*eda14cbcSMatt Macy * multipath devices which otherwise could 1321*eda14cbcSMatt Macy * result in the vdev appearing as UNAVAIL. 1322*eda14cbcSMatt Macy * 1323*eda14cbcSMatt Macy * Under zdb, this step isn't required and 1324*eda14cbcSMatt Macy * would prevent a zdb -e of active pools with 1325*eda14cbcSMatt Macy * no cachefile. 1326*eda14cbcSMatt Macy */ 1327*eda14cbcSMatt Macy fd = open(slice->rn_name, O_RDONLY | O_EXCL); 1328*eda14cbcSMatt Macy if (fd >= 0 || iarg->can_be_active) { 1329*eda14cbcSMatt Macy if (fd >= 0) 1330*eda14cbcSMatt Macy close(fd); 1331*eda14cbcSMatt Macy add_config(hdl, &pools, 1332*eda14cbcSMatt Macy slice->rn_name, slice->rn_order, 1333*eda14cbcSMatt Macy slice->rn_num_labels, config); 1334*eda14cbcSMatt Macy } 1335*eda14cbcSMatt Macy } 1336*eda14cbcSMatt Macy nvlist_free(config); 1337*eda14cbcSMatt Macy } 1338*eda14cbcSMatt Macy free(slice->rn_name); 1339*eda14cbcSMatt Macy free(slice); 1340*eda14cbcSMatt Macy } 1341*eda14cbcSMatt Macy avl_destroy(cache); 1342*eda14cbcSMatt Macy free(cache); 1343*eda14cbcSMatt Macy pthread_mutex_destroy(&lock); 1344*eda14cbcSMatt Macy 1345*eda14cbcSMatt Macy ret = get_configs(hdl, &pools, iarg->can_be_active, iarg->policy); 1346*eda14cbcSMatt Macy 1347*eda14cbcSMatt Macy for (pe = pools.pools; pe != NULL; pe = penext) { 1348*eda14cbcSMatt Macy penext = pe->pe_next; 1349*eda14cbcSMatt Macy for (ve = pe->pe_vdevs; ve != NULL; ve = venext) { 1350*eda14cbcSMatt Macy venext = ve->ve_next; 1351*eda14cbcSMatt Macy for (ce = ve->ve_configs; ce != NULL; ce = cenext) { 1352*eda14cbcSMatt Macy cenext = ce->ce_next; 1353*eda14cbcSMatt Macy nvlist_free(ce->ce_config); 1354*eda14cbcSMatt Macy free(ce); 1355*eda14cbcSMatt Macy } 1356*eda14cbcSMatt Macy free(ve); 1357*eda14cbcSMatt Macy } 1358*eda14cbcSMatt Macy free(pe); 1359*eda14cbcSMatt Macy } 1360*eda14cbcSMatt Macy 1361*eda14cbcSMatt Macy for (ne = pools.names; ne != NULL; ne = nenext) { 1362*eda14cbcSMatt Macy nenext = ne->ne_next; 1363*eda14cbcSMatt Macy free(ne->ne_name); 1364*eda14cbcSMatt Macy free(ne); 1365*eda14cbcSMatt Macy } 1366*eda14cbcSMatt Macy 1367*eda14cbcSMatt Macy return (ret); 1368*eda14cbcSMatt Macy } 1369*eda14cbcSMatt Macy 1370*eda14cbcSMatt Macy /* 1371*eda14cbcSMatt Macy * Given a cache file, return the contents as a list of importable pools. 1372*eda14cbcSMatt Macy * poolname or guid (but not both) are provided by the caller when trying 1373*eda14cbcSMatt Macy * to import a specific pool. 1374*eda14cbcSMatt Macy */ 1375*eda14cbcSMatt Macy static nvlist_t * 1376*eda14cbcSMatt Macy zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile, 1377*eda14cbcSMatt Macy const char *poolname, uint64_t guid) 1378*eda14cbcSMatt Macy { 1379*eda14cbcSMatt Macy char *buf; 1380*eda14cbcSMatt Macy int fd; 1381*eda14cbcSMatt Macy struct stat64 statbuf; 1382*eda14cbcSMatt Macy nvlist_t *raw, *src, *dst; 1383*eda14cbcSMatt Macy nvlist_t *pools; 1384*eda14cbcSMatt Macy nvpair_t *elem; 1385*eda14cbcSMatt Macy char *name; 1386*eda14cbcSMatt Macy uint64_t this_guid; 1387*eda14cbcSMatt Macy boolean_t active; 1388*eda14cbcSMatt Macy 1389*eda14cbcSMatt Macy verify(poolname == NULL || guid == 0); 1390*eda14cbcSMatt Macy 1391*eda14cbcSMatt Macy if ((fd = open(cachefile, O_RDONLY)) < 0) { 1392*eda14cbcSMatt Macy zutil_error_aux(hdl, "%s", strerror(errno)); 1393*eda14cbcSMatt Macy (void) zutil_error(hdl, EZFS_BADCACHE, 1394*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "failed to open cache file")); 1395*eda14cbcSMatt Macy return (NULL); 1396*eda14cbcSMatt Macy } 1397*eda14cbcSMatt Macy 1398*eda14cbcSMatt Macy if (fstat64(fd, &statbuf) != 0) { 1399*eda14cbcSMatt Macy zutil_error_aux(hdl, "%s", strerror(errno)); 1400*eda14cbcSMatt Macy (void) close(fd); 1401*eda14cbcSMatt Macy (void) zutil_error(hdl, EZFS_BADCACHE, 1402*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "failed to get size of cache file")); 1403*eda14cbcSMatt Macy return (NULL); 1404*eda14cbcSMatt Macy } 1405*eda14cbcSMatt Macy 1406*eda14cbcSMatt Macy if ((buf = zutil_alloc(hdl, statbuf.st_size)) == NULL) { 1407*eda14cbcSMatt Macy (void) close(fd); 1408*eda14cbcSMatt Macy return (NULL); 1409*eda14cbcSMatt Macy } 1410*eda14cbcSMatt Macy 1411*eda14cbcSMatt Macy if (read(fd, buf, statbuf.st_size) != statbuf.st_size) { 1412*eda14cbcSMatt Macy (void) close(fd); 1413*eda14cbcSMatt Macy free(buf); 1414*eda14cbcSMatt Macy (void) zutil_error(hdl, EZFS_BADCACHE, 1415*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, 1416*eda14cbcSMatt Macy "failed to read cache file contents")); 1417*eda14cbcSMatt Macy return (NULL); 1418*eda14cbcSMatt Macy } 1419*eda14cbcSMatt Macy 1420*eda14cbcSMatt Macy (void) close(fd); 1421*eda14cbcSMatt Macy 1422*eda14cbcSMatt Macy if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) { 1423*eda14cbcSMatt Macy free(buf); 1424*eda14cbcSMatt Macy (void) zutil_error(hdl, EZFS_BADCACHE, 1425*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, 1426*eda14cbcSMatt Macy "invalid or corrupt cache file contents")); 1427*eda14cbcSMatt Macy return (NULL); 1428*eda14cbcSMatt Macy } 1429*eda14cbcSMatt Macy 1430*eda14cbcSMatt Macy free(buf); 1431*eda14cbcSMatt Macy 1432*eda14cbcSMatt Macy /* 1433*eda14cbcSMatt Macy * Go through and get the current state of the pools and refresh their 1434*eda14cbcSMatt Macy * state. 1435*eda14cbcSMatt Macy */ 1436*eda14cbcSMatt Macy if (nvlist_alloc(&pools, 0, 0) != 0) { 1437*eda14cbcSMatt Macy (void) zutil_no_memory(hdl); 1438*eda14cbcSMatt Macy nvlist_free(raw); 1439*eda14cbcSMatt Macy return (NULL); 1440*eda14cbcSMatt Macy } 1441*eda14cbcSMatt Macy 1442*eda14cbcSMatt Macy elem = NULL; 1443*eda14cbcSMatt Macy while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) { 1444*eda14cbcSMatt Macy src = fnvpair_value_nvlist(elem); 1445*eda14cbcSMatt Macy 1446*eda14cbcSMatt Macy name = fnvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME); 1447*eda14cbcSMatt Macy if (poolname != NULL && strcmp(poolname, name) != 0) 1448*eda14cbcSMatt Macy continue; 1449*eda14cbcSMatt Macy 1450*eda14cbcSMatt Macy this_guid = fnvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID); 1451*eda14cbcSMatt Macy if (guid != 0 && guid != this_guid) 1452*eda14cbcSMatt Macy continue; 1453*eda14cbcSMatt Macy 1454*eda14cbcSMatt Macy if (zutil_pool_active(hdl, name, this_guid, &active) != 0) { 1455*eda14cbcSMatt Macy nvlist_free(raw); 1456*eda14cbcSMatt Macy nvlist_free(pools); 1457*eda14cbcSMatt Macy return (NULL); 1458*eda14cbcSMatt Macy } 1459*eda14cbcSMatt Macy 1460*eda14cbcSMatt Macy if (active) 1461*eda14cbcSMatt Macy continue; 1462*eda14cbcSMatt Macy 1463*eda14cbcSMatt Macy if (nvlist_add_string(src, ZPOOL_CONFIG_CACHEFILE, 1464*eda14cbcSMatt Macy cachefile) != 0) { 1465*eda14cbcSMatt Macy (void) zutil_no_memory(hdl); 1466*eda14cbcSMatt Macy nvlist_free(raw); 1467*eda14cbcSMatt Macy nvlist_free(pools); 1468*eda14cbcSMatt Macy return (NULL); 1469*eda14cbcSMatt Macy } 1470*eda14cbcSMatt Macy 1471*eda14cbcSMatt Macy if ((dst = zutil_refresh_config(hdl, src)) == NULL) { 1472*eda14cbcSMatt Macy nvlist_free(raw); 1473*eda14cbcSMatt Macy nvlist_free(pools); 1474*eda14cbcSMatt Macy return (NULL); 1475*eda14cbcSMatt Macy } 1476*eda14cbcSMatt Macy 1477*eda14cbcSMatt Macy if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) { 1478*eda14cbcSMatt Macy (void) zutil_no_memory(hdl); 1479*eda14cbcSMatt Macy nvlist_free(dst); 1480*eda14cbcSMatt Macy nvlist_free(raw); 1481*eda14cbcSMatt Macy nvlist_free(pools); 1482*eda14cbcSMatt Macy return (NULL); 1483*eda14cbcSMatt Macy } 1484*eda14cbcSMatt Macy nvlist_free(dst); 1485*eda14cbcSMatt Macy } 1486*eda14cbcSMatt Macy 1487*eda14cbcSMatt Macy nvlist_free(raw); 1488*eda14cbcSMatt Macy return (pools); 1489*eda14cbcSMatt Macy } 1490*eda14cbcSMatt Macy 1491*eda14cbcSMatt Macy nvlist_t * 1492*eda14cbcSMatt Macy zpool_search_import(void *hdl, importargs_t *import, 1493*eda14cbcSMatt Macy const pool_config_ops_t *pco) 1494*eda14cbcSMatt Macy { 1495*eda14cbcSMatt Macy libpc_handle_t handle = { 0 }; 1496*eda14cbcSMatt Macy nvlist_t *pools = NULL; 1497*eda14cbcSMatt Macy 1498*eda14cbcSMatt Macy handle.lpc_lib_handle = hdl; 1499*eda14cbcSMatt Macy handle.lpc_ops = pco; 1500*eda14cbcSMatt Macy handle.lpc_printerr = B_TRUE; 1501*eda14cbcSMatt Macy 1502*eda14cbcSMatt Macy verify(import->poolname == NULL || import->guid == 0); 1503*eda14cbcSMatt Macy 1504*eda14cbcSMatt Macy if (import->cachefile != NULL) 1505*eda14cbcSMatt Macy pools = zpool_find_import_cached(&handle, import->cachefile, 1506*eda14cbcSMatt Macy import->poolname, import->guid); 1507*eda14cbcSMatt Macy else 1508*eda14cbcSMatt Macy pools = zpool_find_import_impl(&handle, import); 1509*eda14cbcSMatt Macy 1510*eda14cbcSMatt Macy if ((pools == NULL || nvlist_empty(pools)) && 1511*eda14cbcSMatt Macy handle.lpc_open_access_error && geteuid() != 0) { 1512*eda14cbcSMatt Macy (void) zutil_error(&handle, EZFS_EACESS, dgettext(TEXT_DOMAIN, 1513*eda14cbcSMatt Macy "no pools found")); 1514*eda14cbcSMatt Macy } 1515*eda14cbcSMatt Macy 1516*eda14cbcSMatt Macy return (pools); 1517*eda14cbcSMatt Macy } 1518*eda14cbcSMatt Macy 1519*eda14cbcSMatt Macy static boolean_t 1520*eda14cbcSMatt Macy pool_match(nvlist_t *cfg, char *tgt) 1521*eda14cbcSMatt Macy { 1522*eda14cbcSMatt Macy uint64_t v, guid = strtoull(tgt, NULL, 0); 1523*eda14cbcSMatt Macy char *s; 1524*eda14cbcSMatt Macy 1525*eda14cbcSMatt Macy if (guid != 0) { 1526*eda14cbcSMatt Macy if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0) 1527*eda14cbcSMatt Macy return (v == guid); 1528*eda14cbcSMatt Macy } else { 1529*eda14cbcSMatt Macy if (nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &s) == 0) 1530*eda14cbcSMatt Macy return (strcmp(s, tgt) == 0); 1531*eda14cbcSMatt Macy } 1532*eda14cbcSMatt Macy return (B_FALSE); 1533*eda14cbcSMatt Macy } 1534*eda14cbcSMatt Macy 1535*eda14cbcSMatt Macy int 1536*eda14cbcSMatt Macy zpool_find_config(void *hdl, const char *target, nvlist_t **configp, 1537*eda14cbcSMatt Macy importargs_t *args, const pool_config_ops_t *pco) 1538*eda14cbcSMatt Macy { 1539*eda14cbcSMatt Macy nvlist_t *pools; 1540*eda14cbcSMatt Macy nvlist_t *match = NULL; 1541*eda14cbcSMatt Macy nvlist_t *config = NULL; 1542*eda14cbcSMatt Macy char *name = NULL, *sepp = NULL; 1543*eda14cbcSMatt Macy char sep = '\0'; 1544*eda14cbcSMatt Macy int count = 0; 1545*eda14cbcSMatt Macy char *targetdup = strdup(target); 1546*eda14cbcSMatt Macy 1547*eda14cbcSMatt Macy *configp = NULL; 1548*eda14cbcSMatt Macy 1549*eda14cbcSMatt Macy if ((sepp = strpbrk(targetdup, "/@")) != NULL) { 1550*eda14cbcSMatt Macy sep = *sepp; 1551*eda14cbcSMatt Macy *sepp = '\0'; 1552*eda14cbcSMatt Macy } 1553*eda14cbcSMatt Macy 1554*eda14cbcSMatt Macy pools = zpool_search_import(hdl, args, pco); 1555*eda14cbcSMatt Macy 1556*eda14cbcSMatt Macy if (pools != NULL) { 1557*eda14cbcSMatt Macy nvpair_t *elem = NULL; 1558*eda14cbcSMatt Macy while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1559*eda14cbcSMatt Macy VERIFY0(nvpair_value_nvlist(elem, &config)); 1560*eda14cbcSMatt Macy if (pool_match(config, targetdup)) { 1561*eda14cbcSMatt Macy count++; 1562*eda14cbcSMatt Macy if (match != NULL) { 1563*eda14cbcSMatt Macy /* multiple matches found */ 1564*eda14cbcSMatt Macy continue; 1565*eda14cbcSMatt Macy } else { 1566*eda14cbcSMatt Macy match = config; 1567*eda14cbcSMatt Macy name = nvpair_name(elem); 1568*eda14cbcSMatt Macy } 1569*eda14cbcSMatt Macy } 1570*eda14cbcSMatt Macy } 1571*eda14cbcSMatt Macy } 1572*eda14cbcSMatt Macy 1573*eda14cbcSMatt Macy if (count == 0) { 1574*eda14cbcSMatt Macy free(targetdup); 1575*eda14cbcSMatt Macy return (ENOENT); 1576*eda14cbcSMatt Macy } 1577*eda14cbcSMatt Macy 1578*eda14cbcSMatt Macy if (count > 1) { 1579*eda14cbcSMatt Macy free(targetdup); 1580*eda14cbcSMatt Macy return (EINVAL); 1581*eda14cbcSMatt Macy } 1582*eda14cbcSMatt Macy 1583*eda14cbcSMatt Macy *configp = match; 1584*eda14cbcSMatt Macy free(targetdup); 1585*eda14cbcSMatt Macy 1586*eda14cbcSMatt Macy return (0); 1587*eda14cbcSMatt Macy } 1588