1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 22*10817SEric.Schrock@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens /* 27789Sahrens * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 28789Sahrens * single packed nvlist. While it would be nice to just read in this 29789Sahrens * file from userland, this wouldn't work from a local zone. So we have to have 30789Sahrens * a zpool ioctl to return the complete configuration for all pools. In the 31789Sahrens * global zone, this will be identical to reading the file and unpacking it in 32789Sahrens * userland. 33789Sahrens */ 34789Sahrens 35789Sahrens #include <errno.h> 36789Sahrens #include <sys/stat.h> 37789Sahrens #include <fcntl.h> 38789Sahrens #include <stddef.h> 39789Sahrens #include <string.h> 40789Sahrens #include <unistd.h> 41789Sahrens #include <libintl.h> 42789Sahrens #include <libuutil.h> 43789Sahrens 44789Sahrens #include "libzfs_impl.h" 45789Sahrens 46789Sahrens typedef struct config_node { 47789Sahrens char *cn_name; 48789Sahrens nvlist_t *cn_config; 49789Sahrens uu_avl_node_t cn_avl; 50789Sahrens } config_node_t; 51789Sahrens 52789Sahrens /* ARGSUSED */ 53789Sahrens static int 54789Sahrens config_node_compare(const void *a, const void *b, void *unused) 55789Sahrens { 56789Sahrens int ret; 57789Sahrens 58789Sahrens const config_node_t *ca = (config_node_t *)a; 59789Sahrens const config_node_t *cb = (config_node_t *)b; 60789Sahrens 61789Sahrens ret = strcmp(ca->cn_name, cb->cn_name); 62789Sahrens 63789Sahrens if (ret < 0) 64789Sahrens return (-1); 65789Sahrens else if (ret > 0) 66789Sahrens return (1); 67789Sahrens else 68789Sahrens return (0); 69789Sahrens } 70789Sahrens 712082Seschrock void 722082Seschrock namespace_clear(libzfs_handle_t *hdl) 732082Seschrock { 742082Seschrock if (hdl->libzfs_ns_avl) { 752082Seschrock config_node_t *cn; 764074Seschrock void *cookie = NULL; 772082Seschrock 784074Seschrock while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, 794074Seschrock &cookie)) != NULL) { 802082Seschrock nvlist_free(cn->cn_config); 812082Seschrock free(cn->cn_name); 822082Seschrock free(cn); 832082Seschrock } 842082Seschrock 852082Seschrock uu_avl_destroy(hdl->libzfs_ns_avl); 862082Seschrock hdl->libzfs_ns_avl = NULL; 872082Seschrock } 882082Seschrock 892082Seschrock if (hdl->libzfs_ns_avlpool) { 902082Seschrock uu_avl_pool_destroy(hdl->libzfs_ns_avlpool); 912082Seschrock hdl->libzfs_ns_avlpool = NULL; 922082Seschrock } 932082Seschrock } 942082Seschrock 95789Sahrens /* 96789Sahrens * Loads the pool namespace, or re-loads it if the cache has changed. 97789Sahrens */ 982082Seschrock static int 992082Seschrock namespace_reload(libzfs_handle_t *hdl) 100789Sahrens { 101789Sahrens nvlist_t *config; 102789Sahrens config_node_t *cn; 103789Sahrens nvpair_t *elem; 104789Sahrens zfs_cmd_t zc = { 0 }; 1054074Seschrock void *cookie; 106789Sahrens 1072082Seschrock if (hdl->libzfs_ns_gen == 0) { 108789Sahrens /* 109789Sahrens * This is the first time we've accessed the configuration 110789Sahrens * cache. Initialize the AVL tree and then fall through to the 111789Sahrens * common code. 112789Sahrens */ 1132082Seschrock if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", 114789Sahrens sizeof (config_node_t), 115789Sahrens offsetof(config_node_t, cn_avl), 116789Sahrens config_node_compare, UU_DEFAULT)) == NULL) 1172082Seschrock return (no_memory(hdl)); 118789Sahrens 1192082Seschrock if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, 1202082Seschrock NULL, UU_DEFAULT)) == NULL) 1212082Seschrock return (no_memory(hdl)); 122789Sahrens } 123789Sahrens 1242676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 1252082Seschrock return (-1); 1262676Seschrock 127789Sahrens for (;;) { 1282082Seschrock zc.zc_cookie = hdl->libzfs_ns_gen; 1292082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 130789Sahrens switch (errno) { 131789Sahrens case EEXIST: 132789Sahrens /* 133789Sahrens * The namespace hasn't changed. 134789Sahrens */ 1352676Seschrock zcmd_free_nvlists(&zc); 1362082Seschrock return (0); 137789Sahrens 138789Sahrens case ENOMEM: 1392676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 1402676Seschrock zcmd_free_nvlists(&zc); 1412082Seschrock return (-1); 1422676Seschrock } 143789Sahrens break; 144789Sahrens 145789Sahrens default: 1462676Seschrock zcmd_free_nvlists(&zc); 1472082Seschrock return (zfs_standard_error(hdl, errno, 1482082Seschrock dgettext(TEXT_DOMAIN, "failed to read " 1492082Seschrock "pool configuration"))); 150789Sahrens } 151789Sahrens } else { 1522082Seschrock hdl->libzfs_ns_gen = zc.zc_cookie; 153789Sahrens break; 154789Sahrens } 155789Sahrens } 156789Sahrens 1572676Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 1582676Seschrock zcmd_free_nvlists(&zc); 1592676Seschrock return (-1); 1602142Seschrock } 161789Sahrens 1622676Seschrock zcmd_free_nvlists(&zc); 163789Sahrens 164789Sahrens /* 165789Sahrens * Clear out any existing configuration information. 166789Sahrens */ 1674074Seschrock cookie = NULL; 1684074Seschrock while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) { 169789Sahrens nvlist_free(cn->cn_config); 170789Sahrens free(cn->cn_name); 171789Sahrens free(cn); 172789Sahrens } 173789Sahrens 174789Sahrens elem = NULL; 175789Sahrens while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 176789Sahrens nvlist_t *child; 177789Sahrens uu_avl_index_t where; 178789Sahrens 1792082Seschrock if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) { 1802082Seschrock nvlist_free(config); 1812082Seschrock return (-1); 1822082Seschrock } 1832082Seschrock 1842082Seschrock if ((cn->cn_name = zfs_strdup(hdl, 1852082Seschrock nvpair_name(elem))) == NULL) { 1862082Seschrock free(cn); 1872474Seschrock nvlist_free(config); 1882082Seschrock return (-1); 1892082Seschrock } 190789Sahrens 191789Sahrens verify(nvpair_value_nvlist(elem, &child) == 0); 1922082Seschrock if (nvlist_dup(child, &cn->cn_config, 0) != 0) { 1932474Seschrock free(cn->cn_name); 1942474Seschrock free(cn); 1952082Seschrock nvlist_free(config); 1962082Seschrock return (no_memory(hdl)); 1972082Seschrock } 1982082Seschrock verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) 1992082Seschrock == NULL); 200789Sahrens 2012082Seschrock uu_avl_insert(hdl->libzfs_ns_avl, cn, where); 202789Sahrens } 203789Sahrens 204789Sahrens nvlist_free(config); 2052082Seschrock return (0); 206789Sahrens } 207789Sahrens 208789Sahrens /* 2094074Seschrock * Retrieve the configuration for the given pool. The configuration is a nvlist 210789Sahrens * describing the vdevs, as well as the statistics associated with each one. 211789Sahrens */ 212789Sahrens nvlist_t * 213952Seschrock zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 214789Sahrens { 215952Seschrock if (oldconfig) 216952Seschrock *oldconfig = zhp->zpool_old_config; 217789Sahrens return (zhp->zpool_config); 218789Sahrens } 219789Sahrens 220789Sahrens /* 221789Sahrens * Refresh the vdev statistics associated with the given pool. This is used in 222789Sahrens * iostat to show configuration changes and determine the delta from the last 223789Sahrens * time the function was called. This function can fail, in case the pool has 224789Sahrens * been destroyed. 225789Sahrens */ 226789Sahrens int 2272142Seschrock zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) 228789Sahrens { 229789Sahrens zfs_cmd_t zc = { 0 }; 230789Sahrens int error; 231952Seschrock nvlist_t *config; 2322676Seschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 233789Sahrens 2342142Seschrock *missing = B_FALSE; 235789Sahrens (void) strcpy(zc.zc_name, zhp->zpool_name); 236789Sahrens 237789Sahrens if (zhp->zpool_config_size == 0) 238789Sahrens zhp->zpool_config_size = 1 << 16; 239789Sahrens 2402676Seschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size) != 0) 2412082Seschrock return (-1); 242789Sahrens 2431544Seschrock for (;;) { 2442082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_STATS, 2452082Seschrock &zc) == 0) { 246789Sahrens /* 2471544Seschrock * The real error is returned in the zc_cookie field. 248789Sahrens */ 2492142Seschrock error = zc.zc_cookie; 250789Sahrens break; 251789Sahrens } 252789Sahrens 2531544Seschrock if (errno == ENOMEM) { 2542676Seschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 2552676Seschrock zcmd_free_nvlists(&zc); 2562082Seschrock return (-1); 2572676Seschrock } 2581544Seschrock } else { 2592676Seschrock zcmd_free_nvlists(&zc); 2602142Seschrock if (errno == ENOENT || errno == EINVAL) 2612142Seschrock *missing = B_TRUE; 2622142Seschrock zhp->zpool_state = POOL_STATE_UNAVAIL; 2632142Seschrock return (0); 264789Sahrens } 265789Sahrens } 266789Sahrens 2672676Seschrock if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 2682676Seschrock zcmd_free_nvlists(&zc); 2692676Seschrock return (-1); 2702082Seschrock } 271789Sahrens 2722676Seschrock zcmd_free_nvlists(&zc); 2732676Seschrock 2742676Seschrock zhp->zpool_config_size = zc.zc_nvlist_dst_size; 275789Sahrens 276952Seschrock if (zhp->zpool_config != NULL) { 277952Seschrock uint64_t oldtxg, newtxg; 278952Seschrock 279952Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, 280952Seschrock ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0); 281952Seschrock verify(nvlist_lookup_uint64(config, 282952Seschrock ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0); 283789Sahrens 284952Seschrock if (zhp->zpool_old_config != NULL) 285952Seschrock nvlist_free(zhp->zpool_old_config); 286789Sahrens 287952Seschrock if (oldtxg != newtxg) { 288952Seschrock nvlist_free(zhp->zpool_config); 289952Seschrock zhp->zpool_old_config = NULL; 290952Seschrock } else { 291952Seschrock zhp->zpool_old_config = zhp->zpool_config; 292952Seschrock } 293952Seschrock } 294952Seschrock 295952Seschrock zhp->zpool_config = config; 2962142Seschrock if (error) 2972142Seschrock zhp->zpool_state = POOL_STATE_UNAVAIL; 2982142Seschrock else 2992142Seschrock zhp->zpool_state = POOL_STATE_ACTIVE; 300789Sahrens 3012142Seschrock return (0); 302789Sahrens } 303789Sahrens 304789Sahrens /* 305789Sahrens * Iterate over all pools in the system. 306789Sahrens */ 307789Sahrens int 3082082Seschrock zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) 309789Sahrens { 310789Sahrens config_node_t *cn; 311789Sahrens zpool_handle_t *zhp; 312789Sahrens int ret; 313789Sahrens 314*10817SEric.Schrock@Sun.COM /* 315*10817SEric.Schrock@Sun.COM * If someone makes a recursive call to zpool_iter(), we want to avoid 316*10817SEric.Schrock@Sun.COM * refreshing the namespace because that will invalidate the parent 317*10817SEric.Schrock@Sun.COM * context. We allow recursive calls, but simply re-use the same 318*10817SEric.Schrock@Sun.COM * namespace AVL tree. 319*10817SEric.Schrock@Sun.COM */ 320*10817SEric.Schrock@Sun.COM if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) 3212082Seschrock return (-1); 322789Sahrens 323*10817SEric.Schrock@Sun.COM hdl->libzfs_pool_iter++; 3242082Seschrock for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 3252082Seschrock cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 326789Sahrens 327*10817SEric.Schrock@Sun.COM if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { 328*10817SEric.Schrock@Sun.COM hdl->libzfs_pool_iter--; 3292142Seschrock return (-1); 330*10817SEric.Schrock@Sun.COM } 3312142Seschrock 3322142Seschrock if (zhp == NULL) 333789Sahrens continue; 334789Sahrens 335*10817SEric.Schrock@Sun.COM if ((ret = func(zhp, data)) != 0) { 336*10817SEric.Schrock@Sun.COM hdl->libzfs_pool_iter--; 337789Sahrens return (ret); 338*10817SEric.Schrock@Sun.COM } 339789Sahrens } 340*10817SEric.Schrock@Sun.COM hdl->libzfs_pool_iter--; 341789Sahrens 342789Sahrens return (0); 343789Sahrens } 344789Sahrens 345789Sahrens /* 346789Sahrens * Iterate over root datasets, calling the given function for each. The zfs 347789Sahrens * handle passed each time must be explicitly closed by the callback. 348789Sahrens */ 349789Sahrens int 3502082Seschrock zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) 351789Sahrens { 352789Sahrens config_node_t *cn; 353789Sahrens zfs_handle_t *zhp; 354789Sahrens int ret; 355789Sahrens 3562082Seschrock if (namespace_reload(hdl) != 0) 3572082Seschrock return (-1); 358789Sahrens 3592082Seschrock for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 3602082Seschrock cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 361789Sahrens 3622082Seschrock if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) 363789Sahrens continue; 364789Sahrens 365789Sahrens if ((ret = func(zhp, data)) != 0) 366789Sahrens return (ret); 367789Sahrens } 368789Sahrens 369789Sahrens return (0); 370789Sahrens } 371