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