1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21243674Smm 22168404Spjd/* 23219089Spjd * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24168404Spjd * Use is subject to license terms. 25168404Spjd */ 26168404Spjd 27168404Spjd/* 28243674Smm * Copyright (c) 2012 by Delphix. All rights reserved. 29243674Smm */ 30243674Smm 31243674Smm/* 32168404Spjd * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 33168404Spjd * single packed nvlist. While it would be nice to just read in this 34168404Spjd * file from userland, this wouldn't work from a local zone. So we have to have 35168404Spjd * a zpool ioctl to return the complete configuration for all pools. In the 36168404Spjd * global zone, this will be identical to reading the file and unpacking it in 37168404Spjd * userland. 38168404Spjd */ 39168404Spjd 40168404Spjd#include <errno.h> 41168404Spjd#include <sys/stat.h> 42168404Spjd#include <fcntl.h> 43168404Spjd#include <stddef.h> 44168404Spjd#include <string.h> 45168404Spjd#include <unistd.h> 46168404Spjd#include <libintl.h> 47168404Spjd#include <libuutil.h> 48168404Spjd 49168404Spjd#include "libzfs_impl.h" 50168404Spjd 51168404Spjdtypedef struct config_node { 52168404Spjd char *cn_name; 53168404Spjd nvlist_t *cn_config; 54168404Spjd uu_avl_node_t cn_avl; 55168404Spjd} config_node_t; 56168404Spjd 57168404Spjd/* ARGSUSED */ 58168404Spjdstatic int 59168404Spjdconfig_node_compare(const void *a, const void *b, void *unused) 60168404Spjd{ 61168404Spjd int ret; 62168404Spjd 63168404Spjd const config_node_t *ca = (config_node_t *)a; 64168404Spjd const config_node_t *cb = (config_node_t *)b; 65168404Spjd 66168404Spjd ret = strcmp(ca->cn_name, cb->cn_name); 67168404Spjd 68168404Spjd if (ret < 0) 69168404Spjd return (-1); 70168404Spjd else if (ret > 0) 71168404Spjd return (1); 72168404Spjd else 73168404Spjd return (0); 74168404Spjd} 75168404Spjd 76168404Spjdvoid 77168404Spjdnamespace_clear(libzfs_handle_t *hdl) 78168404Spjd{ 79168404Spjd if (hdl->libzfs_ns_avl) { 80168404Spjd config_node_t *cn; 81168926Spjd void *cookie = NULL; 82168404Spjd 83168926Spjd while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, 84168926Spjd &cookie)) != NULL) { 85168404Spjd nvlist_free(cn->cn_config); 86168404Spjd free(cn->cn_name); 87168404Spjd free(cn); 88168404Spjd } 89168404Spjd 90168404Spjd uu_avl_destroy(hdl->libzfs_ns_avl); 91168404Spjd hdl->libzfs_ns_avl = NULL; 92168404Spjd } 93168404Spjd 94168404Spjd if (hdl->libzfs_ns_avlpool) { 95168404Spjd uu_avl_pool_destroy(hdl->libzfs_ns_avlpool); 96168404Spjd hdl->libzfs_ns_avlpool = NULL; 97168404Spjd } 98168404Spjd} 99168404Spjd 100168404Spjd/* 101168404Spjd * Loads the pool namespace, or re-loads it if the cache has changed. 102168404Spjd */ 103168404Spjdstatic int 104168404Spjdnamespace_reload(libzfs_handle_t *hdl) 105168404Spjd{ 106168404Spjd nvlist_t *config; 107168404Spjd config_node_t *cn; 108168404Spjd nvpair_t *elem; 109168404Spjd zfs_cmd_t zc = { 0 }; 110168926Spjd void *cookie; 111168404Spjd 112168404Spjd if (hdl->libzfs_ns_gen == 0) { 113168404Spjd /* 114168404Spjd * This is the first time we've accessed the configuration 115168404Spjd * cache. Initialize the AVL tree and then fall through to the 116168404Spjd * common code. 117168404Spjd */ 118168404Spjd if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", 119168404Spjd sizeof (config_node_t), 120168404Spjd offsetof(config_node_t, cn_avl), 121168404Spjd config_node_compare, UU_DEFAULT)) == NULL) 122168404Spjd return (no_memory(hdl)); 123168404Spjd 124168404Spjd if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, 125168404Spjd NULL, UU_DEFAULT)) == NULL) 126168404Spjd return (no_memory(hdl)); 127168404Spjd } 128168404Spjd 129168404Spjd if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 130168404Spjd return (-1); 131168404Spjd 132168404Spjd for (;;) { 133168404Spjd zc.zc_cookie = hdl->libzfs_ns_gen; 134168404Spjd if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 135168404Spjd switch (errno) { 136168404Spjd case EEXIST: 137168404Spjd /* 138168404Spjd * The namespace hasn't changed. 139168404Spjd */ 140168404Spjd zcmd_free_nvlists(&zc); 141168404Spjd return (0); 142168404Spjd 143168404Spjd case ENOMEM: 144168404Spjd if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 145168404Spjd zcmd_free_nvlists(&zc); 146168404Spjd return (-1); 147168404Spjd } 148168404Spjd break; 149168404Spjd 150168404Spjd default: 151168404Spjd zcmd_free_nvlists(&zc); 152168404Spjd return (zfs_standard_error(hdl, errno, 153168404Spjd dgettext(TEXT_DOMAIN, "failed to read " 154168404Spjd "pool configuration"))); 155168404Spjd } 156168404Spjd } else { 157168404Spjd hdl->libzfs_ns_gen = zc.zc_cookie; 158168404Spjd break; 159168404Spjd } 160168404Spjd } 161168404Spjd 162168404Spjd if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 163168404Spjd zcmd_free_nvlists(&zc); 164168404Spjd return (-1); 165168404Spjd } 166168404Spjd 167168404Spjd zcmd_free_nvlists(&zc); 168168404Spjd 169168404Spjd /* 170168404Spjd * Clear out any existing configuration information. 171168404Spjd */ 172168926Spjd cookie = NULL; 173168926Spjd while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) { 174168404Spjd nvlist_free(cn->cn_config); 175168404Spjd free(cn->cn_name); 176168404Spjd free(cn); 177168404Spjd } 178168404Spjd 179168404Spjd elem = NULL; 180168404Spjd while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 181168404Spjd nvlist_t *child; 182168404Spjd uu_avl_index_t where; 183168404Spjd 184168404Spjd if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) { 185168404Spjd nvlist_free(config); 186168404Spjd return (-1); 187168404Spjd } 188168404Spjd 189168404Spjd if ((cn->cn_name = zfs_strdup(hdl, 190168404Spjd nvpair_name(elem))) == NULL) { 191168404Spjd free(cn); 192168404Spjd nvlist_free(config); 193168404Spjd return (-1); 194168404Spjd } 195168404Spjd 196168404Spjd verify(nvpair_value_nvlist(elem, &child) == 0); 197168404Spjd if (nvlist_dup(child, &cn->cn_config, 0) != 0) { 198168404Spjd free(cn->cn_name); 199168404Spjd free(cn); 200168404Spjd nvlist_free(config); 201168404Spjd return (no_memory(hdl)); 202168404Spjd } 203168404Spjd verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) 204168404Spjd == NULL); 205168404Spjd 206168404Spjd uu_avl_insert(hdl->libzfs_ns_avl, cn, where); 207168404Spjd } 208168404Spjd 209168404Spjd nvlist_free(config); 210168404Spjd return (0); 211168404Spjd} 212168404Spjd 213168404Spjd/* 214168926Spjd * Retrieve the configuration for the given pool. The configuration is a nvlist 215168404Spjd * describing the vdevs, as well as the statistics associated with each one. 216168404Spjd */ 217168404Spjdnvlist_t * 218168404Spjdzpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 219168404Spjd{ 220168404Spjd if (oldconfig) 221168404Spjd *oldconfig = zhp->zpool_old_config; 222168404Spjd return (zhp->zpool_config); 223168404Spjd} 224168404Spjd 225168404Spjd/* 226243674Smm * Retrieves a list of enabled features and their refcounts and caches it in 227243674Smm * the pool handle. 228243674Smm */ 229243674Smmnvlist_t * 230243674Smmzpool_get_features(zpool_handle_t *zhp) 231243674Smm{ 232243674Smm nvlist_t *config, *features; 233243674Smm 234243674Smm config = zpool_get_config(zhp, NULL); 235243674Smm 236243674Smm if (config == NULL || !nvlist_exists(config, 237243674Smm ZPOOL_CONFIG_FEATURE_STATS)) { 238243674Smm int error; 239243674Smm boolean_t missing = B_FALSE; 240243674Smm 241243674Smm error = zpool_refresh_stats(zhp, &missing); 242243674Smm 243243674Smm if (error != 0 || missing) 244243674Smm return (NULL); 245243674Smm 246243674Smm config = zpool_get_config(zhp, NULL); 247243674Smm } 248243674Smm 249243674Smm verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS, 250243674Smm &features) == 0); 251243674Smm 252243674Smm return (features); 253243674Smm} 254243674Smm 255243674Smm/* 256168404Spjd * Refresh the vdev statistics associated with the given pool. This is used in 257168404Spjd * iostat to show configuration changes and determine the delta from the last 258168404Spjd * time the function was called. This function can fail, in case the pool has 259168404Spjd * been destroyed. 260168404Spjd */ 261168404Spjdint 262168404Spjdzpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) 263168404Spjd{ 264168404Spjd zfs_cmd_t zc = { 0 }; 265168404Spjd int error; 266168404Spjd nvlist_t *config; 267168404Spjd libzfs_handle_t *hdl = zhp->zpool_hdl; 268168404Spjd 269168404Spjd *missing = B_FALSE; 270168404Spjd (void) strcpy(zc.zc_name, zhp->zpool_name); 271168404Spjd 272168404Spjd if (zhp->zpool_config_size == 0) 273168404Spjd zhp->zpool_config_size = 1 << 16; 274168404Spjd 275168404Spjd if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size) != 0) 276168404Spjd return (-1); 277168404Spjd 278168404Spjd for (;;) { 279168404Spjd if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_STATS, 280168404Spjd &zc) == 0) { 281168404Spjd /* 282168404Spjd * The real error is returned in the zc_cookie field. 283168404Spjd */ 284168404Spjd error = zc.zc_cookie; 285168404Spjd break; 286168404Spjd } 287168404Spjd 288168404Spjd if (errno == ENOMEM) { 289168404Spjd if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 290168404Spjd zcmd_free_nvlists(&zc); 291168404Spjd return (-1); 292168404Spjd } 293168404Spjd } else { 294168404Spjd zcmd_free_nvlists(&zc); 295168404Spjd if (errno == ENOENT || errno == EINVAL) 296168404Spjd *missing = B_TRUE; 297168404Spjd zhp->zpool_state = POOL_STATE_UNAVAIL; 298168404Spjd return (0); 299168404Spjd } 300168404Spjd } 301168404Spjd 302168404Spjd if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 303168404Spjd zcmd_free_nvlists(&zc); 304168404Spjd return (-1); 305168404Spjd } 306168404Spjd 307168404Spjd zcmd_free_nvlists(&zc); 308168404Spjd 309168404Spjd zhp->zpool_config_size = zc.zc_nvlist_dst_size; 310168404Spjd 311168404Spjd if (zhp->zpool_config != NULL) { 312168404Spjd uint64_t oldtxg, newtxg; 313168404Spjd 314168404Spjd verify(nvlist_lookup_uint64(zhp->zpool_config, 315168404Spjd ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0); 316168404Spjd verify(nvlist_lookup_uint64(config, 317168404Spjd ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0); 318168404Spjd 319168404Spjd if (zhp->zpool_old_config != NULL) 320168404Spjd nvlist_free(zhp->zpool_old_config); 321168404Spjd 322168404Spjd if (oldtxg != newtxg) { 323168404Spjd nvlist_free(zhp->zpool_config); 324168404Spjd zhp->zpool_old_config = NULL; 325168404Spjd } else { 326168404Spjd zhp->zpool_old_config = zhp->zpool_config; 327168404Spjd } 328168404Spjd } 329168404Spjd 330168404Spjd zhp->zpool_config = config; 331168404Spjd if (error) 332168404Spjd zhp->zpool_state = POOL_STATE_UNAVAIL; 333168404Spjd else 334168404Spjd zhp->zpool_state = POOL_STATE_ACTIVE; 335168404Spjd 336168404Spjd return (0); 337168404Spjd} 338168404Spjd 339168404Spjd/* 340243674Smm * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over 341243674Smm * pools it lists. 342243674Smm * 343243674Smm * This is an undocumented feature for use during testing only. 344243674Smm * 345243674Smm * This function returns B_TRUE if the pool should be skipped 346243674Smm * during iteration. 347243674Smm */ 348243674Smmstatic boolean_t 349243674Smmcheck_restricted(const char *poolname) 350243674Smm{ 351243674Smm static boolean_t initialized = B_FALSE; 352243674Smm static char *restricted = NULL; 353243674Smm 354243674Smm const char *cur, *end; 355243674Smm int len, namelen; 356243674Smm 357243674Smm if (!initialized) { 358243674Smm initialized = B_TRUE; 359243674Smm restricted = getenv("__ZFS_POOL_RESTRICT"); 360243674Smm } 361243674Smm 362243674Smm if (NULL == restricted) 363243674Smm return (B_FALSE); 364243674Smm 365243674Smm cur = restricted; 366243674Smm namelen = strlen(poolname); 367243674Smm do { 368243674Smm end = strchr(cur, ' '); 369243674Smm len = (NULL == end) ? strlen(cur) : (end - cur); 370243674Smm 371243674Smm if (len == namelen && 0 == strncmp(cur, poolname, len)) { 372243674Smm return (B_FALSE); 373243674Smm } 374243674Smm 375243674Smm cur += (len + 1); 376243674Smm } while (NULL != end); 377243674Smm 378243674Smm return (B_TRUE); 379243674Smm} 380243674Smm 381243674Smm/* 382168404Spjd * Iterate over all pools in the system. 383168404Spjd */ 384168404Spjdint 385168404Spjdzpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) 386168404Spjd{ 387168404Spjd config_node_t *cn; 388168404Spjd zpool_handle_t *zhp; 389168404Spjd int ret; 390168404Spjd 391219089Spjd /* 392219089Spjd * If someone makes a recursive call to zpool_iter(), we want to avoid 393219089Spjd * refreshing the namespace because that will invalidate the parent 394219089Spjd * context. We allow recursive calls, but simply re-use the same 395219089Spjd * namespace AVL tree. 396219089Spjd */ 397219089Spjd if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) 398168404Spjd return (-1); 399168404Spjd 400219089Spjd hdl->libzfs_pool_iter++; 401168404Spjd for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 402168404Spjd cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 403168404Spjd 404243674Smm if (check_restricted(cn->cn_name)) 405243674Smm continue; 406243674Smm 407219089Spjd if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { 408219089Spjd hdl->libzfs_pool_iter--; 409168404Spjd return (-1); 410219089Spjd } 411168404Spjd 412168404Spjd if (zhp == NULL) 413168404Spjd continue; 414168404Spjd 415219089Spjd if ((ret = func(zhp, data)) != 0) { 416219089Spjd hdl->libzfs_pool_iter--; 417168404Spjd return (ret); 418219089Spjd } 419168404Spjd } 420219089Spjd hdl->libzfs_pool_iter--; 421168404Spjd 422168404Spjd return (0); 423168404Spjd} 424168404Spjd 425168404Spjd/* 426168404Spjd * Iterate over root datasets, calling the given function for each. The zfs 427168404Spjd * handle passed each time must be explicitly closed by the callback. 428168404Spjd */ 429168404Spjdint 430168404Spjdzfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) 431168404Spjd{ 432168404Spjd config_node_t *cn; 433168404Spjd zfs_handle_t *zhp; 434168404Spjd int ret; 435168404Spjd 436168404Spjd if (namespace_reload(hdl) != 0) 437168404Spjd return (-1); 438168404Spjd 439168404Spjd for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 440168404Spjd cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 441168404Spjd 442243674Smm if (check_restricted(cn->cn_name)) 443243674Smm continue; 444243674Smm 445168404Spjd if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) 446168404Spjd continue; 447168404Spjd 448168404Spjd if ((ret = func(zhp, data)) != 0) 449168404Spjd return (ret); 450168404Spjd } 451168404Spjd 452168404Spjd return (0); 453168404Spjd} 454