1*789Sahrens /* 2*789Sahrens * CDDL HEADER START 3*789Sahrens * 4*789Sahrens * The contents of this file are subject to the terms of the 5*789Sahrens * Common Development and Distribution License, Version 1.0 only 6*789Sahrens * (the "License"). You may not use this file except in compliance 7*789Sahrens * with the License. 8*789Sahrens * 9*789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*789Sahrens * or http://www.opensolaris.org/os/licensing. 11*789Sahrens * See the License for the specific language governing permissions 12*789Sahrens * and limitations under the License. 13*789Sahrens * 14*789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15*789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17*789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18*789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19*789Sahrens * 20*789Sahrens * CDDL HEADER END 21*789Sahrens */ 22*789Sahrens /* 23*789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*789Sahrens * Use is subject to license terms. 25*789Sahrens */ 26*789Sahrens 27*789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28*789Sahrens 29*789Sahrens /* 30*789Sahrens * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 31*789Sahrens * single packed nvlist. While it would be nice to just read in this 32*789Sahrens * file from userland, this wouldn't work from a local zone. So we have to have 33*789Sahrens * a zpool ioctl to return the complete configuration for all pools. In the 34*789Sahrens * global zone, this will be identical to reading the file and unpacking it in 35*789Sahrens * userland. 36*789Sahrens */ 37*789Sahrens 38*789Sahrens #include <errno.h> 39*789Sahrens #include <sys/stat.h> 40*789Sahrens #include <fcntl.h> 41*789Sahrens #include <stddef.h> 42*789Sahrens #include <string.h> 43*789Sahrens #include <unistd.h> 44*789Sahrens #include <libintl.h> 45*789Sahrens #include <libuutil.h> 46*789Sahrens 47*789Sahrens #include "libzfs_impl.h" 48*789Sahrens 49*789Sahrens static uu_avl_t *namespace_avl; 50*789Sahrens static uint64_t namespace_generation; 51*789Sahrens 52*789Sahrens typedef struct config_node { 53*789Sahrens char *cn_name; 54*789Sahrens nvlist_t *cn_config; 55*789Sahrens uu_avl_node_t cn_avl; 56*789Sahrens } config_node_t; 57*789Sahrens 58*789Sahrens /* ARGSUSED */ 59*789Sahrens static int 60*789Sahrens config_node_compare(const void *a, const void *b, void *unused) 61*789Sahrens { 62*789Sahrens int ret; 63*789Sahrens 64*789Sahrens const config_node_t *ca = (config_node_t *)a; 65*789Sahrens const config_node_t *cb = (config_node_t *)b; 66*789Sahrens 67*789Sahrens ret = strcmp(ca->cn_name, cb->cn_name); 68*789Sahrens 69*789Sahrens if (ret < 0) 70*789Sahrens return (-1); 71*789Sahrens else if (ret > 0) 72*789Sahrens return (1); 73*789Sahrens else 74*789Sahrens return (0); 75*789Sahrens } 76*789Sahrens 77*789Sahrens /* 78*789Sahrens * Loads the pool namespace, or re-loads it if the cache has changed. 79*789Sahrens */ 80*789Sahrens static void 81*789Sahrens namespace_reload() 82*789Sahrens { 83*789Sahrens nvlist_t *config; 84*789Sahrens config_node_t *cn; 85*789Sahrens nvpair_t *elem; 86*789Sahrens zfs_cmd_t zc = { 0 }; 87*789Sahrens uu_avl_walk_t *walk; 88*789Sahrens 89*789Sahrens if (namespace_generation == 0) { 90*789Sahrens /* 91*789Sahrens * This is the first time we've accessed the configuration 92*789Sahrens * cache. Initialize the AVL tree and then fall through to the 93*789Sahrens * common code. 94*789Sahrens */ 95*789Sahrens uu_avl_pool_t *pool; 96*789Sahrens 97*789Sahrens if ((pool = uu_avl_pool_create("config_pool", 98*789Sahrens sizeof (config_node_t), 99*789Sahrens offsetof(config_node_t, cn_avl), 100*789Sahrens config_node_compare, UU_DEFAULT)) == NULL) 101*789Sahrens no_memory(); 102*789Sahrens 103*789Sahrens if ((namespace_avl = uu_avl_create(pool, NULL, 104*789Sahrens UU_DEFAULT)) == NULL) 105*789Sahrens no_memory(); 106*789Sahrens } 107*789Sahrens 108*789Sahrens /* 109*789Sahrens * Issue the ZFS_IOC_POOL_CONFIGS ioctl. 110*789Sahrens * This can fail for one of two reasons: 111*789Sahrens * 112*789Sahrens * EEXIST The generation counts match, nothing to do. 113*789Sahrens * ENOMEM The zc_config_dst buffer isn't large enough to 114*789Sahrens * hold the config; zc_config_dst_size will have 115*789Sahrens * been modified to tell us how much to allocate. 116*789Sahrens */ 117*789Sahrens zc.zc_config_dst_size = 1024; 118*789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 119*789Sahrens zfs_malloc(zc.zc_config_dst_size); 120*789Sahrens for (;;) { 121*789Sahrens zc.zc_cookie = namespace_generation; 122*789Sahrens if (ioctl(zfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 123*789Sahrens switch (errno) { 124*789Sahrens case EEXIST: 125*789Sahrens /* 126*789Sahrens * The namespace hasn't changed. 127*789Sahrens */ 128*789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 129*789Sahrens return; 130*789Sahrens 131*789Sahrens case ENOMEM: 132*789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 133*789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 134*789Sahrens zfs_malloc(zc.zc_config_dst_size); 135*789Sahrens break; 136*789Sahrens 137*789Sahrens default: 138*789Sahrens zfs_baderror(errno); 139*789Sahrens } 140*789Sahrens } else { 141*789Sahrens namespace_generation = zc.zc_cookie; 142*789Sahrens break; 143*789Sahrens } 144*789Sahrens } 145*789Sahrens 146*789Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 147*789Sahrens zc.zc_config_dst_size, &config, 0) == 0); 148*789Sahrens 149*789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 150*789Sahrens 151*789Sahrens /* 152*789Sahrens * Clear out any existing configuration information. 153*789Sahrens */ 154*789Sahrens if ((walk = uu_avl_walk_start(namespace_avl, UU_WALK_ROBUST)) == NULL) 155*789Sahrens no_memory(); 156*789Sahrens 157*789Sahrens while ((cn = uu_avl_walk_next(walk)) != NULL) { 158*789Sahrens uu_avl_remove(namespace_avl, cn); 159*789Sahrens nvlist_free(cn->cn_config); 160*789Sahrens free(cn->cn_name); 161*789Sahrens free(cn); 162*789Sahrens } 163*789Sahrens 164*789Sahrens elem = NULL; 165*789Sahrens while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 166*789Sahrens nvlist_t *child; 167*789Sahrens uu_avl_index_t where; 168*789Sahrens 169*789Sahrens cn = zfs_malloc(sizeof (config_node_t)); 170*789Sahrens cn->cn_name = zfs_strdup(nvpair_name(elem)); 171*789Sahrens 172*789Sahrens verify(nvpair_value_nvlist(elem, &child) == 0); 173*789Sahrens verify(nvlist_dup(child, &cn->cn_config, 0) == 0); 174*789Sahrens verify(uu_avl_find(namespace_avl, cn, NULL, &where) == NULL); 175*789Sahrens 176*789Sahrens uu_avl_insert(namespace_avl, cn, where); 177*789Sahrens } 178*789Sahrens 179*789Sahrens nvlist_free(config); 180*789Sahrens } 181*789Sahrens 182*789Sahrens /* 183*789Sahrens * Retrive the configuration for the given pool. The configuration is a nvlist 184*789Sahrens * describing the vdevs, as well as the statistics associated with each one. 185*789Sahrens */ 186*789Sahrens nvlist_t * 187*789Sahrens zpool_get_config(zpool_handle_t *zhp) 188*789Sahrens { 189*789Sahrens return (zhp->zpool_config); 190*789Sahrens } 191*789Sahrens 192*789Sahrens /* 193*789Sahrens * Refresh the vdev statistics associated with the given pool. This is used in 194*789Sahrens * iostat to show configuration changes and determine the delta from the last 195*789Sahrens * time the function was called. This function can fail, in case the pool has 196*789Sahrens * been destroyed. 197*789Sahrens */ 198*789Sahrens int 199*789Sahrens zpool_refresh_stats(zpool_handle_t *zhp, nvlist_t **oldconfig, 200*789Sahrens nvlist_t **newconfig) 201*789Sahrens { 202*789Sahrens zfs_cmd_t zc = { 0 }; 203*789Sahrens int error; 204*789Sahrens 205*789Sahrens (void) strcpy(zc.zc_name, zhp->zpool_name); 206*789Sahrens 207*789Sahrens if (zhp->zpool_config_size == 0) 208*789Sahrens zhp->zpool_config_size = 1 << 16; 209*789Sahrens 210*789Sahrens zc.zc_config_dst_size = zhp->zpool_config_size; 211*789Sahrens zc.zc_config_dst = (uint64_t)(uintptr_t) 212*789Sahrens zfs_malloc(zc.zc_config_dst_size); 213*789Sahrens 214*789Sahrens while ((error = ioctl(zfs_fd, ZFS_IOC_POOL_STATS, &zc)) != 0) { 215*789Sahrens error = errno; 216*789Sahrens 217*789Sahrens if (error == ENXIO) { 218*789Sahrens /* 219*789Sahrens * We can't open one or more top-level vdevs, 220*789Sahrens * but we have the config. 221*789Sahrens */ 222*789Sahrens break; 223*789Sahrens } 224*789Sahrens 225*789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 226*789Sahrens 227*789Sahrens if (error == ENOENT || error == EINVAL) { 228*789Sahrens /* 229*789Sahrens * There's no such pool (ENOENT) 230*789Sahrens * or the config is bogus (EINVAL). 231*789Sahrens */ 232*789Sahrens return (error); 233*789Sahrens } 234*789Sahrens 235*789Sahrens if (error != ENOMEM) 236*789Sahrens zfs_baderror(error); 237*789Sahrens 238*789Sahrens zc.zc_config_dst = 239*789Sahrens (uint64_t)(uintptr_t)zfs_malloc(zc.zc_config_dst_size); 240*789Sahrens } 241*789Sahrens 242*789Sahrens verify(nvlist_unpack((void *)(uintptr_t)zc.zc_config_dst, 243*789Sahrens zc.zc_config_dst_size, newconfig, 0) == 0); 244*789Sahrens 245*789Sahrens zhp->zpool_config_size = zc.zc_config_dst_size; 246*789Sahrens free((void *)(uintptr_t)zc.zc_config_dst); 247*789Sahrens 248*789Sahrens set_pool_health(*newconfig); 249*789Sahrens 250*789Sahrens if (oldconfig != NULL) 251*789Sahrens *oldconfig = zhp->zpool_config; 252*789Sahrens else 253*789Sahrens nvlist_free(zhp->zpool_config); 254*789Sahrens 255*789Sahrens zhp->zpool_config = *newconfig; 256*789Sahrens 257*789Sahrens return (error); 258*789Sahrens } 259*789Sahrens 260*789Sahrens /* 261*789Sahrens * Iterate over all pools in the system. 262*789Sahrens */ 263*789Sahrens int 264*789Sahrens zpool_iter(zpool_iter_f func, void *data) 265*789Sahrens { 266*789Sahrens config_node_t *cn; 267*789Sahrens zpool_handle_t *zhp; 268*789Sahrens int ret; 269*789Sahrens 270*789Sahrens namespace_reload(); 271*789Sahrens 272*789Sahrens for (cn = uu_avl_first(namespace_avl); cn != NULL; 273*789Sahrens cn = uu_avl_next(namespace_avl, cn)) { 274*789Sahrens 275*789Sahrens if ((zhp = zpool_open_silent(cn->cn_name)) == NULL) 276*789Sahrens continue; 277*789Sahrens 278*789Sahrens if ((ret = func(zhp, data)) != 0) 279*789Sahrens return (ret); 280*789Sahrens } 281*789Sahrens 282*789Sahrens return (0); 283*789Sahrens } 284*789Sahrens 285*789Sahrens /* 286*789Sahrens * Iterate over root datasets, calling the given function for each. The zfs 287*789Sahrens * handle passed each time must be explicitly closed by the callback. 288*789Sahrens */ 289*789Sahrens int 290*789Sahrens zfs_iter_root(zfs_iter_f func, void *data) 291*789Sahrens { 292*789Sahrens config_node_t *cn; 293*789Sahrens zfs_handle_t *zhp; 294*789Sahrens int ret; 295*789Sahrens 296*789Sahrens namespace_reload(); 297*789Sahrens 298*789Sahrens for (cn = uu_avl_first(namespace_avl); cn != NULL; 299*789Sahrens cn = uu_avl_next(namespace_avl, cn)) { 300*789Sahrens 301*789Sahrens if ((zhp = make_dataset_handle(cn->cn_name)) == NULL) 302*789Sahrens continue; 303*789Sahrens 304*789Sahrens if ((ret = func(zhp, data)) != 0) 305*789Sahrens return (ret); 306*789Sahrens } 307*789Sahrens 308*789Sahrens return (0); 309*789Sahrens } 310