1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5*1544Seschrock * Common Development and Distribution License (the "License"). 6*1544Seschrock * 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*1544Seschrock * 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 static uu_avl_t *namespace_avl; 49789Sahrens static uint64_t namespace_generation; 50789Sahrens 51789Sahrens typedef struct config_node { 52789Sahrens char *cn_name; 53789Sahrens nvlist_t *cn_config; 54789Sahrens uu_avl_node_t cn_avl; 55789Sahrens } config_node_t; 56789Sahrens 57789Sahrens /* ARGSUSED */ 58789Sahrens static int 59789Sahrens config_node_compare(const void *a, const void *b, void *unused) 60789Sahrens { 61789Sahrens int ret; 62789Sahrens 63789Sahrens const config_node_t *ca = (config_node_t *)a; 64789Sahrens const config_node_t *cb = (config_node_t *)b; 65789Sahrens 66789Sahrens ret = strcmp(ca->cn_name, cb->cn_name); 67789Sahrens 68789Sahrens if (ret < 0) 69789Sahrens return (-1); 70789Sahrens else if (ret > 0) 71789Sahrens return (1); 72789Sahrens else 73789Sahrens return (0); 74789Sahrens } 75789Sahrens 76789Sahrens /* 77789Sahrens * Loads the pool namespace, or re-loads it if the cache has changed. 78789Sahrens */ 79789Sahrens static void 80789Sahrens namespace_reload() 81789Sahrens { 82789Sahrens nvlist_t *config; 83789Sahrens config_node_t *cn; 84789Sahrens nvpair_t *elem; 85789Sahrens zfs_cmd_t zc = { 0 }; 86789Sahrens uu_avl_walk_t *walk; 87789Sahrens 88789Sahrens if (namespace_generation == 0) { 89789Sahrens /* 90789Sahrens * This is the first time we've accessed the configuration 91789Sahrens * cache. Initialize the AVL tree and then fall through to the 92789Sahrens * common code. 93789Sahrens */ 94789Sahrens uu_avl_pool_t *pool; 95789Sahrens 96789Sahrens if ((pool = uu_avl_pool_create("config_pool", 97789Sahrens sizeof (config_node_t), 98789Sahrens offsetof(config_node_t, cn_avl), 99789Sahrens config_node_compare, UU_DEFAULT)) == NULL) 100789Sahrens no_memory(); 101789Sahrens 102789Sahrens if ((namespace_avl = uu_avl_create(pool, NULL, 103789Sahrens UU_DEFAULT)) == NULL) 104789Sahrens no_memory(); 105789Sahrens } 106789Sahrens 107789Sahrens /* 108789Sahrens * Issue the ZFS_IOC_POOL_CONFIGS ioctl. 109789Sahrens * This can fail for one of two reasons: 110789Sahrens * 111789Sahrens * EEXIST The generation counts match, nothing to do. 112789Sahrens * ENOMEM The zc_config_dst buffer isn't large enough to 113789Sahrens * hold the config; zc_config_dst_size will have 114789Sahrens * been modified to tell us how much to allocate. 115789Sahrens */ 116789Sahrens zc.zc_config_dst_size = 1024; 117789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 118789Sahrens zfs_malloc(zc.zc_config_dst_size); 119789Sahrens for (;;) { 120789Sahrens zc.zc_cookie = namespace_generation; 121*1544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 122789Sahrens switch (errno) { 123789Sahrens case EEXIST: 124789Sahrens /* 125789Sahrens * The namespace hasn't changed. 126789Sahrens */ 127789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 128789Sahrens return; 129789Sahrens 130789Sahrens case ENOMEM: 131789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 132789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 133789Sahrens zfs_malloc(zc.zc_config_dst_size); 134789Sahrens break; 135789Sahrens 136789Sahrens default: 137789Sahrens zfs_baderror(errno); 138789Sahrens } 139789Sahrens } else { 140789Sahrens namespace_generation = zc.zc_cookie; 141789Sahrens break; 142789Sahrens } 143789Sahrens } 144789Sahrens 145789Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 146789Sahrens zc.zc_config_dst_size, &config, 0) == 0); 147789Sahrens 148789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 149789Sahrens 150789Sahrens /* 151789Sahrens * Clear out any existing configuration information. 152789Sahrens */ 153789Sahrens if ((walk = uu_avl_walk_start(namespace_avl, UU_WALK_ROBUST)) == NULL) 154789Sahrens no_memory(); 155789Sahrens 156789Sahrens while ((cn = uu_avl_walk_next(walk)) != NULL) { 157789Sahrens uu_avl_remove(namespace_avl, cn); 158789Sahrens nvlist_free(cn->cn_config); 159789Sahrens free(cn->cn_name); 160789Sahrens free(cn); 161789Sahrens } 162789Sahrens 163789Sahrens elem = NULL; 164789Sahrens while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 165789Sahrens nvlist_t *child; 166789Sahrens uu_avl_index_t where; 167789Sahrens 168789Sahrens cn = zfs_malloc(sizeof (config_node_t)); 169789Sahrens cn->cn_name = zfs_strdup(nvpair_name(elem)); 170789Sahrens 171789Sahrens verify(nvpair_value_nvlist(elem, &child) == 0); 172789Sahrens verify(nvlist_dup(child, &cn->cn_config, 0) == 0); 173789Sahrens verify(uu_avl_find(namespace_avl, cn, NULL, &where) == NULL); 174789Sahrens 175789Sahrens uu_avl_insert(namespace_avl, cn, where); 176789Sahrens } 177789Sahrens 178789Sahrens nvlist_free(config); 179789Sahrens } 180789Sahrens 181789Sahrens /* 182789Sahrens * Retrive the configuration for the given pool. The configuration is a nvlist 183789Sahrens * describing the vdevs, as well as the statistics associated with each one. 184789Sahrens */ 185789Sahrens nvlist_t * 186952Seschrock zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 187789Sahrens { 188952Seschrock if (oldconfig) 189952Seschrock *oldconfig = zhp->zpool_old_config; 190789Sahrens return (zhp->zpool_config); 191789Sahrens } 192789Sahrens 193789Sahrens /* 194789Sahrens * Refresh the vdev statistics associated with the given pool. This is used in 195789Sahrens * iostat to show configuration changes and determine the delta from the last 196789Sahrens * time the function was called. This function can fail, in case the pool has 197789Sahrens * been destroyed. 198789Sahrens */ 199789Sahrens int 200952Seschrock zpool_refresh_stats(zpool_handle_t *zhp) 201789Sahrens { 202789Sahrens zfs_cmd_t zc = { 0 }; 203789Sahrens int error; 204952Seschrock nvlist_t *config; 205789Sahrens 206789Sahrens (void) strcpy(zc.zc_name, zhp->zpool_name); 207789Sahrens 208789Sahrens if (zhp->zpool_config_size == 0) 209789Sahrens zhp->zpool_config_size = 1 << 16; 210789Sahrens 211789Sahrens zc.zc_config_dst_size = zhp->zpool_config_size; 212789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 213789Sahrens zfs_malloc(zc.zc_config_dst_size); 214789Sahrens 215*1544Seschrock for (;;) { 216*1544Seschrock if (zfs_ioctl(ZFS_IOC_POOL_STATS, &zc) == 0) { 217789Sahrens /* 218*1544Seschrock * The real error is returned in the zc_cookie field. 219789Sahrens */ 220*1544Seschrock error = zc.zc_cookie; 221789Sahrens break; 222789Sahrens } 223789Sahrens 224*1544Seschrock if (errno == ENOMEM) { 225*1544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 226*1544Seschrock zc.zc_config_dst = (uint64_t)(uintptr_t) 227*1544Seschrock zfs_malloc(zc.zc_config_dst_size); 228*1544Seschrock } else { 229*1544Seschrock free((void *)(uintptr_t)zc.zc_config_dst); 230*1544Seschrock return (errno); 231789Sahrens } 232789Sahrens } 233789Sahrens 234789Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 235952Seschrock zc.zc_config_dst_size, &config, 0) == 0); 236789Sahrens 237789Sahrens zhp->zpool_config_size = zc.zc_config_dst_size; 238789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 239789Sahrens 240952Seschrock set_pool_health(config); 241952Seschrock 242952Seschrock if (zhp->zpool_config != NULL) { 243952Seschrock uint64_t oldtxg, newtxg; 244952Seschrock 245952Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, 246952Seschrock ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0); 247952Seschrock verify(nvlist_lookup_uint64(config, 248952Seschrock ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0); 249789Sahrens 250952Seschrock if (zhp->zpool_old_config != NULL) 251952Seschrock nvlist_free(zhp->zpool_old_config); 252789Sahrens 253952Seschrock if (oldtxg != newtxg) { 254952Seschrock nvlist_free(zhp->zpool_config); 255952Seschrock zhp->zpool_old_config = NULL; 256952Seschrock } else { 257952Seschrock zhp->zpool_old_config = zhp->zpool_config; 258952Seschrock } 259952Seschrock } 260952Seschrock 261952Seschrock zhp->zpool_config = config; 262789Sahrens 263789Sahrens return (error); 264789Sahrens } 265789Sahrens 266789Sahrens /* 267789Sahrens * Iterate over all pools in the system. 268789Sahrens */ 269789Sahrens int 270789Sahrens zpool_iter(zpool_iter_f func, void *data) 271789Sahrens { 272789Sahrens config_node_t *cn; 273789Sahrens zpool_handle_t *zhp; 274789Sahrens int ret; 275789Sahrens 276789Sahrens namespace_reload(); 277789Sahrens 278789Sahrens for (cn = uu_avl_first(namespace_avl); cn != NULL; 279789Sahrens cn = uu_avl_next(namespace_avl, cn)) { 280789Sahrens 281789Sahrens if ((zhp = zpool_open_silent(cn->cn_name)) == NULL) 282789Sahrens continue; 283789Sahrens 284789Sahrens if ((ret = func(zhp, data)) != 0) 285789Sahrens return (ret); 286789Sahrens } 287789Sahrens 288789Sahrens return (0); 289789Sahrens } 290789Sahrens 291789Sahrens /* 292789Sahrens * Iterate over root datasets, calling the given function for each. The zfs 293789Sahrens * handle passed each time must be explicitly closed by the callback. 294789Sahrens */ 295789Sahrens int 296789Sahrens zfs_iter_root(zfs_iter_f func, void *data) 297789Sahrens { 298789Sahrens config_node_t *cn; 299789Sahrens zfs_handle_t *zhp; 300789Sahrens int ret; 301789Sahrens 302789Sahrens namespace_reload(); 303789Sahrens 304789Sahrens for (cn = uu_avl_first(namespace_avl); cn != NULL; 305789Sahrens cn = uu_avl_next(namespace_avl, cn)) { 306789Sahrens 307789Sahrens if ((zhp = make_dataset_handle(cn->cn_name)) == NULL) 308789Sahrens continue; 309789Sahrens 310789Sahrens if ((ret = func(zhp, data)) != 0) 311789Sahrens return (ret); 312789Sahrens } 313789Sahrens 314789Sahrens return (0); 315789Sahrens } 316