zpool_main.c revision 339034
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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2011, 2018 by Delphix. All rights reserved. 25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved. 26 * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved. 28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>. 29 * Copyright 2016 Nexenta Systems, Inc. 30 * Copyright (c) 2017 Datto Inc. 31 */ 32 33#include <solaris.h> 34#include <assert.h> 35#include <ctype.h> 36#include <dirent.h> 37#include <errno.h> 38#include <fcntl.h> 39#include <getopt.h> 40#include <libgen.h> 41#include <libintl.h> 42#include <libuutil.h> 43#include <locale.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <strings.h> 48#include <unistd.h> 49#include <priv.h> 50#include <pwd.h> 51#include <zone.h> 52#include <sys/time.h> 53#include <zfs_prop.h> 54#include <sys/fs/zfs.h> 55#include <sys/stat.h> 56 57#include <libzfs.h> 58 59#include "zpool_util.h" 60#include "zfs_comutil.h" 61#include "zfeature_common.h" 62 63#include "statcommon.h" 64 65static int zpool_do_create(int, char **); 66static int zpool_do_destroy(int, char **); 67 68static int zpool_do_add(int, char **); 69static int zpool_do_remove(int, char **); 70static int zpool_do_labelclear(int, char **); 71 72static int zpool_do_checkpoint(int, char **); 73 74static int zpool_do_list(int, char **); 75static int zpool_do_iostat(int, char **); 76static int zpool_do_status(int, char **); 77 78static int zpool_do_online(int, char **); 79static int zpool_do_offline(int, char **); 80static int zpool_do_clear(int, char **); 81static int zpool_do_reopen(int, char **); 82 83static int zpool_do_reguid(int, char **); 84 85static int zpool_do_attach(int, char **); 86static int zpool_do_detach(int, char **); 87static int zpool_do_replace(int, char **); 88static int zpool_do_split(int, char **); 89 90static int zpool_do_scrub(int, char **); 91 92static int zpool_do_import(int, char **); 93static int zpool_do_export(int, char **); 94 95static int zpool_do_upgrade(int, char **); 96 97static int zpool_do_history(int, char **); 98 99static int zpool_do_get(int, char **); 100static int zpool_do_set(int, char **); 101 102/* 103 * These libumem hooks provide a reasonable set of defaults for the allocator's 104 * debugging facilities. 105 */ 106 107#ifdef DEBUG 108const char * 109_umem_debug_init(void) 110{ 111 return ("default,verbose"); /* $UMEM_DEBUG setting */ 112} 113 114const char * 115_umem_logging_init(void) 116{ 117 return ("fail,contents"); /* $UMEM_LOGGING setting */ 118} 119#endif 120 121typedef enum { 122 HELP_ADD, 123 HELP_ATTACH, 124 HELP_CLEAR, 125 HELP_CREATE, 126 HELP_CHECKPOINT, 127 HELP_DESTROY, 128 HELP_DETACH, 129 HELP_EXPORT, 130 HELP_HISTORY, 131 HELP_IMPORT, 132 HELP_IOSTAT, 133 HELP_LABELCLEAR, 134 HELP_LIST, 135 HELP_OFFLINE, 136 HELP_ONLINE, 137 HELP_REPLACE, 138 HELP_REMOVE, 139 HELP_SCRUB, 140 HELP_STATUS, 141 HELP_UPGRADE, 142 HELP_GET, 143 HELP_SET, 144 HELP_SPLIT, 145 HELP_REGUID, 146 HELP_REOPEN 147} zpool_help_t; 148 149 150typedef struct zpool_command { 151 const char *name; 152 int (*func)(int, char **); 153 zpool_help_t usage; 154} zpool_command_t; 155 156/* 157 * Master command table. Each ZFS command has a name, associated function, and 158 * usage message. The usage messages need to be internationalized, so we have 159 * to have a function to return the usage message based on a command index. 160 * 161 * These commands are organized according to how they are displayed in the usage 162 * message. An empty command (one with a NULL name) indicates an empty line in 163 * the generic usage message. 164 */ 165static zpool_command_t command_table[] = { 166 { "create", zpool_do_create, HELP_CREATE }, 167 { "destroy", zpool_do_destroy, HELP_DESTROY }, 168 { NULL }, 169 { "add", zpool_do_add, HELP_ADD }, 170 { "remove", zpool_do_remove, HELP_REMOVE }, 171 { NULL }, 172 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 173 { NULL }, 174 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 175 { NULL }, 176 { "list", zpool_do_list, HELP_LIST }, 177 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 178 { "status", zpool_do_status, HELP_STATUS }, 179 { NULL }, 180 { "online", zpool_do_online, HELP_ONLINE }, 181 { "offline", zpool_do_offline, HELP_OFFLINE }, 182 { "clear", zpool_do_clear, HELP_CLEAR }, 183 { "reopen", zpool_do_reopen, HELP_REOPEN }, 184 { NULL }, 185 { "attach", zpool_do_attach, HELP_ATTACH }, 186 { "detach", zpool_do_detach, HELP_DETACH }, 187 { "replace", zpool_do_replace, HELP_REPLACE }, 188 { "split", zpool_do_split, HELP_SPLIT }, 189 { NULL }, 190 { "scrub", zpool_do_scrub, HELP_SCRUB }, 191 { NULL }, 192 { "import", zpool_do_import, HELP_IMPORT }, 193 { "export", zpool_do_export, HELP_EXPORT }, 194 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 195 { "reguid", zpool_do_reguid, HELP_REGUID }, 196 { NULL }, 197 { "history", zpool_do_history, HELP_HISTORY }, 198 { "get", zpool_do_get, HELP_GET }, 199 { "set", zpool_do_set, HELP_SET }, 200}; 201 202#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 203 204static zpool_command_t *current_command; 205static char history_str[HIS_MAX_RECORD_LEN]; 206static boolean_t log_history = B_TRUE; 207static uint_t timestamp_fmt = NODATE; 208 209static const char * 210get_usage(zpool_help_t idx) 211{ 212 switch (idx) { 213 case HELP_ADD: 214 return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 215 case HELP_ATTACH: 216 return (gettext("\tattach [-f] <pool> <device> " 217 "<new-device>\n")); 218 case HELP_CLEAR: 219 return (gettext("\tclear [-nF] <pool> [device]\n")); 220 case HELP_CREATE: 221 return (gettext("\tcreate [-fnd] [-B] " 222 "[-o property=value] ... \n" 223 "\t [-O file-system-property=value] ...\n" 224 "\t [-m mountpoint] [-R root] [-t tempname] " 225 "<pool> <vdev> ...\n")); 226 case HELP_CHECKPOINT: 227 return (gettext("\tcheckpoint [--discard] <pool> ...\n")); 228 case HELP_DESTROY: 229 return (gettext("\tdestroy [-f] <pool>\n")); 230 case HELP_DETACH: 231 return (gettext("\tdetach <pool> <device>\n")); 232 case HELP_EXPORT: 233 return (gettext("\texport [-f] <pool> ...\n")); 234 case HELP_HISTORY: 235 return (gettext("\thistory [-il] [<pool>] ...\n")); 236 case HELP_IMPORT: 237 return (gettext("\timport [-d dir] [-D]\n" 238 "\timport [-o mntopts] [-o property=value] ... \n" 239 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 240 "[-R root] [-F [-n]] -a\n" 241 "\timport [-o mntopts] [-o property=value] ... \n" 242 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 243 "[-R root] [-F [-n]] [-t]\n" 244 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 245 case HELP_IOSTAT: 246 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " 247 "[count]]\n")); 248 case HELP_LABELCLEAR: 249 return (gettext("\tlabelclear [-f] <vdev>\n")); 250 case HELP_LIST: 251 return (gettext("\tlist [-Hpv] [-o property[,...]] " 252 "[-T d|u] [pool] ... [interval [count]]\n")); 253 case HELP_OFFLINE: 254 return (gettext("\toffline [-t] <pool> <device> ...\n")); 255 case HELP_ONLINE: 256 return (gettext("\tonline [-e] <pool> <device> ...\n")); 257 case HELP_REPLACE: 258 return (gettext("\treplace [-f] <pool> <device> " 259 "[new-device]\n")); 260 case HELP_REMOVE: 261 return (gettext("\tremove [-nps] <pool> <device> ...\n")); 262 case HELP_REOPEN: 263 return (gettext("\treopen <pool>\n")); 264 case HELP_SCRUB: 265 return (gettext("\tscrub [-s | -p] <pool> ...\n")); 266 case HELP_STATUS: 267 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval " 268 "[count]]\n")); 269 case HELP_UPGRADE: 270 return (gettext("\tupgrade [-v]\n" 271 "\tupgrade [-V version] <-a | pool ...>\n")); 272 case HELP_GET: 273 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 274 "<\"all\" | property[,...]> <pool> ...\n")); 275 case HELP_SET: 276 return (gettext("\tset <property=value> <pool> \n")); 277 case HELP_SPLIT: 278 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" 279 "\t [-o property=value] <pool> <newpool> " 280 "[<device> ...]\n")); 281 case HELP_REGUID: 282 return (gettext("\treguid <pool>\n")); 283 } 284 285 abort(); 286 /* NOTREACHED */ 287} 288 289 290/* 291 * Callback routine that will print out a pool property value. 292 */ 293static int 294print_prop_cb(int prop, void *cb) 295{ 296 FILE *fp = cb; 297 298 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop)); 299 300 if (zpool_prop_readonly(prop)) 301 (void) fprintf(fp, " NO "); 302 else 303 (void) fprintf(fp, " YES "); 304 305 if (zpool_prop_values(prop) == NULL) 306 (void) fprintf(fp, "-\n"); 307 else 308 (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 309 310 return (ZPROP_CONT); 311} 312 313/* 314 * Display usage message. If we're inside a command, display only the usage for 315 * that command. Otherwise, iterate over the entire command table and display 316 * a complete usage message. 317 */ 318void 319usage(boolean_t requested) 320{ 321 FILE *fp = requested ? stdout : stderr; 322 323 if (current_command == NULL) { 324 int i; 325 326 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 327 (void) fprintf(fp, 328 gettext("where 'command' is one of the following:\n\n")); 329 330 for (i = 0; i < NCOMMAND; i++) { 331 if (command_table[i].name == NULL) 332 (void) fprintf(fp, "\n"); 333 else 334 (void) fprintf(fp, "%s", 335 get_usage(command_table[i].usage)); 336 } 337 } else { 338 (void) fprintf(fp, gettext("usage:\n")); 339 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 340 } 341 342 if (current_command != NULL && 343 ((strcmp(current_command->name, "set") == 0) || 344 (strcmp(current_command->name, "get") == 0) || 345 (strcmp(current_command->name, "list") == 0))) { 346 347 (void) fprintf(fp, 348 gettext("\nthe following properties are supported:\n")); 349 350 (void) fprintf(fp, "\n\t%-15s %s %s\n\n", 351 "PROPERTY", "EDIT", "VALUES"); 352 353 /* Iterate over all properties */ 354 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 355 ZFS_TYPE_POOL); 356 357 (void) fprintf(fp, "\t%-15s ", "feature@..."); 358 (void) fprintf(fp, "YES disabled | enabled | active\n"); 359 360 (void) fprintf(fp, gettext("\nThe feature@ properties must be " 361 "appended with a feature name.\nSee zpool-features(7).\n")); 362 } 363 364 /* 365 * See comments at end of main(). 366 */ 367 if (getenv("ZFS_ABORT") != NULL) { 368 (void) printf("dumping core by request\n"); 369 abort(); 370 } 371 372 exit(requested ? 0 : 2); 373} 374 375void 376print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 377 boolean_t print_logs) 378{ 379 nvlist_t **child; 380 uint_t c, children; 381 char *vname; 382 383 if (name != NULL) 384 (void) printf("\t%*s%s\n", indent, "", name); 385 386 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 387 &child, &children) != 0) 388 return; 389 390 for (c = 0; c < children; c++) { 391 uint64_t is_log = B_FALSE; 392 393 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 394 &is_log); 395 if ((is_log && !print_logs) || (!is_log && print_logs)) 396 continue; 397 398 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 399 print_vdev_tree(zhp, vname, child[c], indent + 2, 400 B_FALSE); 401 free(vname); 402 } 403} 404 405static boolean_t 406prop_list_contains_feature(nvlist_t *proplist) 407{ 408 nvpair_t *nvp; 409 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 410 nvp = nvlist_next_nvpair(proplist, nvp)) { 411 if (zpool_prop_feature(nvpair_name(nvp))) 412 return (B_TRUE); 413 } 414 return (B_FALSE); 415} 416 417/* 418 * Add a property pair (name, string-value) into a property nvlist. 419 */ 420static int 421add_prop_list(const char *propname, char *propval, nvlist_t **props, 422 boolean_t poolprop) 423{ 424 zpool_prop_t prop = ZPROP_INVAL; 425 zfs_prop_t fprop; 426 nvlist_t *proplist; 427 const char *normnm; 428 char *strval; 429 430 if (*props == NULL && 431 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 432 (void) fprintf(stderr, 433 gettext("internal error: out of memory\n")); 434 return (1); 435 } 436 437 proplist = *props; 438 439 if (poolprop) { 440 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 441 442 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL && 443 !zpool_prop_feature(propname)) { 444 (void) fprintf(stderr, gettext("property '%s' is " 445 "not a valid pool property\n"), propname); 446 return (2); 447 } 448 449 /* 450 * feature@ properties and version should not be specified 451 * at the same time. 452 */ 453 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 454 nvlist_exists(proplist, vname)) || 455 (prop == ZPOOL_PROP_VERSION && 456 prop_list_contains_feature(proplist))) { 457 (void) fprintf(stderr, gettext("'feature@' and " 458 "'version' properties cannot be specified " 459 "together\n")); 460 return (2); 461 } 462 463 464 if (zpool_prop_feature(propname)) 465 normnm = propname; 466 else 467 normnm = zpool_prop_to_name(prop); 468 } else { 469 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 470 normnm = zfs_prop_to_name(fprop); 471 } else { 472 normnm = propname; 473 } 474 } 475 476 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 477 prop != ZPOOL_PROP_CACHEFILE) { 478 (void) fprintf(stderr, gettext("property '%s' " 479 "specified multiple times\n"), propname); 480 return (2); 481 } 482 483 if (nvlist_add_string(proplist, normnm, propval) != 0) { 484 (void) fprintf(stderr, gettext("internal " 485 "error: out of memory\n")); 486 return (1); 487 } 488 489 return (0); 490} 491 492/* 493 * Set a default property pair (name, string-value) in a property nvlist 494 */ 495static int 496add_prop_list_default(const char *propname, char *propval, nvlist_t **props, 497 boolean_t poolprop) 498{ 499 char *pval; 500 501 if (nvlist_lookup_string(*props, propname, &pval) == 0) 502 return (0); 503 504 return (add_prop_list(propname, propval, props, poolprop)); 505} 506 507/* 508 * zpool add [-fn] <pool> <vdev> ... 509 * 510 * -f Force addition of devices, even if they appear in use 511 * -n Do not add the devices, but display the resulting layout if 512 * they were to be added. 513 * 514 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 515 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 516 * libzfs. 517 */ 518int 519zpool_do_add(int argc, char **argv) 520{ 521 boolean_t force = B_FALSE; 522 boolean_t dryrun = B_FALSE; 523 int c; 524 nvlist_t *nvroot; 525 char *poolname; 526 zpool_boot_label_t boot_type; 527 uint64_t boot_size; 528 int ret; 529 zpool_handle_t *zhp; 530 nvlist_t *config; 531 532 /* check options */ 533 while ((c = getopt(argc, argv, "fn")) != -1) { 534 switch (c) { 535 case 'f': 536 force = B_TRUE; 537 break; 538 case 'n': 539 dryrun = B_TRUE; 540 break; 541 case '?': 542 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 543 optopt); 544 usage(B_FALSE); 545 } 546 } 547 548 argc -= optind; 549 argv += optind; 550 551 /* get pool name and check number of arguments */ 552 if (argc < 1) { 553 (void) fprintf(stderr, gettext("missing pool name argument\n")); 554 usage(B_FALSE); 555 } 556 if (argc < 2) { 557 (void) fprintf(stderr, gettext("missing vdev specification\n")); 558 usage(B_FALSE); 559 } 560 561 poolname = argv[0]; 562 563 argc--; 564 argv++; 565 566 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 567 return (1); 568 569 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 570 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 571 poolname); 572 zpool_close(zhp); 573 return (1); 574 } 575 576 if (zpool_is_bootable(zhp)) 577 boot_type = ZPOOL_COPY_BOOT_LABEL; 578 else 579 boot_type = ZPOOL_NO_BOOT_LABEL; 580 581 /* pass off to get_vdev_spec for processing */ 582 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 583 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 584 boot_type, boot_size, argc, argv); 585 if (nvroot == NULL) { 586 zpool_close(zhp); 587 return (1); 588 } 589 590 if (dryrun) { 591 nvlist_t *poolnvroot; 592 593 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 594 &poolnvroot) == 0); 595 596 (void) printf(gettext("would update '%s' to the following " 597 "configuration:\n"), zpool_get_name(zhp)); 598 599 /* print original main pool and new tree */ 600 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 601 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 602 603 /* Do the same for the logs */ 604 if (num_logs(poolnvroot) > 0) { 605 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 606 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 607 } else if (num_logs(nvroot) > 0) { 608 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 609 } 610 611 ret = 0; 612 } else { 613 ret = (zpool_add(zhp, nvroot) != 0); 614 } 615 616 nvlist_free(nvroot); 617 zpool_close(zhp); 618 619 return (ret); 620} 621 622/* 623 * zpool remove <pool> <vdev> ... 624 * 625 * Removes the given vdev from the pool. 626 */ 627int 628zpool_do_remove(int argc, char **argv) 629{ 630 char *poolname; 631 int i, ret = 0; 632 zpool_handle_t *zhp; 633 boolean_t stop = B_FALSE; 634 boolean_t noop = B_FALSE; 635 boolean_t parsable = B_FALSE; 636 char c; 637 638 /* check options */ 639 while ((c = getopt(argc, argv, "nps")) != -1) { 640 switch (c) { 641 case 'n': 642 noop = B_TRUE; 643 break; 644 case 'p': 645 parsable = B_TRUE; 646 break; 647 case 's': 648 stop = B_TRUE; 649 break; 650 case '?': 651 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 652 optopt); 653 usage(B_FALSE); 654 } 655 } 656 657 argc -= optind; 658 argv += optind; 659 660 /* get pool name and check number of arguments */ 661 if (argc < 1) { 662 (void) fprintf(stderr, gettext("missing pool name argument\n")); 663 usage(B_FALSE); 664 } 665 666 poolname = argv[0]; 667 668 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 669 return (1); 670 671 if (stop && noop) { 672 (void) fprintf(stderr, gettext("stop request ignored\n")); 673 return (0); 674 } 675 676 if (stop) { 677 if (argc > 1) { 678 (void) fprintf(stderr, gettext("too many arguments\n")); 679 usage(B_FALSE); 680 } 681 if (zpool_vdev_remove_cancel(zhp) != 0) 682 ret = 1; 683 } else { 684 if (argc < 2) { 685 (void) fprintf(stderr, gettext("missing device\n")); 686 usage(B_FALSE); 687 } 688 689 for (i = 1; i < argc; i++) { 690 if (noop) { 691 uint64_t size; 692 693 if (zpool_vdev_indirect_size(zhp, argv[i], 694 &size) != 0) { 695 ret = 1; 696 break; 697 } 698 if (parsable) { 699 (void) printf("%s %llu\n", 700 argv[i], size); 701 } else { 702 char valstr[32]; 703 zfs_nicenum(size, valstr, 704 sizeof (valstr)); 705 (void) printf("Memory that will be " 706 "used after removing %s: %s\n", 707 argv[i], valstr); 708 } 709 } else { 710 if (zpool_vdev_remove(zhp, argv[i]) != 0) 711 ret = 1; 712 } 713 } 714 } 715 716 return (ret); 717} 718 719/* 720 * zpool labelclear [-f] <vdev> 721 * 722 * -f Force clearing the label for the vdevs which are members of 723 * the exported or foreign pools. 724 * 725 * Verifies that the vdev is not active and zeros out the label information 726 * on the device. 727 */ 728int 729zpool_do_labelclear(int argc, char **argv) 730{ 731 char vdev[MAXPATHLEN]; 732 char *name = NULL; 733 struct stat st; 734 int c, fd, ret = 0; 735 nvlist_t *config; 736 pool_state_t state; 737 boolean_t inuse = B_FALSE; 738 boolean_t force = B_FALSE; 739 740 /* check options */ 741 while ((c = getopt(argc, argv, "f")) != -1) { 742 switch (c) { 743 case 'f': 744 force = B_TRUE; 745 break; 746 default: 747 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 748 optopt); 749 usage(B_FALSE); 750 } 751 } 752 753 argc -= optind; 754 argv += optind; 755 756 /* get vdev name */ 757 if (argc < 1) { 758 (void) fprintf(stderr, gettext("missing vdev name\n")); 759 usage(B_FALSE); 760 } 761 if (argc > 1) { 762 (void) fprintf(stderr, gettext("too many arguments\n")); 763 usage(B_FALSE); 764 } 765 766 /* 767 * Check if we were given absolute path and use it as is. 768 * Otherwise if the provided vdev name doesn't point to a file, 769 * try prepending dsk path and appending s0. 770 */ 771 (void) strlcpy(vdev, argv[0], sizeof (vdev)); 772 if (vdev[0] != '/' && stat(vdev, &st) != 0) { 773 char *s; 774 775 (void) snprintf(vdev, sizeof (vdev), "%s/%s", 776#ifdef illumos 777 ZFS_DISK_ROOT, argv[0]); 778 if ((s = strrchr(argv[0], 's')) == NULL || 779 !isdigit(*(s + 1))) 780 (void) strlcat(vdev, "s0", sizeof (vdev)); 781#else 782 "/dev", argv[0]); 783#endif 784 if (stat(vdev, &st) != 0) { 785 (void) fprintf(stderr, gettext( 786 "failed to find device %s, try specifying absolute " 787 "path instead\n"), argv[0]); 788 return (1); 789 } 790 } 791 792 if ((fd = open(vdev, O_RDWR)) < 0) { 793 (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 794 vdev, strerror(errno)); 795 return (1); 796 } 797 798 if (zpool_read_label(fd, &config) != 0) { 799 (void) fprintf(stderr, 800 gettext("failed to read label from %s\n"), vdev); 801 return (1); 802 } 803 nvlist_free(config); 804 805 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 806 if (ret != 0) { 807 (void) fprintf(stderr, 808 gettext("failed to check state for %s\n"), vdev); 809 return (1); 810 } 811 812 if (!inuse) 813 goto wipe_label; 814 815 switch (state) { 816 default: 817 case POOL_STATE_ACTIVE: 818 case POOL_STATE_SPARE: 819 case POOL_STATE_L2CACHE: 820 (void) fprintf(stderr, gettext( 821 "%s is a member (%s) of pool \"%s\"\n"), 822 vdev, zpool_pool_state_to_name(state), name); 823 ret = 1; 824 goto errout; 825 826 case POOL_STATE_EXPORTED: 827 if (force) 828 break; 829 (void) fprintf(stderr, gettext( 830 "use '-f' to override the following error:\n" 831 "%s is a member of exported pool \"%s\"\n"), 832 vdev, name); 833 ret = 1; 834 goto errout; 835 836 case POOL_STATE_POTENTIALLY_ACTIVE: 837 if (force) 838 break; 839 (void) fprintf(stderr, gettext( 840 "use '-f' to override the following error:\n" 841 "%s is a member of potentially active pool \"%s\"\n"), 842 vdev, name); 843 ret = 1; 844 goto errout; 845 846 case POOL_STATE_DESTROYED: 847 /* inuse should never be set for a destroyed pool */ 848 assert(0); 849 break; 850 } 851 852wipe_label: 853 ret = zpool_clear_label(fd); 854 if (ret != 0) { 855 (void) fprintf(stderr, 856 gettext("failed to clear label for %s\n"), vdev); 857 } 858 859errout: 860 free(name); 861 (void) close(fd); 862 863 return (ret); 864} 865 866/* 867 * zpool create [-fnd] [-B] [-o property=value] ... 868 * [-O file-system-property=value] ... 869 * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ... 870 * 871 * -B Create boot partition. 872 * -f Force creation, even if devices appear in use 873 * -n Do not create the pool, but display the resulting layout if it 874 * were to be created. 875 * -R Create a pool under an alternate root 876 * -m Set default mountpoint for the root dataset. By default it's 877 * '/<pool>' 878 * -t Use the temporary name until the pool is exported. 879 * -o Set property=value. 880 * -d Don't automatically enable all supported pool features 881 * (individual features can be enabled with -o). 882 * -O Set fsproperty=value in the pool's root file system 883 * 884 * Creates the named pool according to the given vdev specification. The 885 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 886 * we get the nvlist back from get_vdev_spec(), we either print out the contents 887 * (if '-n' was specified), or pass it to libzfs to do the creation. 888 */ 889 890#define SYSTEM256 (256 * 1024 * 1024) 891int 892zpool_do_create(int argc, char **argv) 893{ 894 boolean_t force = B_FALSE; 895 boolean_t dryrun = B_FALSE; 896 boolean_t enable_all_pool_feat = B_TRUE; 897 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 898 uint64_t boot_size = 0; 899 int c; 900 nvlist_t *nvroot = NULL; 901 char *poolname; 902 char *tname = NULL; 903 int ret = 1; 904 char *altroot = NULL; 905 char *mountpoint = NULL; 906 nvlist_t *fsprops = NULL; 907 nvlist_t *props = NULL; 908 char *propval; 909 910 /* check options */ 911 while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) { 912 switch (c) { 913 case 'f': 914 force = B_TRUE; 915 break; 916 case 'n': 917 dryrun = B_TRUE; 918 break; 919 case 'd': 920 enable_all_pool_feat = B_FALSE; 921 break; 922 case 'B': 923#ifdef illumos 924 /* 925 * We should create the system partition. 926 * Also make sure the size is set. 927 */ 928 boot_type = ZPOOL_CREATE_BOOT_LABEL; 929 if (boot_size == 0) 930 boot_size = SYSTEM256; 931 break; 932#else 933 (void) fprintf(stderr, 934 gettext("option '%c' is not supported\n"), 935 optopt); 936 goto badusage; 937#endif 938 case 'R': 939 altroot = optarg; 940 if (add_prop_list(zpool_prop_to_name( 941 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 942 goto errout; 943 if (add_prop_list_default(zpool_prop_to_name( 944 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 945 goto errout; 946 break; 947 case 'm': 948 /* Equivalent to -O mountpoint=optarg */ 949 mountpoint = optarg; 950 break; 951 case 'o': 952 if ((propval = strchr(optarg, '=')) == NULL) { 953 (void) fprintf(stderr, gettext("missing " 954 "'=' for -o option\n")); 955 goto errout; 956 } 957 *propval = '\0'; 958 propval++; 959 960 if (add_prop_list(optarg, propval, &props, B_TRUE)) 961 goto errout; 962 963 /* 964 * Get bootsize value for make_root_vdev(). 965 */ 966 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 967 if (zfs_nicestrtonum(g_zfs, propval, 968 &boot_size) < 0 || boot_size == 0) { 969 (void) fprintf(stderr, 970 gettext("bad boot partition size " 971 "'%s': %s\n"), propval, 972 libzfs_error_description(g_zfs)); 973 goto errout; 974 } 975 } 976 977 /* 978 * If the user is creating a pool that doesn't support 979 * feature flags, don't enable any features. 980 */ 981 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 982 char *end; 983 u_longlong_t ver; 984 985 ver = strtoull(propval, &end, 10); 986 if (*end == '\0' && 987 ver < SPA_VERSION_FEATURES) { 988 enable_all_pool_feat = B_FALSE; 989 } 990 } 991 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 992 altroot = propval; 993 break; 994 case 'O': 995 if ((propval = strchr(optarg, '=')) == NULL) { 996 (void) fprintf(stderr, gettext("missing " 997 "'=' for -O option\n")); 998 goto errout; 999 } 1000 *propval = '\0'; 1001 propval++; 1002 1003 /* 1004 * Mountpoints are checked and then added later. 1005 * Uniquely among properties, they can be specified 1006 * more than once, to avoid conflict with -m. 1007 */ 1008 if (0 == strcmp(optarg, 1009 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 1010 mountpoint = propval; 1011 } else if (add_prop_list(optarg, propval, &fsprops, 1012 B_FALSE)) { 1013 goto errout; 1014 } 1015 break; 1016 case 't': 1017 /* 1018 * Sanity check temporary pool name. 1019 */ 1020 if (strchr(optarg, '/') != NULL) { 1021 (void) fprintf(stderr, gettext("cannot create " 1022 "'%s': invalid character '/' in temporary " 1023 "name\n"), optarg); 1024 (void) fprintf(stderr, gettext("use 'zfs " 1025 "create' to create a dataset\n")); 1026 goto errout; 1027 } 1028 1029 if (add_prop_list(zpool_prop_to_name( 1030 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE)) 1031 goto errout; 1032 if (add_prop_list_default(zpool_prop_to_name( 1033 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1034 goto errout; 1035 tname = optarg; 1036 break; 1037 case ':': 1038 (void) fprintf(stderr, gettext("missing argument for " 1039 "'%c' option\n"), optopt); 1040 goto badusage; 1041 case '?': 1042 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1043 optopt); 1044 goto badusage; 1045 } 1046 } 1047 1048 argc -= optind; 1049 argv += optind; 1050 1051 /* get pool name and check number of arguments */ 1052 if (argc < 1) { 1053 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1054 goto badusage; 1055 } 1056 if (argc < 2) { 1057 (void) fprintf(stderr, gettext("missing vdev specification\n")); 1058 goto badusage; 1059 } 1060 1061 poolname = argv[0]; 1062 1063 /* 1064 * As a special case, check for use of '/' in the name, and direct the 1065 * user to use 'zfs create' instead. 1066 */ 1067 if (strchr(poolname, '/') != NULL) { 1068 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1069 "character '/' in pool name\n"), poolname); 1070 (void) fprintf(stderr, gettext("use 'zfs create' to " 1071 "create a dataset\n")); 1072 goto errout; 1073 } 1074 1075 /* 1076 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 1077 * and not set otherwise. 1078 */ 1079 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 1080 const char *propname; 1081 char *strptr, *buf = NULL; 1082 int rv; 1083 1084 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 1085 if (nvlist_lookup_string(props, propname, &strptr) != 0) { 1086 (void) asprintf(&buf, "%" PRIu64, boot_size); 1087 if (buf == NULL) { 1088 (void) fprintf(stderr, 1089 gettext("internal error: out of memory\n")); 1090 goto errout; 1091 } 1092 rv = add_prop_list(propname, buf, &props, B_TRUE); 1093 free(buf); 1094 if (rv != 0) 1095 goto errout; 1096 } 1097 } else { 1098 const char *propname; 1099 char *strptr; 1100 1101 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 1102 if (nvlist_lookup_string(props, propname, &strptr) == 0) { 1103 (void) fprintf(stderr, gettext("error: setting boot " 1104 "partition size requires option '-B'\n")); 1105 goto errout; 1106 } 1107 } 1108 1109 /* pass off to get_vdev_spec for bulk processing */ 1110 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 1111 boot_type, boot_size, argc - 1, argv + 1); 1112 if (nvroot == NULL) 1113 goto errout; 1114 1115 /* make_root_vdev() allows 0 toplevel children if there are spares */ 1116 if (!zfs_allocatable_devs(nvroot)) { 1117 (void) fprintf(stderr, gettext("invalid vdev " 1118 "specification: at least one toplevel vdev must be " 1119 "specified\n")); 1120 goto errout; 1121 } 1122 1123 if (altroot != NULL && altroot[0] != '/') { 1124 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1125 "must be an absolute path\n"), altroot); 1126 goto errout; 1127 } 1128 1129 /* 1130 * Check the validity of the mountpoint and direct the user to use the 1131 * '-m' mountpoint option if it looks like its in use. 1132 * Ignore the checks if the '-f' option is given. 1133 */ 1134 if (!force && (mountpoint == NULL || 1135 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1136 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) { 1137 char buf[MAXPATHLEN]; 1138 DIR *dirp; 1139 1140 if (mountpoint && mountpoint[0] != '/') { 1141 (void) fprintf(stderr, gettext("invalid mountpoint " 1142 "'%s': must be an absolute path, 'legacy', or " 1143 "'none'\n"), mountpoint); 1144 goto errout; 1145 } 1146 1147 if (mountpoint == NULL) { 1148 if (altroot != NULL) 1149 (void) snprintf(buf, sizeof (buf), "%s/%s", 1150 altroot, poolname); 1151 else 1152 (void) snprintf(buf, sizeof (buf), "/%s", 1153 poolname); 1154 } else { 1155 if (altroot != NULL) 1156 (void) snprintf(buf, sizeof (buf), "%s%s", 1157 altroot, mountpoint); 1158 else 1159 (void) snprintf(buf, sizeof (buf), "%s", 1160 mountpoint); 1161 } 1162 1163 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 1164 (void) fprintf(stderr, gettext("mountpoint '%s' : " 1165 "%s\n"), buf, strerror(errno)); 1166 (void) fprintf(stderr, gettext("use '-m' " 1167 "option to provide a different default\n")); 1168 goto errout; 1169 } else if (dirp) { 1170 int count = 0; 1171 1172 while (count < 3 && readdir(dirp) != NULL) 1173 count++; 1174 (void) closedir(dirp); 1175 1176 if (count > 2) { 1177 (void) fprintf(stderr, gettext("mountpoint " 1178 "'%s' exists and is not empty\n"), buf); 1179 (void) fprintf(stderr, gettext("use '-m' " 1180 "option to provide a " 1181 "different default\n")); 1182 goto errout; 1183 } 1184 } 1185 } 1186 1187 /* 1188 * Now that the mountpoint's validity has been checked, ensure that 1189 * the property is set appropriately prior to creating the pool. 1190 */ 1191 if (mountpoint != NULL) { 1192 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1193 mountpoint, &fsprops, B_FALSE); 1194 if (ret != 0) 1195 goto errout; 1196 } 1197 1198 ret = 1; 1199 if (dryrun) { 1200 /* 1201 * For a dry run invocation, print out a basic message and run 1202 * through all the vdevs in the list and print out in an 1203 * appropriate hierarchy. 1204 */ 1205 (void) printf(gettext("would create '%s' with the " 1206 "following layout:\n\n"), poolname); 1207 1208 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 1209 if (num_logs(nvroot) > 0) 1210 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 1211 1212 ret = 0; 1213 } else { 1214 /* 1215 * Hand off to libzfs. 1216 */ 1217 if (enable_all_pool_feat) { 1218 spa_feature_t i; 1219 for (i = 0; i < SPA_FEATURES; i++) { 1220 char propname[MAXPATHLEN]; 1221 zfeature_info_t *feat = &spa_feature_table[i]; 1222 1223 (void) snprintf(propname, sizeof (propname), 1224 "feature@%s", feat->fi_uname); 1225 1226 /* 1227 * Skip feature if user specified it manually 1228 * on the command line. 1229 */ 1230 if (nvlist_exists(props, propname)) 1231 continue; 1232 1233 ret = add_prop_list(propname, 1234 ZFS_FEATURE_ENABLED, &props, B_TRUE); 1235 if (ret != 0) 1236 goto errout; 1237 } 1238 } 1239 1240 ret = 1; 1241 if (zpool_create(g_zfs, poolname, 1242 nvroot, props, fsprops) == 0) { 1243 zfs_handle_t *pool = zfs_open(g_zfs, 1244 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM); 1245 if (pool != NULL) { 1246 if (zfs_mount(pool, NULL, 0) == 0) 1247 ret = zfs_shareall(pool); 1248 zfs_close(pool); 1249 } 1250 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 1251 (void) fprintf(stderr, gettext("pool name may have " 1252 "been omitted\n")); 1253 } 1254 } 1255 1256errout: 1257 nvlist_free(nvroot); 1258 nvlist_free(fsprops); 1259 nvlist_free(props); 1260 return (ret); 1261badusage: 1262 nvlist_free(fsprops); 1263 nvlist_free(props); 1264 usage(B_FALSE); 1265 return (2); 1266} 1267 1268/* 1269 * zpool destroy <pool> 1270 * 1271 * -f Forcefully unmount any datasets 1272 * 1273 * Destroy the given pool. Automatically unmounts any datasets in the pool. 1274 */ 1275int 1276zpool_do_destroy(int argc, char **argv) 1277{ 1278 boolean_t force = B_FALSE; 1279 int c; 1280 char *pool; 1281 zpool_handle_t *zhp; 1282 int ret; 1283 1284 /* check options */ 1285 while ((c = getopt(argc, argv, "f")) != -1) { 1286 switch (c) { 1287 case 'f': 1288 force = B_TRUE; 1289 break; 1290 case '?': 1291 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1292 optopt); 1293 usage(B_FALSE); 1294 } 1295 } 1296 1297 argc -= optind; 1298 argv += optind; 1299 1300 /* check arguments */ 1301 if (argc < 1) { 1302 (void) fprintf(stderr, gettext("missing pool argument\n")); 1303 usage(B_FALSE); 1304 } 1305 if (argc > 1) { 1306 (void) fprintf(stderr, gettext("too many arguments\n")); 1307 usage(B_FALSE); 1308 } 1309 1310 pool = argv[0]; 1311 1312 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1313 /* 1314 * As a special case, check for use of '/' in the name, and 1315 * direct the user to use 'zfs destroy' instead. 1316 */ 1317 if (strchr(pool, '/') != NULL) 1318 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1319 "destroy a dataset\n")); 1320 return (1); 1321 } 1322 1323 if (zpool_disable_datasets(zhp, force) != 0) { 1324 (void) fprintf(stderr, gettext("could not destroy '%s': " 1325 "could not unmount datasets\n"), zpool_get_name(zhp)); 1326 return (1); 1327 } 1328 1329 /* The history must be logged as part of the export */ 1330 log_history = B_FALSE; 1331 1332 ret = (zpool_destroy(zhp, history_str) != 0); 1333 1334 zpool_close(zhp); 1335 1336 return (ret); 1337} 1338 1339/* 1340 * zpool export [-f] <pool> ... 1341 * 1342 * -f Forcefully unmount datasets 1343 * 1344 * Export the given pools. By default, the command will attempt to cleanly 1345 * unmount any active datasets within the pool. If the '-f' flag is specified, 1346 * then the datasets will be forcefully unmounted. 1347 */ 1348int 1349zpool_do_export(int argc, char **argv) 1350{ 1351 boolean_t force = B_FALSE; 1352 boolean_t hardforce = B_FALSE; 1353 int c; 1354 zpool_handle_t *zhp; 1355 int ret; 1356 int i; 1357 1358 /* check options */ 1359 while ((c = getopt(argc, argv, "fF")) != -1) { 1360 switch (c) { 1361 case 'f': 1362 force = B_TRUE; 1363 break; 1364 case 'F': 1365 hardforce = B_TRUE; 1366 break; 1367 case '?': 1368 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1369 optopt); 1370 usage(B_FALSE); 1371 } 1372 } 1373 1374 argc -= optind; 1375 argv += optind; 1376 1377 /* check arguments */ 1378 if (argc < 1) { 1379 (void) fprintf(stderr, gettext("missing pool argument\n")); 1380 usage(B_FALSE); 1381 } 1382 1383 ret = 0; 1384 for (i = 0; i < argc; i++) { 1385 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1386 ret = 1; 1387 continue; 1388 } 1389 1390 if (zpool_disable_datasets(zhp, force) != 0) { 1391 ret = 1; 1392 zpool_close(zhp); 1393 continue; 1394 } 1395 1396 /* The history must be logged as part of the export */ 1397 log_history = B_FALSE; 1398 1399 if (hardforce) { 1400 if (zpool_export_force(zhp, history_str) != 0) 1401 ret = 1; 1402 } else if (zpool_export(zhp, force, history_str) != 0) { 1403 ret = 1; 1404 } 1405 1406 zpool_close(zhp); 1407 } 1408 1409 return (ret); 1410} 1411 1412/* 1413 * Given a vdev configuration, determine the maximum width needed for the device 1414 * name column. 1415 */ 1416static int 1417max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 1418{ 1419 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); 1420 nvlist_t **child; 1421 uint_t c, children; 1422 int ret; 1423 1424 if (strlen(name) + depth > max) 1425 max = strlen(name) + depth; 1426 1427 free(name); 1428 1429 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1430 &child, &children) == 0) { 1431 for (c = 0; c < children; c++) 1432 if ((ret = max_width(zhp, child[c], depth + 2, 1433 max)) > max) 1434 max = ret; 1435 } 1436 1437 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1438 &child, &children) == 0) { 1439 for (c = 0; c < children; c++) 1440 if ((ret = max_width(zhp, child[c], depth + 2, 1441 max)) > max) 1442 max = ret; 1443 } 1444 1445 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1446 &child, &children) == 0) { 1447 for (c = 0; c < children; c++) 1448 if ((ret = max_width(zhp, child[c], depth + 2, 1449 max)) > max) 1450 max = ret; 1451 } 1452 1453 1454 return (max); 1455} 1456 1457typedef struct spare_cbdata { 1458 uint64_t cb_guid; 1459 zpool_handle_t *cb_zhp; 1460} spare_cbdata_t; 1461 1462static boolean_t 1463find_vdev(nvlist_t *nv, uint64_t search) 1464{ 1465 uint64_t guid; 1466 nvlist_t **child; 1467 uint_t c, children; 1468 1469 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1470 search == guid) 1471 return (B_TRUE); 1472 1473 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1474 &child, &children) == 0) { 1475 for (c = 0; c < children; c++) 1476 if (find_vdev(child[c], search)) 1477 return (B_TRUE); 1478 } 1479 1480 return (B_FALSE); 1481} 1482 1483static int 1484find_spare(zpool_handle_t *zhp, void *data) 1485{ 1486 spare_cbdata_t *cbp = data; 1487 nvlist_t *config, *nvroot; 1488 1489 config = zpool_get_config(zhp, NULL); 1490 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1491 &nvroot) == 0); 1492 1493 if (find_vdev(nvroot, cbp->cb_guid)) { 1494 cbp->cb_zhp = zhp; 1495 return (1); 1496 } 1497 1498 zpool_close(zhp); 1499 return (0); 1500} 1501 1502/* 1503 * Print out configuration state as requested by status_callback. 1504 */ 1505void 1506print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1507 int namewidth, int depth, boolean_t isspare) 1508{ 1509 nvlist_t **child; 1510 uint_t c, vsc, children; 1511 pool_scan_stat_t *ps = NULL; 1512 vdev_stat_t *vs; 1513 char rbuf[6], wbuf[6], cbuf[6]; 1514 char *vname; 1515 uint64_t notpresent; 1516 uint64_t ashift; 1517 spare_cbdata_t cb; 1518 const char *state; 1519 char *type; 1520 1521 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1522 &child, &children) != 0) 1523 children = 0; 1524 1525 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1526 (uint64_t **)&vs, &vsc) == 0); 1527 1528 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1529 1530 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 1531 return; 1532 1533 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1534 if (isspare) { 1535 /* 1536 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1537 * online drives. 1538 */ 1539 if (vs->vs_aux == VDEV_AUX_SPARED) 1540 state = "INUSE"; 1541 else if (vs->vs_state == VDEV_STATE_HEALTHY) 1542 state = "AVAIL"; 1543 } 1544 1545 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1546 name, state); 1547 1548 if (!isspare) { 1549 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1550 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1551 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1552 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1553 } 1554 1555 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1556 ¬present) == 0 || 1557 vs->vs_state <= VDEV_STATE_CANT_OPEN) { 1558 char *path; 1559 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) 1560 (void) printf(" was %s", path); 1561 } else if (vs->vs_aux != 0) { 1562 (void) printf(" "); 1563 1564 switch (vs->vs_aux) { 1565 case VDEV_AUX_OPEN_FAILED: 1566 (void) printf(gettext("cannot open")); 1567 break; 1568 1569 case VDEV_AUX_BAD_GUID_SUM: 1570 (void) printf(gettext("missing device")); 1571 break; 1572 1573 case VDEV_AUX_NO_REPLICAS: 1574 (void) printf(gettext("insufficient replicas")); 1575 break; 1576 1577 case VDEV_AUX_VERSION_NEWER: 1578 (void) printf(gettext("newer version")); 1579 break; 1580 1581 case VDEV_AUX_UNSUP_FEAT: 1582 (void) printf(gettext("unsupported feature(s)")); 1583 break; 1584 1585 case VDEV_AUX_ASHIFT_TOO_BIG: 1586 (void) printf(gettext("unsupported minimum blocksize")); 1587 break; 1588 1589 case VDEV_AUX_SPARED: 1590 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1591 &cb.cb_guid) == 0); 1592 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1593 if (strcmp(zpool_get_name(cb.cb_zhp), 1594 zpool_get_name(zhp)) == 0) 1595 (void) printf(gettext("currently in " 1596 "use")); 1597 else 1598 (void) printf(gettext("in use by " 1599 "pool '%s'"), 1600 zpool_get_name(cb.cb_zhp)); 1601 zpool_close(cb.cb_zhp); 1602 } else { 1603 (void) printf(gettext("currently in use")); 1604 } 1605 break; 1606 1607 case VDEV_AUX_ERR_EXCEEDED: 1608 (void) printf(gettext("too many errors")); 1609 break; 1610 1611 case VDEV_AUX_IO_FAILURE: 1612 (void) printf(gettext("experienced I/O failures")); 1613 break; 1614 1615 case VDEV_AUX_BAD_LOG: 1616 (void) printf(gettext("bad intent log")); 1617 break; 1618 1619 case VDEV_AUX_EXTERNAL: 1620 (void) printf(gettext("external device fault")); 1621 break; 1622 1623 case VDEV_AUX_SPLIT_POOL: 1624 (void) printf(gettext("split into new pool")); 1625 break; 1626 1627 case VDEV_AUX_CHILDREN_OFFLINE: 1628 (void) printf(gettext("all children offline")); 1629 break; 1630 1631 default: 1632 (void) printf(gettext("corrupted data")); 1633 break; 1634 } 1635 } else if (children == 0 && !isspare && 1636 VDEV_STAT_VALID(vs_physical_ashift, vsc) && 1637 vs->vs_configured_ashift < vs->vs_physical_ashift) { 1638 (void) printf( 1639 gettext(" block size: %dB configured, %dB native"), 1640 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift); 1641 } 1642 1643 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, 1644 (uint64_t **)&ps, &c); 1645 1646 if (ps != NULL && ps->pss_state == DSS_SCANNING && 1647 vs->vs_scan_processed != 0 && children == 0) { 1648 (void) printf(gettext(" (%s)"), 1649 (ps->pss_func == POOL_SCAN_RESILVER) ? 1650 "resilvering" : "repairing"); 1651 } 1652 1653 (void) printf("\n"); 1654 1655 for (c = 0; c < children; c++) { 1656 uint64_t islog = B_FALSE, ishole = B_FALSE; 1657 1658 /* Don't print logs or holes here */ 1659 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1660 &islog); 1661 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 1662 &ishole); 1663 if (islog || ishole) 1664 continue; 1665 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1666 print_status_config(zhp, vname, child[c], 1667 namewidth, depth + 2, isspare); 1668 free(vname); 1669 } 1670} 1671 1672 1673/* 1674 * Print the configuration of an exported pool. Iterate over all vdevs in the 1675 * pool, printing out the name and status for each one. 1676 */ 1677void 1678print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1679{ 1680 nvlist_t **child; 1681 uint_t c, children; 1682 vdev_stat_t *vs; 1683 char *type, *vname; 1684 1685 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1686 if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 1687 strcmp(type, VDEV_TYPE_HOLE) == 0) 1688 return; 1689 1690 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1691 (uint64_t **)&vs, &c) == 0); 1692 1693 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1694 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1695 1696 if (vs->vs_aux != 0) { 1697 (void) printf(" "); 1698 1699 switch (vs->vs_aux) { 1700 case VDEV_AUX_OPEN_FAILED: 1701 (void) printf(gettext("cannot open")); 1702 break; 1703 1704 case VDEV_AUX_BAD_GUID_SUM: 1705 (void) printf(gettext("missing device")); 1706 break; 1707 1708 case VDEV_AUX_NO_REPLICAS: 1709 (void) printf(gettext("insufficient replicas")); 1710 break; 1711 1712 case VDEV_AUX_VERSION_NEWER: 1713 (void) printf(gettext("newer version")); 1714 break; 1715 1716 case VDEV_AUX_UNSUP_FEAT: 1717 (void) printf(gettext("unsupported feature(s)")); 1718 break; 1719 1720 case VDEV_AUX_ERR_EXCEEDED: 1721 (void) printf(gettext("too many errors")); 1722 break; 1723 1724 case VDEV_AUX_CHILDREN_OFFLINE: 1725 (void) printf(gettext("all children offline")); 1726 break; 1727 1728 default: 1729 (void) printf(gettext("corrupted data")); 1730 break; 1731 } 1732 } 1733 (void) printf("\n"); 1734 1735 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1736 &child, &children) != 0) 1737 return; 1738 1739 for (c = 0; c < children; c++) { 1740 uint64_t is_log = B_FALSE; 1741 1742 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1743 &is_log); 1744 if (is_log) 1745 continue; 1746 1747 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE); 1748 print_import_config(vname, child[c], namewidth, depth + 2); 1749 free(vname); 1750 } 1751 1752 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1753 &child, &children) == 0) { 1754 (void) printf(gettext("\tcache\n")); 1755 for (c = 0; c < children; c++) { 1756 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1757 (void) printf("\t %s\n", vname); 1758 free(vname); 1759 } 1760 } 1761 1762 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1763 &child, &children) == 0) { 1764 (void) printf(gettext("\tspares\n")); 1765 for (c = 0; c < children; c++) { 1766 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1767 (void) printf("\t %s\n", vname); 1768 free(vname); 1769 } 1770 } 1771} 1772 1773/* 1774 * Print log vdevs. 1775 * Logs are recorded as top level vdevs in the main pool child array 1776 * but with "is_log" set to 1. We use either print_status_config() or 1777 * print_import_config() to print the top level logs then any log 1778 * children (eg mirrored slogs) are printed recursively - which 1779 * works because only the top level vdev is marked "is_log" 1780 */ 1781static void 1782print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1783{ 1784 uint_t c, children; 1785 nvlist_t **child; 1786 1787 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1788 &children) != 0) 1789 return; 1790 1791 (void) printf(gettext("\tlogs\n")); 1792 1793 for (c = 0; c < children; c++) { 1794 uint64_t is_log = B_FALSE; 1795 char *name; 1796 1797 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1798 &is_log); 1799 if (!is_log) 1800 continue; 1801 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1802 if (verbose) 1803 print_status_config(zhp, name, child[c], namewidth, 1804 2, B_FALSE); 1805 else 1806 print_import_config(name, child[c], namewidth, 2); 1807 free(name); 1808 } 1809} 1810 1811/* 1812 * Display the status for the given pool. 1813 */ 1814static void 1815show_import(nvlist_t *config) 1816{ 1817 uint64_t pool_state; 1818 vdev_stat_t *vs; 1819 char *name; 1820 uint64_t guid; 1821 char *msgid; 1822 nvlist_t *nvroot; 1823 int reason; 1824 const char *health; 1825 uint_t vsc; 1826 int namewidth; 1827 char *comment; 1828 1829 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1830 &name) == 0); 1831 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1832 &guid) == 0); 1833 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1834 &pool_state) == 0); 1835 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1836 &nvroot) == 0); 1837 1838 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 1839 (uint64_t **)&vs, &vsc) == 0); 1840 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1841 1842 reason = zpool_import_status(config, &msgid); 1843 1844 (void) printf(gettext(" pool: %s\n"), name); 1845 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1846 (void) printf(gettext(" state: %s"), health); 1847 if (pool_state == POOL_STATE_DESTROYED) 1848 (void) printf(gettext(" (DESTROYED)")); 1849 (void) printf("\n"); 1850 1851 switch (reason) { 1852 case ZPOOL_STATUS_MISSING_DEV_R: 1853 case ZPOOL_STATUS_MISSING_DEV_NR: 1854 case ZPOOL_STATUS_BAD_GUID_SUM: 1855 (void) printf(gettext(" status: One or more devices are " 1856 "missing from the system.\n")); 1857 break; 1858 1859 case ZPOOL_STATUS_CORRUPT_LABEL_R: 1860 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1861 (void) printf(gettext(" status: One or more devices contains " 1862 "corrupted data.\n")); 1863 break; 1864 1865 case ZPOOL_STATUS_CORRUPT_DATA: 1866 (void) printf( 1867 gettext(" status: The pool data is corrupted.\n")); 1868 break; 1869 1870 case ZPOOL_STATUS_OFFLINE_DEV: 1871 (void) printf(gettext(" status: One or more devices " 1872 "are offlined.\n")); 1873 break; 1874 1875 case ZPOOL_STATUS_CORRUPT_POOL: 1876 (void) printf(gettext(" status: The pool metadata is " 1877 "corrupted.\n")); 1878 break; 1879 1880 case ZPOOL_STATUS_VERSION_OLDER: 1881 (void) printf(gettext(" status: The pool is formatted using a " 1882 "legacy on-disk version.\n")); 1883 break; 1884 1885 case ZPOOL_STATUS_VERSION_NEWER: 1886 (void) printf(gettext(" status: The pool is formatted using an " 1887 "incompatible version.\n")); 1888 break; 1889 1890 case ZPOOL_STATUS_FEAT_DISABLED: 1891 (void) printf(gettext(" status: Some supported features are " 1892 "not enabled on the pool.\n")); 1893 break; 1894 1895 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1896 (void) printf(gettext("status: The pool uses the following " 1897 "feature(s) not supported on this system:\n")); 1898 zpool_print_unsup_feat(config); 1899 break; 1900 1901 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1902 (void) printf(gettext("status: The pool can only be accessed " 1903 "in read-only mode on this system. It\n\tcannot be " 1904 "accessed in read-write mode because it uses the " 1905 "following\n\tfeature(s) not supported on this system:\n")); 1906 zpool_print_unsup_feat(config); 1907 break; 1908 1909 case ZPOOL_STATUS_HOSTID_MISMATCH: 1910 (void) printf(gettext(" status: The pool was last accessed by " 1911 "another system.\n")); 1912 break; 1913 1914 case ZPOOL_STATUS_FAULTED_DEV_R: 1915 case ZPOOL_STATUS_FAULTED_DEV_NR: 1916 (void) printf(gettext(" status: One or more devices are " 1917 "faulted.\n")); 1918 break; 1919 1920 case ZPOOL_STATUS_BAD_LOG: 1921 (void) printf(gettext(" status: An intent log record cannot be " 1922 "read.\n")); 1923 break; 1924 1925 case ZPOOL_STATUS_RESILVERING: 1926 (void) printf(gettext(" status: One or more devices were being " 1927 "resilvered.\n")); 1928 break; 1929 1930 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 1931 (void) printf(gettext("status: One or more devices were " 1932 "configured to use a non-native block size.\n" 1933 "\tExpect reduced performance.\n")); 1934 break; 1935 1936 default: 1937 /* 1938 * No other status can be seen when importing pools. 1939 */ 1940 assert(reason == ZPOOL_STATUS_OK); 1941 } 1942 1943 /* 1944 * Print out an action according to the overall state of the pool. 1945 */ 1946 if (vs->vs_state == VDEV_STATE_HEALTHY) { 1947 if (reason == ZPOOL_STATUS_VERSION_OLDER || 1948 reason == ZPOOL_STATUS_FEAT_DISABLED) { 1949 (void) printf(gettext(" action: The pool can be " 1950 "imported using its name or numeric identifier, " 1951 "though\n\tsome features will not be available " 1952 "without an explicit 'zpool upgrade'.\n")); 1953 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 1954 (void) printf(gettext(" action: The pool can be " 1955 "imported using its name or numeric " 1956 "identifier and\n\tthe '-f' flag.\n")); 1957 } else { 1958 (void) printf(gettext(" action: The pool can be " 1959 "imported using its name or numeric " 1960 "identifier.\n")); 1961 } 1962 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1963 (void) printf(gettext(" action: The pool can be imported " 1964 "despite missing or damaged devices. The\n\tfault " 1965 "tolerance of the pool may be compromised if imported.\n")); 1966 } else { 1967 switch (reason) { 1968 case ZPOOL_STATUS_VERSION_NEWER: 1969 (void) printf(gettext(" action: The pool cannot be " 1970 "imported. Access the pool on a system running " 1971 "newer\n\tsoftware, or recreate the pool from " 1972 "backup.\n")); 1973 break; 1974 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1975 (void) printf(gettext("action: The pool cannot be " 1976 "imported. Access the pool on a system that " 1977 "supports\n\tthe required feature(s), or recreate " 1978 "the pool from backup.\n")); 1979 break; 1980 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1981 (void) printf(gettext("action: The pool cannot be " 1982 "imported in read-write mode. Import the pool " 1983 "with\n" 1984 "\t\"-o readonly=on\", access the pool on a system " 1985 "that supports the\n\trequired feature(s), or " 1986 "recreate the pool from backup.\n")); 1987 break; 1988 case ZPOOL_STATUS_MISSING_DEV_R: 1989 case ZPOOL_STATUS_MISSING_DEV_NR: 1990 case ZPOOL_STATUS_BAD_GUID_SUM: 1991 (void) printf(gettext(" action: The pool cannot be " 1992 "imported. Attach the missing\n\tdevices and try " 1993 "again.\n")); 1994 break; 1995 default: 1996 (void) printf(gettext(" action: The pool cannot be " 1997 "imported due to damaged devices or data.\n")); 1998 } 1999 } 2000 2001 /* Print the comment attached to the pool. */ 2002 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 2003 (void) printf(gettext("comment: %s\n"), comment); 2004 2005 /* 2006 * If the state is "closed" or "can't open", and the aux state 2007 * is "corrupt data": 2008 */ 2009 if (((vs->vs_state == VDEV_STATE_CLOSED) || 2010 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 2011 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 2012 if (pool_state == POOL_STATE_DESTROYED) 2013 (void) printf(gettext("\tThe pool was destroyed, " 2014 "but can be imported using the '-Df' flags.\n")); 2015 else if (pool_state != POOL_STATE_EXPORTED) 2016 (void) printf(gettext("\tThe pool may be active on " 2017 "another system, but can be imported using\n\t" 2018 "the '-f' flag.\n")); 2019 } 2020 2021 if (msgid != NULL) 2022 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 2023 msgid); 2024 2025 (void) printf(gettext(" config:\n\n")); 2026 2027 namewidth = max_width(NULL, nvroot, 0, 0); 2028 if (namewidth < 10) 2029 namewidth = 10; 2030 2031 print_import_config(name, nvroot, namewidth, 0); 2032 if (num_logs(nvroot) > 0) 2033 print_logs(NULL, nvroot, namewidth, B_FALSE); 2034 2035 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 2036 (void) printf(gettext("\n\tAdditional devices are known to " 2037 "be part of this pool, though their\n\texact " 2038 "configuration cannot be determined.\n")); 2039 } 2040} 2041 2042/* 2043 * Perform the import for the given configuration. This passes the heavy 2044 * lifting off to zpool_import_props(), and then mounts the datasets contained 2045 * within the pool. 2046 */ 2047static int 2048do_import(nvlist_t *config, const char *newname, const char *mntopts, 2049 nvlist_t *props, int flags) 2050{ 2051 zpool_handle_t *zhp; 2052 char *name; 2053 uint64_t state; 2054 uint64_t version; 2055 2056 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2057 &name) == 0); 2058 2059 verify(nvlist_lookup_uint64(config, 2060 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 2061 verify(nvlist_lookup_uint64(config, 2062 ZPOOL_CONFIG_VERSION, &version) == 0); 2063 if (!SPA_VERSION_IS_SUPPORTED(version)) { 2064 (void) fprintf(stderr, gettext("cannot import '%s': pool " 2065 "is formatted using an unsupported ZFS version\n"), name); 2066 return (1); 2067 } else if (state != POOL_STATE_EXPORTED && 2068 !(flags & ZFS_IMPORT_ANY_HOST)) { 2069 uint64_t hostid; 2070 2071 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 2072 &hostid) == 0) { 2073 if ((unsigned long)hostid != gethostid()) { 2074 char *hostname; 2075 uint64_t timestamp; 2076 time_t t; 2077 2078 verify(nvlist_lookup_string(config, 2079 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 2080 verify(nvlist_lookup_uint64(config, 2081 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 2082 t = timestamp; 2083 (void) fprintf(stderr, gettext("cannot import " 2084 "'%s': pool may be in use from other " 2085 "system, it was last accessed by %s " 2086 "(hostid: 0x%lx) on %s"), name, hostname, 2087 (unsigned long)hostid, 2088 asctime(localtime(&t))); 2089 (void) fprintf(stderr, gettext("use '-f' to " 2090 "import anyway\n")); 2091 return (1); 2092 } 2093 } else { 2094 (void) fprintf(stderr, gettext("cannot import '%s': " 2095 "pool may be in use from other system\n"), name); 2096 (void) fprintf(stderr, gettext("use '-f' to import " 2097 "anyway\n")); 2098 return (1); 2099 } 2100 } 2101 2102 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 2103 return (1); 2104 2105 if (newname != NULL) 2106 name = (char *)newname; 2107 2108 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 2109 return (1); 2110 2111 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 2112 !(flags & ZFS_IMPORT_ONLY) && 2113 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 2114 zpool_close(zhp); 2115 return (1); 2116 } 2117 2118 zpool_close(zhp); 2119 return (0); 2120} 2121 2122/* 2123 * zpool checkpoint <pool> 2124 * checkpoint --discard <pool> 2125 * 2126 * -d Discard the checkpoint from a checkpointed 2127 * --discard pool. 2128 * 2129 * Checkpoints the specified pool, by taking a "snapshot" of its 2130 * current state. A pool can only have one checkpoint at a time. 2131 */ 2132int 2133zpool_do_checkpoint(int argc, char **argv) 2134{ 2135 boolean_t discard; 2136 char *pool; 2137 zpool_handle_t *zhp; 2138 int c, err; 2139 2140 struct option long_options[] = { 2141 {"discard", no_argument, NULL, 'd'}, 2142 {0, 0, 0, 0} 2143 }; 2144 2145 discard = B_FALSE; 2146 while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) { 2147 switch (c) { 2148 case 'd': 2149 discard = B_TRUE; 2150 break; 2151 case '?': 2152 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2153 optopt); 2154 usage(B_FALSE); 2155 } 2156 } 2157 2158 argc -= optind; 2159 argv += optind; 2160 2161 if (argc < 1) { 2162 (void) fprintf(stderr, gettext("missing pool argument\n")); 2163 usage(B_FALSE); 2164 } 2165 2166 if (argc > 1) { 2167 (void) fprintf(stderr, gettext("too many arguments\n")); 2168 usage(B_FALSE); 2169 } 2170 2171 pool = argv[0]; 2172 2173 if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 2174 /* As a special case, check for use of '/' in the name */ 2175 if (strchr(pool, '/') != NULL) 2176 (void) fprintf(stderr, gettext("'zpool checkpoint' " 2177 "doesn't work on datasets. To save the state " 2178 "of a dataset from a specific point in time " 2179 "please use 'zfs snapshot'\n")); 2180 return (1); 2181 } 2182 2183 if (discard) 2184 err = (zpool_discard_checkpoint(zhp) != 0); 2185 else 2186 err = (zpool_checkpoint(zhp) != 0); 2187 2188 zpool_close(zhp); 2189 2190 return (err); 2191} 2192 2193#define CHECKPOINT_OPT 1024 2194 2195/* 2196 * zpool import [-d dir] [-D] 2197 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 2198 * [-d dir | -c cachefile] [-f] -a 2199 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 2200 * [-d dir | -c cachefile] [-f] [-n] [-F] [-t] 2201 * <pool | id> [newpool] 2202 * 2203 * -c Read pool information from a cachefile instead of searching 2204 * devices. 2205 * 2206 * -d Scan in a specific directory, other than /dev/dsk. More than 2207 * one directory can be specified using multiple '-d' options. 2208 * 2209 * -D Scan for previously destroyed pools or import all or only 2210 * specified destroyed pools. 2211 * 2212 * -R Temporarily import the pool, with all mountpoints relative to 2213 * the given root. The pool will remain exported when the machine 2214 * is rebooted. 2215 * 2216 * -V Import even in the presence of faulted vdevs. This is an 2217 * intentionally undocumented option for testing purposes, and 2218 * treats the pool configuration as complete, leaving any bad 2219 * vdevs in the FAULTED state. In other words, it does verbatim 2220 * import. 2221 * 2222 * -f Force import, even if it appears that the pool is active. 2223 * 2224 * -F Attempt rewind if necessary. 2225 * 2226 * -n See if rewind would work, but don't actually rewind. 2227 * 2228 * -N Import the pool but don't mount datasets. 2229 * 2230 * -t Use newpool as a temporary pool name instead of renaming 2231 * the pool. 2232 * 2233 * -T Specify a starting txg to use for import. This option is 2234 * intentionally undocumented option for testing purposes. 2235 * 2236 * -a Import all pools found. 2237 * 2238 * -o Set property=value and/or temporary mount options (without '='). 2239 * 2240 * --rewind-to-checkpoint 2241 * Import the pool and revert back to the checkpoint. 2242 * 2243 * The import command scans for pools to import, and import pools based on pool 2244 * name and GUID. The pool can also be renamed as part of the import process. 2245 */ 2246int 2247zpool_do_import(int argc, char **argv) 2248{ 2249 char **searchdirs = NULL; 2250 int nsearch = 0; 2251 int c; 2252 int err = 0; 2253 nvlist_t *pools = NULL; 2254 boolean_t do_all = B_FALSE; 2255 boolean_t do_destroyed = B_FALSE; 2256 char *mntopts = NULL; 2257 nvpair_t *elem; 2258 nvlist_t *config; 2259 uint64_t searchguid = 0; 2260 char *searchname = NULL; 2261 char *propval; 2262 nvlist_t *found_config; 2263 nvlist_t *policy = NULL; 2264 nvlist_t *props = NULL; 2265 boolean_t first; 2266 int flags = ZFS_IMPORT_NORMAL; 2267 uint32_t rewind_policy = ZPOOL_NO_REWIND; 2268 boolean_t dryrun = B_FALSE; 2269 boolean_t do_rewind = B_FALSE; 2270 boolean_t xtreme_rewind = B_FALSE; 2271 uint64_t pool_state, txg = -1ULL; 2272 char *cachefile = NULL; 2273 importargs_t idata = { 0 }; 2274 char *endptr; 2275 2276 2277 struct option long_options[] = { 2278 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 2279 {0, 0, 0, 0} 2280 }; 2281 2282 /* check options */ 2283 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:tT:VX", 2284 long_options, NULL)) != -1) { 2285 switch (c) { 2286 case 'a': 2287 do_all = B_TRUE; 2288 break; 2289 case 'c': 2290 cachefile = optarg; 2291 break; 2292 case 'd': 2293 if (searchdirs == NULL) { 2294 searchdirs = safe_malloc(sizeof (char *)); 2295 } else { 2296 char **tmp = safe_malloc((nsearch + 1) * 2297 sizeof (char *)); 2298 bcopy(searchdirs, tmp, nsearch * 2299 sizeof (char *)); 2300 free(searchdirs); 2301 searchdirs = tmp; 2302 } 2303 searchdirs[nsearch++] = optarg; 2304 break; 2305 case 'D': 2306 do_destroyed = B_TRUE; 2307 break; 2308 case 'f': 2309 flags |= ZFS_IMPORT_ANY_HOST; 2310 break; 2311 case 'F': 2312 do_rewind = B_TRUE; 2313 break; 2314 case 'm': 2315 flags |= ZFS_IMPORT_MISSING_LOG; 2316 break; 2317 case 'n': 2318 dryrun = B_TRUE; 2319 break; 2320 case 'N': 2321 flags |= ZFS_IMPORT_ONLY; 2322 break; 2323 case 'o': 2324 if ((propval = strchr(optarg, '=')) != NULL) { 2325 *propval = '\0'; 2326 propval++; 2327 if (add_prop_list(optarg, propval, 2328 &props, B_TRUE)) 2329 goto error; 2330 } else { 2331 mntopts = optarg; 2332 } 2333 break; 2334 case 'R': 2335 if (add_prop_list(zpool_prop_to_name( 2336 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2337 goto error; 2338 if (add_prop_list_default(zpool_prop_to_name( 2339 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2340 goto error; 2341 break; 2342 case 't': 2343 flags |= ZFS_IMPORT_TEMP_NAME; 2344 if (add_prop_list_default(zpool_prop_to_name( 2345 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2346 goto error; 2347 break; 2348 case 'T': 2349 errno = 0; 2350 txg = strtoull(optarg, &endptr, 0); 2351 if (errno != 0 || *endptr != '\0') { 2352 (void) fprintf(stderr, 2353 gettext("invalid txg value\n")); 2354 usage(B_FALSE); 2355 } 2356 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2357 break; 2358 case 'V': 2359 flags |= ZFS_IMPORT_VERBATIM; 2360 break; 2361 case 'X': 2362 xtreme_rewind = B_TRUE; 2363 break; 2364 case CHECKPOINT_OPT: 2365 flags |= ZFS_IMPORT_CHECKPOINT; 2366 break; 2367 case ':': 2368 (void) fprintf(stderr, gettext("missing argument for " 2369 "'%c' option\n"), optopt); 2370 usage(B_FALSE); 2371 break; 2372 case '?': 2373 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2374 optopt); 2375 usage(B_FALSE); 2376 } 2377 } 2378 2379 argc -= optind; 2380 argv += optind; 2381 2382 if (cachefile && nsearch != 0) { 2383 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 2384 usage(B_FALSE); 2385 } 2386 2387 if ((dryrun || xtreme_rewind) && !do_rewind) { 2388 (void) fprintf(stderr, 2389 gettext("-n or -X only meaningful with -F\n")); 2390 usage(B_FALSE); 2391 } 2392 if (dryrun) 2393 rewind_policy = ZPOOL_TRY_REWIND; 2394 else if (do_rewind) 2395 rewind_policy = ZPOOL_DO_REWIND; 2396 if (xtreme_rewind) 2397 rewind_policy |= ZPOOL_EXTREME_REWIND; 2398 2399 /* In the future, we can capture further policy and include it here */ 2400 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 2401 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 || 2402 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 2403 rewind_policy) != 0) 2404 goto error; 2405 2406 if (searchdirs == NULL) { 2407 searchdirs = safe_malloc(sizeof (char *)); 2408 searchdirs[0] = "/dev"; 2409 nsearch = 1; 2410 } 2411 2412 /* check argument count */ 2413 if (do_all) { 2414 if (argc != 0) { 2415 (void) fprintf(stderr, gettext("too many arguments\n")); 2416 usage(B_FALSE); 2417 } 2418 } else { 2419 if (argc > 2) { 2420 (void) fprintf(stderr, gettext("too many arguments\n")); 2421 usage(B_FALSE); 2422 } 2423 2424 /* 2425 * Check for the SYS_CONFIG privilege. We do this explicitly 2426 * here because otherwise any attempt to discover pools will 2427 * silently fail. 2428 */ 2429 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2430 (void) fprintf(stderr, gettext("cannot " 2431 "discover pools: permission denied\n")); 2432 free(searchdirs); 2433 nvlist_free(policy); 2434 return (1); 2435 } 2436 } 2437 2438 /* 2439 * Depending on the arguments given, we do one of the following: 2440 * 2441 * <none> Iterate through all pools and display information about 2442 * each one. 2443 * 2444 * -a Iterate through all pools and try to import each one. 2445 * 2446 * <id> Find the pool that corresponds to the given GUID/pool 2447 * name and import that one. 2448 * 2449 * -D Above options applies only to destroyed pools. 2450 */ 2451 if (argc != 0) { 2452 char *endptr; 2453 2454 errno = 0; 2455 searchguid = strtoull(argv[0], &endptr, 10); 2456 if (errno != 0 || *endptr != '\0') { 2457 searchname = argv[0]; 2458 searchguid = 0; 2459 } 2460 found_config = NULL; 2461 2462 /* 2463 * User specified a name or guid. Ensure it's unique. 2464 */ 2465 idata.unique = B_TRUE; 2466 } 2467 2468 2469 idata.path = searchdirs; 2470 idata.paths = nsearch; 2471 idata.poolname = searchname; 2472 idata.guid = searchguid; 2473 idata.cachefile = cachefile; 2474 idata.policy = policy; 2475 2476 pools = zpool_search_import(g_zfs, &idata); 2477 2478 if (pools != NULL && idata.exists && 2479 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2480 (void) fprintf(stderr, gettext("cannot import '%s': " 2481 "a pool with that name already exists\n"), 2482 argv[0]); 2483 (void) fprintf(stderr, gettext("use the form 'zpool import " 2484 "[-t] <pool | id> <newpool>' to give it a new temporary " 2485 "or permanent name\n")); 2486 err = 1; 2487 } else if (pools == NULL && idata.exists) { 2488 (void) fprintf(stderr, gettext("cannot import '%s': " 2489 "a pool with that name is already created/imported,\n"), 2490 argv[0]); 2491 (void) fprintf(stderr, gettext("and no additional pools " 2492 "with that name were found\n")); 2493 err = 1; 2494 } else if (pools == NULL) { 2495 if (argc != 0) { 2496 (void) fprintf(stderr, gettext("cannot import '%s': " 2497 "no such pool available\n"), argv[0]); 2498 } 2499 err = 1; 2500 } 2501 2502 if (err == 1) { 2503 free(searchdirs); 2504 nvlist_free(policy); 2505 return (1); 2506 } 2507 2508 /* 2509 * At this point we have a list of import candidate configs. Even if 2510 * we were searching by pool name or guid, we still need to 2511 * post-process the list to deal with pool state and possible 2512 * duplicate names. 2513 */ 2514 err = 0; 2515 elem = NULL; 2516 first = B_TRUE; 2517 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2518 2519 verify(nvpair_value_nvlist(elem, &config) == 0); 2520 2521 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2522 &pool_state) == 0); 2523 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 2524 continue; 2525 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 2526 continue; 2527 2528 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 2529 policy) == 0); 2530 2531 if (argc == 0) { 2532 if (first) 2533 first = B_FALSE; 2534 else if (!do_all) 2535 (void) printf("\n"); 2536 2537 if (do_all) { 2538 err |= do_import(config, NULL, mntopts, 2539 props, flags); 2540 } else { 2541 show_import(config); 2542 } 2543 } else if (searchname != NULL) { 2544 char *name; 2545 2546 /* 2547 * We are searching for a pool based on name. 2548 */ 2549 verify(nvlist_lookup_string(config, 2550 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2551 2552 if (strcmp(name, searchname) == 0) { 2553 if (found_config != NULL) { 2554 (void) fprintf(stderr, gettext( 2555 "cannot import '%s': more than " 2556 "one matching pool\n"), searchname); 2557 (void) fprintf(stderr, gettext( 2558 "import by numeric ID instead\n")); 2559 err = B_TRUE; 2560 } 2561 found_config = config; 2562 } 2563 } else { 2564 uint64_t guid; 2565 2566 /* 2567 * Search for a pool by guid. 2568 */ 2569 verify(nvlist_lookup_uint64(config, 2570 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 2571 2572 if (guid == searchguid) 2573 found_config = config; 2574 } 2575 } 2576 2577 /* 2578 * If we were searching for a specific pool, verify that we found a 2579 * pool, and then do the import. 2580 */ 2581 if (argc != 0 && err == 0) { 2582 if (found_config == NULL) { 2583 (void) fprintf(stderr, gettext("cannot import '%s': " 2584 "no such pool available\n"), argv[0]); 2585 err = B_TRUE; 2586 } else { 2587 err |= do_import(found_config, argc == 1 ? NULL : 2588 argv[1], mntopts, props, flags); 2589 } 2590 } 2591 2592 /* 2593 * If we were just looking for pools, report an error if none were 2594 * found. 2595 */ 2596 if (argc == 0 && first) 2597 (void) fprintf(stderr, 2598 gettext("no pools available to import\n")); 2599 2600error: 2601 nvlist_free(props); 2602 nvlist_free(pools); 2603 nvlist_free(policy); 2604 free(searchdirs); 2605 2606 return (err ? 1 : 0); 2607} 2608 2609typedef struct iostat_cbdata { 2610 boolean_t cb_verbose; 2611 int cb_namewidth; 2612 int cb_iteration; 2613 zpool_list_t *cb_list; 2614} iostat_cbdata_t; 2615 2616static void 2617print_iostat_separator(iostat_cbdata_t *cb) 2618{ 2619 int i = 0; 2620 2621 for (i = 0; i < cb->cb_namewidth; i++) 2622 (void) printf("-"); 2623 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 2624} 2625 2626static void 2627print_iostat_header(iostat_cbdata_t *cb) 2628{ 2629 (void) printf("%*s capacity operations bandwidth\n", 2630 cb->cb_namewidth, ""); 2631 (void) printf("%-*s alloc free read write read write\n", 2632 cb->cb_namewidth, "pool"); 2633 print_iostat_separator(cb); 2634} 2635 2636/* 2637 * Display a single statistic. 2638 */ 2639static void 2640print_one_stat(uint64_t value) 2641{ 2642 char buf[64]; 2643 2644 zfs_nicenum(value, buf, sizeof (buf)); 2645 (void) printf(" %5s", buf); 2646} 2647 2648/* 2649 * Print out all the statistics for the given vdev. This can either be the 2650 * toplevel configuration, or called recursively. If 'name' is NULL, then this 2651 * is a verbose output, and we don't want to display the toplevel pool stats. 2652 */ 2653void 2654print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 2655 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 2656{ 2657 nvlist_t **oldchild, **newchild; 2658 uint_t c, children; 2659 vdev_stat_t *oldvs, *newvs; 2660 vdev_stat_t zerovs = { 0 }; 2661 uint64_t tdelta; 2662 double scale; 2663 char *vname; 2664 2665 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 2666 return; 2667 2668 if (oldnv != NULL) { 2669 verify(nvlist_lookup_uint64_array(oldnv, 2670 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 2671 } else { 2672 oldvs = &zerovs; 2673 } 2674 2675 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 2676 (uint64_t **)&newvs, &c) == 0); 2677 2678 if (strlen(name) + depth > cb->cb_namewidth) 2679 (void) printf("%*s%s", depth, "", name); 2680 else 2681 (void) printf("%*s%s%*s", depth, "", name, 2682 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 2683 2684 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 2685 2686 if (tdelta == 0) 2687 scale = 1.0; 2688 else 2689 scale = (double)NANOSEC / tdelta; 2690 2691 /* only toplevel vdevs have capacity stats */ 2692 if (newvs->vs_space == 0) { 2693 (void) printf(" - -"); 2694 } else { 2695 print_one_stat(newvs->vs_alloc); 2696 print_one_stat(newvs->vs_space - newvs->vs_alloc); 2697 } 2698 2699 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 2700 oldvs->vs_ops[ZIO_TYPE_READ]))); 2701 2702 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 2703 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 2704 2705 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 2706 oldvs->vs_bytes[ZIO_TYPE_READ]))); 2707 2708 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 2709 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 2710 2711 (void) printf("\n"); 2712 2713 if (!cb->cb_verbose) 2714 return; 2715 2716 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 2717 &newchild, &children) != 0) 2718 return; 2719 2720 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 2721 &oldchild, &c) != 0) 2722 return; 2723 2724 for (c = 0; c < children; c++) { 2725 uint64_t ishole = B_FALSE, islog = B_FALSE; 2726 2727 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 2728 &ishole); 2729 2730 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 2731 &islog); 2732 2733 if (ishole || islog) 2734 continue; 2735 2736 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); 2737 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2738 newchild[c], cb, depth + 2); 2739 free(vname); 2740 } 2741 2742 /* 2743 * Log device section 2744 */ 2745 2746 if (num_logs(newnv) > 0) { 2747 (void) printf("%-*s - - - - - " 2748 "-\n", cb->cb_namewidth, "logs"); 2749 2750 for (c = 0; c < children; c++) { 2751 uint64_t islog = B_FALSE; 2752 (void) nvlist_lookup_uint64(newchild[c], 2753 ZPOOL_CONFIG_IS_LOG, &islog); 2754 2755 if (islog) { 2756 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2757 B_FALSE); 2758 print_vdev_stats(zhp, vname, oldnv ? 2759 oldchild[c] : NULL, newchild[c], 2760 cb, depth + 2); 2761 free(vname); 2762 } 2763 } 2764 2765 } 2766 2767 /* 2768 * Include level 2 ARC devices in iostat output 2769 */ 2770 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 2771 &newchild, &children) != 0) 2772 return; 2773 2774 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 2775 &oldchild, &c) != 0) 2776 return; 2777 2778 if (children > 0) { 2779 (void) printf("%-*s - - - - - " 2780 "-\n", cb->cb_namewidth, "cache"); 2781 for (c = 0; c < children; c++) { 2782 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2783 B_FALSE); 2784 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2785 newchild[c], cb, depth + 2); 2786 free(vname); 2787 } 2788 } 2789} 2790 2791static int 2792refresh_iostat(zpool_handle_t *zhp, void *data) 2793{ 2794 iostat_cbdata_t *cb = data; 2795 boolean_t missing; 2796 2797 /* 2798 * If the pool has disappeared, remove it from the list and continue. 2799 */ 2800 if (zpool_refresh_stats(zhp, &missing) != 0) 2801 return (-1); 2802 2803 if (missing) 2804 pool_list_remove(cb->cb_list, zhp); 2805 2806 return (0); 2807} 2808 2809/* 2810 * Callback to print out the iostats for the given pool. 2811 */ 2812int 2813print_iostat(zpool_handle_t *zhp, void *data) 2814{ 2815 iostat_cbdata_t *cb = data; 2816 nvlist_t *oldconfig, *newconfig; 2817 nvlist_t *oldnvroot, *newnvroot; 2818 2819 newconfig = zpool_get_config(zhp, &oldconfig); 2820 2821 if (cb->cb_iteration == 1) 2822 oldconfig = NULL; 2823 2824 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2825 &newnvroot) == 0); 2826 2827 if (oldconfig == NULL) 2828 oldnvroot = NULL; 2829 else 2830 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2831 &oldnvroot) == 0); 2832 2833 /* 2834 * Print out the statistics for the pool. 2835 */ 2836 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2837 2838 if (cb->cb_verbose) 2839 print_iostat_separator(cb); 2840 2841 return (0); 2842} 2843 2844int 2845get_namewidth(zpool_handle_t *zhp, void *data) 2846{ 2847 iostat_cbdata_t *cb = data; 2848 nvlist_t *config, *nvroot; 2849 2850 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2851 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2852 &nvroot) == 0); 2853 if (!cb->cb_verbose) 2854 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2855 else 2856 cb->cb_namewidth = max_width(zhp, nvroot, 0, 2857 cb->cb_namewidth); 2858 } 2859 2860 /* 2861 * The width must fall into the range [10,38]. The upper limit is the 2862 * maximum we can have and still fit in 80 columns. 2863 */ 2864 if (cb->cb_namewidth < 10) 2865 cb->cb_namewidth = 10; 2866 if (cb->cb_namewidth > 38) 2867 cb->cb_namewidth = 38; 2868 2869 return (0); 2870} 2871 2872/* 2873 * Parse the input string, get the 'interval' and 'count' value if there is one. 2874 */ 2875static void 2876get_interval_count(int *argcp, char **argv, unsigned long *iv, 2877 unsigned long *cnt) 2878{ 2879 unsigned long interval = 0, count = 0; 2880 int argc = *argcp, errno; 2881 2882 /* 2883 * Determine if the last argument is an integer or a pool name 2884 */ 2885 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2886 char *end; 2887 2888 errno = 0; 2889 interval = strtoul(argv[argc - 1], &end, 10); 2890 2891 if (*end == '\0' && errno == 0) { 2892 if (interval == 0) { 2893 (void) fprintf(stderr, gettext("interval " 2894 "cannot be zero\n")); 2895 usage(B_FALSE); 2896 } 2897 /* 2898 * Ignore the last parameter 2899 */ 2900 argc--; 2901 } else { 2902 /* 2903 * If this is not a valid number, just plow on. The 2904 * user will get a more informative error message later 2905 * on. 2906 */ 2907 interval = 0; 2908 } 2909 } 2910 2911 /* 2912 * If the last argument is also an integer, then we have both a count 2913 * and an interval. 2914 */ 2915 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2916 char *end; 2917 2918 errno = 0; 2919 count = interval; 2920 interval = strtoul(argv[argc - 1], &end, 10); 2921 2922 if (*end == '\0' && errno == 0) { 2923 if (interval == 0) { 2924 (void) fprintf(stderr, gettext("interval " 2925 "cannot be zero\n")); 2926 usage(B_FALSE); 2927 } 2928 2929 /* 2930 * Ignore the last parameter 2931 */ 2932 argc--; 2933 } else { 2934 interval = 0; 2935 } 2936 } 2937 2938 *iv = interval; 2939 *cnt = count; 2940 *argcp = argc; 2941} 2942 2943static void 2944get_timestamp_arg(char c) 2945{ 2946 if (c == 'u') 2947 timestamp_fmt = UDATE; 2948 else if (c == 'd') 2949 timestamp_fmt = DDATE; 2950 else 2951 usage(B_FALSE); 2952} 2953 2954/* 2955 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]] 2956 * 2957 * -v Display statistics for individual vdevs 2958 * -T Display a timestamp in date(1) or Unix format 2959 * 2960 * This command can be tricky because we want to be able to deal with pool 2961 * creation/destruction as well as vdev configuration changes. The bulk of this 2962 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 2963 * on pool_list_update() to detect the addition of new pools. Configuration 2964 * changes are all handled within libzfs. 2965 */ 2966int 2967zpool_do_iostat(int argc, char **argv) 2968{ 2969 int c; 2970 int ret; 2971 int npools; 2972 unsigned long interval = 0, count = 0; 2973 zpool_list_t *list; 2974 boolean_t verbose = B_FALSE; 2975 iostat_cbdata_t cb; 2976 2977 /* check options */ 2978 while ((c = getopt(argc, argv, "T:v")) != -1) { 2979 switch (c) { 2980 case 'T': 2981 get_timestamp_arg(*optarg); 2982 break; 2983 case 'v': 2984 verbose = B_TRUE; 2985 break; 2986 case '?': 2987 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2988 optopt); 2989 usage(B_FALSE); 2990 } 2991 } 2992 2993 argc -= optind; 2994 argv += optind; 2995 2996 get_interval_count(&argc, argv, &interval, &count); 2997 2998 /* 2999 * Construct the list of all interesting pools. 3000 */ 3001 ret = 0; 3002 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 3003 return (1); 3004 3005 if (pool_list_count(list) == 0 && argc != 0) { 3006 pool_list_free(list); 3007 return (1); 3008 } 3009 3010 if (pool_list_count(list) == 0 && interval == 0) { 3011 pool_list_free(list); 3012 (void) fprintf(stderr, gettext("no pools available\n")); 3013 return (1); 3014 } 3015 3016 /* 3017 * Enter the main iostat loop. 3018 */ 3019 cb.cb_list = list; 3020 cb.cb_verbose = verbose; 3021 cb.cb_iteration = 0; 3022 cb.cb_namewidth = 0; 3023 3024 for (;;) { 3025 pool_list_update(list); 3026 3027 if ((npools = pool_list_count(list)) == 0) 3028 break; 3029 3030 /* 3031 * Refresh all statistics. This is done as an explicit step 3032 * before calculating the maximum name width, so that any 3033 * configuration changes are properly accounted for. 3034 */ 3035 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 3036 3037 /* 3038 * Iterate over all pools to determine the maximum width 3039 * for the pool / device name column across all pools. 3040 */ 3041 cb.cb_namewidth = 0; 3042 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3043 3044 if (timestamp_fmt != NODATE) 3045 print_timestamp(timestamp_fmt); 3046 3047 /* 3048 * If it's the first time, or verbose mode, print the header. 3049 */ 3050 if (++cb.cb_iteration == 1 || verbose) 3051 print_iostat_header(&cb); 3052 3053 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 3054 3055 /* 3056 * If there's more than one pool, and we're not in verbose mode 3057 * (which prints a separator for us), then print a separator. 3058 */ 3059 if (npools > 1 && !verbose) 3060 print_iostat_separator(&cb); 3061 3062 if (verbose) 3063 (void) printf("\n"); 3064 3065 /* 3066 * Flush the output so that redirection to a file isn't buffered 3067 * indefinitely. 3068 */ 3069 (void) fflush(stdout); 3070 3071 if (interval == 0) 3072 break; 3073 3074 if (count != 0 && --count == 0) 3075 break; 3076 3077 (void) sleep(interval); 3078 } 3079 3080 pool_list_free(list); 3081 3082 return (ret); 3083} 3084 3085typedef struct list_cbdata { 3086 boolean_t cb_verbose; 3087 int cb_namewidth; 3088 boolean_t cb_scripted; 3089 zprop_list_t *cb_proplist; 3090 boolean_t cb_literal; 3091} list_cbdata_t; 3092 3093/* 3094 * Given a list of columns to display, output appropriate headers for each one. 3095 */ 3096static void 3097print_header(list_cbdata_t *cb) 3098{ 3099 zprop_list_t *pl = cb->cb_proplist; 3100 char headerbuf[ZPOOL_MAXPROPLEN]; 3101 const char *header; 3102 boolean_t first = B_TRUE; 3103 boolean_t right_justify; 3104 size_t width = 0; 3105 3106 for (; pl != NULL; pl = pl->pl_next) { 3107 width = pl->pl_width; 3108 if (first && cb->cb_verbose) { 3109 /* 3110 * Reset the width to accommodate the verbose listing 3111 * of devices. 3112 */ 3113 width = cb->cb_namewidth; 3114 } 3115 3116 if (!first) 3117 (void) printf(" "); 3118 else 3119 first = B_FALSE; 3120 3121 right_justify = B_FALSE; 3122 if (pl->pl_prop != ZPROP_INVAL) { 3123 header = zpool_prop_column_name(pl->pl_prop); 3124 right_justify = zpool_prop_align_right(pl->pl_prop); 3125 } else { 3126 int i; 3127 3128 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 3129 headerbuf[i] = toupper(pl->pl_user_prop[i]); 3130 headerbuf[i] = '\0'; 3131 header = headerbuf; 3132 } 3133 3134 if (pl->pl_next == NULL && !right_justify) 3135 (void) printf("%s", header); 3136 else if (right_justify) 3137 (void) printf("%*s", width, header); 3138 else 3139 (void) printf("%-*s", width, header); 3140 3141 } 3142 3143 (void) printf("\n"); 3144} 3145 3146/* 3147 * Given a pool and a list of properties, print out all the properties according 3148 * to the described layout. 3149 */ 3150static void 3151print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 3152{ 3153 zprop_list_t *pl = cb->cb_proplist; 3154 boolean_t first = B_TRUE; 3155 char property[ZPOOL_MAXPROPLEN]; 3156 char *propstr; 3157 boolean_t right_justify; 3158 size_t width; 3159 3160 for (; pl != NULL; pl = pl->pl_next) { 3161 3162 width = pl->pl_width; 3163 if (first && cb->cb_verbose) { 3164 /* 3165 * Reset the width to accommodate the verbose listing 3166 * of devices. 3167 */ 3168 width = cb->cb_namewidth; 3169 } 3170 3171 if (!first) { 3172 if (cb->cb_scripted) 3173 (void) printf("\t"); 3174 else 3175 (void) printf(" "); 3176 } else { 3177 first = B_FALSE; 3178 } 3179 3180 right_justify = B_FALSE; 3181 if (pl->pl_prop != ZPROP_INVAL) { 3182 if (zpool_get_prop(zhp, pl->pl_prop, property, 3183 sizeof (property), NULL, cb->cb_literal) != 0) 3184 propstr = "-"; 3185 else 3186 propstr = property; 3187 3188 right_justify = zpool_prop_align_right(pl->pl_prop); 3189 } else if ((zpool_prop_feature(pl->pl_user_prop) || 3190 zpool_prop_unsupported(pl->pl_user_prop)) && 3191 zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 3192 sizeof (property)) == 0) { 3193 propstr = property; 3194 } else { 3195 propstr = "-"; 3196 } 3197 3198 3199 /* 3200 * If this is being called in scripted mode, or if this is the 3201 * last column and it is left-justified, don't include a width 3202 * format specifier. 3203 */ 3204 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 3205 (void) printf("%s", propstr); 3206 else if (right_justify) 3207 (void) printf("%*s", width, propstr); 3208 else 3209 (void) printf("%-*s", width, propstr); 3210 } 3211 3212 (void) printf("\n"); 3213} 3214 3215static void 3216print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 3217 boolean_t valid) 3218{ 3219 char propval[64]; 3220 boolean_t fixed; 3221 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 3222 3223 switch (prop) { 3224 case ZPOOL_PROP_EXPANDSZ: 3225 case ZPOOL_PROP_CHECKPOINT: 3226 if (value == 0) 3227 (void) strlcpy(propval, "-", sizeof (propval)); 3228 else 3229 zfs_nicenum(value, propval, sizeof (propval)); 3230 break; 3231 case ZPOOL_PROP_FRAGMENTATION: 3232 if (value == ZFS_FRAG_INVALID) { 3233 (void) strlcpy(propval, "-", sizeof (propval)); 3234 } else { 3235 (void) snprintf(propval, sizeof (propval), "%llu%%", 3236 value); 3237 } 3238 break; 3239 case ZPOOL_PROP_CAPACITY: 3240 (void) snprintf(propval, sizeof (propval), "%llu%%", value); 3241 break; 3242 default: 3243 zfs_nicenum(value, propval, sizeof (propval)); 3244 } 3245 3246 if (!valid) 3247 (void) strlcpy(propval, "-", sizeof (propval)); 3248 3249 if (scripted) 3250 (void) printf("\t%s", propval); 3251 else 3252 (void) printf(" %*s", width, propval); 3253} 3254 3255void 3256print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 3257 list_cbdata_t *cb, int depth) 3258{ 3259 nvlist_t **child; 3260 vdev_stat_t *vs; 3261 uint_t c, children; 3262 char *vname; 3263 boolean_t scripted = cb->cb_scripted; 3264 uint64_t islog = B_FALSE; 3265 boolean_t haslog = B_FALSE; 3266 char *dashes = "%-*s - - - - - -\n"; 3267 3268 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 3269 (uint64_t **)&vs, &c) == 0); 3270 3271 if (name != NULL) { 3272 boolean_t toplevel = (vs->vs_space != 0); 3273 uint64_t cap; 3274 3275 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 3276 return; 3277 3278 if (scripted) 3279 (void) printf("\t%s", name); 3280 else if (strlen(name) + depth > cb->cb_namewidth) 3281 (void) printf("%*s%s", depth, "", name); 3282 else 3283 (void) printf("%*s%s%*s", depth, "", name, 3284 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 3285 3286 /* 3287 * Print the properties for the individual vdevs. Some 3288 * properties are only applicable to toplevel vdevs. The 3289 * 'toplevel' boolean value is passed to the print_one_column() 3290 * to indicate that the value is valid. 3291 */ 3292 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 3293 toplevel); 3294 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 3295 toplevel); 3296 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 3297 scripted, toplevel); 3298 print_one_column(ZPOOL_PROP_CHECKPOINT, 3299 vs->vs_checkpoint_space, scripted, toplevel); 3300 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 3301 B_TRUE); 3302 print_one_column(ZPOOL_PROP_FRAGMENTATION, 3303 vs->vs_fragmentation, scripted, 3304 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 3305 cap = (vs->vs_space == 0) ? 0 : 3306 (vs->vs_alloc * 100 / vs->vs_space); 3307 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 3308 (void) printf("\n"); 3309 } 3310 3311 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 3312 &child, &children) != 0) 3313 return; 3314 3315 for (c = 0; c < children; c++) { 3316 uint64_t ishole = B_FALSE; 3317 3318 if (nvlist_lookup_uint64(child[c], 3319 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 3320 continue; 3321 3322 if (nvlist_lookup_uint64(child[c], 3323 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) { 3324 haslog = B_TRUE; 3325 continue; 3326 } 3327 3328 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3329 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3330 free(vname); 3331 } 3332 3333 if (haslog == B_TRUE) { 3334 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3335 (void) printf(dashes, cb->cb_namewidth, "log"); 3336 for (c = 0; c < children; c++) { 3337 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3338 &islog) != 0 || !islog) 3339 continue; 3340 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3341 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3342 free(vname); 3343 } 3344 } 3345 3346 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 3347 &child, &children) == 0 && children > 0) { 3348 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3349 (void) printf(dashes, cb->cb_namewidth, "cache"); 3350 for (c = 0; c < children; c++) { 3351 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3352 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3353 free(vname); 3354 } 3355 } 3356 3357 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 3358 &children) == 0 && children > 0) { 3359 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3360 (void) printf(dashes, cb->cb_namewidth, "spare"); 3361 for (c = 0; c < children; c++) { 3362 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3363 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3364 free(vname); 3365 } 3366 } 3367} 3368 3369 3370/* 3371 * Generic callback function to list a pool. 3372 */ 3373int 3374list_callback(zpool_handle_t *zhp, void *data) 3375{ 3376 list_cbdata_t *cbp = data; 3377 nvlist_t *config; 3378 nvlist_t *nvroot; 3379 3380 config = zpool_get_config(zhp, NULL); 3381 3382 print_pool(zhp, cbp); 3383 if (!cbp->cb_verbose) 3384 return (0); 3385 3386 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3387 &nvroot) == 0); 3388 print_list_stats(zhp, NULL, nvroot, cbp, 0); 3389 3390 return (0); 3391} 3392 3393/* 3394 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3395 * 3396 * -H Scripted mode. Don't display headers, and separate properties 3397 * by a single tab. 3398 * -o List of properties to display. Defaults to 3399 * "name,size,allocated,free,expandsize,fragmentation,capacity," 3400 * "dedupratio,health,altroot" 3401 * -p Diplay values in parsable (exact) format. 3402 * -T Display a timestamp in date(1) or Unix format 3403 * 3404 * List all pools in the system, whether or not they're healthy. Output space 3405 * statistics for each one, as well as health status summary. 3406 */ 3407int 3408zpool_do_list(int argc, char **argv) 3409{ 3410 int c; 3411 int ret; 3412 list_cbdata_t cb = { 0 }; 3413 static char default_props[] = 3414 "name,size,allocated,free,checkpoint,expandsize,fragmentation," 3415 "capacity,dedupratio,health,altroot"; 3416 char *props = default_props; 3417 unsigned long interval = 0, count = 0; 3418 zpool_list_t *list; 3419 boolean_t first = B_TRUE; 3420 3421 /* check options */ 3422 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) { 3423 switch (c) { 3424 case 'H': 3425 cb.cb_scripted = B_TRUE; 3426 break; 3427 case 'o': 3428 props = optarg; 3429 break; 3430 case 'p': 3431 cb.cb_literal = B_TRUE; 3432 break; 3433 case 'T': 3434 get_timestamp_arg(*optarg); 3435 break; 3436 case 'v': 3437 cb.cb_verbose = B_TRUE; 3438 break; 3439 case ':': 3440 (void) fprintf(stderr, gettext("missing argument for " 3441 "'%c' option\n"), optopt); 3442 usage(B_FALSE); 3443 break; 3444 case '?': 3445 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3446 optopt); 3447 usage(B_FALSE); 3448 } 3449 } 3450 3451 argc -= optind; 3452 argv += optind; 3453 3454 get_interval_count(&argc, argv, &interval, &count); 3455 3456 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 3457 usage(B_FALSE); 3458 3459 for (;;) { 3460 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 3461 &ret)) == NULL) 3462 return (1); 3463 3464 if (pool_list_count(list) == 0) 3465 break; 3466 3467 cb.cb_namewidth = 0; 3468 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3469 3470 if (timestamp_fmt != NODATE) 3471 print_timestamp(timestamp_fmt); 3472 3473 if (!cb.cb_scripted && (first || cb.cb_verbose)) { 3474 print_header(&cb); 3475 first = B_FALSE; 3476 } 3477 ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 3478 3479 if (interval == 0) 3480 break; 3481 3482 if (count != 0 && --count == 0) 3483 break; 3484 3485 pool_list_free(list); 3486 (void) sleep(interval); 3487 } 3488 3489 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 3490 (void) printf(gettext("no pools available\n")); 3491 ret = 0; 3492 } 3493 3494 pool_list_free(list); 3495 zprop_free_list(cb.cb_proplist); 3496 return (ret); 3497} 3498 3499static int 3500zpool_do_attach_or_replace(int argc, char **argv, int replacing) 3501{ 3502 boolean_t force = B_FALSE; 3503 int c; 3504 nvlist_t *nvroot; 3505 char *poolname, *old_disk, *new_disk; 3506 zpool_handle_t *zhp; 3507 zpool_boot_label_t boot_type; 3508 uint64_t boot_size; 3509 int ret; 3510 3511 /* check options */ 3512 while ((c = getopt(argc, argv, "f")) != -1) { 3513 switch (c) { 3514 case 'f': 3515 force = B_TRUE; 3516 break; 3517 case '?': 3518 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3519 optopt); 3520 usage(B_FALSE); 3521 } 3522 } 3523 3524 argc -= optind; 3525 argv += optind; 3526 3527 /* get pool name and check number of arguments */ 3528 if (argc < 1) { 3529 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3530 usage(B_FALSE); 3531 } 3532 3533 poolname = argv[0]; 3534 3535 if (argc < 2) { 3536 (void) fprintf(stderr, 3537 gettext("missing <device> specification\n")); 3538 usage(B_FALSE); 3539 } 3540 3541 old_disk = argv[1]; 3542 3543 if (argc < 3) { 3544 if (!replacing) { 3545 (void) fprintf(stderr, 3546 gettext("missing <new_device> specification\n")); 3547 usage(B_FALSE); 3548 } 3549 new_disk = old_disk; 3550 argc -= 1; 3551 argv += 1; 3552 } else { 3553 new_disk = argv[2]; 3554 argc -= 2; 3555 argv += 2; 3556 } 3557 3558 if (argc > 1) { 3559 (void) fprintf(stderr, gettext("too many arguments\n")); 3560 usage(B_FALSE); 3561 } 3562 3563 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3564 return (1); 3565 3566 if (zpool_get_config(zhp, NULL) == NULL) { 3567 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 3568 poolname); 3569 zpool_close(zhp); 3570 return (1); 3571 } 3572 3573 if (zpool_is_bootable(zhp)) 3574 boot_type = ZPOOL_COPY_BOOT_LABEL; 3575 else 3576 boot_type = ZPOOL_NO_BOOT_LABEL; 3577 3578 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 3579 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 3580 boot_type, boot_size, argc, argv); 3581 if (nvroot == NULL) { 3582 zpool_close(zhp); 3583 return (1); 3584 } 3585 3586 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 3587 3588 nvlist_free(nvroot); 3589 zpool_close(zhp); 3590 3591 return (ret); 3592} 3593 3594/* 3595 * zpool replace [-f] <pool> <device> <new_device> 3596 * 3597 * -f Force attach, even if <new_device> appears to be in use. 3598 * 3599 * Replace <device> with <new_device>. 3600 */ 3601/* ARGSUSED */ 3602int 3603zpool_do_replace(int argc, char **argv) 3604{ 3605 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 3606} 3607 3608/* 3609 * zpool attach [-f] <pool> <device> <new_device> 3610 * 3611 * -f Force attach, even if <new_device> appears to be in use. 3612 * 3613 * Attach <new_device> to the mirror containing <device>. If <device> is not 3614 * part of a mirror, then <device> will be transformed into a mirror of 3615 * <device> and <new_device>. In either case, <new_device> will begin life 3616 * with a DTL of [0, now], and will immediately begin to resilver itself. 3617 */ 3618int 3619zpool_do_attach(int argc, char **argv) 3620{ 3621 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 3622} 3623 3624/* 3625 * zpool detach [-f] <pool> <device> 3626 * 3627 * -f Force detach of <device>, even if DTLs argue against it 3628 * (not supported yet) 3629 * 3630 * Detach a device from a mirror. The operation will be refused if <device> 3631 * is the last device in the mirror, or if the DTLs indicate that this device 3632 * has the only valid copy of some data. 3633 */ 3634/* ARGSUSED */ 3635int 3636zpool_do_detach(int argc, char **argv) 3637{ 3638 int c; 3639 char *poolname, *path; 3640 zpool_handle_t *zhp; 3641 int ret; 3642 3643 /* check options */ 3644 while ((c = getopt(argc, argv, "f")) != -1) { 3645 switch (c) { 3646 case 'f': 3647 case '?': 3648 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3649 optopt); 3650 usage(B_FALSE); 3651 } 3652 } 3653 3654 argc -= optind; 3655 argv += optind; 3656 3657 /* get pool name and check number of arguments */ 3658 if (argc < 1) { 3659 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3660 usage(B_FALSE); 3661 } 3662 3663 if (argc < 2) { 3664 (void) fprintf(stderr, 3665 gettext("missing <device> specification\n")); 3666 usage(B_FALSE); 3667 } 3668 3669 poolname = argv[0]; 3670 path = argv[1]; 3671 3672 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3673 return (1); 3674 3675 ret = zpool_vdev_detach(zhp, path); 3676 3677 zpool_close(zhp); 3678 3679 return (ret); 3680} 3681 3682/* 3683 * zpool split [-n] [-o prop=val] ... 3684 * [-o mntopt] ... 3685 * [-R altroot] <pool> <newpool> [<device> ...] 3686 * 3687 * -n Do not split the pool, but display the resulting layout if 3688 * it were to be split. 3689 * -o Set property=value, or set mount options. 3690 * -R Mount the split-off pool under an alternate root. 3691 * 3692 * Splits the named pool and gives it the new pool name. Devices to be split 3693 * off may be listed, provided that no more than one device is specified 3694 * per top-level vdev mirror. The newly split pool is left in an exported 3695 * state unless -R is specified. 3696 * 3697 * Restrictions: the top-level of the pool pool must only be made up of 3698 * mirrors; all devices in the pool must be healthy; no device may be 3699 * undergoing a resilvering operation. 3700 */ 3701int 3702zpool_do_split(int argc, char **argv) 3703{ 3704 char *srcpool, *newpool, *propval; 3705 char *mntopts = NULL; 3706 splitflags_t flags; 3707 int c, ret = 0; 3708 zpool_handle_t *zhp; 3709 nvlist_t *config, *props = NULL; 3710 3711 flags.dryrun = B_FALSE; 3712 flags.import = B_FALSE; 3713 3714 /* check options */ 3715 while ((c = getopt(argc, argv, ":R:no:")) != -1) { 3716 switch (c) { 3717 case 'R': 3718 flags.import = B_TRUE; 3719 if (add_prop_list( 3720 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 3721 &props, B_TRUE) != 0) { 3722 nvlist_free(props); 3723 usage(B_FALSE); 3724 } 3725 break; 3726 case 'n': 3727 flags.dryrun = B_TRUE; 3728 break; 3729 case 'o': 3730 if ((propval = strchr(optarg, '=')) != NULL) { 3731 *propval = '\0'; 3732 propval++; 3733 if (add_prop_list(optarg, propval, 3734 &props, B_TRUE) != 0) { 3735 nvlist_free(props); 3736 usage(B_FALSE); 3737 } 3738 } else { 3739 mntopts = optarg; 3740 } 3741 break; 3742 case ':': 3743 (void) fprintf(stderr, gettext("missing argument for " 3744 "'%c' option\n"), optopt); 3745 usage(B_FALSE); 3746 break; 3747 case '?': 3748 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3749 optopt); 3750 usage(B_FALSE); 3751 break; 3752 } 3753 } 3754 3755 if (!flags.import && mntopts != NULL) { 3756 (void) fprintf(stderr, gettext("setting mntopts is only " 3757 "valid when importing the pool\n")); 3758 usage(B_FALSE); 3759 } 3760 3761 argc -= optind; 3762 argv += optind; 3763 3764 if (argc < 1) { 3765 (void) fprintf(stderr, gettext("Missing pool name\n")); 3766 usage(B_FALSE); 3767 } 3768 if (argc < 2) { 3769 (void) fprintf(stderr, gettext("Missing new pool name\n")); 3770 usage(B_FALSE); 3771 } 3772 3773 srcpool = argv[0]; 3774 newpool = argv[1]; 3775 3776 argc -= 2; 3777 argv += 2; 3778 3779 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 3780 return (1); 3781 3782 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 3783 if (config == NULL) { 3784 ret = 1; 3785 } else { 3786 if (flags.dryrun) { 3787 (void) printf(gettext("would create '%s' with the " 3788 "following layout:\n\n"), newpool); 3789 print_vdev_tree(NULL, newpool, config, 0, B_FALSE); 3790 } 3791 nvlist_free(config); 3792 } 3793 3794 zpool_close(zhp); 3795 3796 if (ret != 0 || flags.dryrun || !flags.import) 3797 return (ret); 3798 3799 /* 3800 * The split was successful. Now we need to open the new 3801 * pool and import it. 3802 */ 3803 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 3804 return (1); 3805 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 3806 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 3807 ret = 1; 3808 (void) fprintf(stderr, gettext("Split was successful, but " 3809 "the datasets could not all be mounted\n")); 3810 (void) fprintf(stderr, gettext("Try doing '%s' with a " 3811 "different altroot\n"), "zpool import"); 3812 } 3813 zpool_close(zhp); 3814 3815 return (ret); 3816} 3817 3818 3819 3820/* 3821 * zpool online <pool> <device> ... 3822 */ 3823int 3824zpool_do_online(int argc, char **argv) 3825{ 3826 int c, i; 3827 char *poolname; 3828 zpool_handle_t *zhp; 3829 int ret = 0; 3830 vdev_state_t newstate; 3831 int flags = 0; 3832 3833 /* check options */ 3834 while ((c = getopt(argc, argv, "et")) != -1) { 3835 switch (c) { 3836 case 'e': 3837 flags |= ZFS_ONLINE_EXPAND; 3838 break; 3839 case 't': 3840 case '?': 3841 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3842 optopt); 3843 usage(B_FALSE); 3844 } 3845 } 3846 3847 argc -= optind; 3848 argv += optind; 3849 3850 /* get pool name and check number of arguments */ 3851 if (argc < 1) { 3852 (void) fprintf(stderr, gettext("missing pool name\n")); 3853 usage(B_FALSE); 3854 } 3855 if (argc < 2) { 3856 (void) fprintf(stderr, gettext("missing device name\n")); 3857 usage(B_FALSE); 3858 } 3859 3860 poolname = argv[0]; 3861 3862 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3863 return (1); 3864 3865 for (i = 1; i < argc; i++) { 3866 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 3867 if (newstate != VDEV_STATE_HEALTHY) { 3868 (void) printf(gettext("warning: device '%s' " 3869 "onlined, but remains in faulted state\n"), 3870 argv[i]); 3871 if (newstate == VDEV_STATE_FAULTED) 3872 (void) printf(gettext("use 'zpool " 3873 "clear' to restore a faulted " 3874 "device\n")); 3875 else 3876 (void) printf(gettext("use 'zpool " 3877 "replace' to replace devices " 3878 "that are no longer present\n")); 3879 } 3880 } else { 3881 ret = 1; 3882 } 3883 } 3884 3885 zpool_close(zhp); 3886 3887 return (ret); 3888} 3889 3890/* 3891 * zpool offline [-ft] <pool> <device> ... 3892 * 3893 * -f Force the device into the offline state, even if doing 3894 * so would appear to compromise pool availability. 3895 * (not supported yet) 3896 * 3897 * -t Only take the device off-line temporarily. The offline 3898 * state will not be persistent across reboots. 3899 */ 3900/* ARGSUSED */ 3901int 3902zpool_do_offline(int argc, char **argv) 3903{ 3904 int c, i; 3905 char *poolname; 3906 zpool_handle_t *zhp; 3907 int ret = 0; 3908 boolean_t istmp = B_FALSE; 3909 3910 /* check options */ 3911 while ((c = getopt(argc, argv, "ft")) != -1) { 3912 switch (c) { 3913 case 't': 3914 istmp = B_TRUE; 3915 break; 3916 case 'f': 3917 case '?': 3918 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3919 optopt); 3920 usage(B_FALSE); 3921 } 3922 } 3923 3924 argc -= optind; 3925 argv += optind; 3926 3927 /* get pool name and check number of arguments */ 3928 if (argc < 1) { 3929 (void) fprintf(stderr, gettext("missing pool name\n")); 3930 usage(B_FALSE); 3931 } 3932 if (argc < 2) { 3933 (void) fprintf(stderr, gettext("missing device name\n")); 3934 usage(B_FALSE); 3935 } 3936 3937 poolname = argv[0]; 3938 3939 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3940 return (1); 3941 3942 for (i = 1; i < argc; i++) { 3943 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 3944 ret = 1; 3945 } 3946 3947 zpool_close(zhp); 3948 3949 return (ret); 3950} 3951 3952/* 3953 * zpool clear <pool> [device] 3954 * 3955 * Clear all errors associated with a pool or a particular device. 3956 */ 3957int 3958zpool_do_clear(int argc, char **argv) 3959{ 3960 int c; 3961 int ret = 0; 3962 boolean_t dryrun = B_FALSE; 3963 boolean_t do_rewind = B_FALSE; 3964 boolean_t xtreme_rewind = B_FALSE; 3965 uint32_t rewind_policy = ZPOOL_NO_REWIND; 3966 nvlist_t *policy = NULL; 3967 zpool_handle_t *zhp; 3968 char *pool, *device; 3969 3970 /* check options */ 3971 while ((c = getopt(argc, argv, "FnX")) != -1) { 3972 switch (c) { 3973 case 'F': 3974 do_rewind = B_TRUE; 3975 break; 3976 case 'n': 3977 dryrun = B_TRUE; 3978 break; 3979 case 'X': 3980 xtreme_rewind = B_TRUE; 3981 break; 3982 case '?': 3983 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3984 optopt); 3985 usage(B_FALSE); 3986 } 3987 } 3988 3989 argc -= optind; 3990 argv += optind; 3991 3992 if (argc < 1) { 3993 (void) fprintf(stderr, gettext("missing pool name\n")); 3994 usage(B_FALSE); 3995 } 3996 3997 if (argc > 2) { 3998 (void) fprintf(stderr, gettext("too many arguments\n")); 3999 usage(B_FALSE); 4000 } 4001 4002 if ((dryrun || xtreme_rewind) && !do_rewind) { 4003 (void) fprintf(stderr, 4004 gettext("-n or -X only meaningful with -F\n")); 4005 usage(B_FALSE); 4006 } 4007 if (dryrun) 4008 rewind_policy = ZPOOL_TRY_REWIND; 4009 else if (do_rewind) 4010 rewind_policy = ZPOOL_DO_REWIND; 4011 if (xtreme_rewind) 4012 rewind_policy |= ZPOOL_EXTREME_REWIND; 4013 4014 /* In future, further rewind policy choices can be passed along here */ 4015 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 4016 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 4017 rewind_policy) != 0) { 4018 return (1); 4019 } 4020 4021 pool = argv[0]; 4022 device = argc == 2 ? argv[1] : NULL; 4023 4024 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 4025 nvlist_free(policy); 4026 return (1); 4027 } 4028 4029 if (zpool_clear(zhp, device, policy) != 0) 4030 ret = 1; 4031 4032 zpool_close(zhp); 4033 4034 nvlist_free(policy); 4035 4036 return (ret); 4037} 4038 4039/* 4040 * zpool reguid <pool> 4041 */ 4042int 4043zpool_do_reguid(int argc, char **argv) 4044{ 4045 int c; 4046 char *poolname; 4047 zpool_handle_t *zhp; 4048 int ret = 0; 4049 4050 /* check options */ 4051 while ((c = getopt(argc, argv, "")) != -1) { 4052 switch (c) { 4053 case '?': 4054 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4055 optopt); 4056 usage(B_FALSE); 4057 } 4058 } 4059 4060 argc -= optind; 4061 argv += optind; 4062 4063 /* get pool name and check number of arguments */ 4064 if (argc < 1) { 4065 (void) fprintf(stderr, gettext("missing pool name\n")); 4066 usage(B_FALSE); 4067 } 4068 4069 if (argc > 1) { 4070 (void) fprintf(stderr, gettext("too many arguments\n")); 4071 usage(B_FALSE); 4072 } 4073 4074 poolname = argv[0]; 4075 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4076 return (1); 4077 4078 ret = zpool_reguid(zhp); 4079 4080 zpool_close(zhp); 4081 return (ret); 4082} 4083 4084 4085/* 4086 * zpool reopen <pool> 4087 * 4088 * Reopen the pool so that the kernel can update the sizes of all vdevs. 4089 */ 4090int 4091zpool_do_reopen(int argc, char **argv) 4092{ 4093 int c; 4094 int ret = 0; 4095 zpool_handle_t *zhp; 4096 char *pool; 4097 4098 /* check options */ 4099 while ((c = getopt(argc, argv, "")) != -1) { 4100 switch (c) { 4101 case '?': 4102 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4103 optopt); 4104 usage(B_FALSE); 4105 } 4106 } 4107 4108 argc--; 4109 argv++; 4110 4111 if (argc < 1) { 4112 (void) fprintf(stderr, gettext("missing pool name\n")); 4113 usage(B_FALSE); 4114 } 4115 4116 if (argc > 1) { 4117 (void) fprintf(stderr, gettext("too many arguments\n")); 4118 usage(B_FALSE); 4119 } 4120 4121 pool = argv[0]; 4122 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 4123 return (1); 4124 4125 ret = zpool_reopen(zhp); 4126 zpool_close(zhp); 4127 return (ret); 4128} 4129 4130typedef struct scrub_cbdata { 4131 int cb_type; 4132 int cb_argc; 4133 char **cb_argv; 4134 pool_scrub_cmd_t cb_scrub_cmd; 4135} scrub_cbdata_t; 4136 4137static boolean_t 4138zpool_has_checkpoint(zpool_handle_t *zhp) 4139{ 4140 nvlist_t *config, *nvroot; 4141 4142 config = zpool_get_config(zhp, NULL); 4143 4144 if (config != NULL) { 4145 pool_checkpoint_stat_t *pcs = NULL; 4146 uint_t c; 4147 4148 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 4149 (void) nvlist_lookup_uint64_array(nvroot, 4150 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 4151 4152 if (pcs == NULL || pcs->pcs_state == CS_NONE) 4153 return (B_FALSE); 4154 4155 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 4156 pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 4157 return (B_TRUE); 4158 } 4159 4160 return (B_FALSE); 4161} 4162 4163int 4164scrub_callback(zpool_handle_t *zhp, void *data) 4165{ 4166 scrub_cbdata_t *cb = data; 4167 int err; 4168 4169 /* 4170 * Ignore faulted pools. 4171 */ 4172 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 4173 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 4174 "currently unavailable\n"), zpool_get_name(zhp)); 4175 return (1); 4176 } 4177 4178 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 4179 4180 if (err == 0 && zpool_has_checkpoint(zhp) && 4181 cb->cb_type == POOL_SCAN_SCRUB) { 4182 (void) printf(gettext("warning: will not scrub state that " 4183 "belongs to the checkpoint of pool '%s'\n"), 4184 zpool_get_name(zhp)); 4185 } 4186 4187 return (err != 0); 4188} 4189 4190/* 4191 * zpool scrub [-s | -p] <pool> ... 4192 * 4193 * -s Stop. Stops any in-progress scrub. 4194 * -p Pause. Pause in-progress scrub. 4195 */ 4196int 4197zpool_do_scrub(int argc, char **argv) 4198{ 4199 int c; 4200 scrub_cbdata_t cb; 4201 4202 cb.cb_type = POOL_SCAN_SCRUB; 4203 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4204 4205 /* check options */ 4206 while ((c = getopt(argc, argv, "sp")) != -1) { 4207 switch (c) { 4208 case 's': 4209 cb.cb_type = POOL_SCAN_NONE; 4210 break; 4211 case 'p': 4212 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 4213 break; 4214 case '?': 4215 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4216 optopt); 4217 usage(B_FALSE); 4218 } 4219 } 4220 4221 if (cb.cb_type == POOL_SCAN_NONE && 4222 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 4223 (void) fprintf(stderr, gettext("invalid option combination: " 4224 "-s and -p are mutually exclusive\n")); 4225 usage(B_FALSE); 4226 } 4227 4228 cb.cb_argc = argc; 4229 cb.cb_argv = argv; 4230 argc -= optind; 4231 argv += optind; 4232 4233 if (argc < 1) { 4234 (void) fprintf(stderr, gettext("missing pool name argument\n")); 4235 usage(B_FALSE); 4236 } 4237 4238 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4239} 4240 4241typedef struct status_cbdata { 4242 int cb_count; 4243 boolean_t cb_allpools; 4244 boolean_t cb_verbose; 4245 boolean_t cb_explain; 4246 boolean_t cb_first; 4247 boolean_t cb_dedup_stats; 4248} status_cbdata_t; 4249 4250/* 4251 * Print out detailed scrub status. 4252 */ 4253static void 4254print_scan_status(pool_scan_stat_t *ps) 4255{ 4256 time_t start, end, pause; 4257 uint64_t total_secs_left; 4258 uint64_t elapsed, secs_left, mins_left, hours_left, days_left; 4259 uint64_t pass_scanned, scanned, pass_issued, issued, total; 4260 uint_t scan_rate, issue_rate; 4261 double fraction_done; 4262 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; 4263 char srate_buf[7], irate_buf[7]; 4264 4265 (void) printf(gettext(" scan: ")); 4266 4267 /* If there's never been a scan, there's not much to say. */ 4268 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 4269 ps->pss_func >= POOL_SCAN_FUNCS) { 4270 (void) printf(gettext("none requested\n")); 4271 return; 4272 } 4273 4274 start = ps->pss_start_time; 4275 end = ps->pss_end_time; 4276 pause = ps->pss_pass_scrub_pause; 4277 4278 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 4279 4280 assert(ps->pss_func == POOL_SCAN_SCRUB || 4281 ps->pss_func == POOL_SCAN_RESILVER); 4282 4283 /* Scan is finished or canceled. */ 4284 if (ps->pss_state == DSS_FINISHED) { 4285 total_secs_left = end - start; 4286 days_left = total_secs_left / 60 / 60 / 24; 4287 hours_left = (total_secs_left / 60 / 60) % 24; 4288 mins_left = (total_secs_left / 60) % 60; 4289 secs_left = (total_secs_left % 60); 4290 4291 if (ps->pss_func == POOL_SCAN_SCRUB) { 4292 (void) printf(gettext("scrub repaired %s " 4293 "in %llu days %02llu:%02llu:%02llu " 4294 "with %llu errors on %s"), processed_buf, 4295 (u_longlong_t)days_left, (u_longlong_t)hours_left, 4296 (u_longlong_t)mins_left, (u_longlong_t)secs_left, 4297 (u_longlong_t)ps->pss_errors, ctime(&end)); 4298 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4299 (void) printf(gettext("resilvered %s " 4300 "in %llu days %02llu:%02llu:%02llu " 4301 "with %llu errors on %s"), processed_buf, 4302 (u_longlong_t)days_left, (u_longlong_t)hours_left, 4303 (u_longlong_t)mins_left, (u_longlong_t)secs_left, 4304 (u_longlong_t)ps->pss_errors, ctime(&end)); 4305 4306 } 4307 4308 return; 4309 } else if (ps->pss_state == DSS_CANCELED) { 4310 if (ps->pss_func == POOL_SCAN_SCRUB) { 4311 (void) printf(gettext("scrub canceled on %s"), 4312 ctime(&end)); 4313 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4314 (void) printf(gettext("resilver canceled on %s"), 4315 ctime(&end)); 4316 } 4317 return; 4318 } 4319 4320 assert(ps->pss_state == DSS_SCANNING); 4321 4322 /* Scan is in progress. Resilvers can't be paused. */ 4323 if (ps->pss_func == POOL_SCAN_SCRUB) { 4324 if (pause == 0) { 4325 (void) printf(gettext("scrub in progress since %s"), 4326 ctime(&start)); 4327 } else { 4328 (void) printf(gettext("scrub paused since %s"), 4329 ctime(&pause)); 4330 (void) printf(gettext("\tscrub started on %s"), 4331 ctime(&start)); 4332 } 4333 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4334 (void) printf(gettext("resilver in progress since %s"), 4335 ctime(&start)); 4336 } 4337 4338 scanned = ps->pss_examined; 4339 pass_scanned = ps->pss_pass_exam; 4340 issued = ps->pss_issued; 4341 pass_issued = ps->pss_pass_issued; 4342 total = ps->pss_to_examine; 4343 4344 /* we are only done with a block once we have issued the IO for it */ 4345 fraction_done = (double)issued / total; 4346 4347 /* elapsed time for this pass, rounding up to 1 if it's 0 */ 4348 elapsed = time(NULL) - ps->pss_pass_start; 4349 elapsed -= ps->pss_pass_scrub_spent_paused; 4350 elapsed = (elapsed != 0) ? elapsed : 1; 4351 4352 scan_rate = pass_scanned / elapsed; 4353 issue_rate = pass_issued / elapsed; 4354 total_secs_left = (issue_rate != 0) ? 4355 ((total - issued) / issue_rate) : UINT64_MAX; 4356 4357 days_left = total_secs_left / 60 / 60 / 24; 4358 hours_left = (total_secs_left / 60 / 60) % 24; 4359 mins_left = (total_secs_left / 60) % 60; 4360 secs_left = (total_secs_left % 60); 4361 4362 /* format all of the numbers we will be reporting */ 4363 zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf)); 4364 zfs_nicenum(issued, issued_buf, sizeof (issued_buf)); 4365 zfs_nicenum(total, total_buf, sizeof (total_buf)); 4366 zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf)); 4367 zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf)); 4368 4369 /* doo not print estimated time if we have a paused scrub */ 4370 if (pause == 0) { 4371 (void) printf(gettext("\t%s scanned at %s/s, " 4372 "%s issued at %s/s, %s total\n"), 4373 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); 4374 } else { 4375 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), 4376 scanned_buf, issued_buf, total_buf); 4377 } 4378 4379 if (ps->pss_func == POOL_SCAN_RESILVER) { 4380 (void) printf(gettext("\t%s resilvered, %.2f%% done"), 4381 processed_buf, 100 * fraction_done); 4382 } else if (ps->pss_func == POOL_SCAN_SCRUB) { 4383 (void) printf(gettext("\t%s repaired, %.2f%% done"), 4384 processed_buf, 100 * fraction_done); 4385 } 4386 4387 if (pause == 0) { 4388 if (issue_rate >= 10 * 1024 * 1024) { 4389 (void) printf(gettext(", %llu days " 4390 "%02llu:%02llu:%02llu to go\n"), 4391 (u_longlong_t)days_left, (u_longlong_t)hours_left, 4392 (u_longlong_t)mins_left, (u_longlong_t)secs_left); 4393 } else { 4394 (void) printf(gettext(", no estimated " 4395 "completion time\n")); 4396 } 4397 } else { 4398 (void) printf(gettext("\n")); 4399 } 4400} 4401 4402/* 4403 * As we don't scrub checkpointed blocks, we want to warn the 4404 * user that we skipped scanning some blocks if a checkpoint exists 4405 * or existed at any time during the scan. 4406 */ 4407static void 4408print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 4409{ 4410 if (ps == NULL || pcs == NULL) 4411 return; 4412 4413 if (pcs->pcs_state == CS_NONE || 4414 pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 4415 return; 4416 4417 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 4418 4419 if (ps->pss_state == DSS_NONE) 4420 return; 4421 4422 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 4423 ps->pss_end_time < pcs->pcs_start_time) 4424 return; 4425 4426 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 4427 (void) printf(gettext(" scan warning: skipped blocks " 4428 "that are only referenced by the checkpoint.\n")); 4429 } else { 4430 assert(ps->pss_state == DSS_SCANNING); 4431 (void) printf(gettext(" scan warning: skipping blocks " 4432 "that are only referenced by the checkpoint.\n")); 4433 } 4434} 4435 4436/* 4437 * Print out detailed removal status. 4438 */ 4439static void 4440print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 4441{ 4442 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 4443 time_t start, end; 4444 nvlist_t *config, *nvroot; 4445 nvlist_t **child; 4446 uint_t children; 4447 char *vdev_name; 4448 4449 if (prs == NULL || prs->prs_state == DSS_NONE) 4450 return; 4451 4452 /* 4453 * Determine name of vdev. 4454 */ 4455 config = zpool_get_config(zhp, NULL); 4456 nvroot = fnvlist_lookup_nvlist(config, 4457 ZPOOL_CONFIG_VDEV_TREE); 4458 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 4459 &child, &children) == 0); 4460 assert(prs->prs_removing_vdev < children); 4461 vdev_name = zpool_vdev_name(g_zfs, zhp, 4462 child[prs->prs_removing_vdev], B_TRUE); 4463 4464 (void) printf(gettext("remove: ")); 4465 4466 start = prs->prs_start_time; 4467 end = prs->prs_end_time; 4468 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 4469 4470 /* 4471 * Removal is finished or canceled. 4472 */ 4473 if (prs->prs_state == DSS_FINISHED) { 4474 uint64_t minutes_taken = (end - start) / 60; 4475 4476 (void) printf(gettext("Removal of vdev %llu copied %s " 4477 "in %lluh%um, completed on %s"), 4478 (longlong_t)prs->prs_removing_vdev, 4479 copied_buf, 4480 (u_longlong_t)(minutes_taken / 60), 4481 (uint_t)(minutes_taken % 60), 4482 ctime((time_t *)&end)); 4483 } else if (prs->prs_state == DSS_CANCELED) { 4484 (void) printf(gettext("Removal of %s canceled on %s"), 4485 vdev_name, ctime(&end)); 4486 } else { 4487 uint64_t copied, total, elapsed, mins_left, hours_left; 4488 double fraction_done; 4489 uint_t rate; 4490 4491 assert(prs->prs_state == DSS_SCANNING); 4492 4493 /* 4494 * Removal is in progress. 4495 */ 4496 (void) printf(gettext( 4497 "Evacuation of %s in progress since %s"), 4498 vdev_name, ctime(&start)); 4499 4500 copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 4501 total = prs->prs_to_copy; 4502 fraction_done = (double)copied / total; 4503 4504 /* elapsed time for this pass */ 4505 elapsed = time(NULL) - prs->prs_start_time; 4506 elapsed = elapsed > 0 ? elapsed : 1; 4507 rate = copied / elapsed; 4508 rate = rate > 0 ? rate : 1; 4509 mins_left = ((total - copied) / rate) / 60; 4510 hours_left = mins_left / 60; 4511 4512 zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 4513 zfs_nicenum(total, total_buf, sizeof (total_buf)); 4514 zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 4515 4516 /* 4517 * do not print estimated time if hours_left is more than 4518 * 30 days 4519 */ 4520 (void) printf(gettext(" %s copied out of %s at %s/s, " 4521 "%.2f%% done"), 4522 examined_buf, total_buf, rate_buf, 100 * fraction_done); 4523 if (hours_left < (30 * 24)) { 4524 (void) printf(gettext(", %lluh%um to go\n"), 4525 (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 4526 } else { 4527 (void) printf(gettext( 4528 ", (copy is slow, no estimated time)\n")); 4529 } 4530 } 4531 4532 if (prs->prs_mapping_memory > 0) { 4533 char mem_buf[7]; 4534 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 4535 (void) printf(gettext(" %s memory used for " 4536 "removed device mappings\n"), 4537 mem_buf); 4538 } 4539} 4540 4541static void 4542print_checkpoint_status(pool_checkpoint_stat_t *pcs) 4543{ 4544 time_t start; 4545 char space_buf[7]; 4546 4547 if (pcs == NULL || pcs->pcs_state == CS_NONE) 4548 return; 4549 4550 (void) printf(gettext("checkpoint: ")); 4551 4552 start = pcs->pcs_start_time; 4553 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 4554 4555 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 4556 char *date = ctime(&start); 4557 4558 /* 4559 * ctime() adds a newline at the end of the generated 4560 * string, thus the weird format specifier and the 4561 * strlen() call used to chop it off from the output. 4562 */ 4563 (void) printf(gettext("created %.*s, consumes %s\n"), 4564 strlen(date) - 1, date, space_buf); 4565 return; 4566 } 4567 4568 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 4569 4570 (void) printf(gettext("discarding, %s remaining.\n"), 4571 space_buf); 4572} 4573 4574static void 4575print_error_log(zpool_handle_t *zhp) 4576{ 4577 nvlist_t *nverrlist = NULL; 4578 nvpair_t *elem; 4579 char *pathname; 4580 size_t len = MAXPATHLEN * 2; 4581 4582 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 4583 (void) printf("errors: List of errors unavailable " 4584 "(insufficient privileges)\n"); 4585 return; 4586 } 4587 4588 (void) printf("errors: Permanent errors have been " 4589 "detected in the following files:\n\n"); 4590 4591 pathname = safe_malloc(len); 4592 elem = NULL; 4593 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 4594 nvlist_t *nv; 4595 uint64_t dsobj, obj; 4596 4597 verify(nvpair_value_nvlist(elem, &nv) == 0); 4598 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 4599 &dsobj) == 0); 4600 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 4601 &obj) == 0); 4602 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 4603 (void) printf("%7s %s\n", "", pathname); 4604 } 4605 free(pathname); 4606 nvlist_free(nverrlist); 4607} 4608 4609static void 4610print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 4611 int namewidth) 4612{ 4613 uint_t i; 4614 char *name; 4615 4616 if (nspares == 0) 4617 return; 4618 4619 (void) printf(gettext("\tspares\n")); 4620 4621 for (i = 0; i < nspares; i++) { 4622 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); 4623 print_status_config(zhp, name, spares[i], 4624 namewidth, 2, B_TRUE); 4625 free(name); 4626 } 4627} 4628 4629static void 4630print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 4631 int namewidth) 4632{ 4633 uint_t i; 4634 char *name; 4635 4636 if (nl2cache == 0) 4637 return; 4638 4639 (void) printf(gettext("\tcache\n")); 4640 4641 for (i = 0; i < nl2cache; i++) { 4642 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE); 4643 print_status_config(zhp, name, l2cache[i], 4644 namewidth, 2, B_FALSE); 4645 free(name); 4646 } 4647} 4648 4649static void 4650print_dedup_stats(nvlist_t *config) 4651{ 4652 ddt_histogram_t *ddh; 4653 ddt_stat_t *dds; 4654 ddt_object_t *ddo; 4655 uint_t c; 4656 4657 /* 4658 * If the pool was faulted then we may not have been able to 4659 * obtain the config. Otherwise, if we have anything in the dedup 4660 * table continue processing the stats. 4661 */ 4662 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 4663 (uint64_t **)&ddo, &c) != 0) 4664 return; 4665 4666 (void) printf("\n"); 4667 (void) printf(gettext(" dedup: ")); 4668 if (ddo->ddo_count == 0) { 4669 (void) printf(gettext("no DDT entries\n")); 4670 return; 4671 } 4672 4673 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 4674 (u_longlong_t)ddo->ddo_count, 4675 (u_longlong_t)ddo->ddo_dspace, 4676 (u_longlong_t)ddo->ddo_mspace); 4677 4678 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 4679 (uint64_t **)&dds, &c) == 0); 4680 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 4681 (uint64_t **)&ddh, &c) == 0); 4682 zpool_dump_ddt(dds, ddh); 4683} 4684 4685/* 4686 * Display a summary of pool status. Displays a summary such as: 4687 * 4688 * pool: tank 4689 * status: DEGRADED 4690 * reason: One or more devices ... 4691 * see: http://illumos.org/msg/ZFS-xxxx-01 4692 * config: 4693 * mirror DEGRADED 4694 * c1t0d0 OK 4695 * c2t0d0 UNAVAIL 4696 * 4697 * When given the '-v' option, we print out the complete config. If the '-e' 4698 * option is specified, then we print out error rate information as well. 4699 */ 4700int 4701status_callback(zpool_handle_t *zhp, void *data) 4702{ 4703 status_cbdata_t *cbp = data; 4704 nvlist_t *config, *nvroot; 4705 char *msgid; 4706 int reason; 4707 const char *health; 4708 uint_t c; 4709 vdev_stat_t *vs; 4710 4711 config = zpool_get_config(zhp, NULL); 4712 reason = zpool_get_status(zhp, &msgid); 4713 4714 cbp->cb_count++; 4715 4716 /* 4717 * If we were given 'zpool status -x', only report those pools with 4718 * problems. 4719 */ 4720 if (cbp->cb_explain && 4721 (reason == ZPOOL_STATUS_OK || 4722 reason == ZPOOL_STATUS_VERSION_OLDER || 4723 reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT || 4724 reason == ZPOOL_STATUS_FEAT_DISABLED)) { 4725 if (!cbp->cb_allpools) { 4726 (void) printf(gettext("pool '%s' is healthy\n"), 4727 zpool_get_name(zhp)); 4728 if (cbp->cb_first) 4729 cbp->cb_first = B_FALSE; 4730 } 4731 return (0); 4732 } 4733 4734 if (cbp->cb_first) 4735 cbp->cb_first = B_FALSE; 4736 else 4737 (void) printf("\n"); 4738 4739 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 4740 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 4741 (uint64_t **)&vs, &c) == 0); 4742 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 4743 4744 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 4745 (void) printf(gettext(" state: %s\n"), health); 4746 4747 switch (reason) { 4748 case ZPOOL_STATUS_MISSING_DEV_R: 4749 (void) printf(gettext("status: One or more devices could not " 4750 "be opened. Sufficient replicas exist for\n\tthe pool to " 4751 "continue functioning in a degraded state.\n")); 4752 (void) printf(gettext("action: Attach the missing device and " 4753 "online it using 'zpool online'.\n")); 4754 break; 4755 4756 case ZPOOL_STATUS_MISSING_DEV_NR: 4757 (void) printf(gettext("status: One or more devices could not " 4758 "be opened. There are insufficient\n\treplicas for the " 4759 "pool to continue functioning.\n")); 4760 (void) printf(gettext("action: Attach the missing device and " 4761 "online it using 'zpool online'.\n")); 4762 break; 4763 4764 case ZPOOL_STATUS_CORRUPT_LABEL_R: 4765 (void) printf(gettext("status: One or more devices could not " 4766 "be used because the label is missing or\n\tinvalid. " 4767 "Sufficient replicas exist for the pool to continue\n\t" 4768 "functioning in a degraded state.\n")); 4769 (void) printf(gettext("action: Replace the device using " 4770 "'zpool replace'.\n")); 4771 break; 4772 4773 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 4774 (void) printf(gettext("status: One or more devices could not " 4775 "be used because the label is missing \n\tor invalid. " 4776 "There are insufficient replicas for the pool to " 4777 "continue\n\tfunctioning.\n")); 4778 zpool_explain_recover(zpool_get_handle(zhp), 4779 zpool_get_name(zhp), reason, config); 4780 break; 4781 4782 case ZPOOL_STATUS_FAILING_DEV: 4783 (void) printf(gettext("status: One or more devices has " 4784 "experienced an unrecoverable error. An\n\tattempt was " 4785 "made to correct the error. Applications are " 4786 "unaffected.\n")); 4787 (void) printf(gettext("action: Determine if the device needs " 4788 "to be replaced, and clear the errors\n\tusing " 4789 "'zpool clear' or replace the device with 'zpool " 4790 "replace'.\n")); 4791 break; 4792 4793 case ZPOOL_STATUS_OFFLINE_DEV: 4794 (void) printf(gettext("status: One or more devices has " 4795 "been taken offline by the administrator.\n\tSufficient " 4796 "replicas exist for the pool to continue functioning in " 4797 "a\n\tdegraded state.\n")); 4798 (void) printf(gettext("action: Online the device using " 4799 "'zpool online' or replace the device with\n\t'zpool " 4800 "replace'.\n")); 4801 break; 4802 4803 case ZPOOL_STATUS_REMOVED_DEV: 4804 (void) printf(gettext("status: One or more devices has " 4805 "been removed by the administrator.\n\tSufficient " 4806 "replicas exist for the pool to continue functioning in " 4807 "a\n\tdegraded state.\n")); 4808 (void) printf(gettext("action: Online the device using " 4809 "'zpool online' or replace the device with\n\t'zpool " 4810 "replace'.\n")); 4811 break; 4812 4813 case ZPOOL_STATUS_RESILVERING: 4814 (void) printf(gettext("status: One or more devices is " 4815 "currently being resilvered. The pool will\n\tcontinue " 4816 "to function, possibly in a degraded state.\n")); 4817 (void) printf(gettext("action: Wait for the resilver to " 4818 "complete.\n")); 4819 break; 4820 4821 case ZPOOL_STATUS_CORRUPT_DATA: 4822 (void) printf(gettext("status: One or more devices has " 4823 "experienced an error resulting in data\n\tcorruption. " 4824 "Applications may be affected.\n")); 4825 (void) printf(gettext("action: Restore the file in question " 4826 "if possible. Otherwise restore the\n\tentire pool from " 4827 "backup.\n")); 4828 break; 4829 4830 case ZPOOL_STATUS_CORRUPT_POOL: 4831 (void) printf(gettext("status: The pool metadata is corrupted " 4832 "and the pool cannot be opened.\n")); 4833 zpool_explain_recover(zpool_get_handle(zhp), 4834 zpool_get_name(zhp), reason, config); 4835 break; 4836 4837 case ZPOOL_STATUS_VERSION_OLDER: 4838 (void) printf(gettext("status: The pool is formatted using a " 4839 "legacy on-disk format. The pool can\n\tstill be used, " 4840 "but some features are unavailable.\n")); 4841 (void) printf(gettext("action: Upgrade the pool using 'zpool " 4842 "upgrade'. Once this is done, the\n\tpool will no longer " 4843 "be accessible on software that does not support feature\n" 4844 "\tflags.\n")); 4845 break; 4846 4847 case ZPOOL_STATUS_VERSION_NEWER: 4848 (void) printf(gettext("status: The pool has been upgraded to a " 4849 "newer, incompatible on-disk version.\n\tThe pool cannot " 4850 "be accessed on this system.\n")); 4851 (void) printf(gettext("action: Access the pool from a system " 4852 "running more recent software, or\n\trestore the pool from " 4853 "backup.\n")); 4854 break; 4855 4856 case ZPOOL_STATUS_FEAT_DISABLED: 4857 (void) printf(gettext("status: Some supported features are not " 4858 "enabled on the pool. The pool can\n\tstill be used, but " 4859 "some features are unavailable.\n")); 4860 (void) printf(gettext("action: Enable all features using " 4861 "'zpool upgrade'. Once this is done,\n\tthe pool may no " 4862 "longer be accessible by software that does not support\n\t" 4863 "the features. See zpool-features(7) for details.\n")); 4864 break; 4865 4866 case ZPOOL_STATUS_UNSUP_FEAT_READ: 4867 (void) printf(gettext("status: The pool cannot be accessed on " 4868 "this system because it uses the\n\tfollowing feature(s) " 4869 "not supported on this system:\n")); 4870 zpool_print_unsup_feat(config); 4871 (void) printf("\n"); 4872 (void) printf(gettext("action: Access the pool from a system " 4873 "that supports the required feature(s),\n\tor restore the " 4874 "pool from backup.\n")); 4875 break; 4876 4877 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 4878 (void) printf(gettext("status: The pool can only be accessed " 4879 "in read-only mode on this system. It\n\tcannot be " 4880 "accessed in read-write mode because it uses the " 4881 "following\n\tfeature(s) not supported on this system:\n")); 4882 zpool_print_unsup_feat(config); 4883 (void) printf("\n"); 4884 (void) printf(gettext("action: The pool cannot be accessed in " 4885 "read-write mode. Import the pool with\n" 4886 "\t\"-o readonly=on\", access the pool from a system that " 4887 "supports the\n\trequired feature(s), or restore the " 4888 "pool from backup.\n")); 4889 break; 4890 4891 case ZPOOL_STATUS_FAULTED_DEV_R: 4892 (void) printf(gettext("status: One or more devices are " 4893 "faulted in response to persistent errors.\n\tSufficient " 4894 "replicas exist for the pool to continue functioning " 4895 "in a\n\tdegraded state.\n")); 4896 (void) printf(gettext("action: Replace the faulted device, " 4897 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 4898 break; 4899 4900 case ZPOOL_STATUS_FAULTED_DEV_NR: 4901 (void) printf(gettext("status: One or more devices are " 4902 "faulted in response to persistent errors. There are " 4903 "insufficient replicas for the pool to\n\tcontinue " 4904 "functioning.\n")); 4905 (void) printf(gettext("action: Destroy and re-create the pool " 4906 "from a backup source. Manually marking the device\n" 4907 "\trepaired using 'zpool clear' may allow some data " 4908 "to be recovered.\n")); 4909 break; 4910 4911 case ZPOOL_STATUS_IO_FAILURE_WAIT: 4912 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 4913 (void) printf(gettext("status: One or more devices are " 4914 "faulted in response to IO failures.\n")); 4915 (void) printf(gettext("action: Make sure the affected devices " 4916 "are connected, then run 'zpool clear'.\n")); 4917 break; 4918 4919 case ZPOOL_STATUS_BAD_LOG: 4920 (void) printf(gettext("status: An intent log record " 4921 "could not be read.\n" 4922 "\tWaiting for adminstrator intervention to fix the " 4923 "faulted pool.\n")); 4924 (void) printf(gettext("action: Either restore the affected " 4925 "device(s) and run 'zpool online',\n" 4926 "\tor ignore the intent log records by running " 4927 "'zpool clear'.\n")); 4928 break; 4929 4930 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 4931 (void) printf(gettext("status: One or more devices are " 4932 "configured to use a non-native block size.\n" 4933 "\tExpect reduced performance.\n")); 4934 (void) printf(gettext("action: Replace affected devices with " 4935 "devices that support the\n\tconfigured block size, or " 4936 "migrate data to a properly configured\n\tpool.\n")); 4937 break; 4938 4939 default: 4940 /* 4941 * The remaining errors can't actually be generated, yet. 4942 */ 4943 assert(reason == ZPOOL_STATUS_OK); 4944 } 4945 4946 if (msgid != NULL) 4947 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 4948 msgid); 4949 4950 if (config != NULL) { 4951 int namewidth; 4952 uint64_t nerr; 4953 nvlist_t **spares, **l2cache; 4954 uint_t nspares, nl2cache; 4955 pool_checkpoint_stat_t *pcs = NULL; 4956 pool_scan_stat_t *ps = NULL; 4957 pool_removal_stat_t *prs = NULL; 4958 4959 (void) nvlist_lookup_uint64_array(nvroot, 4960 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 4961 (void) nvlist_lookup_uint64_array(nvroot, 4962 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 4963 (void) nvlist_lookup_uint64_array(nvroot, 4964 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 4965 4966 print_scan_status(ps); 4967 print_checkpoint_scan_warning(ps, pcs); 4968 print_removal_status(zhp, prs); 4969 print_checkpoint_status(pcs); 4970 4971 namewidth = max_width(zhp, nvroot, 0, 0); 4972 if (namewidth < 10) 4973 namewidth = 10; 4974 4975 (void) printf(gettext("config:\n\n")); 4976 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 4977 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 4978 print_status_config(zhp, zpool_get_name(zhp), nvroot, 4979 namewidth, 0, B_FALSE); 4980 4981 if (num_logs(nvroot) > 0) 4982 print_logs(zhp, nvroot, namewidth, B_TRUE); 4983 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 4984 &l2cache, &nl2cache) == 0) 4985 print_l2cache(zhp, l2cache, nl2cache, namewidth); 4986 4987 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 4988 &spares, &nspares) == 0) 4989 print_spares(zhp, spares, nspares, namewidth); 4990 4991 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 4992 &nerr) == 0) { 4993 nvlist_t *nverrlist = NULL; 4994 4995 /* 4996 * If the approximate error count is small, get a 4997 * precise count by fetching the entire log and 4998 * uniquifying the results. 4999 */ 5000 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 5001 zpool_get_errlog(zhp, &nverrlist) == 0) { 5002 nvpair_t *elem; 5003 5004 elem = NULL; 5005 nerr = 0; 5006 while ((elem = nvlist_next_nvpair(nverrlist, 5007 elem)) != NULL) { 5008 nerr++; 5009 } 5010 } 5011 nvlist_free(nverrlist); 5012 5013 (void) printf("\n"); 5014 5015 if (nerr == 0) 5016 (void) printf(gettext("errors: No known data " 5017 "errors\n")); 5018 else if (!cbp->cb_verbose) 5019 (void) printf(gettext("errors: %llu data " 5020 "errors, use '-v' for a list\n"), 5021 (u_longlong_t)nerr); 5022 else 5023 print_error_log(zhp); 5024 } 5025 5026 if (cbp->cb_dedup_stats) 5027 print_dedup_stats(config); 5028 } else { 5029 (void) printf(gettext("config: The configuration cannot be " 5030 "determined.\n")); 5031 } 5032 5033 return (0); 5034} 5035 5036/* 5037 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]] 5038 * 5039 * -v Display complete error logs 5040 * -x Display only pools with potential problems 5041 * -D Display dedup status (undocumented) 5042 * -T Display a timestamp in date(1) or Unix format 5043 * 5044 * Describes the health status of all pools or some subset. 5045 */ 5046int 5047zpool_do_status(int argc, char **argv) 5048{ 5049 int c; 5050 int ret; 5051 unsigned long interval = 0, count = 0; 5052 status_cbdata_t cb = { 0 }; 5053 5054 /* check options */ 5055 while ((c = getopt(argc, argv, "vxDT:")) != -1) { 5056 switch (c) { 5057 case 'v': 5058 cb.cb_verbose = B_TRUE; 5059 break; 5060 case 'x': 5061 cb.cb_explain = B_TRUE; 5062 break; 5063 case 'D': 5064 cb.cb_dedup_stats = B_TRUE; 5065 break; 5066 case 'T': 5067 get_timestamp_arg(*optarg); 5068 break; 5069 case '?': 5070 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5071 optopt); 5072 usage(B_FALSE); 5073 } 5074 } 5075 5076 argc -= optind; 5077 argv += optind; 5078 5079 get_interval_count(&argc, argv, &interval, &count); 5080 5081 if (argc == 0) 5082 cb.cb_allpools = B_TRUE; 5083 5084 cb.cb_first = B_TRUE; 5085 5086 for (;;) { 5087 if (timestamp_fmt != NODATE) 5088 print_timestamp(timestamp_fmt); 5089 5090 ret = for_each_pool(argc, argv, B_TRUE, NULL, 5091 status_callback, &cb); 5092 5093 if (argc == 0 && cb.cb_count == 0) 5094 (void) printf(gettext("no pools available\n")); 5095 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 5096 (void) printf(gettext("all pools are healthy\n")); 5097 5098 if (ret != 0) 5099 return (ret); 5100 5101 if (interval == 0) 5102 break; 5103 5104 if (count != 0 && --count == 0) 5105 break; 5106 5107 (void) sleep(interval); 5108 } 5109 5110 return (0); 5111} 5112 5113typedef struct upgrade_cbdata { 5114 boolean_t cb_first; 5115 boolean_t cb_unavail; 5116 char cb_poolname[ZFS_MAX_DATASET_NAME_LEN]; 5117 int cb_argc; 5118 uint64_t cb_version; 5119 char **cb_argv; 5120} upgrade_cbdata_t; 5121 5122#ifdef __FreeBSD__ 5123static int 5124is_root_pool(zpool_handle_t *zhp) 5125{ 5126 static struct statfs sfs; 5127 static char *poolname = NULL; 5128 static boolean_t stated = B_FALSE; 5129 char *slash; 5130 5131 if (!stated) { 5132 stated = B_TRUE; 5133 if (statfs("/", &sfs) == -1) { 5134 (void) fprintf(stderr, 5135 "Unable to stat root file system: %s.\n", 5136 strerror(errno)); 5137 return (0); 5138 } 5139 if (strcmp(sfs.f_fstypename, "zfs") != 0) 5140 return (0); 5141 poolname = sfs.f_mntfromname; 5142 if ((slash = strchr(poolname, '/')) != NULL) 5143 *slash = '\0'; 5144 } 5145 return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0); 5146} 5147 5148static void 5149root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size) 5150{ 5151 5152 if (poolname[0] == '\0' && is_root_pool(zhp)) 5153 (void) strlcpy(poolname, zpool_get_name(zhp), size); 5154} 5155#endif /* FreeBSD */ 5156 5157static int 5158upgrade_version(zpool_handle_t *zhp, uint64_t version) 5159{ 5160 int ret; 5161 nvlist_t *config; 5162 uint64_t oldversion; 5163 5164 config = zpool_get_config(zhp, NULL); 5165 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5166 &oldversion) == 0); 5167 5168 assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 5169 assert(oldversion < version); 5170 5171 ret = zpool_upgrade(zhp, version); 5172 if (ret != 0) 5173 return (ret); 5174 5175 if (version >= SPA_VERSION_FEATURES) { 5176 (void) printf(gettext("Successfully upgraded " 5177 "'%s' from version %llu to feature flags.\n"), 5178 zpool_get_name(zhp), oldversion); 5179 } else { 5180 (void) printf(gettext("Successfully upgraded " 5181 "'%s' from version %llu to version %llu.\n"), 5182 zpool_get_name(zhp), oldversion, version); 5183 } 5184 5185 return (0); 5186} 5187 5188static int 5189upgrade_enable_all(zpool_handle_t *zhp, int *countp) 5190{ 5191 int i, ret, count; 5192 boolean_t firstff = B_TRUE; 5193 nvlist_t *enabled = zpool_get_features(zhp); 5194 5195 count = 0; 5196 for (i = 0; i < SPA_FEATURES; i++) { 5197 const char *fname = spa_feature_table[i].fi_uname; 5198 const char *fguid = spa_feature_table[i].fi_guid; 5199 if (!nvlist_exists(enabled, fguid)) { 5200 char *propname; 5201 verify(-1 != asprintf(&propname, "feature@%s", fname)); 5202 ret = zpool_set_prop(zhp, propname, 5203 ZFS_FEATURE_ENABLED); 5204 if (ret != 0) { 5205 free(propname); 5206 return (ret); 5207 } 5208 count++; 5209 5210 if (firstff) { 5211 (void) printf(gettext("Enabled the " 5212 "following features on '%s':\n"), 5213 zpool_get_name(zhp)); 5214 firstff = B_FALSE; 5215 } 5216 (void) printf(gettext(" %s\n"), fname); 5217 free(propname); 5218 } 5219 } 5220 5221 if (countp != NULL) 5222 *countp = count; 5223 return (0); 5224} 5225 5226static int 5227upgrade_cb(zpool_handle_t *zhp, void *arg) 5228{ 5229 upgrade_cbdata_t *cbp = arg; 5230 nvlist_t *config; 5231 uint64_t version; 5232 boolean_t printnl = B_FALSE; 5233 int ret; 5234 5235 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5236 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is " 5237 "currently unavailable.\n\n"), zpool_get_name(zhp)); 5238 cbp->cb_unavail = B_TRUE; 5239 /* Allow iteration to continue. */ 5240 return (0); 5241 } 5242 5243 config = zpool_get_config(zhp, NULL); 5244 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5245 &version) == 0); 5246 5247 assert(SPA_VERSION_IS_SUPPORTED(version)); 5248 5249 if (version < cbp->cb_version) { 5250 cbp->cb_first = B_FALSE; 5251 ret = upgrade_version(zhp, cbp->cb_version); 5252 if (ret != 0) 5253 return (ret); 5254#ifdef __FreeBSD__ 5255 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5256 sizeof(cbp->cb_poolname)); 5257#endif /* __FreeBSD__ */ 5258 printnl = B_TRUE; 5259 5260#ifdef illumos 5261 /* 5262 * If they did "zpool upgrade -a", then we could 5263 * be doing ioctls to different pools. We need 5264 * to log this history once to each pool, and bypass 5265 * the normal history logging that happens in main(). 5266 */ 5267 (void) zpool_log_history(g_zfs, history_str); 5268 log_history = B_FALSE; 5269#endif 5270 } 5271 5272 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 5273 int count; 5274 ret = upgrade_enable_all(zhp, &count); 5275 if (ret != 0) 5276 return (ret); 5277 5278 if (count > 0) { 5279 cbp->cb_first = B_FALSE; 5280 printnl = B_TRUE; 5281#ifdef __FreeBSD__ 5282 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5283 sizeof(cbp->cb_poolname)); 5284#endif /* __FreeBSD__ */ 5285 /* 5286 * If they did "zpool upgrade -a", then we could 5287 * be doing ioctls to different pools. We need 5288 * to log this history once to each pool, and bypass 5289 * the normal history logging that happens in main(). 5290 */ 5291 (void) zpool_log_history(g_zfs, history_str); 5292 log_history = B_FALSE; 5293 } 5294 } 5295 5296 if (printnl) { 5297 (void) printf(gettext("\n")); 5298 } 5299 5300 return (0); 5301} 5302 5303static int 5304upgrade_list_unavail(zpool_handle_t *zhp, void *arg) 5305{ 5306 upgrade_cbdata_t *cbp = arg; 5307 5308 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5309 if (cbp->cb_first) { 5310 (void) fprintf(stderr, gettext("The following pools " 5311 "are unavailable and cannot be upgraded as this " 5312 "time.\n\n")); 5313 (void) fprintf(stderr, gettext("POOL\n")); 5314 (void) fprintf(stderr, gettext("------------\n")); 5315 cbp->cb_first = B_FALSE; 5316 } 5317 (void) printf(gettext("%s\n"), zpool_get_name(zhp)); 5318 cbp->cb_unavail = B_TRUE; 5319 } 5320 return (0); 5321} 5322 5323static int 5324upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 5325{ 5326 upgrade_cbdata_t *cbp = arg; 5327 nvlist_t *config; 5328 uint64_t version; 5329 5330 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5331 /* 5332 * This will have been reported by upgrade_list_unavail so 5333 * just allow iteration to continue. 5334 */ 5335 cbp->cb_unavail = B_TRUE; 5336 return (0); 5337 } 5338 5339 config = zpool_get_config(zhp, NULL); 5340 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5341 &version) == 0); 5342 5343 assert(SPA_VERSION_IS_SUPPORTED(version)); 5344 5345 if (version < SPA_VERSION_FEATURES) { 5346 if (cbp->cb_first) { 5347 (void) printf(gettext("The following pools are " 5348 "formatted with legacy version numbers and can\n" 5349 "be upgraded to use feature flags. After " 5350 "being upgraded, these pools\nwill no " 5351 "longer be accessible by software that does not " 5352 "support feature\nflags.\n\n")); 5353 (void) printf(gettext("VER POOL\n")); 5354 (void) printf(gettext("--- ------------\n")); 5355 cbp->cb_first = B_FALSE; 5356 } 5357 5358 (void) printf("%2llu %s\n", (u_longlong_t)version, 5359 zpool_get_name(zhp)); 5360 } 5361 5362 return (0); 5363} 5364 5365static int 5366upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 5367{ 5368 upgrade_cbdata_t *cbp = arg; 5369 nvlist_t *config; 5370 uint64_t version; 5371 5372 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5373 /* 5374 * This will have been reported by upgrade_list_unavail so 5375 * just allow iteration to continue. 5376 */ 5377 cbp->cb_unavail = B_TRUE; 5378 return (0); 5379 } 5380 5381 config = zpool_get_config(zhp, NULL); 5382 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5383 &version) == 0); 5384 5385 if (version >= SPA_VERSION_FEATURES) { 5386 int i; 5387 boolean_t poolfirst = B_TRUE; 5388 nvlist_t *enabled = zpool_get_features(zhp); 5389 5390 for (i = 0; i < SPA_FEATURES; i++) { 5391 const char *fguid = spa_feature_table[i].fi_guid; 5392 const char *fname = spa_feature_table[i].fi_uname; 5393 if (!nvlist_exists(enabled, fguid)) { 5394 if (cbp->cb_first) { 5395 (void) printf(gettext("\nSome " 5396 "supported features are not " 5397 "enabled on the following pools. " 5398 "Once a\nfeature is enabled the " 5399 "pool may become incompatible with " 5400 "software\nthat does not support " 5401 "the feature. See " 5402 "zpool-features(7) for " 5403 "details.\n\n")); 5404 (void) printf(gettext("POOL " 5405 "FEATURE\n")); 5406 (void) printf(gettext("------" 5407 "---------\n")); 5408 cbp->cb_first = B_FALSE; 5409 } 5410 5411 if (poolfirst) { 5412 (void) printf(gettext("%s\n"), 5413 zpool_get_name(zhp)); 5414 poolfirst = B_FALSE; 5415 } 5416 5417 (void) printf(gettext(" %s\n"), fname); 5418 } 5419 } 5420 } 5421 5422 return (0); 5423} 5424 5425/* ARGSUSED */ 5426static int 5427upgrade_one(zpool_handle_t *zhp, void *data) 5428{ 5429 boolean_t printnl = B_FALSE; 5430 upgrade_cbdata_t *cbp = data; 5431 uint64_t cur_version; 5432 int ret; 5433 5434 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 5435 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is " 5436 "is currently unavailable.\n\n"), zpool_get_name(zhp)); 5437 cbp->cb_unavail = B_TRUE; 5438 return (1); 5439 } 5440 5441 if (strcmp("log", zpool_get_name(zhp)) == 0) { 5442 (void) printf(gettext("'log' is now a reserved word\n" 5443 "Pool 'log' must be renamed using export and import" 5444 " to upgrade.\n\n")); 5445 return (1); 5446 } 5447 5448 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 5449 if (cur_version > cbp->cb_version) { 5450 (void) printf(gettext("Pool '%s' is already formatted " 5451 "using more current version '%llu'.\n\n"), 5452 zpool_get_name(zhp), cur_version); 5453 return (0); 5454 } 5455 5456 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 5457 (void) printf(gettext("Pool '%s' is already formatted " 5458 "using version %llu.\n\n"), zpool_get_name(zhp), 5459 cbp->cb_version); 5460 return (0); 5461 } 5462 5463 if (cur_version != cbp->cb_version) { 5464 printnl = B_TRUE; 5465 ret = upgrade_version(zhp, cbp->cb_version); 5466 if (ret != 0) 5467 return (ret); 5468#ifdef __FreeBSD__ 5469 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5470 sizeof(cbp->cb_poolname)); 5471#endif /* __FreeBSD__ */ 5472 } 5473 5474 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 5475 int count = 0; 5476 ret = upgrade_enable_all(zhp, &count); 5477 if (ret != 0) 5478 return (ret); 5479 5480 if (count != 0) { 5481 printnl = B_TRUE; 5482#ifdef __FreeBSD__ 5483 root_pool_upgrade_check(zhp, cbp->cb_poolname, 5484 sizeof(cbp->cb_poolname)); 5485#endif /* __FreeBSD __*/ 5486 } else if (cur_version == SPA_VERSION) { 5487 (void) printf(gettext("Pool '%s' already has all " 5488 "supported features enabled.\n\n"), 5489 zpool_get_name(zhp)); 5490 } 5491 } 5492 5493 if (printnl) { 5494 (void) printf(gettext("\n")); 5495 } 5496 5497 return (0); 5498} 5499 5500/* 5501 * zpool upgrade 5502 * zpool upgrade -v 5503 * zpool upgrade [-V version] <-a | pool ...> 5504 * 5505 * With no arguments, display downrev'd ZFS pool available for upgrade. 5506 * Individual pools can be upgraded by specifying the pool, and '-a' will 5507 * upgrade all pools. 5508 */ 5509int 5510zpool_do_upgrade(int argc, char **argv) 5511{ 5512 int c; 5513 upgrade_cbdata_t cb = { 0 }; 5514 int ret = 0; 5515 boolean_t showversions = B_FALSE; 5516 boolean_t upgradeall = B_FALSE; 5517 char *end; 5518 5519 5520 /* check options */ 5521 while ((c = getopt(argc, argv, ":avV:")) != -1) { 5522 switch (c) { 5523 case 'a': 5524 upgradeall = B_TRUE; 5525 break; 5526 case 'v': 5527 showversions = B_TRUE; 5528 break; 5529 case 'V': 5530 cb.cb_version = strtoll(optarg, &end, 10); 5531 if (*end != '\0' || 5532 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 5533 (void) fprintf(stderr, 5534 gettext("invalid version '%s'\n"), optarg); 5535 usage(B_FALSE); 5536 } 5537 break; 5538 case ':': 5539 (void) fprintf(stderr, gettext("missing argument for " 5540 "'%c' option\n"), optopt); 5541 usage(B_FALSE); 5542 break; 5543 case '?': 5544 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5545 optopt); 5546 usage(B_FALSE); 5547 } 5548 } 5549 5550 cb.cb_argc = argc; 5551 cb.cb_argv = argv; 5552 argc -= optind; 5553 argv += optind; 5554 5555 if (cb.cb_version == 0) { 5556 cb.cb_version = SPA_VERSION; 5557 } else if (!upgradeall && argc == 0) { 5558 (void) fprintf(stderr, gettext("-V option is " 5559 "incompatible with other arguments\n")); 5560 usage(B_FALSE); 5561 } 5562 5563 if (showversions) { 5564 if (upgradeall || argc != 0) { 5565 (void) fprintf(stderr, gettext("-v option is " 5566 "incompatible with other arguments\n")); 5567 usage(B_FALSE); 5568 } 5569 } else if (upgradeall) { 5570 if (argc != 0) { 5571 (void) fprintf(stderr, gettext("-a option should not " 5572 "be used along with a pool name\n")); 5573 usage(B_FALSE); 5574 } 5575 } 5576 5577 (void) printf(gettext("This system supports ZFS pool feature " 5578 "flags.\n\n")); 5579 if (showversions) { 5580 int i; 5581 5582 (void) printf(gettext("The following features are " 5583 "supported:\n\n")); 5584 (void) printf(gettext("FEAT DESCRIPTION\n")); 5585 (void) printf("----------------------------------------------" 5586 "---------------\n"); 5587 for (i = 0; i < SPA_FEATURES; i++) { 5588 zfeature_info_t *fi = &spa_feature_table[i]; 5589 const char *ro = 5590 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 5591 " (read-only compatible)" : ""; 5592 5593 (void) printf("%-37s%s\n", fi->fi_uname, ro); 5594 (void) printf(" %s\n", fi->fi_desc); 5595 } 5596 (void) printf("\n"); 5597 5598 (void) printf(gettext("The following legacy versions are also " 5599 "supported:\n\n")); 5600 (void) printf(gettext("VER DESCRIPTION\n")); 5601 (void) printf("--- -----------------------------------------" 5602 "---------------\n"); 5603 (void) printf(gettext(" 1 Initial ZFS version\n")); 5604 (void) printf(gettext(" 2 Ditto blocks " 5605 "(replicated metadata)\n")); 5606 (void) printf(gettext(" 3 Hot spares and double parity " 5607 "RAID-Z\n")); 5608 (void) printf(gettext(" 4 zpool history\n")); 5609 (void) printf(gettext(" 5 Compression using the gzip " 5610 "algorithm\n")); 5611 (void) printf(gettext(" 6 bootfs pool property\n")); 5612 (void) printf(gettext(" 7 Separate intent log devices\n")); 5613 (void) printf(gettext(" 8 Delegated administration\n")); 5614 (void) printf(gettext(" 9 refquota and refreservation " 5615 "properties\n")); 5616 (void) printf(gettext(" 10 Cache devices\n")); 5617 (void) printf(gettext(" 11 Improved scrub performance\n")); 5618 (void) printf(gettext(" 12 Snapshot properties\n")); 5619 (void) printf(gettext(" 13 snapused property\n")); 5620 (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 5621 (void) printf(gettext(" 15 user/group space accounting\n")); 5622 (void) printf(gettext(" 16 stmf property support\n")); 5623 (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 5624 (void) printf(gettext(" 18 Snapshot user holds\n")); 5625 (void) printf(gettext(" 19 Log device removal\n")); 5626 (void) printf(gettext(" 20 Compression using zle " 5627 "(zero-length encoding)\n")); 5628 (void) printf(gettext(" 21 Deduplication\n")); 5629 (void) printf(gettext(" 22 Received properties\n")); 5630 (void) printf(gettext(" 23 Slim ZIL\n")); 5631 (void) printf(gettext(" 24 System attributes\n")); 5632 (void) printf(gettext(" 25 Improved scrub stats\n")); 5633 (void) printf(gettext(" 26 Improved snapshot deletion " 5634 "performance\n")); 5635 (void) printf(gettext(" 27 Improved snapshot creation " 5636 "performance\n")); 5637 (void) printf(gettext(" 28 Multiple vdev replacements\n")); 5638 (void) printf(gettext("\nFor more information on a particular " 5639 "version, including supported releases,\n")); 5640 (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 5641 } else if (argc == 0 && upgradeall) { 5642 cb.cb_first = B_TRUE; 5643 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 5644 if (ret == 0 && cb.cb_first) { 5645 if (cb.cb_version == SPA_VERSION) { 5646 (void) printf(gettext("All %spools are already " 5647 "formatted using feature flags.\n\n"), 5648 cb.cb_unavail ? gettext("available ") : ""); 5649 (void) printf(gettext("Every %sfeature flags " 5650 "pool already has all supported features " 5651 "enabled.\n"), 5652 cb.cb_unavail ? gettext("available ") : ""); 5653 } else { 5654 (void) printf(gettext("All pools are already " 5655 "formatted with version %llu or higher.\n"), 5656 cb.cb_version); 5657 } 5658 } 5659 } else if (argc == 0) { 5660 cb.cb_first = B_TRUE; 5661 ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb); 5662 assert(ret == 0); 5663 5664 if (!cb.cb_first) { 5665 (void) fprintf(stderr, "\n"); 5666 } 5667 5668 cb.cb_first = B_TRUE; 5669 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 5670 assert(ret == 0); 5671 5672 if (cb.cb_first) { 5673 (void) printf(gettext("All %spools are formatted using " 5674 "feature flags.\n\n"), cb.cb_unavail ? 5675 gettext("available ") : ""); 5676 } else { 5677 (void) printf(gettext("\nUse 'zpool upgrade -v' " 5678 "for a list of available legacy versions.\n")); 5679 } 5680 5681 cb.cb_first = B_TRUE; 5682 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 5683 assert(ret == 0); 5684 5685 if (cb.cb_first) { 5686 (void) printf(gettext("Every %sfeature flags pool has " 5687 "all supported features enabled.\n"), 5688 cb.cb_unavail ? gettext("available ") : ""); 5689 } else { 5690 (void) printf(gettext("\n")); 5691 } 5692 } else { 5693 ret = for_each_pool(argc, argv, B_TRUE, NULL, 5694 upgrade_one, &cb); 5695 } 5696 5697 if (cb.cb_poolname[0] != '\0') { 5698 (void) printf( 5699 "If you boot from pool '%s', don't forget to update boot code.\n" 5700 "Assuming you use GPT partitioning and da0 is your boot disk\n" 5701 "the following command will do it:\n" 5702 "\n" 5703 "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n", 5704 cb.cb_poolname); 5705 } 5706 5707 return (ret); 5708} 5709 5710typedef struct hist_cbdata { 5711 boolean_t first; 5712 boolean_t longfmt; 5713 boolean_t internal; 5714} hist_cbdata_t; 5715 5716/* 5717 * Print out the command history for a specific pool. 5718 */ 5719static int 5720get_history_one(zpool_handle_t *zhp, void *data) 5721{ 5722 nvlist_t *nvhis; 5723 nvlist_t **records; 5724 uint_t numrecords; 5725 int ret, i; 5726 hist_cbdata_t *cb = (hist_cbdata_t *)data; 5727 5728 cb->first = B_FALSE; 5729 5730 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 5731 5732 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 5733 return (ret); 5734 5735 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 5736 &records, &numrecords) == 0); 5737 for (i = 0; i < numrecords; i++) { 5738 nvlist_t *rec = records[i]; 5739 char tbuf[30] = ""; 5740 5741 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 5742 time_t tsec; 5743 struct tm t; 5744 5745 tsec = fnvlist_lookup_uint64(records[i], 5746 ZPOOL_HIST_TIME); 5747 (void) localtime_r(&tsec, &t); 5748 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 5749 } 5750 5751 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 5752 (void) printf("%s %s", tbuf, 5753 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 5754 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 5755 int ievent = 5756 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 5757 if (!cb->internal) 5758 continue; 5759 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 5760 (void) printf("%s unrecognized record:\n", 5761 tbuf); 5762 dump_nvlist(rec, 4); 5763 continue; 5764 } 5765 (void) printf("%s [internal %s txg:%lld] %s", tbuf, 5766 zfs_history_event_names[ievent], 5767 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5768 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 5769 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 5770 if (!cb->internal) 5771 continue; 5772 (void) printf("%s [txg:%lld] %s", tbuf, 5773 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5774 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 5775 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 5776 (void) printf(" %s (%llu)", 5777 fnvlist_lookup_string(rec, 5778 ZPOOL_HIST_DSNAME), 5779 fnvlist_lookup_uint64(rec, 5780 ZPOOL_HIST_DSID)); 5781 } 5782 (void) printf(" %s", fnvlist_lookup_string(rec, 5783 ZPOOL_HIST_INT_STR)); 5784 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 5785 if (!cb->internal) 5786 continue; 5787 (void) printf("%s ioctl %s\n", tbuf, 5788 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 5789 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 5790 (void) printf(" input:\n"); 5791 dump_nvlist(fnvlist_lookup_nvlist(rec, 5792 ZPOOL_HIST_INPUT_NVL), 8); 5793 } 5794 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 5795 (void) printf(" output:\n"); 5796 dump_nvlist(fnvlist_lookup_nvlist(rec, 5797 ZPOOL_HIST_OUTPUT_NVL), 8); 5798 } 5799 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 5800 (void) printf(" errno: %lld\n", 5801 fnvlist_lookup_int64(rec, 5802 ZPOOL_HIST_ERRNO)); 5803 } 5804 } else { 5805 if (!cb->internal) 5806 continue; 5807 (void) printf("%s unrecognized record:\n", tbuf); 5808 dump_nvlist(rec, 4); 5809 } 5810 5811 if (!cb->longfmt) { 5812 (void) printf("\n"); 5813 continue; 5814 } 5815 (void) printf(" ["); 5816 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 5817 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 5818 struct passwd *pwd = getpwuid(who); 5819 (void) printf("user %d ", (int)who); 5820 if (pwd != NULL) 5821 (void) printf("(%s) ", pwd->pw_name); 5822 } 5823 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 5824 (void) printf("on %s", 5825 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 5826 } 5827 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 5828 (void) printf(":%s", 5829 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 5830 } 5831 (void) printf("]"); 5832 (void) printf("\n"); 5833 } 5834 (void) printf("\n"); 5835 nvlist_free(nvhis); 5836 5837 return (ret); 5838} 5839 5840/* 5841 * zpool history <pool> 5842 * 5843 * Displays the history of commands that modified pools. 5844 */ 5845int 5846zpool_do_history(int argc, char **argv) 5847{ 5848 hist_cbdata_t cbdata = { 0 }; 5849 int ret; 5850 int c; 5851 5852 cbdata.first = B_TRUE; 5853 /* check options */ 5854 while ((c = getopt(argc, argv, "li")) != -1) { 5855 switch (c) { 5856 case 'l': 5857 cbdata.longfmt = B_TRUE; 5858 break; 5859 case 'i': 5860 cbdata.internal = B_TRUE; 5861 break; 5862 case '?': 5863 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5864 optopt); 5865 usage(B_FALSE); 5866 } 5867 } 5868 argc -= optind; 5869 argv += optind; 5870 5871 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 5872 &cbdata); 5873 5874 if (argc == 0 && cbdata.first == B_TRUE) { 5875 (void) printf(gettext("no pools available\n")); 5876 return (0); 5877 } 5878 5879 return (ret); 5880} 5881 5882static int 5883get_callback(zpool_handle_t *zhp, void *data) 5884{ 5885 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 5886 char value[MAXNAMELEN]; 5887 zprop_source_t srctype; 5888 zprop_list_t *pl; 5889 5890 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 5891 5892 /* 5893 * Skip the special fake placeholder. This will also skip 5894 * over the name property when 'all' is specified. 5895 */ 5896 if (pl->pl_prop == ZPOOL_PROP_NAME && 5897 pl == cbp->cb_proplist) 5898 continue; 5899 5900 if (pl->pl_prop == ZPROP_INVAL && 5901 (zpool_prop_feature(pl->pl_user_prop) || 5902 zpool_prop_unsupported(pl->pl_user_prop))) { 5903 srctype = ZPROP_SRC_LOCAL; 5904 5905 if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 5906 value, sizeof (value)) == 0) { 5907 zprop_print_one_property(zpool_get_name(zhp), 5908 cbp, pl->pl_user_prop, value, srctype, 5909 NULL, NULL); 5910 } 5911 } else { 5912 if (zpool_get_prop(zhp, pl->pl_prop, value, 5913 sizeof (value), &srctype, cbp->cb_literal) != 0) 5914 continue; 5915 5916 zprop_print_one_property(zpool_get_name(zhp), cbp, 5917 zpool_prop_to_name(pl->pl_prop), value, srctype, 5918 NULL, NULL); 5919 } 5920 } 5921 return (0); 5922} 5923 5924/* 5925 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 5926 * 5927 * -H Scripted mode. Don't display headers, and separate properties 5928 * by a single tab. 5929 * -o List of columns to display. Defaults to 5930 * "name,property,value,source". 5931 * -p Diplay values in parsable (exact) format. 5932 * 5933 * Get properties of pools in the system. Output space statistics 5934 * for each one as well as other attributes. 5935 */ 5936int 5937zpool_do_get(int argc, char **argv) 5938{ 5939 zprop_get_cbdata_t cb = { 0 }; 5940 zprop_list_t fake_name = { 0 }; 5941 int ret; 5942 int c, i; 5943 char *value; 5944 5945 cb.cb_first = B_TRUE; 5946 5947 /* 5948 * Set up default columns and sources. 5949 */ 5950 cb.cb_sources = ZPROP_SRC_ALL; 5951 cb.cb_columns[0] = GET_COL_NAME; 5952 cb.cb_columns[1] = GET_COL_PROPERTY; 5953 cb.cb_columns[2] = GET_COL_VALUE; 5954 cb.cb_columns[3] = GET_COL_SOURCE; 5955 cb.cb_type = ZFS_TYPE_POOL; 5956 5957 /* check options */ 5958 while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 5959 switch (c) { 5960 case 'p': 5961 cb.cb_literal = B_TRUE; 5962 break; 5963 case 'H': 5964 cb.cb_scripted = B_TRUE; 5965 break; 5966 case 'o': 5967 bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 5968 i = 0; 5969 while (*optarg != '\0') { 5970 static char *col_subopts[] = 5971 { "name", "property", "value", "source", 5972 "all", NULL }; 5973 5974 if (i == ZFS_GET_NCOLS) { 5975 (void) fprintf(stderr, gettext("too " 5976 "many fields given to -o " 5977 "option\n")); 5978 usage(B_FALSE); 5979 } 5980 5981 switch (getsubopt(&optarg, col_subopts, 5982 &value)) { 5983 case 0: 5984 cb.cb_columns[i++] = GET_COL_NAME; 5985 break; 5986 case 1: 5987 cb.cb_columns[i++] = GET_COL_PROPERTY; 5988 break; 5989 case 2: 5990 cb.cb_columns[i++] = GET_COL_VALUE; 5991 break; 5992 case 3: 5993 cb.cb_columns[i++] = GET_COL_SOURCE; 5994 break; 5995 case 4: 5996 if (i > 0) { 5997 (void) fprintf(stderr, 5998 gettext("\"all\" conflicts " 5999 "with specific fields " 6000 "given to -o option\n")); 6001 usage(B_FALSE); 6002 } 6003 cb.cb_columns[0] = GET_COL_NAME; 6004 cb.cb_columns[1] = GET_COL_PROPERTY; 6005 cb.cb_columns[2] = GET_COL_VALUE; 6006 cb.cb_columns[3] = GET_COL_SOURCE; 6007 i = ZFS_GET_NCOLS; 6008 break; 6009 default: 6010 (void) fprintf(stderr, 6011 gettext("invalid column name " 6012 "'%s'\n"), suboptarg); 6013 usage(B_FALSE); 6014 } 6015 } 6016 break; 6017 case '?': 6018 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6019 optopt); 6020 usage(B_FALSE); 6021 } 6022 } 6023 6024 argc -= optind; 6025 argv += optind; 6026 6027 if (argc < 1) { 6028 (void) fprintf(stderr, gettext("missing property " 6029 "argument\n")); 6030 usage(B_FALSE); 6031 } 6032 6033 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 6034 ZFS_TYPE_POOL) != 0) 6035 usage(B_FALSE); 6036 6037 argc--; 6038 argv++; 6039 6040 if (cb.cb_proplist != NULL) { 6041 fake_name.pl_prop = ZPOOL_PROP_NAME; 6042 fake_name.pl_width = strlen(gettext("NAME")); 6043 fake_name.pl_next = cb.cb_proplist; 6044 cb.cb_proplist = &fake_name; 6045 } 6046 6047 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 6048 get_callback, &cb); 6049 6050 if (cb.cb_proplist == &fake_name) 6051 zprop_free_list(fake_name.pl_next); 6052 else 6053 zprop_free_list(cb.cb_proplist); 6054 6055 return (ret); 6056} 6057 6058typedef struct set_cbdata { 6059 char *cb_propname; 6060 char *cb_value; 6061 boolean_t cb_any_successful; 6062} set_cbdata_t; 6063 6064int 6065set_callback(zpool_handle_t *zhp, void *data) 6066{ 6067 int error; 6068 set_cbdata_t *cb = (set_cbdata_t *)data; 6069 6070 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 6071 6072 if (!error) 6073 cb->cb_any_successful = B_TRUE; 6074 6075 return (error); 6076} 6077 6078int 6079zpool_do_set(int argc, char **argv) 6080{ 6081 set_cbdata_t cb = { 0 }; 6082 int error; 6083 6084 if (argc > 1 && argv[1][0] == '-') { 6085 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6086 argv[1][1]); 6087 usage(B_FALSE); 6088 } 6089 6090 if (argc < 2) { 6091 (void) fprintf(stderr, gettext("missing property=value " 6092 "argument\n")); 6093 usage(B_FALSE); 6094 } 6095 6096 if (argc < 3) { 6097 (void) fprintf(stderr, gettext("missing pool name\n")); 6098 usage(B_FALSE); 6099 } 6100 6101 if (argc > 3) { 6102 (void) fprintf(stderr, gettext("too many pool names\n")); 6103 usage(B_FALSE); 6104 } 6105 6106 cb.cb_propname = argv[1]; 6107 cb.cb_value = strchr(cb.cb_propname, '='); 6108 if (cb.cb_value == NULL) { 6109 (void) fprintf(stderr, gettext("missing value in " 6110 "property=value argument\n")); 6111 usage(B_FALSE); 6112 } 6113 6114 *(cb.cb_value) = '\0'; 6115 cb.cb_value++; 6116 6117 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 6118 set_callback, &cb); 6119 6120 return (error); 6121} 6122 6123static int 6124find_command_idx(char *command, int *idx) 6125{ 6126 int i; 6127 6128 for (i = 0; i < NCOMMAND; i++) { 6129 if (command_table[i].name == NULL) 6130 continue; 6131 6132 if (strcmp(command, command_table[i].name) == 0) { 6133 *idx = i; 6134 return (0); 6135 } 6136 } 6137 return (1); 6138} 6139 6140int 6141main(int argc, char **argv) 6142{ 6143 int ret = 0; 6144 int i; 6145 char *cmdname; 6146 6147 (void) setlocale(LC_ALL, ""); 6148 (void) textdomain(TEXT_DOMAIN); 6149 6150 if ((g_zfs = libzfs_init()) == NULL) { 6151 (void) fprintf(stderr, gettext("internal error: failed to " 6152 "initialize ZFS library\n")); 6153 return (1); 6154 } 6155 6156 libzfs_print_on_error(g_zfs, B_TRUE); 6157 6158 opterr = 0; 6159 6160 /* 6161 * Make sure the user has specified some command. 6162 */ 6163 if (argc < 2) { 6164 (void) fprintf(stderr, gettext("missing command\n")); 6165 usage(B_FALSE); 6166 } 6167 6168 cmdname = argv[1]; 6169 6170 /* 6171 * Special case '-?' 6172 */ 6173 if (strcmp(cmdname, "-?") == 0) 6174 usage(B_TRUE); 6175 6176 zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 6177 6178 /* 6179 * Run the appropriate command. 6180 */ 6181 if (find_command_idx(cmdname, &i) == 0) { 6182 current_command = &command_table[i]; 6183 ret = command_table[i].func(argc - 1, argv + 1); 6184 } else if (strchr(cmdname, '=')) { 6185 verify(find_command_idx("set", &i) == 0); 6186 current_command = &command_table[i]; 6187 ret = command_table[i].func(argc, argv); 6188 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 6189 /* 6190 * 'freeze' is a vile debugging abomination, so we treat 6191 * it as such. 6192 */ 6193 zfs_cmd_t zc = { 0 }; 6194 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name)); 6195 return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc)); 6196 } else { 6197 (void) fprintf(stderr, gettext("unrecognized " 6198 "command '%s'\n"), cmdname); 6199 usage(B_FALSE); 6200 } 6201 6202 if (ret == 0 && log_history) 6203 (void) zpool_log_history(g_zfs, history_str); 6204 6205 libzfs_fini(g_zfs); 6206 6207 /* 6208 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 6209 * for the purposes of running ::findleaks. 6210 */ 6211 if (getenv("ZFS_ABORT") != NULL) { 6212 (void) printf("dumping core by request\n"); 6213 abort(); 6214 } 6215 6216 return (ret); 6217} 6218