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 nvlist_free(zhp->zpool_old_config); 323 324 if (oldtxg != newtxg) { 325 nvlist_free(zhp->zpool_config); 326 zhp->zpool_old_config = NULL; 327 } else { 328 zhp->zpool_old_config = zhp->zpool_config; 329 } 330 } 331 332 zhp->zpool_config = config; 333 if (error) 334 zhp->zpool_state = POOL_STATE_UNAVAIL; 335 else 336 zhp->zpool_state = POOL_STATE_ACTIVE; 337 338 return (0); 339 } 340 341 /* 342 * The following environment variables are undocumented 343 * and should be used for testing purposes only: 344 * 345 * __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists 346 * __ZFS_POOL_RESTRICT - iterate only over the pools it lists 347 * 348 * This function returns B_TRUE if the pool should be skipped 349 * during iteration. 350 */ 351 boolean_t 352 zpool_skip_pool(const char *poolname) 353 { 354 static boolean_t initialized = B_FALSE; 355 static const char *exclude = NULL; 356 static const char *restricted = NULL; 357 358 const char *cur, *end; 359 int len; 360 int namelen = strlen(poolname); 361 362 if (!initialized) { 363 initialized = B_TRUE; 364 exclude = getenv("__ZFS_POOL_EXCLUDE"); 365 restricted = getenv("__ZFS_POOL_RESTRICT"); 366 } 367 368 if (exclude != NULL) { 369 cur = exclude; 370 do { 371 end = strchr(cur, ' '); 372 len = (NULL == end) ? strlen(cur) : (end - cur); 373 if (len == namelen && 0 == strncmp(cur, poolname, len)) 374 return (B_TRUE); 375 cur += (len + 1); 376 } while (NULL != end); 377 } 378 379 if (NULL == restricted) 380 return (B_FALSE); 381 382 cur = restricted; 383 do { 384 end = strchr(cur, ' '); 385 len = (NULL == end) ? strlen(cur) : (end - cur); 386 387 if (len == namelen && 0 == strncmp(cur, poolname, len)) { 388 return (B_FALSE); 389 } 390 391 cur += (len + 1); 392 } while (NULL != end); 393 394 return (B_TRUE); 395 } 396 397 /* 398 * Iterate over all pools in the system. 399 */ 400 int 401 zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) 402 { 403 config_node_t *cn; 404 zpool_handle_t *zhp; 405 int ret; 406 407 /* 408 * If someone makes a recursive call to zpool_iter(), we want to avoid 409 * refreshing the namespace because that will invalidate the parent 410 * context. We allow recursive calls, but simply re-use the same 411 * namespace AVL tree. 412 */ 413 if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0) 414 return (-1); 415 416 hdl->libzfs_pool_iter++; 417 for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 418 cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 419 420 if (zpool_skip_pool(cn->cn_name)) 421 continue; 422 423 if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { 424 hdl->libzfs_pool_iter--; 425 return (-1); 426 } 427 428 if (zhp == NULL) 429 continue; 430 431 if ((ret = func(zhp, data)) != 0) { 432 hdl->libzfs_pool_iter--; 433 return (ret); 434 } 435 } 436 hdl->libzfs_pool_iter--; 437 438 return (0); 439 } 440 441 /* 442 * Iterate over root datasets, calling the given function for each. The zfs 443 * handle passed each time must be explicitly closed by the callback. 444 */ 445 int 446 zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) 447 { 448 config_node_t *cn; 449 zfs_handle_t *zhp; 450 int ret; 451 452 if (namespace_reload(hdl) != 0) 453 return (-1); 454 455 for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; 456 cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { 457 458 if (zpool_skip_pool(cn->cn_name)) 459 continue; 460 461 if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) 462 continue; 463 464 if ((ret = func(zhp, data)) != 0) 465 return (ret); 466 } 467 468 return (0); 469 } 470