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