1281SN/A/*
2963Sjoehw * CDDL HEADER START
3281SN/A *
4281SN/A * The contents of this file are subject to the terms of the
5798Sjoehw * Common Development and Distribution License (the "License").
6798Sjoehw * You may not use this file except in compliance with the License.
7798Sjoehw *
8798Sjoehw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9798Sjoehw * or http://www.opensolaris.org/os/licensing.
10798Sjoehw * See the License for the specific language governing permissions
11281SN/A * and limitations under the License.
12281SN/A *
13281SN/A * When distributing Covered Code, include this CDDL HEADER in each
14281SN/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15281SN/A * If applicable, add the following below this CDDL HEADER, with the
16281SN/A * fields enclosed by brackets "[]" replaced with your own identifying
17281SN/A * information: Portions Copyright [yyyy] [name of copyright owner]
18281SN/A *
19281SN/A * CDDL HEADER END
20281SN/A */
21281SN/A
22281SN/A/*
23440SN/A * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24440SN/A * Use is subject to license terms.
25526SN/A */
26440SN/A
27440SN/A/*
28510SN/A * Copyright (c) 2012 by Delphix. All rights reserved.
29464SN/A */
30464SN/A
31440SN/A/*
32440SN/A * The pool configuration repository is stored in /etc/zfs/zpool.cache as a
33440SN/A * single packed nvlist.  While it would be nice to just read in this
34440SN/A * file from userland, this wouldn't work from a local zone.  So we have to have
35440SN/A * a zpool ioctl to return the complete configuration for all pools.  In the
36440SN/A * global zone, this will be identical to reading the file and unpacking it in
37440SN/A * userland.
38281SN/A */
39281SN/A
40281SN/A#include <errno.h>
41281SN/A#include <sys/stat.h>
42281SN/A#include <fcntl.h>
43281SN/A#include <stddef.h>
44281SN/A#include <string.h>
45281SN/A#include <unistd.h>
46963Sjoehw#include <libintl.h>
47281SN/A#include <libuutil.h>
48720Saefimov
49281SN/A#include "libzfs_impl.h"
50281SN/A
51281SN/Atypedef struct config_node {
52281SN/A	char		*cn_name;
53281SN/A	nvlist_t	*cn_config;
54988Sjoehw	uu_avl_node_t	cn_avl;
55963Sjoehw} config_node_t;
56963Sjoehw
57963Sjoehw/* ARGSUSED */
58988Sjoehwstatic int
59440SN/Aconfig_node_compare(const void *a, const void *b, void *unused)
60281SN/A{
61281SN/A	int ret;
62281SN/A
63281SN/A	const config_node_t *ca = (config_node_t *)a;
64281SN/A	const config_node_t *cb = (config_node_t *)b;
65281SN/A
66281SN/A	ret = strcmp(ca->cn_name, cb->cn_name);
67293SN/A
68281SN/A	if (ret < 0)
69281SN/A		return (-1);
70281SN/A	else if (ret > 0)
71281SN/A		return (1);
72281SN/A	else
73281SN/A		return (0);
74281SN/A}
75281SN/A
76440SN/Avoid
77281SN/Anamespace_clear(libzfs_handle_t *hdl)
78281SN/A{
79963Sjoehw	if (hdl->libzfs_ns_avl) {
80963Sjoehw		config_node_t *cn;
81281SN/A		void *cookie = NULL;
82281SN/A
83281SN/A		while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl,
84281SN/A		    &cookie)) != NULL) {
85281SN/A			nvlist_free(cn->cn_config);
86281SN/A			free(cn->cn_name);
87281SN/A			free(cn);
88281SN/A		}
89281SN/A
90281SN/A		uu_avl_destroy(hdl->libzfs_ns_avl);
91281SN/A		hdl->libzfs_ns_avl = NULL;
92963Sjoehw	}
93281SN/A
94281SN/A	if (hdl->libzfs_ns_avlpool) {
95281SN/A		uu_avl_pool_destroy(hdl->libzfs_ns_avlpool);
96281SN/A		hdl->libzfs_ns_avlpool = NULL;
97281SN/A	}
98281SN/A}
99281SN/A
100281SN/A/*
101281SN/A * Loads the pool namespace, or re-loads it if the cache has changed.
102281SN/A */
103281SN/Astatic int
104281SN/Anamespace_reload(libzfs_handle_t *hdl)
105281SN/A{
106281SN/A	nvlist_t *config;
107281SN/A	config_node_t *cn;
108281SN/A	nvpair_t *elem;
109281SN/A	zfs_cmd_t zc = { 0 };
110281SN/A	void *cookie;
111281SN/A
112281SN/A	if (hdl->libzfs_ns_gen == 0) {
113281SN/A		/*
114281SN/A		 * This is the first time we've accessed the configuration
115281SN/A		 * cache.  Initialize the AVL tree and then fall through to the
116281SN/A		 * common code.
117281SN/A		 */
118281SN/A		if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool",
119281SN/A		    sizeof (config_node_t),
120281SN/A		    offsetof(config_node_t, cn_avl),
121281SN/A		    config_node_compare, UU_DEFAULT)) == NULL)
122281SN/A			return (no_memory(hdl));
123281SN/A
124281SN/A		if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool,
125281SN/A		    NULL, UU_DEFAULT)) == NULL)
126281SN/A			return (no_memory(hdl));
127281SN/A	}
128281SN/A
129281SN/A	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
130281SN/A		return (-1);
131281SN/A
132281SN/A	for (;;) {
133281SN/A		zc.zc_cookie = hdl->libzfs_ns_gen;
134281SN/A		if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) {
135281SN/A			switch (errno) {
136281SN/A			case EEXIST:
137281SN/A				/*
138281SN/A				 * The namespace hasn't changed.
139281SN/A				 */
140281SN/A				zcmd_free_nvlists(&zc);
141281SN/A				return (0);
142281SN/A
143281SN/A			case ENOMEM:
144890Salanb				if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
145890Salanb					zcmd_free_nvlists(&zc);
146281SN/A					return (-1);
147281SN/A				}
148281SN/A				break;
149281SN/A
150281SN/A			default:
151281SN/A				zcmd_free_nvlists(&zc);
152281SN/A				return (zfs_standard_error(hdl, errno,
153798Sjoehw				    dgettext(TEXT_DOMAIN, "failed to read "
154281SN/A				    "pool configuration")));
155281SN/A			}
156798Sjoehw		} else {
157281SN/A			hdl->libzfs_ns_gen = zc.zc_cookie;
158281SN/A			break;
159798Sjoehw		}
160281SN/A	}
161281SN/A
162281SN/A	if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) {
163281SN/A		zcmd_free_nvlists(&zc);
164281SN/A		return (-1);
165281SN/A	}
166281SN/A
167281SN/A	zcmd_free_nvlists(&zc);
168281SN/A
169281SN/A	/*
170281SN/A	 * Clear out any existing configuration information.
171281SN/A	 */
172281SN/A	cookie = NULL;
173281SN/A	while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) {
174281SN/A		nvlist_free(cn->cn_config);
175281SN/A		free(cn->cn_name);
176281SN/A		free(cn);
177281SN/A	}
178281SN/A
179281SN/A	elem = NULL;
180281SN/A	while ((elem = nvlist_next_nvpair(config, elem)) != NULL) {
181281SN/A		nvlist_t *child;
182281SN/A		uu_avl_index_t where;
183281SN/A
184281SN/A		if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) {
185281SN/A			nvlist_free(config);
186281SN/A			return (-1);
187281SN/A		}
188281SN/A
189281SN/A		if ((cn->cn_name = zfs_strdup(hdl,
190281SN/A		    nvpair_name(elem))) == NULL) {
191281SN/A			free(cn);
192281SN/A			nvlist_free(config);
193281SN/A			return (-1);
194281SN/A		}
195281SN/A
196281SN/A		verify(nvpair_value_nvlist(elem, &child) == 0);
197281SN/A		if (nvlist_dup(child, &cn->cn_config, 0) != 0) {
198281SN/A			free(cn->cn_name);
199281SN/A			free(cn);
200281SN/A			nvlist_free(config);
201281SN/A			return (no_memory(hdl));
202281SN/A		}
203281SN/A		verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where)
204281SN/A		    == NULL);
205281SN/A
206281SN/A		uu_avl_insert(hdl->libzfs_ns_avl, cn, where);
207281SN/A	}
208281SN/A
209281SN/A	nvlist_free(config);
210281SN/A	return (0);
211281SN/A}
212281SN/A
213281SN/A/*
214281SN/A * Retrieve the configuration for the given pool.  The configuration is a nvlist
215281SN/A * describing the vdevs, as well as the statistics associated with each one.
216293SN/A */
217293SN/Anvlist_t *
218293SN/Azpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig)
219293SN/A{
220293SN/A	if (oldconfig)
221293SN/A		*oldconfig = zhp->zpool_old_config;
222293SN/A	return (zhp->zpool_config);
223293SN/A}
224281SN/A
2251031Sjoehw/*
2261031Sjoehw * Retrieves a list of enabled features and their refcounts and caches it in
227418SN/A * the pool handle.
228418SN/A */
229418SN/Anvlist_t *
230418SN/Azpool_get_features(zpool_handle_t *zhp)
231418SN/A{
232418SN/A	nvlist_t *config, *features;
233418SN/A
234464SN/A	config = zpool_get_config(zhp, NULL);
235510SN/A
236418SN/A	if (config == NULL || !nvlist_exists(config,
237963Sjoehw	    ZPOOL_CONFIG_FEATURE_STATS)) {
238526SN/A		int error;
239720Saefimov		boolean_t missing = B_FALSE;
240720Saefimov
241720Saefimov		error = zpool_refresh_stats(zhp, &missing);
242720Saefimov
243720Saefimov		if (error != 0 || missing)
2441031Sjoehw			return (NULL);
245720Saefimov
246988Sjoehw		config = zpool_get_config(zhp, NULL);
247963Sjoehw	}
248963Sjoehw
249963Sjoehw	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
250963Sjoehw	    &features) == 0);
251963Sjoehw
252963Sjoehw	return (features);
253963Sjoehw}
254963Sjoehw
2551031Sjoehw/*
2561031Sjoehw * Refresh the vdev statistics associated with the given pool.  This is used in
257418SN/A * iostat to show configuration changes and determine the delta from the last
258281SN/A * time the function was called.  This function can fail, in case the pool has
259281SN/A * been destroyed.
260281SN/A */
261293SN/Aint
262293SN/Azpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing)
263293SN/A{
264293SN/A	zfs_cmd_t zc = { 0 };
265293SN/A	int error;
266293SN/A	nvlist_t *config;
267293SN/A	libzfs_handle_t *hdl = zhp->zpool_hdl;
268293SN/A
269293SN/A	*missing = B_FALSE;
270418SN/A	(void) strcpy(zc.zc_name, zhp->zpool_name);
271281SN/A
272281SN/A	if (zhp->zpool_config_size == 0)
273281SN/A		zhp->zpool_config_size = 1 << 16;
274281SN/A
275464SN/A	if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size) != 0)
276963Sjoehw		return (-1);
277464SN/A
278464SN/A	for (;;) {
279464SN/A		if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_STATS,
280464SN/A		    &zc) == 0) {
281464SN/A			/*
282510SN/A			 * The real error is returned in the zc_cookie field.
283510SN/A			 */
284510SN/A			error = zc.zc_cookie;
285720Saefimov			break;
286720Saefimov		}
287720Saefimov
288720Saefimov		if (errno == ENOMEM) {
2891031Sjoehw			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
290720Saefimov				zcmd_free_nvlists(&zc);
291281SN/A				return (-1);
292281SN/A			}
293281SN/A		} else {
294281SN/A			zcmd_free_nvlists(&zc);
295281SN/A			if (errno == ENOENT || errno == EINVAL)
296281SN/A				*missing = B_TRUE;
297281SN/A			zhp->zpool_state = POOL_STATE_UNAVAIL;
298281SN/A			return (0);
299281SN/A		}
300281SN/A	}
301281SN/A
302440SN/A	if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) {
303281SN/A		zcmd_free_nvlists(&zc);
304281SN/A		return (-1);
305281SN/A	}
306281SN/A
307281SN/A	zcmd_free_nvlists(&zc);
308281SN/A
309281SN/A	zhp->zpool_config_size = zc.zc_nvlist_dst_size;
310281SN/A
311281SN/A	if (zhp->zpool_config != NULL) {
312281SN/A		uint64_t oldtxg, newtxg;
313281SN/A
314281SN/A		verify(nvlist_lookup_uint64(zhp->zpool_config,
315281SN/A		    ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0);
316281SN/A		verify(nvlist_lookup_uint64(config,
317281SN/A		    ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0);
318281SN/A
319281SN/A		if (zhp->zpool_old_config != NULL)
320440SN/A			nvlist_free(zhp->zpool_old_config);
321281SN/A
322281SN/A		if (oldtxg != newtxg) {
323281SN/A			nvlist_free(zhp->zpool_config);
324281SN/A			zhp->zpool_old_config = NULL;
325281SN/A		} else {
326890Salanb			zhp->zpool_old_config = zhp->zpool_config;
327890Salanb		}
328890Salanb	}
329890Salanb
330890Salanb	zhp->zpool_config = config;
331890Salanb	if (error)
332890Salanb		zhp->zpool_state = POOL_STATE_UNAVAIL;
333281SN/A	else
334281SN/A		zhp->zpool_state = POOL_STATE_ACTIVE;
335281SN/A
336281SN/A	return (0);
337281SN/A}
338281SN/A
339281SN/A/*
340440SN/A * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over
341281SN/A * pools it lists.
342281SN/A *
343281SN/A * This is an undocumented feature for use during testing only.
344281SN/A *
345281SN/A * This function returns B_TRUE if the pool should be skipped
346281SN/A * during iteration.
347281SN/A */
348281SN/Astatic boolean_t
349963Sjoehwcheck_restricted(const char *poolname)
350281SN/A{
351281SN/A	static boolean_t initialized = B_FALSE;
352963Sjoehw	static char *restricted = NULL;
353281SN/A
354293SN/A	const char *cur, *end;
355293SN/A	int len, namelen;
356293SN/A
357293SN/A	if (!initialized) {
358293SN/A		initialized = B_TRUE;
359510SN/A		restricted = getenv("__ZFS_POOL_RESTRICT");
360510SN/A	}
361720Saefimov
362720Saefimov	if (NULL == restricted)
363963Sjoehw		return (B_FALSE);
364963Sjoehw
365963Sjoehw	cur = restricted;
366963Sjoehw	namelen = strlen(poolname);
367963Sjoehw	do {
368963Sjoehw		end = strchr(cur, ' ');
369963Sjoehw		len = (NULL == end) ? strlen(cur) : (end - cur);
370963Sjoehw
371963Sjoehw		if (len == namelen && 0 == strncmp(cur, poolname, len)) {
372963Sjoehw			return (B_FALSE);
3731031Sjoehw		}
3741031Sjoehw
375293SN/A		cur += (len + 1);
376464SN/A	} while (NULL != end);
377510SN/A
378510SN/A	return (B_TRUE);
379510SN/A}
380510SN/A
381510SN/A/*
382510SN/A * Iterate over all pools in the system.
383510SN/A */
384510SN/Aint
385510SN/Azpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data)
386510SN/A{
387510SN/A	config_node_t *cn;
388418SN/A	zpool_handle_t *zhp;
389281SN/A	int ret;
390281SN/A
391281SN/A	/*
392281SN/A	 * If someone makes a recursive call to zpool_iter(), we want to avoid
393281SN/A	 * refreshing the namespace because that will invalidate the parent
394281SN/A	 * context.  We allow recursive calls, but simply re-use the same
395281SN/A	 * namespace AVL tree.
396281SN/A	 */
397281SN/A	if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0)
398281SN/A		return (-1);
399281SN/A
400281SN/A	hdl->libzfs_pool_iter++;
401281SN/A	for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
402281SN/A	    cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
403440SN/A
404281SN/A		if (check_restricted(cn->cn_name))
405281SN/A			continue;
406281SN/A
407281SN/A		if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) {
408281SN/A			hdl->libzfs_pool_iter--;
409281SN/A			return (-1);
410281SN/A		}
411281SN/A
412281SN/A		if (zhp == NULL)
413281SN/A			continue;
414281SN/A
415281SN/A		if ((ret = func(zhp, data)) != 0) {
416281SN/A			hdl->libzfs_pool_iter--;
417281SN/A			return (ret);
418281SN/A		}
419281SN/A	}
420281SN/A	hdl->libzfs_pool_iter--;
421281SN/A
422281SN/A	return (0);
423281SN/A}
424281SN/A
425281SN/A/*
426281SN/A * Iterate over root datasets, calling the given function for each.  The zfs
427963Sjoehw * handle passed each time must be explicitly closed by the callback.
428281SN/A */
429281SN/Aint
430281SN/Azfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data)
431281SN/A{
432281SN/A	config_node_t *cn;
433281SN/A	zfs_handle_t *zhp;
434281SN/A	int ret;
435281SN/A
436281SN/A	if (namespace_reload(hdl) != 0)
437963Sjoehw		return (-1);
438281SN/A
439281SN/A	for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
440281SN/A	    cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
441281SN/A
442281SN/A		if (check_restricted(cn->cn_name))
443281SN/A			continue;
444281SN/A
445281SN/A		if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL)
446281SN/A			continue;
447963Sjoehw
448281SN/A		if ((ret = func(zhp, data)) != 0)
449281SN/A			return (ret);
450281SN/A	}
451281SN/A
452281SN/A	return (0);
453281SN/A}
454281SN/A