4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * The pool configuration repository is stored in /etc/zfs/zpool.cache as a
30 * single packed nvlist. While it would be nice to just read in this
31 * file from userland, this wouldn't work from a local zone. So we have to have
32 * a zpool ioctl to return the complete configuration for all pools. In the
33 * global zone, this will be identical to reading the file and unpacking it in
46 #include "libzfs_impl.h"
48 typedef struct config_node
{
56 config_node_compare(const void *a
, const void *b
, void *unused
)
60 const config_node_t
*ca
= (config_node_t
*)a
;
61 const config_node_t
*cb
= (config_node_t
*)b
;
63 ret
= strcmp(ca
->cn_name
, cb
->cn_name
);
74 namespace_clear(libzfs_handle_t
*hdl
)
76 if (hdl
->libzfs_ns_avl
) {
80 while ((cn
= uu_avl_teardown(hdl
->libzfs_ns_avl
,
82 nvlist_free(cn
->cn_config
);
87 uu_avl_destroy(hdl
->libzfs_ns_avl
);
88 hdl
->libzfs_ns_avl
= NULL
;
91 if (hdl
->libzfs_ns_avlpool
) {
92 uu_avl_pool_destroy(hdl
->libzfs_ns_avlpool
);
93 hdl
->libzfs_ns_avlpool
= NULL
;
98 * Loads the pool namespace, or re-loads it if the cache has changed.
101 namespace_reload(libzfs_handle_t
*hdl
)
106 zfs_cmd_t zc
= { 0 };
109 if (hdl
->libzfs_ns_gen
== 0) {
111 * This is the first time we've accessed the configuration
112 * cache. Initialize the AVL tree and then fall through to the
115 if ((hdl
->libzfs_ns_avlpool
= uu_avl_pool_create("config_pool",
116 sizeof (config_node_t
),
117 offsetof(config_node_t
, cn_avl
),
118 config_node_compare
, UU_DEFAULT
)) == NULL
)
119 return (no_memory(hdl
));
121 if ((hdl
->libzfs_ns_avl
= uu_avl_create(hdl
->libzfs_ns_avlpool
,
122 NULL
, UU_DEFAULT
)) == NULL
)
123 return (no_memory(hdl
));
126 if (zcmd_alloc_dst_nvlist(hdl
, &zc
, 0) != 0)
130 zc
.zc_cookie
= hdl
->libzfs_ns_gen
;
131 if (ioctl(hdl
->libzfs_fd
, ZFS_IOC_POOL_CONFIGS
, &zc
) != 0) {
135 * The namespace hasn't changed.
137 zcmd_free_nvlists(&zc
);
141 if (zcmd_expand_dst_nvlist(hdl
, &zc
) != 0) {
142 zcmd_free_nvlists(&zc
);
148 zcmd_free_nvlists(&zc
);
149 return (zfs_standard_error(hdl
, errno
,
150 dgettext(TEXT_DOMAIN
, "failed to read "
151 "pool configuration")));
154 hdl
->libzfs_ns_gen
= zc
.zc_cookie
;
159 if (zcmd_read_dst_nvlist(hdl
, &zc
, &config
) != 0) {
160 zcmd_free_nvlists(&zc
);
164 zcmd_free_nvlists(&zc
);
167 * Clear out any existing configuration information.
170 while ((cn
= uu_avl_teardown(hdl
->libzfs_ns_avl
, &cookie
)) != NULL
) {
171 nvlist_free(cn
->cn_config
);
177 while ((elem
= nvlist_next_nvpair(config
, elem
)) != NULL
) {
179 uu_avl_index_t where
;
181 if ((cn
= zfs_alloc(hdl
, sizeof (config_node_t
))) == NULL
) {
186 if ((cn
->cn_name
= zfs_strdup(hdl
,
187 nvpair_name(elem
))) == NULL
) {
193 verify(nvpair_value_nvlist(elem
, &child
) == 0);
194 if (nvlist_dup(child
, &cn
->cn_config
, 0) != 0) {
198 return (no_memory(hdl
));
200 verify(uu_avl_find(hdl
->libzfs_ns_avl
, cn
, NULL
, &where
)
203 uu_avl_insert(hdl
->libzfs_ns_avl
, cn
, where
);
211 * Retrieve the configuration for the given pool. The configuration is a nvlist
212 * describing the vdevs, as well as the statistics associated with each one.
215 zpool_get_config(zpool_handle_t
*zhp
, nvlist_t
**oldconfig
)
218 *oldconfig
= zhp
->zpool_old_config
;
219 return (zhp
->zpool_config
);
223 * Refresh the vdev statistics associated with the given pool. This is used in
224 * iostat to show configuration changes and determine the delta from the last
225 * time the function was called. This function can fail, in case the pool has
229 zpool_refresh_stats(zpool_handle_t
*zhp
, boolean_t
*missing
)
231 zfs_cmd_t zc
= { 0 };
234 libzfs_handle_t
*hdl
= zhp
->zpool_hdl
;
237 (void) strcpy(zc
.zc_name
, zhp
->zpool_name
);
239 if (zhp
->zpool_config_size
== 0)
240 zhp
->zpool_config_size
= 1 << 16;
242 if (zcmd_alloc_dst_nvlist(hdl
, &zc
, zhp
->zpool_config_size
) != 0)
246 if (ioctl(zhp
->zpool_hdl
->libzfs_fd
, ZFS_IOC_POOL_STATS
,
249 * The real error is returned in the zc_cookie field.
251 error
= zc
.zc_cookie
;
255 if (errno
== ENOMEM
) {
256 if (zcmd_expand_dst_nvlist(hdl
, &zc
) != 0) {
257 zcmd_free_nvlists(&zc
);
261 zcmd_free_nvlists(&zc
);
262 if (errno
== ENOENT
|| errno
== EINVAL
)
264 zhp
->zpool_state
= POOL_STATE_UNAVAIL
;
269 if (zcmd_read_dst_nvlist(hdl
, &zc
, &config
) != 0) {
270 zcmd_free_nvlists(&zc
);
274 zcmd_free_nvlists(&zc
);
276 zhp
->zpool_config_size
= zc
.zc_nvlist_dst_size
;
278 if (zhp
->zpool_config
!= NULL
) {
279 uint64_t oldtxg
, newtxg
;
281 verify(nvlist_lookup_uint64(zhp
->zpool_config
,
282 ZPOOL_CONFIG_POOL_TXG
, &oldtxg
) == 0);
283 verify(nvlist_lookup_uint64(config
,
284 ZPOOL_CONFIG_POOL_TXG
, &newtxg
) == 0);
286 if (zhp
->zpool_old_config
!= NULL
)
287 nvlist_free(zhp
->zpool_old_config
);
289 if (oldtxg
!= newtxg
) {
290 nvlist_free(zhp
->zpool_config
);
291 zhp
->zpool_old_config
= NULL
;
293 zhp
->zpool_old_config
= zhp
->zpool_config
;
297 zhp
->zpool_config
= config
;
299 zhp
->zpool_state
= POOL_STATE_UNAVAIL
;
301 zhp
->zpool_state
= POOL_STATE_ACTIVE
;
307 * Iterate over all pools in the system.
310 zpool_iter(libzfs_handle_t
*hdl
, zpool_iter_f func
, void *data
)
316 if (namespace_reload(hdl
) != 0)
319 for (cn
= uu_avl_first(hdl
->libzfs_ns_avl
); cn
!= NULL
;
320 cn
= uu_avl_next(hdl
->libzfs_ns_avl
, cn
)) {
322 if (zpool_open_silent(hdl
, cn
->cn_name
, &zhp
) != 0)
328 if ((ret
= func(zhp
, data
)) != 0)
336 * Iterate over root datasets, calling the given function for each. The zfs
337 * handle passed each time must be explicitly closed by the callback.
340 zfs_iter_root(libzfs_handle_t
*hdl
, zfs_iter_f func
, void *data
)
346 if (namespace_reload(hdl
) != 0)
349 for (cn
= uu_avl_first(hdl
->libzfs_ns_avl
); cn
!= NULL
;
350 cn
= uu_avl_next(hdl
->libzfs_ns_avl
, cn
)) {
352 if ((zhp
= make_dataset_handle(hdl
, cn
->cn_name
)) == NULL
)
355 if ((ret
= func(zhp
, data
)) != 0)