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