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