1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5789Sahrens * Common Development and Distribution License, Version 1.0 only 6789Sahrens * (the "License"). You may not use this file except in compliance 7789Sahrens * with the License. 8789Sahrens * 9789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10789Sahrens * or http://www.opensolaris.org/os/licensing. 11789Sahrens * See the License for the specific language governing permissions 12789Sahrens * and limitations under the License. 13789Sahrens * 14789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19789Sahrens * 20789Sahrens * CDDL HEADER END 21789Sahrens */ 22789Sahrens /* 23789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 29789Sahrens /* 30789Sahrens * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 31789Sahrens * single packed nvlist. While it would be nice to just read in this 32789Sahrens * file from userland, this wouldn't work from a local zone. So we have to have 33789Sahrens * a zpool ioctl to return the complete configuration for all pools. In the 34789Sahrens * global zone, this will be identical to reading the file and unpacking it in 35789Sahrens * userland. 36789Sahrens */ 37789Sahrens 38789Sahrens #include <errno.h> 39789Sahrens #include <sys/stat.h> 40789Sahrens #include <fcntl.h> 41789Sahrens #include <stddef.h> 42789Sahrens #include <string.h> 43789Sahrens #include <unistd.h> 44789Sahrens #include <libintl.h> 45789Sahrens #include <libuutil.h> 46789Sahrens 47789Sahrens #include "libzfs_impl.h" 48789Sahrens 49789Sahrens static uu_avl_t *namespace_avl; 50789Sahrens static uint64_t namespace_generation; 51789Sahrens 52789Sahrens typedef struct config_node { 53789Sahrens char *cn_name; 54789Sahrens nvlist_t *cn_config; 55789Sahrens uu_avl_node_t cn_avl; 56789Sahrens } config_node_t; 57789Sahrens 58789Sahrens /* ARGSUSED */ 59789Sahrens static int 60789Sahrens config_node_compare(const void *a, const void *b, void *unused) 61789Sahrens { 62789Sahrens int ret; 63789Sahrens 64789Sahrens const config_node_t *ca = (config_node_t *)a; 65789Sahrens const config_node_t *cb = (config_node_t *)b; 66789Sahrens 67789Sahrens ret = strcmp(ca->cn_name, cb->cn_name); 68789Sahrens 69789Sahrens if (ret < 0) 70789Sahrens return (-1); 71789Sahrens else if (ret > 0) 72789Sahrens return (1); 73789Sahrens else 74789Sahrens return (0); 75789Sahrens } 76789Sahrens 77789Sahrens /* 78789Sahrens * Loads the pool namespace, or re-loads it if the cache has changed. 79789Sahrens */ 80789Sahrens static void 81789Sahrens namespace_reload() 82789Sahrens { 83789Sahrens nvlist_t *config; 84789Sahrens config_node_t *cn; 85789Sahrens nvpair_t *elem; 86789Sahrens zfs_cmd_t zc = { 0 }; 87789Sahrens uu_avl_walk_t *walk; 88789Sahrens 89789Sahrens if (namespace_generation == 0) { 90789Sahrens /* 91789Sahrens * This is the first time we've accessed the configuration 92789Sahrens * cache. Initialize the AVL tree and then fall through to the 93789Sahrens * common code. 94789Sahrens */ 95789Sahrens uu_avl_pool_t *pool; 96789Sahrens 97789Sahrens if ((pool = uu_avl_pool_create("config_pool", 98789Sahrens sizeof (config_node_t), 99789Sahrens offsetof(config_node_t, cn_avl), 100789Sahrens config_node_compare, UU_DEFAULT)) == NULL) 101789Sahrens no_memory(); 102789Sahrens 103789Sahrens if ((namespace_avl = uu_avl_create(pool, NULL, 104789Sahrens UU_DEFAULT)) == NULL) 105789Sahrens no_memory(); 106789Sahrens } 107789Sahrens 108789Sahrens /* 109789Sahrens * Issue the ZFS_IOC_POOL_CONFIGS ioctl. 110789Sahrens * This can fail for one of two reasons: 111789Sahrens * 112789Sahrens * EEXIST The generation counts match, nothing to do. 113789Sahrens * ENOMEM The zc_config_dst buffer isn't large enough to 114789Sahrens * hold the config; zc_config_dst_size will have 115789Sahrens * been modified to tell us how much to allocate. 116789Sahrens */ 117789Sahrens zc.zc_config_dst_size = 1024; 118789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 119789Sahrens zfs_malloc(zc.zc_config_dst_size); 120789Sahrens for (;;) { 121789Sahrens zc.zc_cookie = namespace_generation; 122789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 123789Sahrens switch (errno) { 124789Sahrens case EEXIST: 125789Sahrens /* 126789Sahrens * The namespace hasn't changed. 127789Sahrens */ 128789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 129789Sahrens return; 130789Sahrens 131789Sahrens case ENOMEM: 132789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 133789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 134789Sahrens zfs_malloc(zc.zc_config_dst_size); 135789Sahrens break; 136789Sahrens 137789Sahrens default: 138789Sahrens zfs_baderror(errno); 139789Sahrens } 140789Sahrens } else { 141789Sahrens namespace_generation = zc.zc_cookie; 142789Sahrens break; 143789Sahrens } 144789Sahrens } 145789Sahrens 146789Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 147789Sahrens zc.zc_config_dst_size, &config, 0) == 0); 148789Sahrens 149789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 150789Sahrens 151789Sahrens /* 152789Sahrens * Clear out any existing configuration information. 153789Sahrens */ 154789Sahrens if ((walk = uu_avl_walk_start(namespace_avl, UU_WALK_ROBUST)) == NULL) 155789Sahrens no_memory(); 156789Sahrens 157789Sahrens while ((cn = uu_avl_walk_next(walk)) != NULL) { 158789Sahrens uu_avl_remove(namespace_avl, cn); 159789Sahrens nvlist_free(cn->cn_config); 160789Sahrens free(cn->cn_name); 161789Sahrens free(cn); 162789Sahrens } 163789Sahrens 164789Sahrens elem = NULL; 165789Sahrens while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 166789Sahrens nvlist_t *child; 167789Sahrens uu_avl_index_t where; 168789Sahrens 169789Sahrens cn = zfs_malloc(sizeof (config_node_t)); 170789Sahrens cn->cn_name = zfs_strdup(nvpair_name(elem)); 171789Sahrens 172789Sahrens verify(nvpair_value_nvlist(elem, &child) == 0); 173789Sahrens verify(nvlist_dup(child, &cn->cn_config, 0) == 0); 174789Sahrens verify(uu_avl_find(namespace_avl, cn, NULL, &where) == NULL); 175789Sahrens 176789Sahrens uu_avl_insert(namespace_avl, cn, where); 177789Sahrens } 178789Sahrens 179789Sahrens nvlist_free(config); 180789Sahrens } 181789Sahrens 182789Sahrens /* 183789Sahrens * Retrive the configuration for the given pool. The configuration is a nvlist 184789Sahrens * describing the vdevs, as well as the statistics associated with each one. 185789Sahrens */ 186789Sahrens nvlist_t * 187*952Seschrock zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 188789Sahrens { 189*952Seschrock if (oldconfig) 190*952Seschrock *oldconfig = zhp->zpool_old_config; 191789Sahrens return (zhp->zpool_config); 192789Sahrens } 193789Sahrens 194789Sahrens /* 195789Sahrens * Refresh the vdev statistics associated with the given pool. This is used in 196789Sahrens * iostat to show configuration changes and determine the delta from the last 197789Sahrens * time the function was called. This function can fail, in case the pool has 198789Sahrens * been destroyed. 199789Sahrens */ 200789Sahrens int 201*952Seschrock zpool_refresh_stats(zpool_handle_t *zhp) 202789Sahrens { 203789Sahrens zfs_cmd_t zc = { 0 }; 204789Sahrens int error; 205*952Seschrock nvlist_t *config; 206789Sahrens 207789Sahrens (void) strcpy(zc.zc_name, zhp->zpool_name); 208789Sahrens 209789Sahrens if (zhp->zpool_config_size == 0) 210789Sahrens zhp->zpool_config_size = 1 << 16; 211789Sahrens 212789Sahrens zc.zc_config_dst_size = zhp->zpool_config_size; 213789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 214789Sahrens zfs_malloc(zc.zc_config_dst_size); 215789Sahrens 216789Sahrens while ((error = ioctl(zfs_fd, ZFS_IOC_POOL_STATS, &zc)) != 0) { 217789Sahrens error = errno; 218789Sahrens 219789Sahrens if (error == ENXIO) { 220789Sahrens /* 221789Sahrens * We can't open one or more top-level vdevs, 222789Sahrens * but we have the config. 223789Sahrens */ 224789Sahrens break; 225789Sahrens } 226789Sahrens 227789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 228789Sahrens 229789Sahrens if (error == ENOENT || error == EINVAL) { 230789Sahrens /* 231789Sahrens * There's no such pool (ENOENT) 232789Sahrens * or the config is bogus (EINVAL). 233789Sahrens */ 234789Sahrens return (error); 235789Sahrens } 236789Sahrens 237789Sahrens if (error != ENOMEM) 238789Sahrens zfs_baderror(error); 239789Sahrens 240789Sahrens zc.zc_config_dst = 241789Sahrens (uint64_t)(uintptr_t)zfs_malloc(zc.zc_config_dst_size); 242789Sahrens } 243789Sahrens 244789Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 245*952Seschrock zc.zc_config_dst_size, &config, 0) == 0); 246789Sahrens 247789Sahrens zhp->zpool_config_size = zc.zc_config_dst_size; 248789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 249789Sahrens 250*952Seschrock set_pool_health(config); 251*952Seschrock 252*952Seschrock if (zhp->zpool_config != NULL) { 253*952Seschrock uint64_t oldtxg, newtxg; 254*952Seschrock 255*952Seschrock verify(nvlist_lookup_uint64(zhp->zpool_config, 256*952Seschrock ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0); 257*952Seschrock verify(nvlist_lookup_uint64(config, 258*952Seschrock ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0); 259789Sahrens 260*952Seschrock if (zhp->zpool_old_config != NULL) 261*952Seschrock nvlist_free(zhp->zpool_old_config); 262789Sahrens 263*952Seschrock if (oldtxg != newtxg) { 264*952Seschrock nvlist_free(zhp->zpool_config); 265*952Seschrock zhp->zpool_old_config = NULL; 266*952Seschrock } else { 267*952Seschrock zhp->zpool_old_config = zhp->zpool_config; 268*952Seschrock } 269*952Seschrock } 270*952Seschrock 271*952Seschrock zhp->zpool_config = config; 272789Sahrens 273789Sahrens return (error); 274789Sahrens } 275789Sahrens 276789Sahrens /* 277789Sahrens * Iterate over all pools in the system. 278789Sahrens */ 279789Sahrens int 280789Sahrens zpool_iter(zpool_iter_f func, void *data) 281789Sahrens { 282789Sahrens config_node_t *cn; 283789Sahrens zpool_handle_t *zhp; 284789Sahrens int ret; 285789Sahrens 286789Sahrens namespace_reload(); 287789Sahrens 288789Sahrens for (cn = uu_avl_first(namespace_avl); cn != NULL; 289789Sahrens cn = uu_avl_next(namespace_avl, cn)) { 290789Sahrens 291789Sahrens if ((zhp = zpool_open_silent(cn->cn_name)) == NULL) 292789Sahrens continue; 293789Sahrens 294789Sahrens if ((ret = func(zhp, data)) != 0) 295789Sahrens return (ret); 296789Sahrens } 297789Sahrens 298789Sahrens return (0); 299789Sahrens } 300789Sahrens 301789Sahrens /* 302789Sahrens * Iterate over root datasets, calling the given function for each. The zfs 303789Sahrens * handle passed each time must be explicitly closed by the callback. 304789Sahrens */ 305789Sahrens int 306789Sahrens zfs_iter_root(zfs_iter_f func, void *data) 307789Sahrens { 308789Sahrens config_node_t *cn; 309789Sahrens zfs_handle_t *zhp; 310789Sahrens int ret; 311789Sahrens 312789Sahrens namespace_reload(); 313789Sahrens 314789Sahrens for (cn = uu_avl_first(namespace_avl); cn != NULL; 315789Sahrens cn = uu_avl_next(namespace_avl, cn)) { 316789Sahrens 317789Sahrens if ((zhp = make_dataset_handle(cn->cn_name)) == NULL) 318789Sahrens continue; 319789Sahrens 320789Sahrens if ((ret = func(zhp, data)) != 0) 321789Sahrens return (ret); 322789Sahrens } 323789Sahrens 324789Sahrens return (0); 325789Sahrens } 326