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 /* 221544Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens /* 29789Sahrens * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 30789Sahrens * single packed nvlist. While it would be nice to just read in this 31789Sahrens * file from userland, this wouldn't work from a local zone. So we have to have 32789Sahrens * a zpool ioctl to return the complete configuration for all pools. In the 33789Sahrens * global zone, this will be identical to reading the file and unpacking it in 34789Sahrens * userland. 35789Sahrens */ 36789Sahrens 37789Sahrens #include <errno.h> 38789Sahrens #include <sys/stat.h> 39789Sahrens #include <fcntl.h> 40789Sahrens #include <stddef.h> 41789Sahrens #include <string.h> 42789Sahrens #include <unistd.h> 43789Sahrens #include <libintl.h> 44789Sahrens #include <libuutil.h> 45789Sahrens 46789Sahrens #include "libzfs_impl.h" 47789Sahrens 48789Sahrens typedef struct config_node { 49789Sahrens char *cn_name; 50789Sahrens nvlist_t *cn_config; 51789Sahrens uu_avl_node_t cn_avl; 52789Sahrens } config_node_t; 53789Sahrens 54789Sahrens /* ARGSUSED */ 55789Sahrens static int 56789Sahrens config_node_compare(const void *a, const void *b, void *unused) 57789Sahrens { 58789Sahrens int ret; 59789Sahrens 60789Sahrens const config_node_t *ca = (config_node_t *)a; 61789Sahrens const config_node_t *cb = (config_node_t *)b; 62789Sahrens 63789Sahrens ret = strcmp(ca->cn_name, cb->cn_name); 64789Sahrens 65789Sahrens if (ret < 0) 66789Sahrens return (-1); 67789Sahrens else if (ret > 0) 68789Sahrens return (1); 69789Sahrens else 70789Sahrens return (0); 71789Sahrens } 72789Sahrens 73*2082Seschrock void 74*2082Seschrock namespace_clear(libzfs_handle_t *hdl) 75*2082Seschrock { 76*2082Seschrock if (hdl->libzfs_ns_avl) { 77*2082Seschrock uu_avl_walk_t *walk; 78*2082Seschrock config_node_t *cn; 79*2082Seschrock 80*2082Seschrock if ((walk = uu_avl_walk_start(hdl->libzfs_ns_avl, 81*2082Seschrock UU_WALK_ROBUST)) == NULL) 82*2082Seschrock return; 83*2082Seschrock 84*2082Seschrock while ((cn = uu_avl_walk_next(walk)) != NULL) { 85*2082Seschrock uu_avl_remove(hdl->libzfs_ns_avl, cn); 86*2082Seschrock nvlist_free(cn->cn_config); 87*2082Seschrock free(cn->cn_name); 88*2082Seschrock free(cn); 89*2082Seschrock } 90*2082Seschrock 91*2082Seschrock uu_avl_walk_end(walk); 92*2082Seschrock 93*2082Seschrock uu_avl_destroy(hdl->libzfs_ns_avl); 94*2082Seschrock hdl->libzfs_ns_avl = NULL; 95*2082Seschrock } 96*2082Seschrock 97*2082Seschrock if (hdl->libzfs_ns_avlpool) { 98*2082Seschrock uu_avl_pool_destroy(hdl->libzfs_ns_avlpool); 99*2082Seschrock hdl->libzfs_ns_avlpool = NULL; 100*2082Seschrock } 101*2082Seschrock } 102*2082Seschrock 103789Sahrens /* 104789Sahrens * Loads the pool namespace, or re-loads it if the cache has changed. 105789Sahrens */ 106*2082Seschrock static int 107*2082Seschrock namespace_reload(libzfs_handle_t *hdl) 108789Sahrens { 109789Sahrens nvlist_t *config; 110789Sahrens config_node_t *cn; 111789Sahrens nvpair_t *elem; 112789Sahrens zfs_cmd_t zc = { 0 }; 113789Sahrens uu_avl_walk_t *walk; 114789Sahrens 115*2082Seschrock if (hdl->libzfs_ns_gen == 0) { 116789Sahrens /* 117789Sahrens * This is the first time we've accessed the configuration 118789Sahrens * cache. Initialize the AVL tree and then fall through to the 119789Sahrens * common code. 120789Sahrens */ 121*2082Seschrock if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", 122789Sahrens sizeof (config_node_t), 123789Sahrens offsetof(config_node_t, cn_avl), 124789Sahrens config_node_compare, UU_DEFAULT)) == NULL) 125*2082Seschrock return (no_memory(hdl)); 126789Sahrens 127*2082Seschrock if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, 128*2082Seschrock NULL, UU_DEFAULT)) == NULL) 129*2082Seschrock return (no_memory(hdl)); 130789Sahrens } 131789Sahrens 132789Sahrens /* 133789Sahrens * Issue the ZFS_IOC_POOL_CONFIGS ioctl. 134789Sahrens * This can fail for one of two reasons: 135789Sahrens * 136789Sahrens * EEXIST The generation counts match, nothing to do. 137789Sahrens * ENOMEM The zc_config_dst buffer isn't large enough to 138789Sahrens * hold the config; zc_config_dst_size will have 139789Sahrens * been modified to tell us how much to allocate. 140789Sahrens */ 141789Sahrens zc.zc_config_dst_size = 1024; 142*2082Seschrock if ((zc.zc_config_dst = (uint64_t)(uintptr_t) 143*2082Seschrock zfs_alloc(hdl, zc.zc_config_dst_size)) == NULL) 144*2082Seschrock return (-1); 145789Sahrens for (;;) { 146*2082Seschrock zc.zc_cookie = hdl->libzfs_ns_gen; 147*2082Seschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 148789Sahrens switch (errno) { 149789Sahrens case EEXIST: 150789Sahrens /* 151789Sahrens * The namespace hasn't changed. 152789Sahrens */ 153789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 154*2082Seschrock return (0); 155789Sahrens 156789Sahrens case ENOMEM: 157789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 158*2082Seschrock if ((zc.zc_config_dst = (uint64_t)(uintptr_t) 159*2082Seschrock zfs_alloc(hdl, zc.zc_config_dst_size)) 160*2082Seschrock == NULL) 161*2082Seschrock return (-1); 162789Sahrens break; 163789Sahrens 164789Sahrens default: 165*2082Seschrock return (zfs_standard_error(hdl, errno, 166*2082Seschrock dgettext(TEXT_DOMAIN, "failed to read " 167*2082Seschrock "pool configuration"))); 168789Sahrens } 169789Sahrens } else { 170*2082Seschrock hdl->libzfs_ns_gen = zc.zc_cookie; 171789Sahrens break; 172789Sahrens } 173789Sahrens } 174789Sahrens 175*2082Seschrock if (nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 176*2082Seschrock zc.zc_config_dst_size, &config, 0) != 0) 177*2082Seschrock return (no_memory(hdl)); 178789Sahrens 179789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 180789Sahrens 181789Sahrens /* 182789Sahrens * Clear out any existing configuration information. 183789Sahrens */ 184*2082Seschrock if ((walk = uu_avl_walk_start(hdl->libzfs_ns_avl, 185*2082Seschrock UU_WALK_ROBUST)) == NULL) { 186*2082Seschrock nvlist_free(config); 187*2082Seschrock return (no_memory(hdl)); 188*2082Seschrock } 189789Sahrens 190789Sahrens while ((cn = uu_avl_walk_next(walk)) != NULL) { 191*2082Seschrock uu_avl_remove(hdl->libzfs_ns_avl, cn); 192789Sahrens nvlist_free(cn->cn_config); 193789Sahrens free(cn->cn_name); 194789Sahrens free(cn); 195789Sahrens } 196789Sahrens 197*2082Seschrock uu_avl_walk_end(walk); 198*2082Seschrock 199789Sahrens elem = NULL; 200789Sahrens while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 201789Sahrens nvlist_t *child; 202789Sahrens uu_avl_index_t where; 203789Sahrens 204*2082Seschrock if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) { 205*2082Seschrock nvlist_free(config); 206*2082Seschrock return (-1); 207*2082Seschrock } 208*2082Seschrock 209*2082Seschrock if ((cn->cn_name = zfs_strdup(hdl, 210*2082Seschrock nvpair_name(elem))) == NULL) { 211*2082Seschrock free(cn); 212*2082Seschrock return (-1); 213*2082Seschrock } 214789Sahrens 215789Sahrens verify(nvpair_value_nvlist(elem, &child) == 0); 216*2082Seschrock if (nvlist_dup(child, &cn->cn_config, 0) != 0) { 217*2082Seschrock nvlist_free(config); 218*2082Seschrock return (no_memory(hdl)); 219*2082Seschrock } 220*2082Seschrock verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) 221*2082Seschrock == NULL); 222789Sahrens 223*2082Seschrock uu_avl_insert(hdl->libzfs_ns_avl, cn, where); 224789Sahrens } 225789Sahrens 226789Sahrens nvlist_free(config); 227*2082Seschrock return (0); 228789Sahrens } 229789Sahrens 230789Sahrens /* 231789Sahrens * Retrive the configuration for the given pool. The configuration is a nvlist 232789Sahrens * describing the vdevs, as well as the statistics associated with each one. 233789Sahrens */ 234789Sahrens nvlist_t * 235952Seschrock zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 236789Sahrens { 237952Seschrock if (oldconfig) 238952Seschrock *oldconfig = zhp->zpool_old_config; 239789Sahrens return (zhp->zpool_config); 240789Sahrens } 241789Sahrens 242789Sahrens /* 243789Sahrens * Refresh the vdev statistics associated with the given pool. This is used in 244789Sahrens * iostat to show configuration changes and determine the delta from the last 245789Sahrens * time the function was called. This function can fail, in case the pool has 246789Sahrens * been destroyed. 247789Sahrens */ 248789Sahrens int 249952Seschrock zpool_refresh_stats(zpool_handle_t *zhp) 250789Sahrens { 251789Sahrens zfs_cmd_t zc = { 0 }; 252789Sahrens int error; 253952Seschrock nvlist_t *config; 254789Sahrens 255789Sahrens (void) strcpy(zc.zc_name, zhp->zpool_name); 256789Sahrens 257789Sahrens if (zhp->zpool_config_size == 0) 258789Sahrens zhp->zpool_config_size = 1 << 16; 259789Sahrens 260789Sahrens zc.zc_config_dst_size = zhp->zpool_config_size; 261*2082Seschrock if ((zc.zc_config_dst = (uint64_t)(uintptr_t) 262*2082Seschrock zfs_alloc(zhp->zpool_hdl, zc.zc_config_dst_size)) == NULL) 263*2082Seschrock return (-1); 264789Sahrens 2651544Seschrock for (;;) { 266*2082Seschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_STATS, 267*2082Seschrock &zc) == 0) { 268789Sahrens /* 2691544Seschrock * The real error is returned in the zc_cookie field. 270789Sahrens */ 271*2082Seschrock error = errno = zc.zc_cookie; 272789Sahrens break; 273789Sahrens } 274789Sahrens 2751544Seschrock if (errno == ENOMEM) { 2761544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 277*2082Seschrock if ((zc.zc_config_dst = (uint64_t)(uintptr_t) 278*2082Seschrock zfs_alloc(zhp->zpool_hdl, 279*2082Seschrock zc.zc_config_dst_size)) == NULL) 280*2082Seschrock return (-1); 2811544Seschrock } else { 2821544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 283*2082Seschrock return (-1); 284789Sahrens } 285789Sahrens } 286789Sahrens 287*2082Seschrock if (nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 288*2082Seschrock zc.zc_config_dst_size, &config, 0) != 0) { 289*2082Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 290*2082Seschrock return (no_memory(zhp->zpool_hdl)); 291*2082Seschrock } 292789Sahrens 293789Sahrens zhp->zpool_config_size = zc.zc_config_dst_size; 294789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 295789Sahrens 296*2082Seschrock if (set_pool_health(config) != 0) 297*2082Seschrock return (no_memory(zhp->zpool_hdl)); 298952Seschrock 299952Seschrock if (zhp->zpool_config != NULL) { 300952Seschrock uint64_t oldtxg, newtxg; 301952Seschrock 302952Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, 303952Seschrock ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0); 304952Seschrock verify(nvlist_lookup_uint64(config, 305952Seschrock ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0); 306789Sahrens 307952Seschrock if (zhp->zpool_old_config != NULL) 308952Seschrock nvlist_free(zhp->zpool_old_config); 309789Sahrens 310952Seschrock if (oldtxg != newtxg) { 311952Seschrock nvlist_free(zhp->zpool_config); 312952Seschrock zhp->zpool_old_config = NULL; 313952Seschrock } else { 314952Seschrock zhp->zpool_old_config = zhp->zpool_config; 315952Seschrock } 316952Seschrock } 317952Seschrock 318952Seschrock zhp->zpool_config = config; 319789Sahrens 320*2082Seschrock return (error ? -1 : 0); 321789Sahrens } 322789Sahrens 323789Sahrens /* 324789Sahrens * Iterate over all pools in the system. 325789Sahrens */ 326789Sahrens int 327*2082Seschrock zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) 328789Sahrens { 329789Sahrens config_node_t *cn; 330789Sahrens zpool_handle_t *zhp; 331789Sahrens int ret; 332789Sahrens 333*2082Seschrock if (namespace_reload(hdl) != 0) 334*2082Seschrock return (-1); 335789Sahrens 336*2082Seschrock for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 337*2082Seschrock cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 338789Sahrens 339*2082Seschrock if ((zhp = zpool_open_silent(hdl, cn->cn_name)) == NULL) 340789Sahrens continue; 341789Sahrens 342789Sahrens if ((ret = func(zhp, data)) != 0) 343789Sahrens return (ret); 344789Sahrens } 345789Sahrens 346789Sahrens return (0); 347789Sahrens } 348789Sahrens 349789Sahrens /* 350789Sahrens * Iterate over root datasets, calling the given function for each. The zfs 351789Sahrens * handle passed each time must be explicitly closed by the callback. 352789Sahrens */ 353789Sahrens int 354*2082Seschrock zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) 355789Sahrens { 356789Sahrens config_node_t *cn; 357789Sahrens zfs_handle_t *zhp; 358789Sahrens int ret; 359789Sahrens 360*2082Seschrock if (namespace_reload(hdl) != 0) 361*2082Seschrock return (-1); 362789Sahrens 363*2082Seschrock for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 364*2082Seschrock cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 365789Sahrens 366*2082Seschrock if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) 367789Sahrens continue; 368789Sahrens 369789Sahrens if ((ret = func(zhp, data)) != 0) 370789Sahrens return (ret); 371789Sahrens } 372789Sahrens 373789Sahrens return (0); 374789Sahrens } 375