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 /* 23*eda14cbcSMatt Macy * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*eda14cbcSMatt Macy * Use is subject to license terms. 25*eda14cbcSMatt Macy */ 26*eda14cbcSMatt Macy 27*eda14cbcSMatt Macy /* 28*eda14cbcSMatt Macy * Copyright (c) 2012 by Delphix. All rights reserved. 29*eda14cbcSMatt Macy * Copyright (c) 2015 by Syneto S.R.L. All rights reserved. 30*eda14cbcSMatt Macy * Copyright 2016 Nexenta Systems, Inc. 31*eda14cbcSMatt Macy */ 32*eda14cbcSMatt Macy 33*eda14cbcSMatt Macy /* 34*eda14cbcSMatt Macy * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 35*eda14cbcSMatt Macy * single packed nvlist. While it would be nice to just read in this 36*eda14cbcSMatt Macy * file from userland, this wouldn't work from a local zone. So we have to have 37*eda14cbcSMatt Macy * a zpool ioctl to return the complete configuration for all pools. In the 38*eda14cbcSMatt Macy * global zone, this will be identical to reading the file and unpacking it in 39*eda14cbcSMatt Macy * userland. 40*eda14cbcSMatt Macy */ 41*eda14cbcSMatt Macy 42*eda14cbcSMatt Macy #include <errno.h> 43*eda14cbcSMatt Macy #include <sys/stat.h> 44*eda14cbcSMatt Macy #include <fcntl.h> 45*eda14cbcSMatt Macy #include <stddef.h> 46*eda14cbcSMatt Macy #include <string.h> 47*eda14cbcSMatt Macy #include <unistd.h> 48*eda14cbcSMatt Macy #include <libintl.h> 49*eda14cbcSMatt Macy #include <libuutil.h> 50*eda14cbcSMatt Macy 51*eda14cbcSMatt Macy #include "libzfs_impl.h" 52*eda14cbcSMatt Macy 53*eda14cbcSMatt Macy typedef struct config_node { 54*eda14cbcSMatt Macy char *cn_name; 55*eda14cbcSMatt Macy nvlist_t *cn_config; 56*eda14cbcSMatt Macy uu_avl_node_t cn_avl; 57*eda14cbcSMatt Macy } config_node_t; 58*eda14cbcSMatt Macy 59*eda14cbcSMatt Macy /* ARGSUSED */ 60*eda14cbcSMatt Macy static int 61*eda14cbcSMatt Macy config_node_compare(const void *a, const void *b, void *unused) 62*eda14cbcSMatt Macy { 63*eda14cbcSMatt Macy int ret; 64*eda14cbcSMatt Macy 65*eda14cbcSMatt Macy const config_node_t *ca = (config_node_t *)a; 66*eda14cbcSMatt Macy const config_node_t *cb = (config_node_t *)b; 67*eda14cbcSMatt Macy 68*eda14cbcSMatt Macy ret = strcmp(ca->cn_name, cb->cn_name); 69*eda14cbcSMatt Macy 70*eda14cbcSMatt Macy if (ret < 0) 71*eda14cbcSMatt Macy return (-1); 72*eda14cbcSMatt Macy else if (ret > 0) 73*eda14cbcSMatt Macy return (1); 74*eda14cbcSMatt Macy else 75*eda14cbcSMatt Macy return (0); 76*eda14cbcSMatt Macy } 77*eda14cbcSMatt Macy 78*eda14cbcSMatt Macy void 79*eda14cbcSMatt Macy namespace_clear(libzfs_handle_t *hdl) 80*eda14cbcSMatt Macy { 81*eda14cbcSMatt Macy if (hdl->libzfs_ns_avl) { 82*eda14cbcSMatt Macy config_node_t *cn; 83*eda14cbcSMatt Macy void *cookie = NULL; 84*eda14cbcSMatt Macy 85*eda14cbcSMatt Macy while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, 86*eda14cbcSMatt Macy &cookie)) != NULL) { 87*eda14cbcSMatt Macy nvlist_free(cn->cn_config); 88*eda14cbcSMatt Macy free(cn->cn_name); 89*eda14cbcSMatt Macy free(cn); 90*eda14cbcSMatt Macy } 91*eda14cbcSMatt Macy 92*eda14cbcSMatt Macy uu_avl_destroy(hdl->libzfs_ns_avl); 93*eda14cbcSMatt Macy hdl->libzfs_ns_avl = NULL; 94*eda14cbcSMatt Macy } 95*eda14cbcSMatt Macy 96*eda14cbcSMatt Macy if (hdl->libzfs_ns_avlpool) { 97*eda14cbcSMatt Macy uu_avl_pool_destroy(hdl->libzfs_ns_avlpool); 98*eda14cbcSMatt Macy hdl->libzfs_ns_avlpool = NULL; 99*eda14cbcSMatt Macy } 100*eda14cbcSMatt Macy } 101*eda14cbcSMatt Macy 102*eda14cbcSMatt Macy /* 103*eda14cbcSMatt Macy * Loads the pool namespace, or re-loads it if the cache has changed. 104*eda14cbcSMatt Macy */ 105*eda14cbcSMatt Macy static int 106*eda14cbcSMatt Macy namespace_reload(libzfs_handle_t *hdl) 107*eda14cbcSMatt Macy { 108*eda14cbcSMatt Macy nvlist_t *config; 109*eda14cbcSMatt Macy config_node_t *cn; 110*eda14cbcSMatt Macy nvpair_t *elem; 111*eda14cbcSMatt Macy zfs_cmd_t zc = {"\0"}; 112*eda14cbcSMatt Macy void *cookie; 113*eda14cbcSMatt Macy 114*eda14cbcSMatt Macy if (hdl->libzfs_ns_gen == 0) { 115*eda14cbcSMatt Macy /* 116*eda14cbcSMatt Macy * This is the first time we've accessed the configuration 117*eda14cbcSMatt Macy * cache. Initialize the AVL tree and then fall through to the 118*eda14cbcSMatt Macy * common code. 119*eda14cbcSMatt Macy */ 120*eda14cbcSMatt Macy if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", 121*eda14cbcSMatt Macy sizeof (config_node_t), 122*eda14cbcSMatt Macy offsetof(config_node_t, cn_avl), 123*eda14cbcSMatt Macy config_node_compare, UU_DEFAULT)) == NULL) 124*eda14cbcSMatt Macy return (no_memory(hdl)); 125*eda14cbcSMatt Macy 126*eda14cbcSMatt Macy if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, 127*eda14cbcSMatt Macy NULL, UU_DEFAULT)) == NULL) 128*eda14cbcSMatt Macy return (no_memory(hdl)); 129*eda14cbcSMatt Macy } 130*eda14cbcSMatt Macy 131*eda14cbcSMatt Macy if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 132*eda14cbcSMatt Macy return (-1); 133*eda14cbcSMatt Macy 134*eda14cbcSMatt Macy for (;;) { 135*eda14cbcSMatt Macy zc.zc_cookie = hdl->libzfs_ns_gen; 136*eda14cbcSMatt Macy if (zfs_ioctl(hdl, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 137*eda14cbcSMatt Macy switch (errno) { 138*eda14cbcSMatt Macy case EEXIST: 139*eda14cbcSMatt Macy /* 140*eda14cbcSMatt Macy * The namespace hasn't changed. 141*eda14cbcSMatt Macy */ 142*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 143*eda14cbcSMatt Macy return (0); 144*eda14cbcSMatt Macy 145*eda14cbcSMatt Macy case ENOMEM: 146*eda14cbcSMatt Macy if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 147*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 148*eda14cbcSMatt Macy return (-1); 149*eda14cbcSMatt Macy } 150*eda14cbcSMatt Macy break; 151*eda14cbcSMatt Macy 152*eda14cbcSMatt Macy default: 153*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 154*eda14cbcSMatt Macy return (zfs_standard_error(hdl, errno, 155*eda14cbcSMatt Macy dgettext(TEXT_DOMAIN, "failed to read " 156*eda14cbcSMatt Macy "pool configuration"))); 157*eda14cbcSMatt Macy } 158*eda14cbcSMatt Macy } else { 159*eda14cbcSMatt Macy hdl->libzfs_ns_gen = zc.zc_cookie; 160*eda14cbcSMatt Macy break; 161*eda14cbcSMatt Macy } 162*eda14cbcSMatt Macy } 163*eda14cbcSMatt Macy 164*eda14cbcSMatt Macy if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 165*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 166*eda14cbcSMatt Macy return (-1); 167*eda14cbcSMatt Macy } 168*eda14cbcSMatt Macy 169*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 170*eda14cbcSMatt Macy 171*eda14cbcSMatt Macy /* 172*eda14cbcSMatt Macy * Clear out any existing configuration information. 173*eda14cbcSMatt Macy */ 174*eda14cbcSMatt Macy cookie = NULL; 175*eda14cbcSMatt Macy while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) { 176*eda14cbcSMatt Macy nvlist_free(cn->cn_config); 177*eda14cbcSMatt Macy free(cn->cn_name); 178*eda14cbcSMatt Macy free(cn); 179*eda14cbcSMatt Macy } 180*eda14cbcSMatt Macy 181*eda14cbcSMatt Macy elem = NULL; 182*eda14cbcSMatt Macy while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 183*eda14cbcSMatt Macy nvlist_t *child; 184*eda14cbcSMatt Macy uu_avl_index_t where; 185*eda14cbcSMatt Macy 186*eda14cbcSMatt Macy if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) { 187*eda14cbcSMatt Macy nvlist_free(config); 188*eda14cbcSMatt Macy return (-1); 189*eda14cbcSMatt Macy } 190*eda14cbcSMatt Macy 191*eda14cbcSMatt Macy if ((cn->cn_name = zfs_strdup(hdl, 192*eda14cbcSMatt Macy nvpair_name(elem))) == NULL) { 193*eda14cbcSMatt Macy free(cn); 194*eda14cbcSMatt Macy nvlist_free(config); 195*eda14cbcSMatt Macy return (-1); 196*eda14cbcSMatt Macy } 197*eda14cbcSMatt Macy 198*eda14cbcSMatt Macy verify(nvpair_value_nvlist(elem, &child) == 0); 199*eda14cbcSMatt Macy if (nvlist_dup(child, &cn->cn_config, 0) != 0) { 200*eda14cbcSMatt Macy free(cn->cn_name); 201*eda14cbcSMatt Macy free(cn); 202*eda14cbcSMatt Macy nvlist_free(config); 203*eda14cbcSMatt Macy return (no_memory(hdl)); 204*eda14cbcSMatt Macy } 205*eda14cbcSMatt Macy verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) 206*eda14cbcSMatt Macy == NULL); 207*eda14cbcSMatt Macy 208*eda14cbcSMatt Macy uu_avl_insert(hdl->libzfs_ns_avl, cn, where); 209*eda14cbcSMatt Macy } 210*eda14cbcSMatt Macy 211*eda14cbcSMatt Macy nvlist_free(config); 212*eda14cbcSMatt Macy return (0); 213*eda14cbcSMatt Macy } 214*eda14cbcSMatt Macy 215*eda14cbcSMatt Macy /* 216*eda14cbcSMatt Macy * Retrieve the configuration for the given pool. The configuration is an nvlist 217*eda14cbcSMatt Macy * describing the vdevs, as well as the statistics associated with each one. 218*eda14cbcSMatt Macy */ 219*eda14cbcSMatt Macy nvlist_t * 220*eda14cbcSMatt Macy zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 221*eda14cbcSMatt Macy { 222*eda14cbcSMatt Macy if (oldconfig) 223*eda14cbcSMatt Macy *oldconfig = zhp->zpool_old_config; 224*eda14cbcSMatt Macy return (zhp->zpool_config); 225*eda14cbcSMatt Macy } 226*eda14cbcSMatt Macy 227*eda14cbcSMatt Macy /* 228*eda14cbcSMatt Macy * Retrieves a list of enabled features and their refcounts and caches it in 229*eda14cbcSMatt Macy * the pool handle. 230*eda14cbcSMatt Macy */ 231*eda14cbcSMatt Macy nvlist_t * 232*eda14cbcSMatt Macy zpool_get_features(zpool_handle_t *zhp) 233*eda14cbcSMatt Macy { 234*eda14cbcSMatt Macy nvlist_t *config, *features; 235*eda14cbcSMatt Macy 236*eda14cbcSMatt Macy config = zpool_get_config(zhp, NULL); 237*eda14cbcSMatt Macy 238*eda14cbcSMatt Macy if (config == NULL || !nvlist_exists(config, 239*eda14cbcSMatt Macy ZPOOL_CONFIG_FEATURE_STATS)) { 240*eda14cbcSMatt Macy int error; 241*eda14cbcSMatt Macy boolean_t missing = B_FALSE; 242*eda14cbcSMatt Macy 243*eda14cbcSMatt Macy error = zpool_refresh_stats(zhp, &missing); 244*eda14cbcSMatt Macy 245*eda14cbcSMatt Macy if (error != 0 || missing) 246*eda14cbcSMatt Macy return (NULL); 247*eda14cbcSMatt Macy 248*eda14cbcSMatt Macy config = zpool_get_config(zhp, NULL); 249*eda14cbcSMatt Macy } 250*eda14cbcSMatt Macy 251*eda14cbcSMatt Macy if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, 252*eda14cbcSMatt Macy &features) != 0) 253*eda14cbcSMatt Macy return (NULL); 254*eda14cbcSMatt Macy 255*eda14cbcSMatt Macy return (features); 256*eda14cbcSMatt Macy } 257*eda14cbcSMatt Macy 258*eda14cbcSMatt Macy /* 259*eda14cbcSMatt Macy * Refresh the vdev statistics associated with the given pool. This is used in 260*eda14cbcSMatt Macy * iostat to show configuration changes and determine the delta from the last 261*eda14cbcSMatt Macy * time the function was called. This function can fail, in case the pool has 262*eda14cbcSMatt Macy * been destroyed. 263*eda14cbcSMatt Macy */ 264*eda14cbcSMatt Macy int 265*eda14cbcSMatt Macy zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) 266*eda14cbcSMatt Macy { 267*eda14cbcSMatt Macy zfs_cmd_t zc = {"\0"}; 268*eda14cbcSMatt Macy int error; 269*eda14cbcSMatt Macy nvlist_t *config; 270*eda14cbcSMatt Macy libzfs_handle_t *hdl = zhp->zpool_hdl; 271*eda14cbcSMatt Macy 272*eda14cbcSMatt Macy *missing = B_FALSE; 273*eda14cbcSMatt Macy (void) strcpy(zc.zc_name, zhp->zpool_name); 274*eda14cbcSMatt Macy 275*eda14cbcSMatt Macy if (zhp->zpool_config_size == 0) 276*eda14cbcSMatt Macy zhp->zpool_config_size = 1 << 16; 277*eda14cbcSMatt Macy 278*eda14cbcSMatt Macy if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size) != 0) 279*eda14cbcSMatt Macy return (-1); 280*eda14cbcSMatt Macy 281*eda14cbcSMatt Macy for (;;) { 282*eda14cbcSMatt Macy if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_STATS, 283*eda14cbcSMatt Macy &zc) == 0) { 284*eda14cbcSMatt Macy /* 285*eda14cbcSMatt Macy * The real error is returned in the zc_cookie field. 286*eda14cbcSMatt Macy */ 287*eda14cbcSMatt Macy error = zc.zc_cookie; 288*eda14cbcSMatt Macy break; 289*eda14cbcSMatt Macy } 290*eda14cbcSMatt Macy 291*eda14cbcSMatt Macy if (errno == ENOMEM) { 292*eda14cbcSMatt Macy if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 293*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 294*eda14cbcSMatt Macy return (-1); 295*eda14cbcSMatt Macy } 296*eda14cbcSMatt Macy } else { 297*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 298*eda14cbcSMatt Macy if (errno == ENOENT || errno == EINVAL) 299*eda14cbcSMatt Macy *missing = B_TRUE; 300*eda14cbcSMatt Macy zhp->zpool_state = POOL_STATE_UNAVAIL; 301*eda14cbcSMatt Macy return (0); 302*eda14cbcSMatt Macy } 303*eda14cbcSMatt Macy } 304*eda14cbcSMatt Macy 305*eda14cbcSMatt Macy if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 306*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 307*eda14cbcSMatt Macy return (-1); 308*eda14cbcSMatt Macy } 309*eda14cbcSMatt Macy 310*eda14cbcSMatt Macy zcmd_free_nvlists(&zc); 311*eda14cbcSMatt Macy 312*eda14cbcSMatt Macy zhp->zpool_config_size = zc.zc_nvlist_dst_size; 313*eda14cbcSMatt Macy 314*eda14cbcSMatt Macy if (zhp->zpool_config != NULL) { 315*eda14cbcSMatt Macy nvlist_free(zhp->zpool_old_config); 316*eda14cbcSMatt Macy 317*eda14cbcSMatt Macy zhp->zpool_old_config = zhp->zpool_config; 318*eda14cbcSMatt Macy } 319*eda14cbcSMatt Macy 320*eda14cbcSMatt Macy zhp->zpool_config = config; 321*eda14cbcSMatt Macy if (error) 322*eda14cbcSMatt Macy zhp->zpool_state = POOL_STATE_UNAVAIL; 323*eda14cbcSMatt Macy else 324*eda14cbcSMatt Macy zhp->zpool_state = POOL_STATE_ACTIVE; 325*eda14cbcSMatt Macy 326*eda14cbcSMatt Macy return (0); 327*eda14cbcSMatt Macy } 328*eda14cbcSMatt Macy 329*eda14cbcSMatt Macy /* 330*eda14cbcSMatt Macy * The following environment variables are undocumented 331*eda14cbcSMatt Macy * and should be used for testing purposes only: 332*eda14cbcSMatt Macy * 333*eda14cbcSMatt Macy * __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists 334*eda14cbcSMatt Macy * __ZFS_POOL_RESTRICT - iterate only over the pools it lists 335*eda14cbcSMatt Macy * 336*eda14cbcSMatt Macy * This function returns B_TRUE if the pool should be skipped 337*eda14cbcSMatt Macy * during iteration. 338*eda14cbcSMatt Macy */ 339*eda14cbcSMatt Macy boolean_t 340*eda14cbcSMatt Macy zpool_skip_pool(const char *poolname) 341*eda14cbcSMatt Macy { 342*eda14cbcSMatt Macy static boolean_t initialized = B_FALSE; 343*eda14cbcSMatt Macy static const char *exclude = NULL; 344*eda14cbcSMatt Macy static const char *restricted = NULL; 345*eda14cbcSMatt Macy 346*eda14cbcSMatt Macy const char *cur, *end; 347*eda14cbcSMatt Macy int len; 348*eda14cbcSMatt Macy int namelen = strlen(poolname); 349*eda14cbcSMatt Macy 350*eda14cbcSMatt Macy if (!initialized) { 351*eda14cbcSMatt Macy initialized = B_TRUE; 352*eda14cbcSMatt Macy exclude = getenv("__ZFS_POOL_EXCLUDE"); 353*eda14cbcSMatt Macy restricted = getenv("__ZFS_POOL_RESTRICT"); 354*eda14cbcSMatt Macy } 355*eda14cbcSMatt Macy 356*eda14cbcSMatt Macy if (exclude != NULL) { 357*eda14cbcSMatt Macy cur = exclude; 358*eda14cbcSMatt Macy do { 359*eda14cbcSMatt Macy end = strchr(cur, ' '); 360*eda14cbcSMatt Macy len = (NULL == end) ? strlen(cur) : (end - cur); 361*eda14cbcSMatt Macy if (len == namelen && 0 == strncmp(cur, poolname, len)) 362*eda14cbcSMatt Macy return (B_TRUE); 363*eda14cbcSMatt Macy cur += (len + 1); 364*eda14cbcSMatt Macy } while (NULL != end); 365*eda14cbcSMatt Macy } 366*eda14cbcSMatt Macy 367*eda14cbcSMatt Macy if (NULL == restricted) 368*eda14cbcSMatt Macy return (B_FALSE); 369*eda14cbcSMatt Macy 370*eda14cbcSMatt Macy cur = restricted; 371*eda14cbcSMatt Macy do { 372*eda14cbcSMatt Macy end = strchr(cur, ' '); 373*eda14cbcSMatt Macy len = (NULL == end) ? strlen(cur) : (end - cur); 374*eda14cbcSMatt Macy 375*eda14cbcSMatt Macy if (len == namelen && 0 == strncmp(cur, poolname, len)) { 376*eda14cbcSMatt Macy return (B_FALSE); 377*eda14cbcSMatt Macy } 378*eda14cbcSMatt Macy 379*eda14cbcSMatt Macy cur += (len + 1); 380*eda14cbcSMatt Macy } while (NULL != end); 381*eda14cbcSMatt Macy 382*eda14cbcSMatt Macy return (B_TRUE); 383*eda14cbcSMatt Macy } 384*eda14cbcSMatt Macy 385*eda14cbcSMatt Macy /* 386*eda14cbcSMatt Macy * Iterate over all pools in the system. 387*eda14cbcSMatt Macy */ 388*eda14cbcSMatt Macy int 389*eda14cbcSMatt Macy zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) 390*eda14cbcSMatt Macy { 391*eda14cbcSMatt Macy config_node_t *cn; 392*eda14cbcSMatt Macy zpool_handle_t *zhp; 393*eda14cbcSMatt Macy int ret; 394*eda14cbcSMatt Macy 395*eda14cbcSMatt Macy /* 396*eda14cbcSMatt Macy * If someone makes a recursive call to zpool_iter(), we want to avoid 397*eda14cbcSMatt Macy * refreshing the namespace because that will invalidate the parent 398*eda14cbcSMatt Macy * context. We allow recursive calls, but simply re-use the same 399*eda14cbcSMatt Macy * namespace AVL tree. 400*eda14cbcSMatt Macy */ 401*eda14cbcSMatt Macy if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) 402*eda14cbcSMatt Macy return (-1); 403*eda14cbcSMatt Macy 404*eda14cbcSMatt Macy hdl->libzfs_pool_iter++; 405*eda14cbcSMatt Macy for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 406*eda14cbcSMatt Macy cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 407*eda14cbcSMatt Macy 408*eda14cbcSMatt Macy if (zpool_skip_pool(cn->cn_name)) 409*eda14cbcSMatt Macy continue; 410*eda14cbcSMatt Macy 411*eda14cbcSMatt Macy if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { 412*eda14cbcSMatt Macy hdl->libzfs_pool_iter--; 413*eda14cbcSMatt Macy return (-1); 414*eda14cbcSMatt Macy } 415*eda14cbcSMatt Macy 416*eda14cbcSMatt Macy if (zhp == NULL) 417*eda14cbcSMatt Macy continue; 418*eda14cbcSMatt Macy 419*eda14cbcSMatt Macy if ((ret = func(zhp, data)) != 0) { 420*eda14cbcSMatt Macy hdl->libzfs_pool_iter--; 421*eda14cbcSMatt Macy return (ret); 422*eda14cbcSMatt Macy } 423*eda14cbcSMatt Macy } 424*eda14cbcSMatt Macy hdl->libzfs_pool_iter--; 425*eda14cbcSMatt Macy 426*eda14cbcSMatt Macy return (0); 427*eda14cbcSMatt Macy } 428*eda14cbcSMatt Macy 429*eda14cbcSMatt Macy /* 430*eda14cbcSMatt Macy * Iterate over root datasets, calling the given function for each. The zfs 431*eda14cbcSMatt Macy * handle passed each time must be explicitly closed by the callback. 432*eda14cbcSMatt Macy */ 433*eda14cbcSMatt Macy int 434*eda14cbcSMatt Macy zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) 435*eda14cbcSMatt Macy { 436*eda14cbcSMatt Macy config_node_t *cn; 437*eda14cbcSMatt Macy zfs_handle_t *zhp; 438*eda14cbcSMatt Macy int ret; 439*eda14cbcSMatt Macy 440*eda14cbcSMatt Macy if (namespace_reload(hdl) != 0) 441*eda14cbcSMatt Macy return (-1); 442*eda14cbcSMatt Macy 443*eda14cbcSMatt Macy for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 444*eda14cbcSMatt Macy cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 445*eda14cbcSMatt Macy 446*eda14cbcSMatt Macy if (zpool_skip_pool(cn->cn_name)) 447*eda14cbcSMatt Macy continue; 448*eda14cbcSMatt Macy 449*eda14cbcSMatt Macy if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) 450*eda14cbcSMatt Macy continue; 451*eda14cbcSMatt Macy 452*eda14cbcSMatt Macy if ((ret = func(zhp, data)) != 0) 453*eda14cbcSMatt Macy return (ret); 454*eda14cbcSMatt Macy } 455*eda14cbcSMatt Macy 456*eda14cbcSMatt Macy return (0); 457*eda14cbcSMatt Macy } 458