diff options
Diffstat (limited to 'sys/contrib/openzfs/lib/libzutil/zutil_import.c')
-rw-r--r-- | sys/contrib/openzfs/lib/libzutil/zutil_import.c | 340 |
1 files changed, 249 insertions, 91 deletions
diff --git a/sys/contrib/openzfs/lib/libzutil/zutil_import.c b/sys/contrib/openzfs/lib/libzutil/zutil_import.c index 9eb55aaf77ce..06705ff4d9b4 100644 --- a/sys/contrib/openzfs/lib/libzutil/zutil_import.c +++ b/sys/contrib/openzfs/lib/libzutil/zutil_import.c @@ -6,7 +6,7 @@ * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. + * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * @@ -47,7 +47,9 @@ * using our derived config, and record the results. */ +#ifdef HAVE_AIO_H #include <aio.h> +#endif #include <ctype.h> #include <dirent.h> #include <errno.h> @@ -69,6 +71,30 @@ #include "zutil_import.h" +const char * +libpc_error_description(libpc_handle_t *hdl) +{ + if (hdl->lpc_desc[0] != '\0') + return (hdl->lpc_desc); + + switch (hdl->lpc_error) { + case LPC_BADCACHE: + return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); + case LPC_BADPATH: + return (dgettext(TEXT_DOMAIN, "must be an absolute path")); + case LPC_NOMEM: + return (dgettext(TEXT_DOMAIN, "out of memory")); + case LPC_EACCESS: + return (dgettext(TEXT_DOMAIN, "some devices require root " + "privileges")); + case LPC_UNKNOWN: + return (dgettext(TEXT_DOMAIN, "unknown error")); + default: + assert(hdl->lpc_error == 0); + return (dgettext(TEXT_DOMAIN, "no error")); + } +} + static __attribute__((format(printf, 2, 3))) void zutil_error_aux(libpc_handle_t *hdl, const char *fmt, ...) { @@ -83,28 +109,27 @@ zutil_error_aux(libpc_handle_t *hdl, const char *fmt, ...) } static void -zutil_verror(libpc_handle_t *hdl, const char *error, const char *fmt, +zutil_verror(libpc_handle_t *hdl, lpc_error_t error, const char *fmt, va_list ap) { char action[1024]; (void) vsnprintf(action, sizeof (action), fmt, ap); + hdl->lpc_error = error; if (hdl->lpc_desc_active) hdl->lpc_desc_active = B_FALSE; else hdl->lpc_desc[0] = '\0'; - if (hdl->lpc_printerr) { - if (hdl->lpc_desc[0] != '\0') - error = hdl->lpc_desc; - - (void) fprintf(stderr, "%s: %s\n", action, error); - } + if (hdl->lpc_printerr) + (void) fprintf(stderr, "%s: %s\n", action, + libpc_error_description(hdl)); } static __attribute__((format(printf, 3, 4))) int -zutil_error_fmt(libpc_handle_t *hdl, const char *error, const char *fmt, ...) +zutil_error_fmt(libpc_handle_t *hdl, lpc_error_t error, + const char *fmt, ...) { va_list ap; @@ -118,7 +143,7 @@ zutil_error_fmt(libpc_handle_t *hdl, const char *error, const char *fmt, ...) } static int -zutil_error(libpc_handle_t *hdl, const char *error, const char *msg) +zutil_error(libpc_handle_t *hdl, lpc_error_t error, const char *msg) { return (zutil_error_fmt(hdl, error, "%s", msg)); } @@ -126,7 +151,7 @@ zutil_error(libpc_handle_t *hdl, const char *error, const char *msg) static int zutil_no_memory(libpc_handle_t *hdl) { - zutil_error(hdl, EZFS_NOMEM, "internal error"); + zutil_error(hdl, LPC_NOMEM, "internal error"); exit(1); } @@ -208,7 +233,7 @@ fix_paths(libpc_handle_t *hdl, nvlist_t *nv, name_entry_t *names) uint_t c, children; uint64_t guid; name_entry_t *ne, *best; - char *path; + const char *path; if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0) { @@ -472,15 +497,13 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, uint_t i, nspares, nl2cache; boolean_t config_seen; uint64_t best_txg; - char *name, *hostname = NULL; + const char *name, *hostname = NULL; uint64_t guid; uint_t children = 0; nvlist_t **child = NULL; - uint_t holes; uint64_t *hole_array, max_id; uint_t c; boolean_t isactive; - uint64_t hostid; nvlist_t *nvl; boolean_t valid_top_config = B_FALSE; @@ -488,7 +511,8 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, goto nomem; for (pe = pl->pools; pe != NULL; pe = pe->pe_next) { - uint64_t id, max_txg = 0; + uint64_t id, max_txg = 0, hostid = 0; + uint_t holes = 0; if (nvlist_alloc(&config, NV_UNIQUE_NAME, 0) != 0) goto nomem; @@ -567,8 +591,8 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, * hostname (if available) */ uint64_t state, version; - char *comment = NULL; - char *compatibility = NULL; + const char *comment = NULL; + const char *compatibility = NULL; version = fnvlist_lookup_uint64(tmp, ZPOOL_CONFIG_VERSION); @@ -749,7 +773,7 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, nvlist_add_uint64(nvroot, ZPOOL_CONFIG_ID, 0ULL) != 0 || nvlist_add_uint64(nvroot, ZPOOL_CONFIG_GUID, guid) != 0 || nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, - child, children) != 0) { + (const nvlist_t **)child, children) != 0) { nvlist_free(nvroot); goto nomem; } @@ -910,7 +934,6 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels) vdev_phys_t *label; nvlist_t *expected_config = NULL; uint64_t expected_guid = 0, size; - int error; *config = NULL; @@ -918,8 +941,9 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels) return (0); size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); - error = posix_memalign((void **)&label, PAGESIZE, sizeof (*label)); - if (error) + label = (vdev_phys_t *)umem_alloc_aligned(sizeof (*label), PAGESIZE, + UMEM_DEFAULT); + if (label == NULL) return (-1); for (l = 0; l < VDEV_LABELS; l++) { @@ -968,7 +992,7 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels) if (num_labels != NULL) *num_labels = count; - free(label); + umem_free_aligned(label, sizeof (*label)); *config = expected_config; return (0); @@ -982,6 +1006,9 @@ zpool_read_label_slow(int fd, nvlist_t **config, int *num_labels) int zpool_read_label(int fd, nvlist_t **config, int *num_labels) { +#ifndef HAVE_AIO_H + return (zpool_read_label_slow(fd, config, num_labels)); +#else struct stat64 statbuf; struct aiocb aiocbs[VDEV_LABELS]; struct aiocb *aiocbps[VDEV_LABELS]; @@ -996,9 +1023,9 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) return (0); size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); - error = posix_memalign((void **)&labels, PAGESIZE, - VDEV_LABELS * sizeof (*labels)); - if (error) + labels = (vdev_phys_t *)umem_alloc_aligned( + VDEV_LABELS * sizeof (*labels), PAGESIZE, UMEM_DEFAULT); + if (labels == NULL) return (-1); memset(aiocbs, 0, sizeof (aiocbs)); @@ -1029,14 +1056,25 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) case EINVAL: break; case EINPROGRESS: - // This shouldn't be possible to - // encounter, die if we do. + /* + * This shouldn't be possible to + * encounter, die if we do. + */ ASSERT(B_FALSE); - fallthrough; + zfs_fallthrough; + case EREMOTEIO: + /* + * May be returned by an NVMe device + * which is visible in /dev/ but due + * to a low-level format change, or + * other error, needs to be rescanned. + * Try the slow method. + */ + zfs_fallthrough; case EOPNOTSUPP: case ENOSYS: do_slow = B_TRUE; - fallthrough; + zfs_fallthrough; case 0: default: (void) aio_return(&aiocbs[l]); @@ -1051,7 +1089,7 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) error = zpool_read_label_slow(fd, config, num_labels); saved_errno = errno; } - free(labels); + umem_free_aligned(labels, VDEV_LABELS * sizeof (*labels)); errno = saved_errno; return (error); } @@ -1100,10 +1138,11 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) if (num_labels != NULL) *num_labels = count; - free(labels); + umem_free_aligned(labels, VDEV_LABELS * sizeof (*labels)); *config = expected_config; return (0); +#endif } /* @@ -1133,12 +1172,12 @@ slice_cache_compare(const void *arg1, const void *arg2) static int label_paths_impl(libpc_handle_t *hdl, nvlist_t *nvroot, uint64_t pool_guid, - uint64_t vdev_guid, char **path, char **devid) + uint64_t vdev_guid, const char **path, const char **devid) { nvlist_t **child; uint_t c, children; uint64_t guid; - char *val; + const char *val; int error; if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, @@ -1176,18 +1215,32 @@ label_paths_impl(libpc_handle_t *hdl, nvlist_t *nvroot, uint64_t pool_guid, * The returned pointers are only valid as long as label remains valid. */ int -label_paths(libpc_handle_t *hdl, nvlist_t *label, char **path, char **devid) +label_paths(libpc_handle_t *hdl, nvlist_t *label, const char **path, + const char **devid) { nvlist_t *nvroot; uint64_t pool_guid; uint64_t vdev_guid; + uint64_t state; *path = NULL; *devid = NULL; + if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid) != 0) + return (ENOENT); + + /* + * In case of spare or l2cache, we directly return path/devid from the + * label. + */ + if (!(nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_STATE, &state)) && + (state == POOL_STATE_SPARE || state == POOL_STATE_L2CACHE)) { + (void) nvlist_lookup_string(label, ZPOOL_CONFIG_PATH, path); + (void) nvlist_lookup_string(label, ZPOOL_CONFIG_DEVID, devid); + return (0); + } if (nvlist_lookup_nvlist(label, ZPOOL_CONFIG_VDEV_TREE, &nvroot) || - nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid) || - nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid)) + nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid)) return (ENOENT); return (label_paths_impl(hdl, nvroot, pool_guid, vdev_guid, path, @@ -1237,18 +1290,18 @@ zpool_find_import_scan_dir(libpc_handle_t *hdl, pthread_mutex_t *lock, if (error == ENOENT) return (0); - zutil_error_aux(hdl, "%s", strerror(error)); - (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext( - TEXT_DOMAIN, "cannot resolve path '%s'"), dir); + zutil_error_aux(hdl, "%s", zfs_strerror(error)); + (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(TEXT_DOMAIN, + "cannot resolve path '%s'"), dir); return (error); } dirp = opendir(path); if (dirp == NULL) { error = errno; - zutil_error_aux(hdl, "%s", strerror(error)); - (void) zutil_error_fmt(hdl, EZFS_BADPATH, - dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); + zutil_error_aux(hdl, "%s", zfs_strerror(error)); + (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(TEXT_DOMAIN, + "cannot open '%s'"), path); return (error); } @@ -1308,9 +1361,9 @@ zpool_find_import_scan_path(libpc_handle_t *hdl, pthread_mutex_t *lock, goto out; } - zutil_error_aux(hdl, "%s", strerror(error)); - (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext( - TEXT_DOMAIN, "cannot resolve path '%s'"), dir); + zutil_error_aux(hdl, "%s", zfs_strerror(error)); + (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext(TEXT_DOMAIN, + "cannot resolve path '%s'"), dir); goto out; } @@ -1346,8 +1399,8 @@ zpool_find_import_scan(libpc_handle_t *hdl, pthread_mutex_t *lock, if (error == ENOENT) continue; - zutil_error_aux(hdl, "%s", strerror(error)); - (void) zutil_error_fmt(hdl, EZFS_BADPATH, dgettext( + zutil_error_aux(hdl, "%s", zfs_strerror(error)); + (void) zutil_error_fmt(hdl, LPC_BADPATH, dgettext( TEXT_DOMAIN, "cannot resolve path '%s'"), dir[i]); goto error; } @@ -1393,6 +1446,7 @@ static nvlist_t * zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg, pthread_mutex_t *lock, avl_tree_t *cache) { + (void) lock; nvlist_t *ret = NULL; pool_list_t pools = { 0 }; pool_entry_t *pe, *penext; @@ -1444,7 +1498,7 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg, } if (iarg->poolname != NULL && !aux) { - char *pname; + const char *pname; matched = nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &pname) == 0 && @@ -1518,7 +1572,7 @@ static int discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv, avl_tree_t *cache, pthread_mutex_t *lock) { - char *path = NULL; + const char *path = NULL; ssize_t dl; uint_t children; nvlist_t **child; @@ -1535,12 +1589,21 @@ discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv, * our directory cache. */ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { - if ((dl = zfs_dirnamelen(path)) == -1) + int ret; + char c = '\0'; + if ((dl = zfs_dirnamelen(path)) == -1) { path = "."; - else - path[dl] = '\0'; - return (zpool_find_import_scan_dir(hdl, lock, cache, - path, 0)); + } else { + c = path[dl]; + ((char *)path)[dl] = '\0'; + + } + ret = zpool_find_import_scan_dir(hdl, lock, cache, + path, 0); + if (c != '\0') + ((char *)path)[dl] = c; + + return (ret); } return (0); } @@ -1559,24 +1622,24 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg) nvlist_t *raw, *src, *dst; nvlist_t *pools; nvpair_t *elem; - char *name; + const char *name; uint64_t this_guid; boolean_t active; verify(iarg->poolname == NULL || iarg->guid == 0); if ((fd = open(iarg->cachefile, O_RDONLY | O_CLOEXEC)) < 0) { - zutil_error_aux(hdl, "%s", strerror(errno)); - (void) zutil_error(hdl, EZFS_BADCACHE, - dgettext(TEXT_DOMAIN, "failed to open cache file")); + zutil_error_aux(hdl, "%s", zfs_strerror(errno)); + (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN, + "failed to open cache file")); return (NULL); } if (fstat64(fd, &statbuf) != 0) { - zutil_error_aux(hdl, "%s", strerror(errno)); + zutil_error_aux(hdl, "%s", zfs_strerror(errno)); (void) close(fd); - (void) zutil_error(hdl, EZFS_BADCACHE, - dgettext(TEXT_DOMAIN, "failed to get size of cache file")); + (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN, + "failed to get size of cache file")); return (NULL); } @@ -1588,8 +1651,7 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg) if (read(fd, buf, statbuf.st_size) != statbuf.st_size) { (void) close(fd); free(buf); - (void) zutil_error(hdl, EZFS_BADCACHE, - dgettext(TEXT_DOMAIN, + (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN, "failed to read cache file contents")); return (NULL); } @@ -1598,8 +1660,7 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg) if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) { free(buf); - (void) zutil_error(hdl, EZFS_BADCACHE, - dgettext(TEXT_DOMAIN, + (void) zutil_error(hdl, LPC_BADCACHE, dgettext(TEXT_DOMAIN, "invalid or corrupt cache file contents")); return (NULL); } @@ -1687,6 +1748,8 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg) * caller. */ nvpair_t *pair = nvlist_next_nvpair(nv, NULL); + if (pair == NULL) + continue; fnvlist_add_nvlist(pools, nvpair_name(pair), fnvpair_value_nvlist(pair)); @@ -1768,26 +1831,20 @@ zpool_find_import(libpc_handle_t *hdl, importargs_t *iarg) nvlist_t * -zpool_search_import(void *hdl, importargs_t *import, - const pool_config_ops_t *pco) +zpool_search_import(libpc_handle_t *hdl, importargs_t *import) { - libpc_handle_t handle = { 0 }; nvlist_t *pools = NULL; - handle.lpc_lib_handle = hdl; - handle.lpc_ops = pco; - handle.lpc_printerr = B_TRUE; - verify(import->poolname == NULL || import->guid == 0); if (import->cachefile != NULL) - pools = zpool_find_import_cached(&handle, import); + pools = zpool_find_import_cached(hdl, import); else - pools = zpool_find_import(&handle, import); + pools = zpool_find_import(hdl, import); if ((pools == NULL || nvlist_empty(pools)) && - handle.lpc_open_access_error && geteuid() != 0) { - (void) zutil_error(&handle, EZFS_EACESS, dgettext(TEXT_DOMAIN, + hdl->lpc_open_access_error && geteuid() != 0) { + (void) zutil_error(hdl, LPC_EACCESS, dgettext(TEXT_DOMAIN, "no pools found")); } @@ -1795,10 +1852,10 @@ zpool_search_import(void *hdl, importargs_t *import, } static boolean_t -pool_match(nvlist_t *cfg, char *tgt) +pool_match(nvlist_t *cfg, const char *tgt) { uint64_t v, guid = strtoull(tgt, NULL, 0); - char *s; + const char *s; if (guid != 0) { if (nvlist_lookup_uint64(cfg, ZPOOL_CONFIG_POOL_GUID, &v) == 0) @@ -1811,8 +1868,8 @@ pool_match(nvlist_t *cfg, char *tgt) } int -zpool_find_config(void *hdl, const char *target, nvlist_t **configp, - importargs_t *args, const pool_config_ops_t *pco) +zpool_find_config(libpc_handle_t *hdl, const char *target, nvlist_t **configp, + importargs_t *args) { nvlist_t *pools; nvlist_t *match = NULL; @@ -1821,12 +1878,15 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp, int count = 0; char *targetdup = strdup(target); + if (targetdup == NULL) + return (ENOMEM); + *configp = NULL; if ((sepp = strpbrk(targetdup, "/@")) != NULL) *sepp = '\0'; - pools = zpool_search_import(hdl, args, pco); + pools = zpool_search_import(hdl, args); if (pools != NULL) { nvpair_t *elem = NULL; @@ -1862,6 +1922,104 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp, return (0); } +/* Return if a vdev is a leaf vdev. Note: draid spares are leaf vdevs. */ +static boolean_t +vdev_is_leaf(nvlist_t *nv) +{ + uint_t children = 0; + nvlist_t **child; + + (void) nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, + &child, &children); + + return (children == 0); +} + +/* Return if a vdev is a leaf vdev and a real device (disk or file) */ +static boolean_t +vdev_is_real_leaf(nvlist_t *nv) +{ + const char *type = NULL; + if (!vdev_is_leaf(nv)) + return (B_FALSE); + + (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type); + if ((strcmp(type, VDEV_TYPE_DISK) == 0) || + (strcmp(type, VDEV_TYPE_FILE) == 0)) { + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * This function is called by our FOR_EACH_VDEV() macros. + * + * state: State machine status (stored inside of a (nvlist_t *)) + * nv: The current vdev nvlist_t we are iterating over. + * last_nv: The previous vdev nvlist_t we returned to the user in + * the last iteration of FOR_EACH_VDEV(). We use it + * to find the next vdev nvlist_t we should return. + * real_leaves_only: Only return leaf vdevs. + * + * Returns 1 if we found the next vdev nvlist_t for this iteration. 0 if + * we're still searching for it. + */ +static int +__for_each_vdev_macro_helper_func(void *state, nvlist_t *nv, void *last_nv, + boolean_t real_leaves_only) +{ + enum {FIRST_NV = 0, NEXT_IS_MATCH = 1, STOP_LOOKING = 2}; + + /* The very first entry in the NV list is a special case */ + if (*((nvlist_t **)state) == (nvlist_t *)FIRST_NV) { + if (real_leaves_only && !vdev_is_real_leaf(nv)) + return (0); + + *((nvlist_t **)last_nv) = nv; + *((nvlist_t **)state) = (nvlist_t *)STOP_LOOKING; + return (1); + } + + /* + * We came across our last_nv, meaning the next one is the one we + * want + */ + if (nv == *((nvlist_t **)last_nv)) { + /* Next iteration of this function will return the nvlist_t */ + *((nvlist_t **)state) = (nvlist_t *)NEXT_IS_MATCH; + return (0); + } + + /* + * We marked NEXT_IS_MATCH on the previous iteration, so this is the one + * we want. + */ + if (*(nvlist_t **)state == (nvlist_t *)NEXT_IS_MATCH) { + if (real_leaves_only && !vdev_is_real_leaf(nv)) + return (0); + + *((nvlist_t **)last_nv) = nv; + *((nvlist_t **)state) = (nvlist_t *)STOP_LOOKING; + return (1); + } + + return (0); +} + +int +for_each_vdev_macro_helper_func(void *state, nvlist_t *nv, void *last_nv) +{ + return (__for_each_vdev_macro_helper_func(state, nv, last_nv, B_FALSE)); +} + +int +for_each_real_leaf_vdev_macro_helper_func(void *state, nvlist_t *nv, + void *last_nv) +{ + return (__for_each_vdev_macro_helper_func(state, nv, last_nv, B_TRUE)); +} + /* * Internal function for iterating over the vdevs. * @@ -1880,7 +2038,7 @@ for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func, uint_t c, children; int ret = 0; int i; - char *type; + const char *type; const char *list[] = { ZPOOL_CONFIG_SPARES, @@ -1888,6 +2046,14 @@ for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func, ZPOOL_CONFIG_CHILDREN }; + if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0) + return (ret); + + /* Don't run our function on indirect vdevs */ + if (strcmp(type, VDEV_TYPE_INDIRECT) != 0) { + ret |= func(zhp, nv, data); + } + for (i = 0; i < ARRAY_SIZE(list); i++) { if (nvlist_lookup_nvlist_array(nv, list[i], &child, &children) == 0) { @@ -1906,14 +2072,6 @@ for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func, } } - if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0) - return (ret); - - /* Don't run our function on root vdevs */ - if (strcmp(type, VDEV_TYPE_ROOT) != 0) { - ret |= func(zhp, nv, data); - } - return (ret); } |