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