]>
git.proxmox.com Git - mirror_zfs-debian.git/blob - lib/libzfs/libzfs_config.c
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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * The pool configuration repository is stored in /etc/zfs/zpool.cache as a
28 * single packed nvlist. While it would be nice to just read in this
29 * file from userland, this wouldn't work from a local zone. So we have to have
30 * a zpool ioctl to return the complete configuration for all pools. In the
31 * global zone, this will be identical to reading the file and unpacking it in
44 #include "libzfs_impl.h"
46 typedef struct config_node
{
54 config_node_compare(const void *a
, const void *b
, void *unused
)
58 const config_node_t
*ca
= (config_node_t
*)a
;
59 const config_node_t
*cb
= (config_node_t
*)b
;
61 ret
= strcmp(ca
->cn_name
, cb
->cn_name
);
72 namespace_clear(libzfs_handle_t
*hdl
)
74 if (hdl
->libzfs_ns_avl
) {
78 while ((cn
= uu_avl_teardown(hdl
->libzfs_ns_avl
,
80 nvlist_free(cn
->cn_config
);
85 uu_avl_destroy(hdl
->libzfs_ns_avl
);
86 hdl
->libzfs_ns_avl
= NULL
;
89 if (hdl
->libzfs_ns_avlpool
) {
90 uu_avl_pool_destroy(hdl
->libzfs_ns_avlpool
);
91 hdl
->libzfs_ns_avlpool
= NULL
;
96 * Loads the pool namespace, or re-loads it if the cache has changed.
99 namespace_reload(libzfs_handle_t
*hdl
)
104 zfs_cmd_t zc
= { "\0", "\0", "\0", "\0", 0 };
107 if (hdl
->libzfs_ns_gen
== 0) {
109 * This is the first time we've accessed the configuration
110 * cache. Initialize the AVL tree and then fall through to the
113 if ((hdl
->libzfs_ns_avlpool
= uu_avl_pool_create("config_pool",
114 sizeof (config_node_t
),
115 offsetof(config_node_t
, cn_avl
),
116 config_node_compare
, UU_DEFAULT
)) == NULL
)
117 return (no_memory(hdl
));
119 if ((hdl
->libzfs_ns_avl
= uu_avl_create(hdl
->libzfs_ns_avlpool
,
120 NULL
, UU_DEFAULT
)) == NULL
)
121 return (no_memory(hdl
));
124 if (zcmd_alloc_dst_nvlist(hdl
, &zc
, 0) != 0)
128 zc
.zc_cookie
= hdl
->libzfs_ns_gen
;
129 if (ioctl(hdl
->libzfs_fd
, ZFS_IOC_POOL_CONFIGS
, &zc
) != 0) {
133 * The namespace hasn't changed.
135 zcmd_free_nvlists(&zc
);
139 if (zcmd_expand_dst_nvlist(hdl
, &zc
) != 0) {
140 zcmd_free_nvlists(&zc
);
146 zcmd_free_nvlists(&zc
);
147 return (zfs_standard_error(hdl
, errno
,
148 dgettext(TEXT_DOMAIN
, "failed to read "
149 "pool configuration")));
152 hdl
->libzfs_ns_gen
= zc
.zc_cookie
;
157 if (zcmd_read_dst_nvlist(hdl
, &zc
, &config
) != 0) {
158 zcmd_free_nvlists(&zc
);
162 zcmd_free_nvlists(&zc
);
165 * Clear out any existing configuration information.
168 while ((cn
= uu_avl_teardown(hdl
->libzfs_ns_avl
, &cookie
)) != NULL
) {
169 nvlist_free(cn
->cn_config
);
175 while ((elem
= nvlist_next_nvpair(config
, elem
)) != NULL
) {
177 uu_avl_index_t where
;
179 if ((cn
= zfs_alloc(hdl
, sizeof (config_node_t
))) == NULL
) {
184 if ((cn
->cn_name
= zfs_strdup(hdl
,
185 nvpair_name(elem
))) == NULL
) {
191 verify(nvpair_value_nvlist(elem
, &child
) == 0);
192 if (nvlist_dup(child
, &cn
->cn_config
, 0) != 0) {
196 return (no_memory(hdl
));
198 verify(uu_avl_find(hdl
->libzfs_ns_avl
, cn
, NULL
, &where
)
201 uu_avl_insert(hdl
->libzfs_ns_avl
, cn
, where
);
209 * Retrieve the configuration for the given pool. The configuration is a nvlist
210 * describing the vdevs, as well as the statistics associated with each one.
213 zpool_get_config(zpool_handle_t
*zhp
, nvlist_t
**oldconfig
)
216 *oldconfig
= zhp
->zpool_old_config
;
217 return (zhp
->zpool_config
);
221 * Refresh the vdev statistics associated with the given pool. This is used in
222 * iostat to show configuration changes and determine the delta from the last
223 * time the function was called. This function can fail, in case the pool has
227 zpool_refresh_stats(zpool_handle_t
*zhp
, boolean_t
*missing
)
229 zfs_cmd_t zc
= { "\0", "\0", "\0", "\0", 0 };
232 libzfs_handle_t
*hdl
= zhp
->zpool_hdl
;
235 (void) strcpy(zc
.zc_name
, zhp
->zpool_name
);
237 if (zhp
->zpool_config_size
== 0)
238 zhp
->zpool_config_size
= 1 << 16;
240 if (zcmd_alloc_dst_nvlist(hdl
, &zc
, zhp
->zpool_config_size
) != 0)
244 if (ioctl(zhp
->zpool_hdl
->libzfs_fd
, ZFS_IOC_POOL_STATS
,
247 * The real error is returned in the zc_cookie field.
249 error
= zc
.zc_cookie
;
253 if (errno
== ENOMEM
) {
254 if (zcmd_expand_dst_nvlist(hdl
, &zc
) != 0) {
255 zcmd_free_nvlists(&zc
);
259 zcmd_free_nvlists(&zc
);
260 if (errno
== ENOENT
|| errno
== EINVAL
)
262 zhp
->zpool_state
= POOL_STATE_UNAVAIL
;
267 if (zcmd_read_dst_nvlist(hdl
, &zc
, &config
) != 0) {
268 zcmd_free_nvlists(&zc
);
272 zcmd_free_nvlists(&zc
);
274 zhp
->zpool_config_size
= zc
.zc_nvlist_dst_size
;
276 if (zhp
->zpool_config
!= NULL
) {
277 uint64_t oldtxg
, newtxg
;
279 verify(nvlist_lookup_uint64(zhp
->zpool_config
,
280 ZPOOL_CONFIG_POOL_TXG
, &oldtxg
) == 0);
281 verify(nvlist_lookup_uint64(config
,
282 ZPOOL_CONFIG_POOL_TXG
, &newtxg
) == 0);
284 if (zhp
->zpool_old_config
!= NULL
)
285 nvlist_free(zhp
->zpool_old_config
);
287 if (oldtxg
!= newtxg
) {
288 nvlist_free(zhp
->zpool_config
);
289 zhp
->zpool_old_config
= NULL
;
291 zhp
->zpool_old_config
= zhp
->zpool_config
;
295 zhp
->zpool_config
= config
;
297 zhp
->zpool_state
= POOL_STATE_UNAVAIL
;
299 zhp
->zpool_state
= POOL_STATE_ACTIVE
;
305 * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over
308 * This is an undocumented feature for use during testing only.
310 * This function returns B_TRUE if the pool should be skipped
314 check_restricted(const char *poolname
)
316 static boolean_t initialized
= B_FALSE
;
317 static char *restricted
= NULL
;
319 const char *cur
, *end
;
323 initialized
= B_TRUE
;
324 restricted
= getenv("__ZFS_POOL_RESTRICT");
327 if (NULL
== restricted
)
331 namelen
= strlen(poolname
);
333 end
= strchr(cur
, ' ');
334 len
= (NULL
== end
) ? strlen(cur
) : (end
- cur
);
336 if (len
== namelen
&& 0 == strncmp(cur
, poolname
, len
)) {
341 } while (NULL
!= end
);
347 * Iterate over all pools in the system.
350 zpool_iter(libzfs_handle_t
*hdl
, zpool_iter_f func
, void *data
)
357 * If someone makes a recursive call to zpool_iter(), we want to avoid
358 * refreshing the namespace because that will invalidate the parent
359 * context. We allow recursive calls, but simply re-use the same
360 * namespace AVL tree.
362 if (!hdl
->libzfs_pool_iter
&& namespace_reload(hdl
) != 0)
365 hdl
->libzfs_pool_iter
++;
366 for (cn
= uu_avl_first(hdl
->libzfs_ns_avl
); cn
!= NULL
;
367 cn
= uu_avl_next(hdl
->libzfs_ns_avl
, cn
)) {
369 if (check_restricted(cn
->cn_name
))
372 if (zpool_open_silent(hdl
, cn
->cn_name
, &zhp
) != 0) {
373 hdl
->libzfs_pool_iter
--;
380 if ((ret
= func(zhp
, data
)) != 0) {
381 hdl
->libzfs_pool_iter
--;
385 hdl
->libzfs_pool_iter
--;
391 * Iterate over root datasets, calling the given function for each. The zfs
392 * handle passed each time must be explicitly closed by the callback.
395 zfs_iter_root(libzfs_handle_t
*hdl
, zfs_iter_f func
, void *data
)
401 if (namespace_reload(hdl
) != 0)
404 for (cn
= uu_avl_first(hdl
->libzfs_ns_avl
); cn
!= NULL
;
405 cn
= uu_avl_next(hdl
->libzfs_ns_avl
, cn
)) {
407 if (check_restricted(cn
->cn_name
))
410 if ((zhp
= make_dataset_handle(hdl
, cn
->cn_name
)) == NULL
)
413 if ((ret
= func(zhp
, data
)) != 0)