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