X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=lib%2Flibzfs%2Flibzfs_config.c;h=b36dee1e522fd7986c8525969803538645e338a8;hb=fc24f7c887a040b6dc9f2a3dd3d5ae0c03a5d639;hp=94640d1b128cfe0c6bf7dc1276218ff89d9993e0;hpb=172bb4bd5e4afef721dd4d2972d8680d983f144b;p=zfs.git diff --git a/lib/libzfs/libzfs_config.c b/lib/libzfs/libzfs_config.c index 94640d1..b36dee1 100644 --- a/lib/libzfs/libzfs_config.c +++ b/lib/libzfs/libzfs_config.c @@ -19,12 +19,10 @@ * 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" - /* * The pool configuration repository is stored in /etc/zfs/zpool.cache as a * single packed nvlist. While it would be nice to just read in this @@ -103,7 +101,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) { @@ -228,7 +226,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 +302,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 +353,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 +404,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;