xref: /freebsd-src/sys/contrib/openzfs/lib/libzfs/libzfs_config.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
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