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 #include <errno.h> 30*eda14cbcSMatt Macy #include <libintl.h> 31*eda14cbcSMatt Macy #include <libgen.h> 32*eda14cbcSMatt Macy #include <stddef.h> 33*eda14cbcSMatt Macy #include <stdlib.h> 34*eda14cbcSMatt Macy #include <string.h> 35*eda14cbcSMatt Macy #include <sys/stat.h> 36*eda14cbcSMatt Macy #include <unistd.h> 37*eda14cbcSMatt Macy #include <sys/vdev_impl.h> 38*eda14cbcSMatt Macy #include <libzfs.h> 39*eda14cbcSMatt Macy #include <libzfs_impl.h> 40*eda14cbcSMatt Macy #include <libzutil.h> 41*eda14cbcSMatt Macy #include <sys/arc_impl.h> 42*eda14cbcSMatt Macy 43*eda14cbcSMatt Macy /* 44*eda14cbcSMatt Macy * Returns true if the named pool matches the given GUID. 45*eda14cbcSMatt Macy */ 46*eda14cbcSMatt Macy static int 47*eda14cbcSMatt Macy pool_active(libzfs_handle_t *hdl, const char *name, uint64_t guid, 48*eda14cbcSMatt Macy boolean_t *isactive) 49*eda14cbcSMatt Macy { 50*eda14cbcSMatt Macy zpool_handle_t *zhp; 51*eda14cbcSMatt Macy uint64_t theguid; 52*eda14cbcSMatt Macy 53*eda14cbcSMatt Macy if (zpool_open_silent(hdl, name, &zhp) != 0) 54*eda14cbcSMatt Macy return (-1); 55*eda14cbcSMatt Macy 56*eda14cbcSMatt Macy if (zhp == NULL) { 57*eda14cbcSMatt Macy *isactive = B_FALSE; 58*eda14cbcSMatt Macy return (0); 59*eda14cbcSMatt Macy } 60*eda14cbcSMatt Macy 61*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(zhp->zpool_config, ZPOOL_CONFIG_POOL_GUID, 62*eda14cbcSMatt Macy &theguid) == 0); 63*eda14cbcSMatt Macy 64*eda14cbcSMatt Macy zpool_close(zhp); 65*eda14cbcSMatt Macy 66*eda14cbcSMatt Macy *isactive = (theguid == guid); 67*eda14cbcSMatt Macy return (0); 68*eda14cbcSMatt Macy } 69*eda14cbcSMatt Macy 70*eda14cbcSMatt Macy static nvlist_t * 71*eda14cbcSMatt Macy refresh_config(libzfs_handle_t *hdl, nvlist_t *config) 72*eda14cbcSMatt Macy { 73*eda14cbcSMatt Macy nvlist_t *nvl; 74*eda14cbcSMatt Macy zfs_cmd_t zc = {"\0"}; 75*eda14cbcSMatt Macy int err, dstbuf_size; 76*eda14cbcSMatt Macy 77*eda14cbcSMatt Macy if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) 78*eda14cbcSMatt Macy return (NULL); 79*eda14cbcSMatt Macy 80*eda14cbcSMatt Macy dstbuf_size = MAX(CONFIG_BUF_MINSIZE, zc.zc_nvlist_conf_size * 4); 81*eda14cbcSMatt Macy 82*eda14cbcSMatt Macy if (zcmd_alloc_dst_nvlist(hdl, &zc, dstbuf_size) != 0) { 83*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 84*eda14cbcSMatt Macy return (NULL); 85*eda14cbcSMatt Macy } 86*eda14cbcSMatt Macy 87*eda14cbcSMatt Macy while ((err = zfs_ioctl(hdl, ZFS_IOC_POOL_TRYIMPORT, 88*eda14cbcSMatt Macy &zc)) != 0 && errno == ENOMEM) { 89*eda14cbcSMatt Macy if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 90*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 91*eda14cbcSMatt Macy return (NULL); 92*eda14cbcSMatt Macy } 93*eda14cbcSMatt Macy } 94*eda14cbcSMatt Macy 95*eda14cbcSMatt Macy if (err) { 96*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 97*eda14cbcSMatt Macy return (NULL); 98*eda14cbcSMatt Macy } 99*eda14cbcSMatt Macy 100*eda14cbcSMatt Macy if (zcmd_read_dst_nvlist(hdl, &zc, &nvl) != 0) { 101*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 102*eda14cbcSMatt Macy return (NULL); 103*eda14cbcSMatt Macy } 104*eda14cbcSMatt Macy 105*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 106*eda14cbcSMatt Macy return (nvl); 107*eda14cbcSMatt Macy } 108*eda14cbcSMatt Macy 109*eda14cbcSMatt Macy static nvlist_t * 110*eda14cbcSMatt Macy refresh_config_libzfs(void *handle, nvlist_t *tryconfig) 111*eda14cbcSMatt Macy { 112*eda14cbcSMatt Macy return (refresh_config((libzfs_handle_t *)handle, tryconfig)); 113*eda14cbcSMatt Macy } 114*eda14cbcSMatt Macy 115*eda14cbcSMatt Macy 116*eda14cbcSMatt Macy static int 117*eda14cbcSMatt Macy pool_active_libzfs(void *handle, const char *name, uint64_t guid, 118*eda14cbcSMatt Macy boolean_t *isactive) 119*eda14cbcSMatt Macy { 120*eda14cbcSMatt Macy return (pool_active((libzfs_handle_t *)handle, name, guid, isactive)); 121*eda14cbcSMatt Macy } 122*eda14cbcSMatt Macy 123*eda14cbcSMatt Macy const pool_config_ops_t libzfs_config_ops = { 124*eda14cbcSMatt Macy .pco_refresh_config = refresh_config_libzfs, 125*eda14cbcSMatt Macy .pco_pool_active = pool_active_libzfs, 126*eda14cbcSMatt Macy }; 127*eda14cbcSMatt Macy 128*eda14cbcSMatt Macy /* 129*eda14cbcSMatt Macy * Return the offset of the given label. 130*eda14cbcSMatt Macy */ 131*eda14cbcSMatt Macy static uint64_t 132*eda14cbcSMatt Macy label_offset(uint64_t size, int l) 133*eda14cbcSMatt Macy { 134*eda14cbcSMatt Macy ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0); 135*eda14cbcSMatt Macy return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ? 136*eda14cbcSMatt Macy 0 : size - VDEV_LABELS * sizeof (vdev_label_t))); 137*eda14cbcSMatt Macy } 138*eda14cbcSMatt Macy 139*eda14cbcSMatt Macy /* 140*eda14cbcSMatt Macy * Given a file descriptor, clear (zero) the label information. This function 141*eda14cbcSMatt Macy * is used in the appliance stack as part of the ZFS sysevent module and 142*eda14cbcSMatt Macy * to implement the "zpool labelclear" command. 143*eda14cbcSMatt Macy */ 144*eda14cbcSMatt Macy int 145*eda14cbcSMatt Macy zpool_clear_label(int fd) 146*eda14cbcSMatt Macy { 147*eda14cbcSMatt Macy struct stat64 statbuf; 148*eda14cbcSMatt Macy int l; 149*eda14cbcSMatt Macy vdev_label_t *label; 150*eda14cbcSMatt Macy l2arc_dev_hdr_phys_t *l2dhdr; 151*eda14cbcSMatt Macy uint64_t size; 152*eda14cbcSMatt Macy int labels_cleared = 0, header_cleared = 0; 153*eda14cbcSMatt Macy boolean_t clear_l2arc_header = B_FALSE; 154*eda14cbcSMatt Macy 155*eda14cbcSMatt Macy if (fstat64_blk(fd, &statbuf) == -1) 156*eda14cbcSMatt Macy return (0); 157*eda14cbcSMatt Macy 158*eda14cbcSMatt Macy size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); 159*eda14cbcSMatt Macy 160*eda14cbcSMatt Macy if ((label = calloc(1, sizeof (vdev_label_t))) == NULL) 161*eda14cbcSMatt Macy return (-1); 162*eda14cbcSMatt Macy 163*eda14cbcSMatt Macy if ((l2dhdr = calloc(1, sizeof (l2arc_dev_hdr_phys_t))) == NULL) { 164*eda14cbcSMatt Macy free(label); 165*eda14cbcSMatt Macy return (-1); 166*eda14cbcSMatt Macy } 167*eda14cbcSMatt Macy 168*eda14cbcSMatt Macy for (l = 0; l < VDEV_LABELS; l++) { 169*eda14cbcSMatt Macy uint64_t state, guid, l2cache; 170*eda14cbcSMatt Macy nvlist_t *config; 171*eda14cbcSMatt Macy 172*eda14cbcSMatt Macy if (pread64(fd, label, sizeof (vdev_label_t), 173*eda14cbcSMatt Macy label_offset(size, l)) != sizeof (vdev_label_t)) { 174*eda14cbcSMatt Macy continue; 175*eda14cbcSMatt Macy } 176*eda14cbcSMatt Macy 177*eda14cbcSMatt Macy if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, 178*eda14cbcSMatt Macy sizeof (label->vl_vdev_phys.vp_nvlist), &config, 0) != 0) { 179*eda14cbcSMatt Macy continue; 180*eda14cbcSMatt Macy } 181*eda14cbcSMatt Macy 182*eda14cbcSMatt Macy /* Skip labels which do not have a valid guid. */ 183*eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, 184*eda14cbcSMatt Macy &guid) != 0 || guid == 0) { 185*eda14cbcSMatt Macy nvlist_free(config); 186*eda14cbcSMatt Macy continue; 187*eda14cbcSMatt Macy } 188*eda14cbcSMatt Macy 189*eda14cbcSMatt Macy /* Skip labels which are not in a known valid state. */ 190*eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 191*eda14cbcSMatt Macy &state) != 0 || state > POOL_STATE_L2CACHE) { 192*eda14cbcSMatt Macy nvlist_free(config); 193*eda14cbcSMatt Macy continue; 194*eda14cbcSMatt Macy } 195*eda14cbcSMatt Macy 196*eda14cbcSMatt Macy /* If the device is a cache device clear the header. */ 197*eda14cbcSMatt Macy if (!clear_l2arc_header) { 198*eda14cbcSMatt Macy if (nvlist_lookup_uint64(config, 199*eda14cbcSMatt Macy ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 && 200*eda14cbcSMatt Macy l2cache == POOL_STATE_L2CACHE) { 201*eda14cbcSMatt Macy clear_l2arc_header = B_TRUE; 202*eda14cbcSMatt Macy } 203*eda14cbcSMatt Macy } 204*eda14cbcSMatt Macy 205*eda14cbcSMatt Macy nvlist_free(config); 206*eda14cbcSMatt Macy 207*eda14cbcSMatt Macy /* 208*eda14cbcSMatt Macy * A valid label was found, overwrite this label's nvlist 209*eda14cbcSMatt Macy * and uberblocks with zeros on disk. This is done to prevent 210*eda14cbcSMatt Macy * system utilities, like blkid, from incorrectly detecting a 211*eda14cbcSMatt Macy * partial label. The leading pad space is left untouched. 212*eda14cbcSMatt Macy */ 213*eda14cbcSMatt Macy memset(label, 0, sizeof (vdev_label_t)); 214*eda14cbcSMatt Macy size_t label_size = sizeof (vdev_label_t) - (2 * VDEV_PAD_SIZE); 215*eda14cbcSMatt Macy 216*eda14cbcSMatt Macy if (pwrite64(fd, label, label_size, label_offset(size, l) + 217*eda14cbcSMatt Macy (2 * VDEV_PAD_SIZE)) == label_size) { 218*eda14cbcSMatt Macy labels_cleared++; 219*eda14cbcSMatt Macy } 220*eda14cbcSMatt Macy } 221*eda14cbcSMatt Macy 222*eda14cbcSMatt Macy /* Clear the L2ARC header. */ 223*eda14cbcSMatt Macy if (clear_l2arc_header) { 224*eda14cbcSMatt Macy memset(l2dhdr, 0, sizeof (l2arc_dev_hdr_phys_t)); 225*eda14cbcSMatt Macy if (pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t), 226*eda14cbcSMatt Macy VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t)) { 227*eda14cbcSMatt Macy header_cleared++; 228*eda14cbcSMatt Macy } 229*eda14cbcSMatt Macy } 230*eda14cbcSMatt Macy 231*eda14cbcSMatt Macy free(label); 232*eda14cbcSMatt Macy free(l2dhdr); 233*eda14cbcSMatt Macy 234*eda14cbcSMatt Macy if (labels_cleared == 0) 235*eda14cbcSMatt Macy return (-1); 236*eda14cbcSMatt Macy 237*eda14cbcSMatt Macy return (0); 238*eda14cbcSMatt Macy } 239*eda14cbcSMatt Macy 240*eda14cbcSMatt Macy static boolean_t 241*eda14cbcSMatt Macy find_guid(nvlist_t *nv, uint64_t guid) 242*eda14cbcSMatt Macy { 243*eda14cbcSMatt Macy uint64_t tmp; 244*eda14cbcSMatt Macy nvlist_t **child; 245*eda14cbcSMatt Macy uint_t c, children; 246*eda14cbcSMatt Macy 247*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &tmp) == 0); 248*eda14cbcSMatt Macy if (tmp == guid) 249*eda14cbcSMatt Macy return (B_TRUE); 250*eda14cbcSMatt Macy 251*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 252*eda14cbcSMatt Macy &child, &children) == 0) { 253*eda14cbcSMatt Macy for (c = 0; c < children; c++) 254*eda14cbcSMatt Macy if (find_guid(child[c], guid)) 255*eda14cbcSMatt Macy return (B_TRUE); 256*eda14cbcSMatt Macy } 257*eda14cbcSMatt Macy 258*eda14cbcSMatt Macy return (B_FALSE); 259*eda14cbcSMatt Macy } 260*eda14cbcSMatt Macy 261*eda14cbcSMatt Macy typedef struct aux_cbdata { 262*eda14cbcSMatt Macy const char *cb_type; 263*eda14cbcSMatt Macy uint64_t cb_guid; 264*eda14cbcSMatt Macy zpool_handle_t *cb_zhp; 265*eda14cbcSMatt Macy } aux_cbdata_t; 266*eda14cbcSMatt Macy 267*eda14cbcSMatt Macy static int 268*eda14cbcSMatt Macy find_aux(zpool_handle_t *zhp, void *data) 269*eda14cbcSMatt Macy { 270*eda14cbcSMatt Macy aux_cbdata_t *cbp = data; 271*eda14cbcSMatt Macy nvlist_t **list; 272*eda14cbcSMatt Macy uint_t i, count; 273*eda14cbcSMatt Macy uint64_t guid; 274*eda14cbcSMatt Macy nvlist_t *nvroot; 275*eda14cbcSMatt Macy 276*eda14cbcSMatt Macy verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE, 277*eda14cbcSMatt Macy &nvroot) == 0); 278*eda14cbcSMatt Macy 279*eda14cbcSMatt Macy if (nvlist_lookup_nvlist_array(nvroot, cbp->cb_type, 280*eda14cbcSMatt Macy &list, &count) == 0) { 281*eda14cbcSMatt Macy for (i = 0; i < count; i++) { 282*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(list[i], 283*eda14cbcSMatt Macy ZPOOL_CONFIG_GUID, &guid) == 0); 284*eda14cbcSMatt Macy if (guid == cbp->cb_guid) { 285*eda14cbcSMatt Macy cbp->cb_zhp = zhp; 286*eda14cbcSMatt Macy return (1); 287*eda14cbcSMatt Macy } 288*eda14cbcSMatt Macy } 289*eda14cbcSMatt Macy } 290*eda14cbcSMatt Macy 291*eda14cbcSMatt Macy zpool_close(zhp); 292*eda14cbcSMatt Macy return (0); 293*eda14cbcSMatt Macy } 294*eda14cbcSMatt Macy 295*eda14cbcSMatt Macy /* 296*eda14cbcSMatt Macy * Determines if the pool is in use. If so, it returns true and the state of 297*eda14cbcSMatt Macy * the pool as well as the name of the pool. Name string is allocated and 298*eda14cbcSMatt Macy * must be freed by the caller. 299*eda14cbcSMatt Macy */ 300*eda14cbcSMatt Macy int 301*eda14cbcSMatt Macy zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr, 302*eda14cbcSMatt Macy boolean_t *inuse) 303*eda14cbcSMatt Macy { 304*eda14cbcSMatt Macy nvlist_t *config; 305*eda14cbcSMatt Macy char *name; 306*eda14cbcSMatt Macy boolean_t ret; 307*eda14cbcSMatt Macy uint64_t guid, vdev_guid; 308*eda14cbcSMatt Macy zpool_handle_t *zhp; 309*eda14cbcSMatt Macy nvlist_t *pool_config; 310*eda14cbcSMatt Macy uint64_t stateval, isspare; 311*eda14cbcSMatt Macy aux_cbdata_t cb = { 0 }; 312*eda14cbcSMatt Macy boolean_t isactive; 313*eda14cbcSMatt Macy 314*eda14cbcSMatt Macy *inuse = B_FALSE; 315*eda14cbcSMatt Macy 316*eda14cbcSMatt Macy if (zpool_read_label(fd, &config, NULL) != 0) { 317*eda14cbcSMatt Macy (void) no_memory(hdl); 318*eda14cbcSMatt Macy return (-1); 319*eda14cbcSMatt Macy } 320*eda14cbcSMatt Macy 321*eda14cbcSMatt Macy if (config == NULL) 322*eda14cbcSMatt Macy return (0); 323*eda14cbcSMatt Macy 324*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 325*eda14cbcSMatt Macy &stateval) == 0); 326*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, 327*eda14cbcSMatt Macy &vdev_guid) == 0); 328*eda14cbcSMatt Macy 329*eda14cbcSMatt Macy if (stateval != POOL_STATE_SPARE && stateval != POOL_STATE_L2CACHE) { 330*eda14cbcSMatt Macy verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 331*eda14cbcSMatt Macy &name) == 0); 332*eda14cbcSMatt Macy verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 333*eda14cbcSMatt Macy &guid) == 0); 334*eda14cbcSMatt Macy } 335*eda14cbcSMatt Macy 336*eda14cbcSMatt Macy switch (stateval) { 337*eda14cbcSMatt Macy case POOL_STATE_EXPORTED: 338*eda14cbcSMatt Macy /* 339*eda14cbcSMatt Macy * A pool with an exported state may in fact be imported 340*eda14cbcSMatt Macy * read-only, so check the in-core state to see if it's 341*eda14cbcSMatt Macy * active and imported read-only. If it is, set 342*eda14cbcSMatt Macy * its state to active. 343*eda14cbcSMatt Macy */ 344*eda14cbcSMatt Macy if (pool_active(hdl, name, guid, &isactive) == 0 && isactive && 345*eda14cbcSMatt Macy (zhp = zpool_open_canfail(hdl, name)) != NULL) { 346*eda14cbcSMatt Macy if (zpool_get_prop_int(zhp, ZPOOL_PROP_READONLY, NULL)) 347*eda14cbcSMatt Macy stateval = POOL_STATE_ACTIVE; 348*eda14cbcSMatt Macy 349*eda14cbcSMatt Macy /* 350*eda14cbcSMatt Macy * All we needed the zpool handle for is the 351*eda14cbcSMatt Macy * readonly prop check. 352*eda14cbcSMatt Macy */ 353*eda14cbcSMatt Macy zpool_close(zhp); 354*eda14cbcSMatt Macy } 355*eda14cbcSMatt Macy 356*eda14cbcSMatt Macy ret = B_TRUE; 357*eda14cbcSMatt Macy break; 358*eda14cbcSMatt Macy 359*eda14cbcSMatt Macy case POOL_STATE_ACTIVE: 360*eda14cbcSMatt Macy /* 361*eda14cbcSMatt Macy * For an active pool, we have to determine if it's really part 362*eda14cbcSMatt Macy * of a currently active pool (in which case the pool will exist 363*eda14cbcSMatt Macy * and the guid will be the same), or whether it's part of an 364*eda14cbcSMatt Macy * active pool that was disconnected without being explicitly 365*eda14cbcSMatt Macy * exported. 366*eda14cbcSMatt Macy */ 367*eda14cbcSMatt Macy if (pool_active(hdl, name, guid, &isactive) != 0) { 368*eda14cbcSMatt Macy nvlist_free(config); 369*eda14cbcSMatt Macy return (-1); 370*eda14cbcSMatt Macy } 371*eda14cbcSMatt Macy 372*eda14cbcSMatt Macy if (isactive) { 373*eda14cbcSMatt Macy /* 374*eda14cbcSMatt Macy * Because the device may have been removed while 375*eda14cbcSMatt Macy * offlined, we only report it as active if the vdev is 376*eda14cbcSMatt Macy * still present in the config. Otherwise, pretend like 377*eda14cbcSMatt Macy * it's not in use. 378*eda14cbcSMatt Macy */ 379*eda14cbcSMatt Macy if ((zhp = zpool_open_canfail(hdl, name)) != NULL && 380*eda14cbcSMatt Macy (pool_config = zpool_get_config(zhp, NULL)) 381*eda14cbcSMatt Macy != NULL) { 382*eda14cbcSMatt Macy nvlist_t *nvroot; 383*eda14cbcSMatt Macy 384*eda14cbcSMatt Macy verify(nvlist_lookup_nvlist(pool_config, 385*eda14cbcSMatt Macy ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); 386*eda14cbcSMatt Macy ret = find_guid(nvroot, vdev_guid); 387*eda14cbcSMatt Macy } else { 388*eda14cbcSMatt Macy ret = B_FALSE; 389*eda14cbcSMatt Macy } 390*eda14cbcSMatt Macy 391*eda14cbcSMatt Macy /* 392*eda14cbcSMatt Macy * If this is an active spare within another pool, we 393*eda14cbcSMatt Macy * treat it like an unused hot spare. This allows the 394*eda14cbcSMatt Macy * user to create a pool with a hot spare that currently 395*eda14cbcSMatt Macy * in use within another pool. Since we return B_TRUE, 396*eda14cbcSMatt Macy * libdiskmgt will continue to prevent generic consumers 397*eda14cbcSMatt Macy * from using the device. 398*eda14cbcSMatt Macy */ 399*eda14cbcSMatt Macy if (ret && nvlist_lookup_uint64(config, 400*eda14cbcSMatt Macy ZPOOL_CONFIG_IS_SPARE, &isspare) == 0 && isspare) 401*eda14cbcSMatt Macy stateval = POOL_STATE_SPARE; 402*eda14cbcSMatt Macy 403*eda14cbcSMatt Macy if (zhp != NULL) 404*eda14cbcSMatt Macy zpool_close(zhp); 405*eda14cbcSMatt Macy } else { 406*eda14cbcSMatt Macy stateval = POOL_STATE_POTENTIALLY_ACTIVE; 407*eda14cbcSMatt Macy ret = B_TRUE; 408*eda14cbcSMatt Macy } 409*eda14cbcSMatt Macy break; 410*eda14cbcSMatt Macy 411*eda14cbcSMatt Macy case POOL_STATE_SPARE: 412*eda14cbcSMatt Macy /* 413*eda14cbcSMatt Macy * For a hot spare, it can be either definitively in use, or 414*eda14cbcSMatt Macy * potentially active. To determine if it's in use, we iterate 415*eda14cbcSMatt Macy * over all pools in the system and search for one with a spare 416*eda14cbcSMatt Macy * with a matching guid. 417*eda14cbcSMatt Macy * 418*eda14cbcSMatt Macy * Due to the shared nature of spares, we don't actually report 419*eda14cbcSMatt Macy * the potentially active case as in use. This means the user 420*eda14cbcSMatt Macy * can freely create pools on the hot spares of exported pools, 421*eda14cbcSMatt Macy * but to do otherwise makes the resulting code complicated, and 422*eda14cbcSMatt Macy * we end up having to deal with this case anyway. 423*eda14cbcSMatt Macy */ 424*eda14cbcSMatt Macy cb.cb_zhp = NULL; 425*eda14cbcSMatt Macy cb.cb_guid = vdev_guid; 426*eda14cbcSMatt Macy cb.cb_type = ZPOOL_CONFIG_SPARES; 427*eda14cbcSMatt Macy if (zpool_iter(hdl, find_aux, &cb) == 1) { 428*eda14cbcSMatt Macy name = (char *)zpool_get_name(cb.cb_zhp); 429*eda14cbcSMatt Macy ret = B_TRUE; 430*eda14cbcSMatt Macy } else { 431*eda14cbcSMatt Macy ret = B_FALSE; 432*eda14cbcSMatt Macy } 433*eda14cbcSMatt Macy break; 434*eda14cbcSMatt Macy 435*eda14cbcSMatt Macy case POOL_STATE_L2CACHE: 436*eda14cbcSMatt Macy 437*eda14cbcSMatt Macy /* 438*eda14cbcSMatt Macy * Check if any pool is currently using this l2cache device. 439*eda14cbcSMatt Macy */ 440*eda14cbcSMatt Macy cb.cb_zhp = NULL; 441*eda14cbcSMatt Macy cb.cb_guid = vdev_guid; 442*eda14cbcSMatt Macy cb.cb_type = ZPOOL_CONFIG_L2CACHE; 443*eda14cbcSMatt Macy if (zpool_iter(hdl, find_aux, &cb) == 1) { 444*eda14cbcSMatt Macy name = (char *)zpool_get_name(cb.cb_zhp); 445*eda14cbcSMatt Macy ret = B_TRUE; 446*eda14cbcSMatt Macy } else { 447*eda14cbcSMatt Macy ret = B_FALSE; 448*eda14cbcSMatt Macy } 449*eda14cbcSMatt Macy break; 450*eda14cbcSMatt Macy 451*eda14cbcSMatt Macy default: 452*eda14cbcSMatt Macy ret = B_FALSE; 453*eda14cbcSMatt Macy } 454*eda14cbcSMatt Macy 455*eda14cbcSMatt Macy 456*eda14cbcSMatt Macy if (ret) { 457*eda14cbcSMatt Macy if ((*namestr = zfs_strdup(hdl, name)) == NULL) { 458*eda14cbcSMatt Macy if (cb.cb_zhp) 459*eda14cbcSMatt Macy zpool_close(cb.cb_zhp); 460*eda14cbcSMatt Macy nvlist_free(config); 461*eda14cbcSMatt Macy return (-1); 462*eda14cbcSMatt Macy } 463*eda14cbcSMatt Macy *state = (pool_state_t)stateval; 464*eda14cbcSMatt Macy } 465*eda14cbcSMatt Macy 466*eda14cbcSMatt Macy if (cb.cb_zhp) 467*eda14cbcSMatt Macy zpool_close(cb.cb_zhp); 468*eda14cbcSMatt Macy 469*eda14cbcSMatt Macy nvlist_free(config); 470*eda14cbcSMatt Macy *inuse = ret; 471*eda14cbcSMatt Macy return (0); 472*eda14cbcSMatt Macy } 473