1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
5*1544Seschrock  * Common Development and Distribution License (the "License").
6*1544Seschrock  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
21789Sahrens /*
22*1544Seschrock  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27789Sahrens 
28789Sahrens /*
29789Sahrens  * The pool configuration repository is stored in /etc/zfs/zpool.cache as a
30789Sahrens  * single packed nvlist.  While it would be nice to just read in this
31789Sahrens  * file from userland, this wouldn't work from a local zone.  So we have to have
32789Sahrens  * a zpool ioctl to return the complete configuration for all pools.  In the
33789Sahrens  * global zone, this will be identical to reading the file and unpacking it in
34789Sahrens  * userland.
35789Sahrens  */
36789Sahrens 
37789Sahrens #include <errno.h>
38789Sahrens #include <sys/stat.h>
39789Sahrens #include <fcntl.h>
40789Sahrens #include <stddef.h>
41789Sahrens #include <string.h>
42789Sahrens #include <unistd.h>
43789Sahrens #include <libintl.h>
44789Sahrens #include <libuutil.h>
45789Sahrens 
46789Sahrens #include "libzfs_impl.h"
47789Sahrens 
48789Sahrens static uu_avl_t *namespace_avl;
49789Sahrens static uint64_t namespace_generation;
50789Sahrens 
51789Sahrens typedef struct config_node {
52789Sahrens 	char		*cn_name;
53789Sahrens 	nvlist_t	*cn_config;
54789Sahrens 	uu_avl_node_t	cn_avl;
55789Sahrens } config_node_t;
56789Sahrens 
57789Sahrens /* ARGSUSED */
58789Sahrens static int
59789Sahrens config_node_compare(const void *a, const void *b, void *unused)
60789Sahrens {
61789Sahrens 	int ret;
62789Sahrens 
63789Sahrens 	const config_node_t *ca = (config_node_t *)a;
64789Sahrens 	const config_node_t *cb = (config_node_t *)b;
65789Sahrens 
66789Sahrens 	ret = strcmp(ca->cn_name, cb->cn_name);
67789Sahrens 
68789Sahrens 	if (ret < 0)
69789Sahrens 		return (-1);
70789Sahrens 	else if (ret > 0)
71789Sahrens 		return (1);
72789Sahrens 	else
73789Sahrens 		return (0);
74789Sahrens }
75789Sahrens 
76789Sahrens /*
77789Sahrens  * Loads the pool namespace, or re-loads it if the cache has changed.
78789Sahrens  */
79789Sahrens static void
80789Sahrens namespace_reload()
81789Sahrens {
82789Sahrens 	nvlist_t *config;
83789Sahrens 	config_node_t *cn;
84789Sahrens 	nvpair_t *elem;
85789Sahrens 	zfs_cmd_t zc = { 0 };
86789Sahrens 	uu_avl_walk_t *walk;
87789Sahrens 
88789Sahrens 	if (namespace_generation == 0) {
89789Sahrens 		/*
90789Sahrens 		 * This is the first time we've accessed the configuration
91789Sahrens 		 * cache.  Initialize the AVL tree and then fall through to the
92789Sahrens 		 * common code.
93789Sahrens 		 */
94789Sahrens 		uu_avl_pool_t *pool;
95789Sahrens 
96789Sahrens 		if ((pool = uu_avl_pool_create("config_pool",
97789Sahrens 		    sizeof (config_node_t),
98789Sahrens 		    offsetof(config_node_t, cn_avl),
99789Sahrens 		    config_node_compare, UU_DEFAULT)) == NULL)
100789Sahrens 			no_memory();
101789Sahrens 
102789Sahrens 		if ((namespace_avl = uu_avl_create(pool, NULL,
103789Sahrens 		    UU_DEFAULT)) == NULL)
104789Sahrens 			no_memory();
105789Sahrens 	}
106789Sahrens 
107789Sahrens 	/*
108789Sahrens 	 * Issue the ZFS_IOC_POOL_CONFIGS ioctl.
109789Sahrens 	 * This can fail for one of two reasons:
110789Sahrens 	 *
111789Sahrens 	 * 	EEXIST		The generation counts match, nothing to do.
112789Sahrens 	 * 	ENOMEM		The zc_config_dst buffer isn't large enough to
113789Sahrens 	 * 			hold the config; zc_config_dst_size will have
114789Sahrens 	 *			been modified to tell us how much to allocate.
115789Sahrens 	 */
116789Sahrens 	zc.zc_config_dst_size = 1024;
117789Sahrens 	zc.zc_config_dst = (uint64_t)(uintptr_t)
118789Sahrens 	    zfs_malloc(zc.zc_config_dst_size);
119789Sahrens 	for (;;) {
120789Sahrens 		zc.zc_cookie = namespace_generation;
121*1544Seschrock 		if (zfs_ioctl(ZFS_IOC_POOL_CONFIGS, &zc) != 0) {
122789Sahrens 			switch (errno) {
123789Sahrens 			case EEXIST:
124789Sahrens 				/*
125789Sahrens 				 * The namespace hasn't changed.
126789Sahrens 				 */
127789Sahrens 				free((void *)(uintptr_t)zc.zc_config_dst);
128789Sahrens 				return;
129789Sahrens 
130789Sahrens 			case ENOMEM:
131789Sahrens 				free((void *)(uintptr_t)zc.zc_config_dst);
132789Sahrens 				zc.zc_config_dst = (uint64_t)(uintptr_t)
133789Sahrens 				    zfs_malloc(zc.zc_config_dst_size);
134789Sahrens 				break;
135789Sahrens 
136789Sahrens 			default:
137789Sahrens 				zfs_baderror(errno);
138789Sahrens 			}
139789Sahrens 		} else {
140789Sahrens 			namespace_generation = zc.zc_cookie;
141789Sahrens 			break;
142789Sahrens 		}
143789Sahrens 	}
144789Sahrens 
145789Sahrens 	verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst,
146789Sahrens 	    zc.zc_config_dst_size, &config, 0) == 0);
147789Sahrens 
148789Sahrens 	free((void *)(uintptr_t)zc.zc_config_dst);
149789Sahrens 
150789Sahrens 	/*
151789Sahrens 	 * Clear out any existing configuration information.
152789Sahrens 	 */
153789Sahrens 	if ((walk = uu_avl_walk_start(namespace_avl, UU_WALK_ROBUST)) == NULL)
154789Sahrens 		no_memory();
155789Sahrens 
156789Sahrens 	while ((cn = uu_avl_walk_next(walk)) != NULL) {
157789Sahrens 		uu_avl_remove(namespace_avl, cn);
158789Sahrens 		nvlist_free(cn->cn_config);
159789Sahrens 		free(cn->cn_name);
160789Sahrens 		free(cn);
161789Sahrens 	}
162789Sahrens 
163789Sahrens 	elem = NULL;
164789Sahrens 	while ((elem = nvlist_next_nvpair(config, elem)) != NULL) {
165789Sahrens 		nvlist_t *child;
166789Sahrens 		uu_avl_index_t where;
167789Sahrens 
168789Sahrens 		cn = zfs_malloc(sizeof (config_node_t));
169789Sahrens 		cn->cn_name = zfs_strdup(nvpair_name(elem));
170789Sahrens 
171789Sahrens 		verify(nvpair_value_nvlist(elem, &child) == 0);
172789Sahrens 		verify(nvlist_dup(child, &cn->cn_config, 0) == 0);
173789Sahrens 		verify(uu_avl_find(namespace_avl, cn, NULL, &where) == NULL);
174789Sahrens 
175789Sahrens 		uu_avl_insert(namespace_avl, cn, where);
176789Sahrens 	}
177789Sahrens 
178789Sahrens 	nvlist_free(config);
179789Sahrens }
180789Sahrens 
181789Sahrens /*
182789Sahrens  * Retrive the configuration for the given pool.  The configuration is a nvlist
183789Sahrens  * describing the vdevs, as well as the statistics associated with each one.
184789Sahrens  */
185789Sahrens nvlist_t *
186952Seschrock zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig)
187789Sahrens {
188952Seschrock 	if (oldconfig)
189952Seschrock 		*oldconfig = zhp->zpool_old_config;
190789Sahrens 	return (zhp->zpool_config);
191789Sahrens }
192789Sahrens 
193789Sahrens /*
194789Sahrens  * Refresh the vdev statistics associated with the given pool.  This is used in
195789Sahrens  * iostat to show configuration changes and determine the delta from the last
196789Sahrens  * time the function was called.  This function can fail, in case the pool has
197789Sahrens  * been destroyed.
198789Sahrens  */
199789Sahrens int
200952Seschrock zpool_refresh_stats(zpool_handle_t *zhp)
201789Sahrens {
202789Sahrens 	zfs_cmd_t zc = { 0 };
203789Sahrens 	int error;
204952Seschrock 	nvlist_t *config;
205789Sahrens 
206789Sahrens 	(void) strcpy(zc.zc_name, zhp->zpool_name);
207789Sahrens 
208789Sahrens 	if (zhp->zpool_config_size == 0)
209789Sahrens 		zhp->zpool_config_size = 1 << 16;
210789Sahrens 
211789Sahrens 	zc.zc_config_dst_size = zhp->zpool_config_size;
212789Sahrens 	zc.zc_config_dst = (uint64_t)(uintptr_t)
213789Sahrens 	    zfs_malloc(zc.zc_config_dst_size);
214789Sahrens 
215*1544Seschrock 	for (;;) {
216*1544Seschrock 		if (zfs_ioctl(ZFS_IOC_POOL_STATS, &zc) == 0) {
217789Sahrens 			/*
218*1544Seschrock 			 * The real error is returned in the zc_cookie field.
219789Sahrens 			 */
220*1544Seschrock 			error = zc.zc_cookie;
221789Sahrens 			break;
222789Sahrens 		}
223789Sahrens 
224*1544Seschrock 		if (errno == ENOMEM) {
225*1544Seschrock 			free((void *)(uintptr_t)zc.zc_config_dst);
226*1544Seschrock 			zc.zc_config_dst = (uint64_t)(uintptr_t)
227*1544Seschrock 			    zfs_malloc(zc.zc_config_dst_size);
228*1544Seschrock 		} else {
229*1544Seschrock 			free((void *)(uintptr_t)zc.zc_config_dst);
230*1544Seschrock 			return (errno);
231789Sahrens 		}
232789Sahrens 	}
233789Sahrens 
234789Sahrens 	verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst,
235952Seschrock 	    zc.zc_config_dst_size, &config, 0) == 0);
236789Sahrens 
237789Sahrens 	zhp->zpool_config_size = zc.zc_config_dst_size;
238789Sahrens 	free((void *)(uintptr_t)zc.zc_config_dst);
239789Sahrens 
240952Seschrock 	set_pool_health(config);
241952Seschrock 
242952Seschrock 	if (zhp->zpool_config != NULL) {
243952Seschrock 		uint64_t oldtxg, newtxg;
244952Seschrock 
245952Seschrock 		verify(nvlist_lookup_uint64(zhp->zpool_config,
246952Seschrock 		    ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0);
247952Seschrock 		verify(nvlist_lookup_uint64(config,
248952Seschrock 		    ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0);
249789Sahrens 
250952Seschrock 		if (zhp->zpool_old_config != NULL)
251952Seschrock 			nvlist_free(zhp->zpool_old_config);
252789Sahrens 
253952Seschrock 		if (oldtxg != newtxg) {
254952Seschrock 			nvlist_free(zhp->zpool_config);
255952Seschrock 			zhp->zpool_old_config = NULL;
256952Seschrock 		} else {
257952Seschrock 			zhp->zpool_old_config = zhp->zpool_config;
258952Seschrock 		}
259952Seschrock 	}
260952Seschrock 
261952Seschrock 	zhp->zpool_config = config;
262789Sahrens 
263789Sahrens 	return (error);
264789Sahrens }
265789Sahrens 
266789Sahrens /*
267789Sahrens  * Iterate over all pools in the system.
268789Sahrens  */
269789Sahrens int
270789Sahrens zpool_iter(zpool_iter_f func, void *data)
271789Sahrens {
272789Sahrens 	config_node_t *cn;
273789Sahrens 	zpool_handle_t *zhp;
274789Sahrens 	int ret;
275789Sahrens 
276789Sahrens 	namespace_reload();
277789Sahrens 
278789Sahrens 	for (cn = uu_avl_first(namespace_avl); cn != NULL;
279789Sahrens 	    cn = uu_avl_next(namespace_avl, cn)) {
280789Sahrens 
281789Sahrens 		if ((zhp = zpool_open_silent(cn->cn_name)) == NULL)
282789Sahrens 			continue;
283789Sahrens 
284789Sahrens 		if ((ret = func(zhp, data)) != 0)
285789Sahrens 			return (ret);
286789Sahrens 	}
287789Sahrens 
288789Sahrens 	return (0);
289789Sahrens }
290789Sahrens 
291789Sahrens /*
292789Sahrens  * Iterate over root datasets, calling the given function for each.  The zfs
293789Sahrens  * handle passed each time must be explicitly closed by the callback.
294789Sahrens  */
295789Sahrens int
296789Sahrens zfs_iter_root(zfs_iter_f func, void *data)
297789Sahrens {
298789Sahrens 	config_node_t *cn;
299789Sahrens 	zfs_handle_t *zhp;
300789Sahrens 	int ret;
301789Sahrens 
302789Sahrens 	namespace_reload();
303789Sahrens 
304789Sahrens 	for (cn = uu_avl_first(namespace_avl); cn != NULL;
305789Sahrens 	    cn = uu_avl_next(namespace_avl, cn)) {
306789Sahrens 
307789Sahrens 		if ((zhp = make_dataset_handle(cn->cn_name)) == NULL)
308789Sahrens 			continue;
309789Sahrens 
310789Sahrens 		if ((ret = func(zhp, data)) != 0)
311789Sahrens 			return (ret);
312789Sahrens 	}
313789Sahrens 
314789Sahrens 	return (0);
315789Sahrens }
316