X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=lib%2Flibzfs%2Flibzfs_config.c;h=ee94fe106d73dcba2b01dfd738405273cd45e0f7;hb=cc92e9d0c3e67a7e66c844466f85696a087bf60a;hp=94640d1b128cfe0c6bf7dc1276218ff89d9993e0;hpb=172bb4bd5e4afef721dd4d2972d8680d983f144b;p=zfs.git diff --git a/lib/libzfs/libzfs_config.c b/lib/libzfs/libzfs_config.c index 94640d1..ee94fe1 100644 --- a/lib/libzfs/libzfs_config.c +++ b/lib/libzfs/libzfs_config.c @@ -18,12 +18,15 @@ * * CDDL HEADER END */ + /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * The pool configuration repository is stored in /etc/zfs/zpool.cache as a @@ -103,7 +106,7 @@ namespace_reload(libzfs_handle_t *hdl) nvlist_t *config; config_node_t *cn; nvpair_t *elem; - zfs_cmd_t zc = { 0 }; + zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 }; void *cookie; if (hdl->libzfs_ns_gen == 0) { @@ -220,6 +223,36 @@ zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) } /* + * Retrieves a list of enabled features and their refcounts and caches it in + * the pool handle. + */ +nvlist_t * +zpool_get_features(zpool_handle_t *zhp) +{ + nvlist_t *config, *features; + + config = zpool_get_config(zhp, NULL); + + if (config == NULL || !nvlist_exists(config, + ZPOOL_CONFIG_FEATURE_STATS)) { + int error; + boolean_t missing = B_FALSE; + + error = zpool_refresh_stats(zhp, &missing); + + if (error != 0 || missing) + return (NULL); + + config = zpool_get_config(zhp, NULL); + } + + verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, + &features) == 0); + + return (features); +} + +/* * Refresh the vdev statistics associated with the given pool. This is used in * iostat to show configuration changes and determine the delta from the last * time the function was called. This function can fail, in case the pool has @@ -228,7 +261,7 @@ zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) int zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) { - zfs_cmd_t zc = { 0 }; + zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 }; int error; nvlist_t *config; libzfs_handle_t *hdl = zhp->zpool_hdl; @@ -304,6 +337,48 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) } /* + * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over + * pools it lists. + * + * This is an undocumented feature for use during testing only. + * + * This function returns B_TRUE if the pool should be skipped + * during iteration. + */ +static boolean_t +check_restricted(const char *poolname) +{ + static boolean_t initialized = B_FALSE; + static char *restricted = NULL; + + const char *cur, *end; + int len, namelen; + + if (!initialized) { + initialized = B_TRUE; + restricted = getenv("__ZFS_POOL_RESTRICT"); + } + + if (NULL == restricted) + return (B_FALSE); + + cur = restricted; + namelen = strlen(poolname); + do { + end = strchr(cur, ' '); + len = (NULL == end) ? strlen(cur) : (end - cur); + + if (len == namelen && 0 == strncmp(cur, poolname, len)) { + return (B_FALSE); + } + + cur += (len + 1); + } while (NULL != end); + + return (B_TRUE); +} + +/* * Iterate over all pools in the system. */ int @@ -313,21 +388,36 @@ zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) zpool_handle_t *zhp; int ret; - if (namespace_reload(hdl) != 0) + /* + * If someone makes a recursive call to zpool_iter(), we want to avoid + * refreshing the namespace because that will invalidate the parent + * context. We allow recursive calls, but simply re-use the same + * namespace AVL tree. + */ + if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) return (-1); + hdl->libzfs_pool_iter++; for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { - if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) + if (check_restricted(cn->cn_name)) + continue; + + if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { + hdl->libzfs_pool_iter--; return (-1); + } if (zhp == NULL) continue; - if ((ret = func(zhp, data)) != 0) + if ((ret = func(zhp, data)) != 0) { + hdl->libzfs_pool_iter--; return (ret); + } } + hdl->libzfs_pool_iter--; return (0); } @@ -349,6 +439,9 @@ zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { + if (check_restricted(cn->cn_name)) + continue; + if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) continue;