1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1544 eschrock * Common Development and Distribution License (the "License"). 6 1544 eschrock * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 789 ahrens /* 22 10817 Eric * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 789 ahrens * Use is subject to license terms. 24 789 ahrens */ 25 789 ahrens 26 789 ahrens /* 27 789 ahrens * The pool configuration repository is stored in /etc/zfs/zpool.cache as a 28 789 ahrens * single packed nvlist. While it would be nice to just read in this 29 789 ahrens * file from userland, this wouldn't work from a local zone. So we have to have 30 789 ahrens * a zpool ioctl to return the complete configuration for all pools. In the 31 789 ahrens * global zone, this will be identical to reading the file and unpacking it in 32 789 ahrens * userland. 33 789 ahrens */ 34 789 ahrens 35 789 ahrens #include <errno.h> 36 789 ahrens #include <sys/stat.h> 37 789 ahrens #include <fcntl.h> 38 789 ahrens #include <stddef.h> 39 789 ahrens #include <string.h> 40 789 ahrens #include <unistd.h> 41 789 ahrens #include <libintl.h> 42 789 ahrens #include <libuutil.h> 43 789 ahrens 44 789 ahrens #include "libzfs_impl.h" 45 789 ahrens 46 789 ahrens typedef struct config_node { 47 789 ahrens char *cn_name; 48 789 ahrens nvlist_t *cn_config; 49 789 ahrens uu_avl_node_t cn_avl; 50 789 ahrens } config_node_t; 51 789 ahrens 52 789 ahrens /* ARGSUSED */ 53 789 ahrens static int 54 789 ahrens config_node_compare(const void *a, const void *b, void *unused) 55 789 ahrens { 56 789 ahrens int ret; 57 789 ahrens 58 789 ahrens const config_node_t *ca = (config_node_t *)a; 59 789 ahrens const config_node_t *cb = (config_node_t *)b; 60 789 ahrens 61 789 ahrens ret = strcmp(ca->cn_name, cb->cn_name); 62 789 ahrens 63 789 ahrens if (ret < 0) 64 789 ahrens return (-1); 65 789 ahrens else if (ret > 0) 66 789 ahrens return (1); 67 789 ahrens else 68 789 ahrens return (0); 69 789 ahrens } 70 789 ahrens 71 2082 eschrock void 72 2082 eschrock namespace_clear(libzfs_handle_t *hdl) 73 2082 eschrock { 74 2082 eschrock if (hdl->libzfs_ns_avl) { 75 2082 eschrock config_node_t *cn; 76 4074 eschrock void *cookie = NULL; 77 2082 eschrock 78 4074 eschrock while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, 79 4074 eschrock &cookie)) != NULL) { 80 2082 eschrock nvlist_free(cn->cn_config); 81 2082 eschrock free(cn->cn_name); 82 2082 eschrock free(cn); 83 2082 eschrock } 84 2082 eschrock 85 2082 eschrock uu_avl_destroy(hdl->libzfs_ns_avl); 86 2082 eschrock hdl->libzfs_ns_avl = NULL; 87 2082 eschrock } 88 2082 eschrock 89 2082 eschrock if (hdl->libzfs_ns_avlpool) { 90 2082 eschrock uu_avl_pool_destroy(hdl->libzfs_ns_avlpool); 91 2082 eschrock hdl->libzfs_ns_avlpool = NULL; 92 2082 eschrock } 93 2082 eschrock } 94 2082 eschrock 95 789 ahrens /* 96 789 ahrens * Loads the pool namespace, or re-loads it if the cache has changed. 97 789 ahrens */ 98 2082 eschrock static int 99 2082 eschrock namespace_reload(libzfs_handle_t *hdl) 100 789 ahrens { 101 789 ahrens nvlist_t *config; 102 789 ahrens config_node_t *cn; 103 789 ahrens nvpair_t *elem; 104 789 ahrens zfs_cmd_t zc = { 0 }; 105 4074 eschrock void *cookie; 106 789 ahrens 107 2082 eschrock if (hdl->libzfs_ns_gen == 0) { 108 789 ahrens /* 109 789 ahrens * This is the first time we've accessed the configuration 110 789 ahrens * cache. Initialize the AVL tree and then fall through to the 111 789 ahrens * common code. 112 789 ahrens */ 113 2082 eschrock if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", 114 789 ahrens sizeof (config_node_t), 115 789 ahrens offsetof(config_node_t, cn_avl), 116 789 ahrens config_node_compare, UU_DEFAULT)) == NULL) 117 2082 eschrock return (no_memory(hdl)); 118 789 ahrens 119 2082 eschrock if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, 120 2082 eschrock NULL, UU_DEFAULT)) == NULL) 121 2082 eschrock return (no_memory(hdl)); 122 789 ahrens } 123 789 ahrens 124 2676 eschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 125 2082 eschrock return (-1); 126 2676 eschrock 127 789 ahrens for (;;) { 128 2082 eschrock zc.zc_cookie = hdl->libzfs_ns_gen; 129 2082 eschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { 130 789 ahrens switch (errno) { 131 789 ahrens case EEXIST: 132 789 ahrens /* 133 789 ahrens * The namespace hasn't changed. 134 789 ahrens */ 135 2676 eschrock zcmd_free_nvlists(&zc); 136 2082 eschrock return (0); 137 789 ahrens 138 789 ahrens case ENOMEM: 139 2676 eschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 140 2676 eschrock zcmd_free_nvlists(&zc); 141 2082 eschrock return (-1); 142 2676 eschrock } 143 789 ahrens break; 144 789 ahrens 145 789 ahrens default: 146 2676 eschrock zcmd_free_nvlists(&zc); 147 2082 eschrock return (zfs_standard_error(hdl, errno, 148 2082 eschrock dgettext(TEXT_DOMAIN, "failed to read " 149 2082 eschrock "pool configuration"))); 150 789 ahrens } 151 789 ahrens } else { 152 2082 eschrock hdl->libzfs_ns_gen = zc.zc_cookie; 153 789 ahrens break; 154 789 ahrens } 155 789 ahrens } 156 789 ahrens 157 2676 eschrock if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 158 2676 eschrock zcmd_free_nvlists(&zc); 159 2676 eschrock return (-1); 160 2142 eschrock } 161 789 ahrens 162 2676 eschrock zcmd_free_nvlists(&zc); 163 789 ahrens 164 789 ahrens /* 165 789 ahrens * Clear out any existing configuration information. 166 789 ahrens */ 167 4074 eschrock cookie = NULL; 168 4074 eschrock while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) { 169 789 ahrens nvlist_free(cn->cn_config); 170 789 ahrens free(cn->cn_name); 171 789 ahrens free(cn); 172 789 ahrens } 173 789 ahrens 174 789 ahrens elem = NULL; 175 789 ahrens while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { 176 789 ahrens nvlist_t *child; 177 789 ahrens uu_avl_index_t where; 178 789 ahrens 179 2082 eschrock if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) { 180 2082 eschrock nvlist_free(config); 181 2082 eschrock return (-1); 182 2082 eschrock } 183 2082 eschrock 184 2082 eschrock if ((cn->cn_name = zfs_strdup(hdl, 185 2082 eschrock nvpair_name(elem))) == NULL) { 186 2082 eschrock free(cn); 187 2474 eschrock nvlist_free(config); 188 2082 eschrock return (-1); 189 2082 eschrock } 190 789 ahrens 191 789 ahrens verify(nvpair_value_nvlist(elem, &child) == 0); 192 2082 eschrock if (nvlist_dup(child, &cn->cn_config, 0) != 0) { 193 2474 eschrock free(cn->cn_name); 194 2474 eschrock free(cn); 195 2082 eschrock nvlist_free(config); 196 2082 eschrock return (no_memory(hdl)); 197 2082 eschrock } 198 2082 eschrock verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) 199 2082 eschrock == NULL); 200 789 ahrens 201 2082 eschrock uu_avl_insert(hdl->libzfs_ns_avl, cn, where); 202 789 ahrens } 203 789 ahrens 204 789 ahrens nvlist_free(config); 205 2082 eschrock return (0); 206 789 ahrens } 207 789 ahrens 208 789 ahrens /* 209 4074 eschrock * Retrieve the configuration for the given pool. The configuration is a nvlist 210 789 ahrens * describing the vdevs, as well as the statistics associated with each one. 211 789 ahrens */ 212 789 ahrens nvlist_t * 213 952 eschrock zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig) 214 789 ahrens { 215 952 eschrock if (oldconfig) 216 952 eschrock *oldconfig = zhp->zpool_old_config; 217 789 ahrens return (zhp->zpool_config); 218 789 ahrens } 219 789 ahrens 220 789 ahrens /* 221 789 ahrens * Refresh the vdev statistics associated with the given pool. This is used in 222 789 ahrens * iostat to show configuration changes and determine the delta from the last 223 789 ahrens * time the function was called. This function can fail, in case the pool has 224 789 ahrens * been destroyed. 225 789 ahrens */ 226 789 ahrens int 227 2142 eschrock zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) 228 789 ahrens { 229 789 ahrens zfs_cmd_t zc = { 0 }; 230 789 ahrens int error; 231 952 eschrock nvlist_t *config; 232 2676 eschrock libzfs_handle_t *hdl = zhp->zpool_hdl; 233 789 ahrens 234 2142 eschrock *missing = B_FALSE; 235 789 ahrens (void) strcpy(zc.zc_name, zhp->zpool_name); 236 789 ahrens 237 789 ahrens if (zhp->zpool_config_size == 0) 238 789 ahrens zhp->zpool_config_size = 1 << 16; 239 789 ahrens 240 2676 eschrock if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size) != 0) 241 2082 eschrock return (-1); 242 789 ahrens 243 1544 eschrock for (;;) { 244 2082 eschrock if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_STATS, 245 2082 eschrock &zc) == 0) { 246 789 ahrens /* 247 1544 eschrock * The real error is returned in the zc_cookie field. 248 789 ahrens */ 249 2142 eschrock error = zc.zc_cookie; 250 789 ahrens break; 251 789 ahrens } 252 789 ahrens 253 1544 eschrock if (errno == ENOMEM) { 254 2676 eschrock if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 255 2676 eschrock zcmd_free_nvlists(&zc); 256 2082 eschrock return (-1); 257 2676 eschrock } 258 1544 eschrock } else { 259 2676 eschrock zcmd_free_nvlists(&zc); 260 2142 eschrock if (errno == ENOENT || errno == EINVAL) 261 2142 eschrock *missing = B_TRUE; 262 2142 eschrock zhp->zpool_state = POOL_STATE_UNAVAIL; 263 2142 eschrock return (0); 264 789 ahrens } 265 789 ahrens } 266 789 ahrens 267 2676 eschrock if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { 268 2676 eschrock zcmd_free_nvlists(&zc); 269 2676 eschrock return (-1); 270 2082 eschrock } 271 789 ahrens 272 2676 eschrock zcmd_free_nvlists(&zc); 273 2676 eschrock 274 2676 eschrock zhp->zpool_config_size = zc.zc_nvlist_dst_size; 275 789 ahrens 276 952 eschrock if (zhp->zpool_config != NULL) { 277 952 eschrock uint64_t oldtxg, newtxg; 278 789 ahrens 279 952 eschrock verify(nvlist_lookup_uint64(zhp->zpool_config, 280 952 eschrock ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0); 281 952 eschrock verify(nvlist_lookup_uint64(config, 282 952 eschrock ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0); 283 952 eschrock 284 952 eschrock if (zhp->zpool_old_config != NULL) 285 952 eschrock nvlist_free(zhp->zpool_old_config); 286 952 eschrock 287 952 eschrock if (oldtxg != newtxg) { 288 952 eschrock nvlist_free(zhp->zpool_config); 289 952 eschrock zhp->zpool_old_config = NULL; 290 952 eschrock } else { 291 952 eschrock zhp->zpool_old_config = zhp->zpool_config; 292 952 eschrock } 293 952 eschrock } 294 952 eschrock 295 952 eschrock zhp->zpool_config = config; 296 2142 eschrock if (error) 297 2142 eschrock zhp->zpool_state = POOL_STATE_UNAVAIL; 298 2142 eschrock else 299 2142 eschrock zhp->zpool_state = POOL_STATE_ACTIVE; 300 789 ahrens 301 2142 eschrock return (0); 302 789 ahrens } 303 789 ahrens 304 789 ahrens /* 305 789 ahrens * Iterate over all pools in the system. 306 789 ahrens */ 307 789 ahrens int 308 2082 eschrock zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) 309 789 ahrens { 310 789 ahrens config_node_t *cn; 311 789 ahrens zpool_handle_t *zhp; 312 789 ahrens int ret; 313 789 ahrens 314 10817 Eric /* 315 10817 Eric * If someone makes a recursive call to zpool_iter(), we want to avoid 316 10817 Eric * refreshing the namespace because that will invalidate the parent 317 10817 Eric * context. We allow recursive calls, but simply re-use the same 318 10817 Eric * namespace AVL tree. 319 10817 Eric */ 320 10817 Eric if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) 321 2082 eschrock return (-1); 322 789 ahrens 323 10817 Eric hdl->libzfs_pool_iter++; 324 2082 eschrock for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 325 2082 eschrock cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 326 789 ahrens 327 10817 Eric if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { 328 10817 Eric hdl->libzfs_pool_iter--; 329 2142 eschrock return (-1); 330 10817 Eric } 331 2142 eschrock 332 2142 eschrock if (zhp == NULL) 333 789 ahrens continue; 334 789 ahrens 335 10817 Eric if ((ret = func(zhp, data)) != 0) { 336 10817 Eric hdl->libzfs_pool_iter--; 337 789 ahrens return (ret); 338 10817 Eric } 339 789 ahrens } 340 10817 Eric hdl->libzfs_pool_iter--; 341 789 ahrens 342 789 ahrens return (0); 343 789 ahrens } 344 789 ahrens 345 789 ahrens /* 346 789 ahrens * Iterate over root datasets, calling the given function for each. The zfs 347 789 ahrens * handle passed each time must be explicitly closed by the callback. 348 789 ahrens */ 349 789 ahrens int 350 2082 eschrock zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) 351 789 ahrens { 352 789 ahrens config_node_t *cn; 353 789 ahrens zfs_handle_t *zhp; 354 789 ahrens int ret; 355 789 ahrens 356 2082 eschrock if (namespace_reload(hdl) != 0) 357 2082 eschrock return (-1); 358 789 ahrens 359 2082 eschrock for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 360 2082 eschrock cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 361 789 ahrens 362 2082 eschrock if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) 363 789 ahrens continue; 364 789 ahrens 365 789 ahrens if ((ret = func(zhp, data)) != 0) 366 789 ahrens return (ret); 367 789 ahrens } 368 789 ahrens 369 789 ahrens return (0); 370 789 ahrens } 371