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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <assert.h> 30 #include <ctype.h> 31 #include <dirent.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <libgen.h> 35 #include <libintl.h> 36 #include <libuutil.h> 37 #include <locale.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <strings.h> 42 #include <unistd.h> 43 #include <priv.h> 44 #include <pwd.h> 45 #include <zone.h> 46 #include <sys/fs/zfs.h> 47 48 #include <sys/stat.h> 49 50 #include <libzfs.h> 51 52 #include "zpool_util.h" 53 #include "zfs_comutil.h" 54 55 static int zpool_do_create(int, char **); 56 static int zpool_do_destroy(int, char **); 57 58 static int zpool_do_add(int, char **); 59 static int zpool_do_remove(int, char **); 60 61 static int zpool_do_list(int, char **); 62 static int zpool_do_iostat(int, char **); 63 static int zpool_do_status(int, char **); 64 65 static int zpool_do_online(int, char **); 66 static int zpool_do_offline(int, char **); 67 static int zpool_do_clear(int, char **); 68 69 static int zpool_do_attach(int, char **); 70 static int zpool_do_detach(int, char **); 71 static int zpool_do_replace(int, char **); 72 73 static int zpool_do_scrub(int, char **); 74 75 static int zpool_do_import(int, char **); 76 static int zpool_do_export(int, char **); 77 78 static int zpool_do_upgrade(int, char **); 79 80 static int zpool_do_history(int, char **); 81 82 static int zpool_do_get(int, char **); 83 static int zpool_do_set(int, char **); 84 85 /* 86 * These libumem hooks provide a reasonable set of defaults for the allocator's 87 * debugging facilities. 88 */ 89 90 #ifdef DEBUG 91 const char * 92 _umem_debug_init(void) 93 { 94 return ("default,verbose"); /* $UMEM_DEBUG setting */ 95 } 96 97 const char * 98 _umem_logging_init(void) 99 { 100 return ("fail,contents"); /* $UMEM_LOGGING setting */ 101 } 102 #endif 103 104 typedef enum { 105 HELP_ADD, 106 HELP_ATTACH, 107 HELP_CLEAR, 108 HELP_CREATE, 109 HELP_DESTROY, 110 HELP_DETACH, 111 HELP_EXPORT, 112 HELP_HISTORY, 113 HELP_IMPORT, 114 HELP_IOSTAT, 115 HELP_LIST, 116 HELP_OFFLINE, 117 HELP_ONLINE, 118 HELP_REPLACE, 119 HELP_REMOVE, 120 HELP_SCRUB, 121 HELP_STATUS, 122 HELP_UPGRADE, 123 HELP_GET, 124 HELP_SET 125 } zpool_help_t; 126 127 128 typedef struct zpool_command { 129 const char *name; 130 int (*func)(int, char **); 131 zpool_help_t usage; 132 } zpool_command_t; 133 134 /* 135 * Master command table. Each ZFS command has a name, associated function, and 136 * usage message. The usage messages need to be internationalized, so we have 137 * to have a function to return the usage message based on a command index. 138 * 139 * These commands are organized according to how they are displayed in the usage 140 * message. An empty command (one with a NULL name) indicates an empty line in 141 * the generic usage message. 142 */ 143 static zpool_command_t command_table[] = { 144 { "create", zpool_do_create, HELP_CREATE }, 145 { "destroy", zpool_do_destroy, HELP_DESTROY }, 146 { NULL }, 147 { "add", zpool_do_add, HELP_ADD }, 148 { "remove", zpool_do_remove, HELP_REMOVE }, 149 { NULL }, 150 { "list", zpool_do_list, HELP_LIST }, 151 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 152 { "status", zpool_do_status, HELP_STATUS }, 153 { NULL }, 154 { "online", zpool_do_online, HELP_ONLINE }, 155 { "offline", zpool_do_offline, HELP_OFFLINE }, 156 { "clear", zpool_do_clear, HELP_CLEAR }, 157 { NULL }, 158 { "attach", zpool_do_attach, HELP_ATTACH }, 159 { "detach", zpool_do_detach, HELP_DETACH }, 160 { "replace", zpool_do_replace, HELP_REPLACE }, 161 { NULL }, 162 { "scrub", zpool_do_scrub, HELP_SCRUB }, 163 { NULL }, 164 { "import", zpool_do_import, HELP_IMPORT }, 165 { "export", zpool_do_export, HELP_EXPORT }, 166 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 167 { NULL }, 168 { "history", zpool_do_history, HELP_HISTORY }, 169 { "get", zpool_do_get, HELP_GET }, 170 { "set", zpool_do_set, HELP_SET }, 171 }; 172 173 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 174 175 zpool_command_t *current_command; 176 static char history_str[HIS_MAX_RECORD_LEN]; 177 178 static const char * 179 get_usage(zpool_help_t idx) { 180 switch (idx) { 181 case HELP_ADD: 182 return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 183 case HELP_ATTACH: 184 return (gettext("\tattach [-f] <pool> <device> " 185 "<new-device>\n")); 186 case HELP_CLEAR: 187 return (gettext("\tclear <pool> [device]\n")); 188 case HELP_CREATE: 189 return (gettext("\tcreate [-fn] [-o property=value] ... \n" 190 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 191 case HELP_DESTROY: 192 return (gettext("\tdestroy [-f] <pool>\n")); 193 case HELP_DETACH: 194 return (gettext("\tdetach <pool> <device>\n")); 195 case HELP_EXPORT: 196 return (gettext("\texport [-f] <pool> ...\n")); 197 case HELP_HISTORY: 198 return (gettext("\thistory [-il] [<pool>] ...\n")); 199 case HELP_IMPORT: 200 return (gettext("\timport [-d dir] [-D]\n" 201 "\timport [-o mntopts] [-o property=value] ... \n" 202 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n" 203 "\timport [-o mntopts] [-o property=value] ... \n" 204 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] " 205 "<pool | id> [newpool]\n")); 206 case HELP_IOSTAT: 207 return (gettext("\tiostat [-v] [pool] ... [interval " 208 "[count]]\n")); 209 case HELP_LIST: 210 return (gettext("\tlist [-H] [-o property[,...]] " 211 "[pool] ...\n")); 212 case HELP_OFFLINE: 213 return (gettext("\toffline [-t] <pool> <device> ...\n")); 214 case HELP_ONLINE: 215 return (gettext("\tonline <pool> <device> ...\n")); 216 case HELP_REPLACE: 217 return (gettext("\treplace [-f] <pool> <device> " 218 "[new-device]\n")); 219 case HELP_REMOVE: 220 return (gettext("\tremove <pool> <device> ...\n")); 221 case HELP_SCRUB: 222 return (gettext("\tscrub [-s] <pool> ...\n")); 223 case HELP_STATUS: 224 return (gettext("\tstatus [-vx] [pool] ...\n")); 225 case HELP_UPGRADE: 226 return (gettext("\tupgrade\n" 227 "\tupgrade -v\n" 228 "\tupgrade [-V version] <-a | pool ...>\n")); 229 case HELP_GET: 230 return (gettext("\tget <\"all\" | property[,...]> " 231 "<pool> ...\n")); 232 case HELP_SET: 233 return (gettext("\tset <property=value> <pool> \n")); 234 } 235 236 abort(); 237 /* NOTREACHED */ 238 } 239 240 241 /* 242 * Callback routine that will print out a pool property value. 243 */ 244 static int 245 print_prop_cb(int prop, void *cb) 246 { 247 FILE *fp = cb; 248 249 (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop)); 250 251 if (zpool_prop_readonly(prop)) 252 (void) fprintf(fp, " NO "); 253 else 254 (void) fprintf(fp, " YES "); 255 256 if (zpool_prop_values(prop) == NULL) 257 (void) fprintf(fp, "-\n"); 258 else 259 (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 260 261 return (ZPROP_CONT); 262 } 263 264 /* 265 * Display usage message. If we're inside a command, display only the usage for 266 * that command. Otherwise, iterate over the entire command table and display 267 * a complete usage message. 268 */ 269 void 270 usage(boolean_t requested) 271 { 272 FILE *fp = requested ? stdout : stderr; 273 274 if (current_command == NULL) { 275 int i; 276 277 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 278 (void) fprintf(fp, 279 gettext("where 'command' is one of the following:\n\n")); 280 281 for (i = 0; i < NCOMMAND; i++) { 282 if (command_table[i].name == NULL) 283 (void) fprintf(fp, "\n"); 284 else 285 (void) fprintf(fp, "%s", 286 get_usage(command_table[i].usage)); 287 } 288 } else { 289 (void) fprintf(fp, gettext("usage:\n")); 290 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 291 } 292 293 if (current_command != NULL && 294 ((strcmp(current_command->name, "set") == 0) || 295 (strcmp(current_command->name, "get") == 0) || 296 (strcmp(current_command->name, "list") == 0))) { 297 298 (void) fprintf(fp, 299 gettext("\nthe following properties are supported:\n")); 300 301 (void) fprintf(fp, "\n\t%-13s %s %s\n\n", 302 "PROPERTY", "EDIT", "VALUES"); 303 304 /* Iterate over all properties */ 305 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 306 ZFS_TYPE_POOL); 307 } 308 309 /* 310 * See comments at end of main(). 311 */ 312 if (getenv("ZFS_ABORT") != NULL) { 313 (void) printf("dumping core by request\n"); 314 abort(); 315 } 316 317 exit(requested ? 0 : 2); 318 } 319 320 void 321 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 322 boolean_t print_logs) 323 { 324 nvlist_t **child; 325 uint_t c, children; 326 char *vname; 327 328 if (name != NULL) 329 (void) printf("\t%*s%s\n", indent, "", name); 330 331 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 332 &child, &children) != 0) 333 return; 334 335 for (c = 0; c < children; c++) { 336 uint64_t is_log = B_FALSE; 337 338 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 339 &is_log); 340 if ((is_log && !print_logs) || (!is_log && print_logs)) 341 continue; 342 343 vname = zpool_vdev_name(g_zfs, zhp, child[c]); 344 print_vdev_tree(zhp, vname, child[c], indent + 2, 345 B_FALSE); 346 free(vname); 347 } 348 } 349 350 /* 351 * Add a property pair (name, string-value) into a property nvlist. 352 */ 353 static int 354 add_prop_list(const char *propname, char *propval, nvlist_t **props) 355 { 356 char *strval; 357 nvlist_t *proplist; 358 zpool_prop_t prop; 359 360 if (*props == NULL && 361 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 362 (void) fprintf(stderr, 363 gettext("internal error: out of memory\n")); 364 return (1); 365 } 366 367 proplist = *props; 368 369 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { 370 (void) fprintf(stderr, gettext("property '%s' is " 371 "not a valid pool property\n"), propname); 372 return (2); 373 } 374 375 /* Use normalized property name for nvlist operations */ 376 if (nvlist_lookup_string(proplist, zpool_prop_to_name(prop), 377 &strval) == 0 && prop != ZPOOL_PROP_CACHEFILE) { 378 (void) fprintf(stderr, gettext("property '%s' " 379 "specified multiple times\n"), propname); 380 return (2); 381 } 382 383 if (nvlist_add_string(proplist, zpool_prop_to_name(prop), 384 propval) != 0) { 385 (void) fprintf(stderr, gettext("internal " 386 "error: out of memory\n")); 387 return (1); 388 } 389 390 return (0); 391 } 392 393 /* 394 * zpool add [-fn] <pool> <vdev> ... 395 * 396 * -f Force addition of devices, even if they appear in use 397 * -n Do not add the devices, but display the resulting layout if 398 * they were to be added. 399 * 400 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 401 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 402 * libzfs. 403 */ 404 int 405 zpool_do_add(int argc, char **argv) 406 { 407 boolean_t force = B_FALSE; 408 boolean_t dryrun = B_FALSE; 409 int c; 410 nvlist_t *nvroot; 411 char *poolname; 412 int ret; 413 zpool_handle_t *zhp; 414 nvlist_t *config; 415 416 /* check options */ 417 while ((c = getopt(argc, argv, "fn")) != -1) { 418 switch (c) { 419 case 'f': 420 force = B_TRUE; 421 break; 422 case 'n': 423 dryrun = B_TRUE; 424 break; 425 case '?': 426 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 427 optopt); 428 usage(B_FALSE); 429 } 430 } 431 432 argc -= optind; 433 argv += optind; 434 435 /* get pool name and check number of arguments */ 436 if (argc < 1) { 437 (void) fprintf(stderr, gettext("missing pool name argument\n")); 438 usage(B_FALSE); 439 } 440 if (argc < 2) { 441 (void) fprintf(stderr, gettext("missing vdev specification\n")); 442 usage(B_FALSE); 443 } 444 445 poolname = argv[0]; 446 447 argc--; 448 argv++; 449 450 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 451 return (1); 452 453 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 454 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 455 poolname); 456 zpool_close(zhp); 457 return (1); 458 } 459 460 /* pass off to get_vdev_spec for processing */ 461 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, argc, argv); 462 if (nvroot == NULL) { 463 zpool_close(zhp); 464 return (1); 465 } 466 467 if (dryrun) { 468 nvlist_t *poolnvroot; 469 470 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 471 &poolnvroot) == 0); 472 473 (void) printf(gettext("would update '%s' to the following " 474 "configuration:\n"), zpool_get_name(zhp)); 475 476 /* print original main pool and new tree */ 477 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 478 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 479 480 /* Do the same for the logs */ 481 if (num_logs(poolnvroot) > 0) { 482 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 483 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 484 } else if (num_logs(nvroot) > 0) { 485 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 486 } 487 488 ret = 0; 489 } else { 490 ret = (zpool_add(zhp, nvroot) != 0); 491 } 492 493 nvlist_free(nvroot); 494 zpool_close(zhp); 495 496 return (ret); 497 } 498 499 /* 500 * zpool remove <pool> <vdev> ... 501 * 502 * Removes the given vdev from the pool. Currently, this only supports removing 503 * spares and cache devices from the pool. Eventually, we'll want to support 504 * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs. 505 */ 506 int 507 zpool_do_remove(int argc, char **argv) 508 { 509 char *poolname; 510 int i, ret = 0; 511 zpool_handle_t *zhp; 512 513 argc--; 514 argv++; 515 516 /* get pool name and check number of arguments */ 517 if (argc < 1) { 518 (void) fprintf(stderr, gettext("missing pool name argument\n")); 519 usage(B_FALSE); 520 } 521 if (argc < 2) { 522 (void) fprintf(stderr, gettext("missing device\n")); 523 usage(B_FALSE); 524 } 525 526 poolname = argv[0]; 527 528 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 529 return (1); 530 531 for (i = 1; i < argc; i++) { 532 if (zpool_vdev_remove(zhp, argv[i]) != 0) 533 ret = 1; 534 } 535 536 return (ret); 537 } 538 539 /* 540 * zpool create [-fn] [-o property=value] ... [-R root] [-m mountpoint] 541 * <pool> <dev> ... 542 * 543 * -f Force creation, even if devices appear in use 544 * -n Do not create the pool, but display the resulting layout if it 545 * were to be created. 546 * -R Create a pool under an alternate root 547 * -m Set default mountpoint for the root dataset. By default it's 548 * '/<pool>' 549 * -o Set property=value. 550 * 551 * Creates the named pool according to the given vdev specification. The 552 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 553 * we get the nvlist back from get_vdev_spec(), we either print out the contents 554 * (if '-n' was specified), or pass it to libzfs to do the creation. 555 */ 556 int 557 zpool_do_create(int argc, char **argv) 558 { 559 boolean_t force = B_FALSE; 560 boolean_t dryrun = B_FALSE; 561 int c; 562 nvlist_t *nvroot = NULL; 563 char *poolname; 564 int ret = 1; 565 char *altroot = NULL; 566 char *mountpoint = NULL; 567 nvlist_t *props = NULL; 568 char *propval; 569 570 /* check options */ 571 while ((c = getopt(argc, argv, ":fnR:m:o:")) != -1) { 572 switch (c) { 573 case 'f': 574 force = B_TRUE; 575 break; 576 case 'n': 577 dryrun = B_TRUE; 578 break; 579 case 'R': 580 altroot = optarg; 581 if (add_prop_list(zpool_prop_to_name( 582 ZPOOL_PROP_ALTROOT), optarg, &props)) 583 goto errout; 584 if (nvlist_lookup_string(props, 585 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 586 &propval) == 0) 587 break; 588 if (add_prop_list(zpool_prop_to_name( 589 ZPOOL_PROP_CACHEFILE), "none", &props)) 590 goto errout; 591 break; 592 case 'm': 593 mountpoint = optarg; 594 break; 595 case 'o': 596 if ((propval = strchr(optarg, '=')) == NULL) { 597 (void) fprintf(stderr, gettext("missing " 598 "'=' for -o option\n")); 599 goto errout; 600 } 601 *propval = '\0'; 602 propval++; 603 604 if (add_prop_list(optarg, propval, &props)) 605 goto errout; 606 break; 607 case ':': 608 (void) fprintf(stderr, gettext("missing argument for " 609 "'%c' option\n"), optopt); 610 goto badusage; 611 case '?': 612 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 613 optopt); 614 goto badusage; 615 } 616 } 617 618 argc -= optind; 619 argv += optind; 620 621 /* get pool name and check number of arguments */ 622 if (argc < 1) { 623 (void) fprintf(stderr, gettext("missing pool name argument\n")); 624 goto badusage; 625 } 626 if (argc < 2) { 627 (void) fprintf(stderr, gettext("missing vdev specification\n")); 628 goto badusage; 629 } 630 631 poolname = argv[0]; 632 633 /* 634 * As a special case, check for use of '/' in the name, and direct the 635 * user to use 'zfs create' instead. 636 */ 637 if (strchr(poolname, '/') != NULL) { 638 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 639 "character '/' in pool name\n"), poolname); 640 (void) fprintf(stderr, gettext("use 'zfs create' to " 641 "create a dataset\n")); 642 goto errout; 643 } 644 645 /* pass off to get_vdev_spec for bulk processing */ 646 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1, 647 argv + 1); 648 if (nvroot == NULL) 649 return (1); 650 651 /* make_root_vdev() allows 0 toplevel children if there are spares */ 652 if (!zfs_allocatable_devs(nvroot)) { 653 (void) fprintf(stderr, gettext("invalid vdev " 654 "specification: at least one toplevel vdev must be " 655 "specified\n")); 656 goto errout; 657 } 658 659 660 if (altroot != NULL && altroot[0] != '/') { 661 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 662 "must be an absolute path\n"), altroot); 663 goto errout; 664 } 665 666 /* 667 * Check the validity of the mountpoint and direct the user to use the 668 * '-m' mountpoint option if it looks like its in use. 669 */ 670 if (mountpoint == NULL || 671 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 672 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 673 char buf[MAXPATHLEN]; 674 DIR *dirp; 675 676 if (mountpoint && mountpoint[0] != '/') { 677 (void) fprintf(stderr, gettext("invalid mountpoint " 678 "'%s': must be an absolute path, 'legacy', or " 679 "'none'\n"), mountpoint); 680 goto errout; 681 } 682 683 if (mountpoint == NULL) { 684 if (altroot != NULL) 685 (void) snprintf(buf, sizeof (buf), "%s/%s", 686 altroot, poolname); 687 else 688 (void) snprintf(buf, sizeof (buf), "/%s", 689 poolname); 690 } else { 691 if (altroot != NULL) 692 (void) snprintf(buf, sizeof (buf), "%s%s", 693 altroot, mountpoint); 694 else 695 (void) snprintf(buf, sizeof (buf), "%s", 696 mountpoint); 697 } 698 699 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 700 (void) fprintf(stderr, gettext("mountpoint '%s' : " 701 "%s\n"), buf, strerror(errno)); 702 (void) fprintf(stderr, gettext("use '-m' " 703 "option to provide a different default\n")); 704 goto errout; 705 } else if (dirp) { 706 int count = 0; 707 708 while (count < 3 && readdir(dirp) != NULL) 709 count++; 710 (void) closedir(dirp); 711 712 if (count > 2) { 713 (void) fprintf(stderr, gettext("mountpoint " 714 "'%s' exists and is not empty\n"), buf); 715 (void) fprintf(stderr, gettext("use '-m' " 716 "option to provide a " 717 "different default\n")); 718 goto errout; 719 } 720 } 721 } 722 723 if (dryrun) { 724 /* 725 * For a dry run invocation, print out a basic message and run 726 * through all the vdevs in the list and print out in an 727 * appropriate hierarchy. 728 */ 729 (void) printf(gettext("would create '%s' with the " 730 "following layout:\n\n"), poolname); 731 732 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 733 if (num_logs(nvroot) > 0) 734 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 735 736 ret = 0; 737 } else { 738 /* 739 * Hand off to libzfs. 740 */ 741 if (zpool_create(g_zfs, poolname, nvroot, props) == 0) { 742 zfs_handle_t *pool = zfs_open(g_zfs, poolname, 743 ZFS_TYPE_FILESYSTEM); 744 if (pool != NULL) { 745 if (mountpoint != NULL) 746 verify(zfs_prop_set(pool, 747 zfs_prop_to_name( 748 ZFS_PROP_MOUNTPOINT), 749 mountpoint) == 0); 750 if (zfs_mount(pool, NULL, 0) == 0) 751 ret = zfs_shareall(pool); 752 zfs_close(pool); 753 } 754 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 755 (void) fprintf(stderr, gettext("pool name may have " 756 "been omitted\n")); 757 } 758 } 759 760 errout: 761 nvlist_free(nvroot); 762 nvlist_free(props); 763 return (ret); 764 badusage: 765 nvlist_free(props); 766 usage(B_FALSE); 767 return (2); 768 } 769 770 /* 771 * zpool destroy <pool> 772 * 773 * -f Forcefully unmount any datasets 774 * 775 * Destroy the given pool. Automatically unmounts any datasets in the pool. 776 */ 777 int 778 zpool_do_destroy(int argc, char **argv) 779 { 780 boolean_t force = B_FALSE; 781 int c; 782 char *pool; 783 zpool_handle_t *zhp; 784 int ret; 785 786 /* check options */ 787 while ((c = getopt(argc, argv, "f")) != -1) { 788 switch (c) { 789 case 'f': 790 force = B_TRUE; 791 break; 792 case '?': 793 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 794 optopt); 795 usage(B_FALSE); 796 } 797 } 798 799 argc -= optind; 800 argv += optind; 801 802 /* check arguments */ 803 if (argc < 1) { 804 (void) fprintf(stderr, gettext("missing pool argument\n")); 805 usage(B_FALSE); 806 } 807 if (argc > 1) { 808 (void) fprintf(stderr, gettext("too many arguments\n")); 809 usage(B_FALSE); 810 } 811 812 pool = argv[0]; 813 814 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 815 /* 816 * As a special case, check for use of '/' in the name, and 817 * direct the user to use 'zfs destroy' instead. 818 */ 819 if (strchr(pool, '/') != NULL) 820 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 821 "destroy a dataset\n")); 822 return (1); 823 } 824 825 if (zpool_disable_datasets(zhp, force) != 0) { 826 (void) fprintf(stderr, gettext("could not destroy '%s': " 827 "could not unmount datasets\n"), zpool_get_name(zhp)); 828 return (1); 829 } 830 831 ret = (zpool_destroy(zhp) != 0); 832 833 zpool_close(zhp); 834 835 return (ret); 836 } 837 838 /* 839 * zpool export [-f] <pool> ... 840 * 841 * -f Forcefully unmount datasets 842 * 843 * Export the given pools. By default, the command will attempt to cleanly 844 * unmount any active datasets within the pool. If the '-f' flag is specified, 845 * then the datasets will be forcefully unmounted. 846 */ 847 int 848 zpool_do_export(int argc, char **argv) 849 { 850 boolean_t force = B_FALSE; 851 int c; 852 zpool_handle_t *zhp; 853 int ret; 854 int i; 855 856 /* check options */ 857 while ((c = getopt(argc, argv, "f")) != -1) { 858 switch (c) { 859 case 'f': 860 force = B_TRUE; 861 break; 862 case '?': 863 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 864 optopt); 865 usage(B_FALSE); 866 } 867 } 868 869 argc -= optind; 870 argv += optind; 871 872 /* check arguments */ 873 if (argc < 1) { 874 (void) fprintf(stderr, gettext("missing pool argument\n")); 875 usage(B_FALSE); 876 } 877 878 ret = 0; 879 for (i = 0; i < argc; i++) { 880 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 881 ret = 1; 882 continue; 883 } 884 885 if (zpool_disable_datasets(zhp, force) != 0) { 886 ret = 1; 887 zpool_close(zhp); 888 continue; 889 } 890 891 if (zpool_export(zhp) != 0) 892 ret = 1; 893 894 zpool_close(zhp); 895 } 896 897 return (ret); 898 } 899 900 /* 901 * Given a vdev configuration, determine the maximum width needed for the device 902 * name column. 903 */ 904 static int 905 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 906 { 907 char *name = zpool_vdev_name(g_zfs, zhp, nv); 908 nvlist_t **child; 909 uint_t c, children; 910 int ret; 911 912 if (strlen(name) + depth > max) 913 max = strlen(name) + depth; 914 915 free(name); 916 917 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 918 &child, &children) == 0) { 919 for (c = 0; c < children; c++) 920 if ((ret = max_width(zhp, child[c], depth + 2, 921 max)) > max) 922 max = ret; 923 } 924 925 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 926 &child, &children) == 0) { 927 for (c = 0; c < children; c++) 928 if ((ret = max_width(zhp, child[c], depth + 2, 929 max)) > max) 930 max = ret; 931 } 932 933 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 934 &child, &children) == 0) { 935 for (c = 0; c < children; c++) 936 if ((ret = max_width(zhp, child[c], depth + 2, 937 max)) > max) 938 max = ret; 939 } 940 941 942 return (max); 943 } 944 945 946 /* 947 * Print the configuration of an exported pool. Iterate over all vdevs in the 948 * pool, printing out the name and status for each one. 949 */ 950 void 951 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth, 952 boolean_t print_logs) 953 { 954 nvlist_t **child; 955 uint_t c, children; 956 vdev_stat_t *vs; 957 char *type, *vname; 958 959 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 960 if (strcmp(type, VDEV_TYPE_MISSING) == 0) 961 return; 962 963 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 964 (uint64_t **)&vs, &c) == 0); 965 966 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 967 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 968 969 if (vs->vs_aux != 0) { 970 (void) printf(" "); 971 972 switch (vs->vs_aux) { 973 case VDEV_AUX_OPEN_FAILED: 974 (void) printf(gettext("cannot open")); 975 break; 976 977 case VDEV_AUX_BAD_GUID_SUM: 978 (void) printf(gettext("missing device")); 979 break; 980 981 case VDEV_AUX_NO_REPLICAS: 982 (void) printf(gettext("insufficient replicas")); 983 break; 984 985 case VDEV_AUX_VERSION_NEWER: 986 (void) printf(gettext("newer version")); 987 break; 988 989 case VDEV_AUX_ERR_EXCEEDED: 990 (void) printf(gettext("too many errors")); 991 break; 992 993 default: 994 (void) printf(gettext("corrupted data")); 995 break; 996 } 997 } 998 (void) printf("\n"); 999 1000 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1001 &child, &children) != 0) 1002 return; 1003 1004 for (c = 0; c < children; c++) { 1005 uint64_t is_log = B_FALSE; 1006 1007 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1008 &is_log); 1009 if ((is_log && !print_logs) || (!is_log && print_logs)) 1010 continue; 1011 1012 vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1013 print_import_config(vname, child[c], 1014 namewidth, depth + 2, B_FALSE); 1015 free(vname); 1016 } 1017 1018 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1019 &child, &children) == 0) { 1020 (void) printf(gettext("\tcache\n")); 1021 for (c = 0; c < children; c++) { 1022 vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1023 (void) printf("\t %s\n", vname); 1024 free(vname); 1025 } 1026 } 1027 1028 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1029 &child, &children) == 0) { 1030 (void) printf(gettext("\tspares\n")); 1031 for (c = 0; c < children; c++) { 1032 vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1033 (void) printf("\t %s\n", vname); 1034 free(vname); 1035 } 1036 } 1037 } 1038 1039 /* 1040 * Display the status for the given pool. 1041 */ 1042 static void 1043 show_import(nvlist_t *config) 1044 { 1045 uint64_t pool_state; 1046 vdev_stat_t *vs; 1047 char *name; 1048 uint64_t guid; 1049 char *msgid; 1050 nvlist_t *nvroot; 1051 int reason; 1052 const char *health; 1053 uint_t vsc; 1054 int namewidth; 1055 1056 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1057 &name) == 0); 1058 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1059 &guid) == 0); 1060 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1061 &pool_state) == 0); 1062 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1063 &nvroot) == 0); 1064 1065 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 1066 (uint64_t **)&vs, &vsc) == 0); 1067 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1068 1069 reason = zpool_import_status(config, &msgid); 1070 1071 (void) printf(gettext(" pool: %s\n"), name); 1072 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1073 (void) printf(gettext(" state: %s"), health); 1074 if (pool_state == POOL_STATE_DESTROYED) 1075 (void) printf(gettext(" (DESTROYED)")); 1076 (void) printf("\n"); 1077 1078 switch (reason) { 1079 case ZPOOL_STATUS_MISSING_DEV_R: 1080 case ZPOOL_STATUS_MISSING_DEV_NR: 1081 case ZPOOL_STATUS_BAD_GUID_SUM: 1082 (void) printf(gettext("status: One or more devices are missing " 1083 "from the system.\n")); 1084 break; 1085 1086 case ZPOOL_STATUS_CORRUPT_LABEL_R: 1087 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1088 (void) printf(gettext("status: One or more devices contains " 1089 "corrupted data.\n")); 1090 break; 1091 1092 case ZPOOL_STATUS_CORRUPT_DATA: 1093 (void) printf(gettext("status: The pool data is corrupted.\n")); 1094 break; 1095 1096 case ZPOOL_STATUS_OFFLINE_DEV: 1097 (void) printf(gettext("status: One or more devices " 1098 "are offlined.\n")); 1099 break; 1100 1101 case ZPOOL_STATUS_CORRUPT_POOL: 1102 (void) printf(gettext("status: The pool metadata is " 1103 "corrupted.\n")); 1104 break; 1105 1106 case ZPOOL_STATUS_VERSION_OLDER: 1107 (void) printf(gettext("status: The pool is formatted using an " 1108 "older on-disk version.\n")); 1109 break; 1110 1111 case ZPOOL_STATUS_VERSION_NEWER: 1112 (void) printf(gettext("status: The pool is formatted using an " 1113 "incompatible version.\n")); 1114 break; 1115 case ZPOOL_STATUS_HOSTID_MISMATCH: 1116 (void) printf(gettext("status: The pool was last accessed by " 1117 "another system.\n")); 1118 break; 1119 case ZPOOL_STATUS_FAULTED_DEV_R: 1120 case ZPOOL_STATUS_FAULTED_DEV_NR: 1121 (void) printf(gettext("status: One or more devices are " 1122 "faulted.\n")); 1123 break; 1124 1125 default: 1126 /* 1127 * No other status can be seen when importing pools. 1128 */ 1129 assert(reason == ZPOOL_STATUS_OK); 1130 } 1131 1132 /* 1133 * Print out an action according to the overall state of the pool. 1134 */ 1135 if (vs->vs_state == VDEV_STATE_HEALTHY) { 1136 if (reason == ZPOOL_STATUS_VERSION_OLDER) 1137 (void) printf(gettext("action: The pool can be " 1138 "imported using its name or numeric identifier, " 1139 "though\n\tsome features will not be available " 1140 "without an explicit 'zpool upgrade'.\n")); 1141 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) 1142 (void) printf(gettext("action: The pool can be " 1143 "imported using its name or numeric " 1144 "identifier and\n\tthe '-f' flag.\n")); 1145 else 1146 (void) printf(gettext("action: The pool can be " 1147 "imported using its name or numeric " 1148 "identifier.\n")); 1149 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1150 (void) printf(gettext("action: The pool can be imported " 1151 "despite missing or damaged devices. The\n\tfault " 1152 "tolerance of the pool may be compromised if imported.\n")); 1153 } else { 1154 switch (reason) { 1155 case ZPOOL_STATUS_VERSION_NEWER: 1156 (void) printf(gettext("action: The pool cannot be " 1157 "imported. Access the pool on a system running " 1158 "newer\n\tsoftware, or recreate the pool from " 1159 "backup.\n")); 1160 break; 1161 case ZPOOL_STATUS_MISSING_DEV_R: 1162 case ZPOOL_STATUS_MISSING_DEV_NR: 1163 case ZPOOL_STATUS_BAD_GUID_SUM: 1164 (void) printf(gettext("action: The pool cannot be " 1165 "imported. Attach the missing\n\tdevices and try " 1166 "again.\n")); 1167 break; 1168 default: 1169 (void) printf(gettext("action: The pool cannot be " 1170 "imported due to damaged devices or data.\n")); 1171 } 1172 } 1173 1174 /* 1175 * If the state is "closed" or "can't open", and the aux state 1176 * is "corrupt data": 1177 */ 1178 if (((vs->vs_state == VDEV_STATE_CLOSED) || 1179 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 1180 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1181 if (pool_state == POOL_STATE_DESTROYED) 1182 (void) printf(gettext("\tThe pool was destroyed, " 1183 "but can be imported using the '-Df' flags.\n")); 1184 else if (pool_state != POOL_STATE_EXPORTED) 1185 (void) printf(gettext("\tThe pool may be active on " 1186 "another system, but can be imported using\n\t" 1187 "the '-f' flag.\n")); 1188 } 1189 1190 if (msgid != NULL) 1191 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 1192 msgid); 1193 1194 (void) printf(gettext("config:\n\n")); 1195 1196 namewidth = max_width(NULL, nvroot, 0, 0); 1197 if (namewidth < 10) 1198 namewidth = 10; 1199 1200 print_import_config(name, nvroot, namewidth, 0, B_FALSE); 1201 if (num_logs(nvroot) > 0) { 1202 (void) printf(gettext("\tlogs\n")); 1203 print_import_config(name, nvroot, namewidth, 0, B_TRUE); 1204 } 1205 1206 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 1207 (void) printf(gettext("\n\tAdditional devices are known to " 1208 "be part of this pool, though their\n\texact " 1209 "configuration cannot be determined.\n")); 1210 } 1211 } 1212 1213 /* 1214 * Perform the import for the given configuration. This passes the heavy 1215 * lifting off to zpool_import_props(), and then mounts the datasets contained 1216 * within the pool. 1217 */ 1218 static int 1219 do_import(nvlist_t *config, const char *newname, const char *mntopts, 1220 int force, nvlist_t *props, boolean_t allowfaulted) 1221 { 1222 zpool_handle_t *zhp; 1223 char *name; 1224 uint64_t state; 1225 uint64_t version; 1226 int error = 0; 1227 1228 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1229 &name) == 0); 1230 1231 verify(nvlist_lookup_uint64(config, 1232 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1233 verify(nvlist_lookup_uint64(config, 1234 ZPOOL_CONFIG_VERSION, &version) == 0); 1235 if (version > SPA_VERSION) { 1236 (void) fprintf(stderr, gettext("cannot import '%s': pool " 1237 "is formatted using a newer ZFS version\n"), name); 1238 return (1); 1239 } else if (state != POOL_STATE_EXPORTED && !force) { 1240 uint64_t hostid; 1241 1242 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 1243 &hostid) == 0) { 1244 if ((unsigned long)hostid != gethostid()) { 1245 char *hostname; 1246 uint64_t timestamp; 1247 time_t t; 1248 1249 verify(nvlist_lookup_string(config, 1250 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 1251 verify(nvlist_lookup_uint64(config, 1252 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 1253 t = timestamp; 1254 (void) fprintf(stderr, gettext("cannot import " 1255 "'%s': pool may be in use from other " 1256 "system, it was last accessed by %s " 1257 "(hostid: 0x%lx) on %s"), name, hostname, 1258 (unsigned long)hostid, 1259 asctime(localtime(&t))); 1260 (void) fprintf(stderr, gettext("use '-f' to " 1261 "import anyway\n")); 1262 return (1); 1263 } 1264 } else { 1265 (void) fprintf(stderr, gettext("cannot import '%s': " 1266 "pool may be in use from other system\n"), name); 1267 (void) fprintf(stderr, gettext("use '-f' to import " 1268 "anyway\n")); 1269 return (1); 1270 } 1271 } 1272 1273 if (zpool_import_props(g_zfs, config, newname, props, 1274 allowfaulted) != 0) 1275 return (1); 1276 1277 if (newname != NULL) 1278 name = (char *)newname; 1279 1280 verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL); 1281 1282 if (zpool_enable_datasets(zhp, mntopts, 0) != 0) { 1283 zpool_close(zhp); 1284 return (1); 1285 } 1286 1287 zpool_close(zhp); 1288 return (error); 1289 } 1290 1291 /* 1292 * zpool import [-d dir] [-D] 1293 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1294 * [-d dir | -c cachefile] [-f] -a 1295 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1296 * [-d dir | -c cachefile] [-f] <pool | id> [newpool] 1297 * 1298 * -c Read pool information from a cachefile instead of searching 1299 * devices. 1300 * 1301 * -d Scan in a specific directory, other than /dev/dsk. More than 1302 * one directory can be specified using multiple '-d' options. 1303 * 1304 * -D Scan for previously destroyed pools or import all or only 1305 * specified destroyed pools. 1306 * 1307 * -R Temporarily import the pool, with all mountpoints relative to 1308 * the given root. The pool will remain exported when the machine 1309 * is rebooted. 1310 * 1311 * -f Force import, even if it appears that the pool is active. 1312 * 1313 * -F Import even in the presence of faulted vdevs. This is an 1314 * intentionally undocumented option for testing purposes, and 1315 * treats the pool configuration as complete, leaving any bad 1316 * vdevs in the FAULTED state. 1317 * 1318 * -a Import all pools found. 1319 * 1320 * -o Set property=value and/or temporary mount options (without '='). 1321 * 1322 * The import command scans for pools to import, and import pools based on pool 1323 * name and GUID. The pool can also be renamed as part of the import process. 1324 */ 1325 int 1326 zpool_do_import(int argc, char **argv) 1327 { 1328 char **searchdirs = NULL; 1329 int nsearch = 0; 1330 int c; 1331 int err; 1332 nvlist_t *pools = NULL; 1333 boolean_t do_all = B_FALSE; 1334 boolean_t do_destroyed = B_FALSE; 1335 char *mntopts = NULL; 1336 boolean_t do_force = B_FALSE; 1337 nvpair_t *elem; 1338 nvlist_t *config; 1339 uint64_t searchguid = 0; 1340 char *searchname = NULL; 1341 char *propval; 1342 nvlist_t *found_config; 1343 nvlist_t *props = NULL; 1344 boolean_t first; 1345 boolean_t allow_faulted = B_FALSE; 1346 uint64_t pool_state; 1347 char *cachefile = NULL; 1348 1349 /* check options */ 1350 while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) { 1351 switch (c) { 1352 case 'a': 1353 do_all = B_TRUE; 1354 break; 1355 case 'c': 1356 cachefile = optarg; 1357 break; 1358 case 'd': 1359 if (searchdirs == NULL) { 1360 searchdirs = safe_malloc(sizeof (char *)); 1361 } else { 1362 char **tmp = safe_malloc((nsearch + 1) * 1363 sizeof (char *)); 1364 bcopy(searchdirs, tmp, nsearch * 1365 sizeof (char *)); 1366 free(searchdirs); 1367 searchdirs = tmp; 1368 } 1369 searchdirs[nsearch++] = optarg; 1370 break; 1371 case 'D': 1372 do_destroyed = B_TRUE; 1373 break; 1374 case 'f': 1375 do_force = B_TRUE; 1376 break; 1377 case 'F': 1378 allow_faulted = B_TRUE; 1379 break; 1380 case 'o': 1381 if ((propval = strchr(optarg, '=')) != NULL) { 1382 *propval = '\0'; 1383 propval++; 1384 if (add_prop_list(optarg, propval, &props)) 1385 goto error; 1386 } else { 1387 mntopts = optarg; 1388 } 1389 break; 1390 case 'R': 1391 if (add_prop_list(zpool_prop_to_name( 1392 ZPOOL_PROP_ALTROOT), optarg, &props)) 1393 goto error; 1394 if (nvlist_lookup_string(props, 1395 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 1396 &propval) == 0) 1397 break; 1398 if (add_prop_list(zpool_prop_to_name( 1399 ZPOOL_PROP_CACHEFILE), "none", &props)) 1400 goto error; 1401 break; 1402 case ':': 1403 (void) fprintf(stderr, gettext("missing argument for " 1404 "'%c' option\n"), optopt); 1405 usage(B_FALSE); 1406 break; 1407 case '?': 1408 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1409 optopt); 1410 usage(B_FALSE); 1411 } 1412 } 1413 1414 argc -= optind; 1415 argv += optind; 1416 1417 if (cachefile && nsearch != 0) { 1418 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 1419 usage(B_FALSE); 1420 } 1421 1422 if (searchdirs == NULL) { 1423 searchdirs = safe_malloc(sizeof (char *)); 1424 searchdirs[0] = "/dev/dsk"; 1425 nsearch = 1; 1426 } 1427 1428 /* check argument count */ 1429 if (do_all) { 1430 if (argc != 0) { 1431 (void) fprintf(stderr, gettext("too many arguments\n")); 1432 usage(B_FALSE); 1433 } 1434 } else { 1435 if (argc > 2) { 1436 (void) fprintf(stderr, gettext("too many arguments\n")); 1437 usage(B_FALSE); 1438 } 1439 1440 /* 1441 * Check for the SYS_CONFIG privilege. We do this explicitly 1442 * here because otherwise any attempt to discover pools will 1443 * silently fail. 1444 */ 1445 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 1446 (void) fprintf(stderr, gettext("cannot " 1447 "discover pools: permission denied\n")); 1448 free(searchdirs); 1449 return (1); 1450 } 1451 } 1452 1453 /* 1454 * Depending on the arguments given, we do one of the following: 1455 * 1456 * <none> Iterate through all pools and display information about 1457 * each one. 1458 * 1459 * -a Iterate through all pools and try to import each one. 1460 * 1461 * <id> Find the pool that corresponds to the given GUID/pool 1462 * name and import that one. 1463 * 1464 * -D Above options applies only to destroyed pools. 1465 */ 1466 if (argc != 0) { 1467 char *endptr; 1468 1469 errno = 0; 1470 searchguid = strtoull(argv[0], &endptr, 10); 1471 if (errno != 0 || *endptr != '\0') 1472 searchname = argv[0]; 1473 found_config = NULL; 1474 } 1475 1476 if (cachefile) { 1477 pools = zpool_find_import_cached(g_zfs, cachefile, searchname, 1478 searchguid); 1479 } else if (searchname != NULL) { 1480 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs, 1481 searchname); 1482 } else { 1483 /* 1484 * It's OK to search by guid even if searchguid is 0. 1485 */ 1486 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs, 1487 searchguid); 1488 } 1489 1490 if (pools == NULL) { 1491 if (argc != 0) { 1492 (void) fprintf(stderr, gettext("cannot import '%s': " 1493 "no such pool available\n"), argv[0]); 1494 } 1495 free(searchdirs); 1496 return (1); 1497 } 1498 1499 /* 1500 * At this point we have a list of import candidate configs. Even if 1501 * we were searching by pool name or guid, we still need to 1502 * post-process the list to deal with pool state and possible 1503 * duplicate names. 1504 */ 1505 err = 0; 1506 elem = NULL; 1507 first = B_TRUE; 1508 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1509 1510 verify(nvpair_value_nvlist(elem, &config) == 0); 1511 1512 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1513 &pool_state) == 0); 1514 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 1515 continue; 1516 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 1517 continue; 1518 1519 if (argc == 0) { 1520 if (first) 1521 first = B_FALSE; 1522 else if (!do_all) 1523 (void) printf("\n"); 1524 1525 if (do_all) 1526 err |= do_import(config, NULL, mntopts, 1527 do_force, props, allow_faulted); 1528 else 1529 show_import(config); 1530 } else if (searchname != NULL) { 1531 char *name; 1532 1533 /* 1534 * We are searching for a pool based on name. 1535 */ 1536 verify(nvlist_lookup_string(config, 1537 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 1538 1539 if (strcmp(name, searchname) == 0) { 1540 if (found_config != NULL) { 1541 (void) fprintf(stderr, gettext( 1542 "cannot import '%s': more than " 1543 "one matching pool\n"), searchname); 1544 (void) fprintf(stderr, gettext( 1545 "import by numeric ID instead\n")); 1546 err = B_TRUE; 1547 } 1548 found_config = config; 1549 } 1550 } else { 1551 uint64_t guid; 1552 1553 /* 1554 * Search for a pool by guid. 1555 */ 1556 verify(nvlist_lookup_uint64(config, 1557 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 1558 1559 if (guid == searchguid) 1560 found_config = config; 1561 } 1562 } 1563 1564 /* 1565 * If we were searching for a specific pool, verify that we found a 1566 * pool, and then do the import. 1567 */ 1568 if (argc != 0 && err == 0) { 1569 if (found_config == NULL) { 1570 (void) fprintf(stderr, gettext("cannot import '%s': " 1571 "no such pool available\n"), argv[0]); 1572 err = B_TRUE; 1573 } else { 1574 err |= do_import(found_config, argc == 1 ? NULL : 1575 argv[1], mntopts, do_force, props, allow_faulted); 1576 } 1577 } 1578 1579 /* 1580 * If we were just looking for pools, report an error if none were 1581 * found. 1582 */ 1583 if (argc == 0 && first) 1584 (void) fprintf(stderr, 1585 gettext("no pools available to import\n")); 1586 1587 error: 1588 nvlist_free(props); 1589 nvlist_free(pools); 1590 free(searchdirs); 1591 1592 return (err ? 1 : 0); 1593 } 1594 1595 typedef struct iostat_cbdata { 1596 zpool_list_t *cb_list; 1597 int cb_verbose; 1598 int cb_iteration; 1599 int cb_namewidth; 1600 } iostat_cbdata_t; 1601 1602 static void 1603 print_iostat_separator(iostat_cbdata_t *cb) 1604 { 1605 int i = 0; 1606 1607 for (i = 0; i < cb->cb_namewidth; i++) 1608 (void) printf("-"); 1609 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 1610 } 1611 1612 static void 1613 print_iostat_header(iostat_cbdata_t *cb) 1614 { 1615 (void) printf("%*s capacity operations bandwidth\n", 1616 cb->cb_namewidth, ""); 1617 (void) printf("%-*s used avail read write read write\n", 1618 cb->cb_namewidth, "pool"); 1619 print_iostat_separator(cb); 1620 } 1621 1622 /* 1623 * Display a single statistic. 1624 */ 1625 static void 1626 print_one_stat(uint64_t value) 1627 { 1628 char buf[64]; 1629 1630 zfs_nicenum(value, buf, sizeof (buf)); 1631 (void) printf(" %5s", buf); 1632 } 1633 1634 /* 1635 * Print out all the statistics for the given vdev. This can either be the 1636 * toplevel configuration, or called recursively. If 'name' is NULL, then this 1637 * is a verbose output, and we don't want to display the toplevel pool stats. 1638 */ 1639 void 1640 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 1641 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 1642 { 1643 nvlist_t **oldchild, **newchild; 1644 uint_t c, children; 1645 vdev_stat_t *oldvs, *newvs; 1646 vdev_stat_t zerovs = { 0 }; 1647 uint64_t tdelta; 1648 double scale; 1649 char *vname; 1650 1651 if (oldnv != NULL) { 1652 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS, 1653 (uint64_t **)&oldvs, &c) == 0); 1654 } else { 1655 oldvs = &zerovs; 1656 } 1657 1658 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS, 1659 (uint64_t **)&newvs, &c) == 0); 1660 1661 if (strlen(name) + depth > cb->cb_namewidth) 1662 (void) printf("%*s%s", depth, "", name); 1663 else 1664 (void) printf("%*s%s%*s", depth, "", name, 1665 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 1666 1667 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 1668 1669 if (tdelta == 0) 1670 scale = 1.0; 1671 else 1672 scale = (double)NANOSEC / tdelta; 1673 1674 /* only toplevel vdevs have capacity stats */ 1675 if (newvs->vs_space == 0) { 1676 (void) printf(" - -"); 1677 } else { 1678 print_one_stat(newvs->vs_alloc); 1679 print_one_stat(newvs->vs_space - newvs->vs_alloc); 1680 } 1681 1682 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 1683 oldvs->vs_ops[ZIO_TYPE_READ]))); 1684 1685 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 1686 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 1687 1688 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 1689 oldvs->vs_bytes[ZIO_TYPE_READ]))); 1690 1691 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 1692 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 1693 1694 (void) printf("\n"); 1695 1696 if (!cb->cb_verbose) 1697 return; 1698 1699 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 1700 &newchild, &children) != 0) 1701 return; 1702 1703 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 1704 &oldchild, &c) != 0) 1705 return; 1706 1707 for (c = 0; c < children; c++) { 1708 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]); 1709 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1710 newchild[c], cb, depth + 2); 1711 free(vname); 1712 } 1713 1714 /* 1715 * Include level 2 ARC devices in iostat output 1716 */ 1717 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 1718 &newchild, &children) != 0) 1719 return; 1720 1721 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 1722 &oldchild, &c) != 0) 1723 return; 1724 1725 if (children > 0) { 1726 (void) printf("%-*s - - - - - " 1727 "-\n", cb->cb_namewidth, "cache"); 1728 for (c = 0; c < children; c++) { 1729 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]); 1730 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1731 newchild[c], cb, depth + 2); 1732 free(vname); 1733 } 1734 } 1735 } 1736 1737 static int 1738 refresh_iostat(zpool_handle_t *zhp, void *data) 1739 { 1740 iostat_cbdata_t *cb = data; 1741 boolean_t missing; 1742 1743 /* 1744 * If the pool has disappeared, remove it from the list and continue. 1745 */ 1746 if (zpool_refresh_stats(zhp, &missing) != 0) 1747 return (-1); 1748 1749 if (missing) 1750 pool_list_remove(cb->cb_list, zhp); 1751 1752 return (0); 1753 } 1754 1755 /* 1756 * Callback to print out the iostats for the given pool. 1757 */ 1758 int 1759 print_iostat(zpool_handle_t *zhp, void *data) 1760 { 1761 iostat_cbdata_t *cb = data; 1762 nvlist_t *oldconfig, *newconfig; 1763 nvlist_t *oldnvroot, *newnvroot; 1764 1765 newconfig = zpool_get_config(zhp, &oldconfig); 1766 1767 if (cb->cb_iteration == 1) 1768 oldconfig = NULL; 1769 1770 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 1771 &newnvroot) == 0); 1772 1773 if (oldconfig == NULL) 1774 oldnvroot = NULL; 1775 else 1776 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 1777 &oldnvroot) == 0); 1778 1779 /* 1780 * Print out the statistics for the pool. 1781 */ 1782 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 1783 1784 if (cb->cb_verbose) 1785 print_iostat_separator(cb); 1786 1787 return (0); 1788 } 1789 1790 int 1791 get_namewidth(zpool_handle_t *zhp, void *data) 1792 { 1793 iostat_cbdata_t *cb = data; 1794 nvlist_t *config, *nvroot; 1795 1796 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 1797 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1798 &nvroot) == 0); 1799 if (!cb->cb_verbose) 1800 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 1801 else 1802 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); 1803 } 1804 1805 /* 1806 * The width must fall into the range [10,38]. The upper limit is the 1807 * maximum we can have and still fit in 80 columns. 1808 */ 1809 if (cb->cb_namewidth < 10) 1810 cb->cb_namewidth = 10; 1811 if (cb->cb_namewidth > 38) 1812 cb->cb_namewidth = 38; 1813 1814 return (0); 1815 } 1816 1817 /* 1818 * zpool iostat [-v] [pool] ... [interval [count]] 1819 * 1820 * -v Display statistics for individual vdevs 1821 * 1822 * This command can be tricky because we want to be able to deal with pool 1823 * creation/destruction as well as vdev configuration changes. The bulk of this 1824 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 1825 * on pool_list_update() to detect the addition of new pools. Configuration 1826 * changes are all handled within libzfs. 1827 */ 1828 int 1829 zpool_do_iostat(int argc, char **argv) 1830 { 1831 int c; 1832 int ret; 1833 int npools; 1834 unsigned long interval = 0, count = 0; 1835 zpool_list_t *list; 1836 boolean_t verbose = B_FALSE; 1837 iostat_cbdata_t cb; 1838 1839 /* check options */ 1840 while ((c = getopt(argc, argv, "v")) != -1) { 1841 switch (c) { 1842 case 'v': 1843 verbose = B_TRUE; 1844 break; 1845 case '?': 1846 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1847 optopt); 1848 usage(B_FALSE); 1849 } 1850 } 1851 1852 argc -= optind; 1853 argv += optind; 1854 1855 /* 1856 * Determine if the last argument is an integer or a pool name 1857 */ 1858 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1859 char *end; 1860 1861 errno = 0; 1862 interval = strtoul(argv[argc - 1], &end, 10); 1863 1864 if (*end == '\0' && errno == 0) { 1865 if (interval == 0) { 1866 (void) fprintf(stderr, gettext("interval " 1867 "cannot be zero\n")); 1868 usage(B_FALSE); 1869 } 1870 1871 /* 1872 * Ignore the last parameter 1873 */ 1874 argc--; 1875 } else { 1876 /* 1877 * If this is not a valid number, just plow on. The 1878 * user will get a more informative error message later 1879 * on. 1880 */ 1881 interval = 0; 1882 } 1883 } 1884 1885 /* 1886 * If the last argument is also an integer, then we have both a count 1887 * and an integer. 1888 */ 1889 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1890 char *end; 1891 1892 errno = 0; 1893 count = interval; 1894 interval = strtoul(argv[argc - 1], &end, 10); 1895 1896 if (*end == '\0' && errno == 0) { 1897 if (interval == 0) { 1898 (void) fprintf(stderr, gettext("interval " 1899 "cannot be zero\n")); 1900 usage(B_FALSE); 1901 } 1902 1903 /* 1904 * Ignore the last parameter 1905 */ 1906 argc--; 1907 } else { 1908 interval = 0; 1909 } 1910 } 1911 1912 /* 1913 * Construct the list of all interesting pools. 1914 */ 1915 ret = 0; 1916 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 1917 return (1); 1918 1919 if (pool_list_count(list) == 0 && argc != 0) { 1920 pool_list_free(list); 1921 return (1); 1922 } 1923 1924 if (pool_list_count(list) == 0 && interval == 0) { 1925 pool_list_free(list); 1926 (void) fprintf(stderr, gettext("no pools available\n")); 1927 return (1); 1928 } 1929 1930 /* 1931 * Enter the main iostat loop. 1932 */ 1933 cb.cb_list = list; 1934 cb.cb_verbose = verbose; 1935 cb.cb_iteration = 0; 1936 cb.cb_namewidth = 0; 1937 1938 for (;;) { 1939 pool_list_update(list); 1940 1941 if ((npools = pool_list_count(list)) == 0) 1942 break; 1943 1944 /* 1945 * Refresh all statistics. This is done as an explicit step 1946 * before calculating the maximum name width, so that any 1947 * configuration changes are properly accounted for. 1948 */ 1949 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 1950 1951 /* 1952 * Iterate over all pools to determine the maximum width 1953 * for the pool / device name column across all pools. 1954 */ 1955 cb.cb_namewidth = 0; 1956 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 1957 1958 /* 1959 * If it's the first time, or verbose mode, print the header. 1960 */ 1961 if (++cb.cb_iteration == 1 || verbose) 1962 print_iostat_header(&cb); 1963 1964 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 1965 1966 /* 1967 * If there's more than one pool, and we're not in verbose mode 1968 * (which prints a separator for us), then print a separator. 1969 */ 1970 if (npools > 1 && !verbose) 1971 print_iostat_separator(&cb); 1972 1973 if (verbose) 1974 (void) printf("\n"); 1975 1976 /* 1977 * Flush the output so that redirection to a file isn't buffered 1978 * indefinitely. 1979 */ 1980 (void) fflush(stdout); 1981 1982 if (interval == 0) 1983 break; 1984 1985 if (count != 0 && --count == 0) 1986 break; 1987 1988 (void) sleep(interval); 1989 } 1990 1991 pool_list_free(list); 1992 1993 return (ret); 1994 } 1995 1996 typedef struct list_cbdata { 1997 boolean_t cb_scripted; 1998 boolean_t cb_first; 1999 zprop_list_t *cb_proplist; 2000 } list_cbdata_t; 2001 2002 /* 2003 * Given a list of columns to display, output appropriate headers for each one. 2004 */ 2005 static void 2006 print_header(zprop_list_t *pl) 2007 { 2008 const char *header; 2009 boolean_t first = B_TRUE; 2010 boolean_t right_justify; 2011 2012 for (; pl != NULL; pl = pl->pl_next) { 2013 if (pl->pl_prop == ZPROP_INVAL) 2014 continue; 2015 2016 if (!first) 2017 (void) printf(" "); 2018 else 2019 first = B_FALSE; 2020 2021 header = zpool_prop_column_name(pl->pl_prop); 2022 right_justify = zpool_prop_align_right(pl->pl_prop); 2023 2024 if (pl->pl_next == NULL && !right_justify) 2025 (void) printf("%s", header); 2026 else if (right_justify) 2027 (void) printf("%*s", pl->pl_width, header); 2028 else 2029 (void) printf("%-*s", pl->pl_width, header); 2030 } 2031 2032 (void) printf("\n"); 2033 } 2034 2035 /* 2036 * Given a pool and a list of properties, print out all the properties according 2037 * to the described layout. 2038 */ 2039 static void 2040 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted) 2041 { 2042 boolean_t first = B_TRUE; 2043 char property[ZPOOL_MAXPROPLEN]; 2044 char *propstr; 2045 boolean_t right_justify; 2046 int width; 2047 2048 for (; pl != NULL; pl = pl->pl_next) { 2049 if (!first) { 2050 if (scripted) 2051 (void) printf("\t"); 2052 else 2053 (void) printf(" "); 2054 } else { 2055 first = B_FALSE; 2056 } 2057 2058 right_justify = B_FALSE; 2059 if (pl->pl_prop != ZPROP_INVAL) { 2060 if (zpool_get_prop(zhp, pl->pl_prop, property, 2061 sizeof (property), NULL) != 0) 2062 propstr = "-"; 2063 else 2064 propstr = property; 2065 2066 right_justify = zpool_prop_align_right(pl->pl_prop); 2067 } else { 2068 propstr = "-"; 2069 } 2070 2071 width = pl->pl_width; 2072 2073 /* 2074 * If this is being called in scripted mode, or if this is the 2075 * last column and it is left-justified, don't include a width 2076 * format specifier. 2077 */ 2078 if (scripted || (pl->pl_next == NULL && !right_justify)) 2079 (void) printf("%s", propstr); 2080 else if (right_justify) 2081 (void) printf("%*s", width, propstr); 2082 else 2083 (void) printf("%-*s", width, propstr); 2084 } 2085 2086 (void) printf("\n"); 2087 } 2088 2089 /* 2090 * Generic callback function to list a pool. 2091 */ 2092 int 2093 list_callback(zpool_handle_t *zhp, void *data) 2094 { 2095 list_cbdata_t *cbp = data; 2096 2097 if (cbp->cb_first) { 2098 if (!cbp->cb_scripted) 2099 print_header(cbp->cb_proplist); 2100 cbp->cb_first = B_FALSE; 2101 } 2102 2103 print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted); 2104 2105 return (0); 2106 } 2107 2108 /* 2109 * zpool list [-H] [-o prop[,prop]*] [pool] ... 2110 * 2111 * -H Scripted mode. Don't display headers, and separate properties 2112 * by a single tab. 2113 * -o List of properties to display. Defaults to 2114 * "name,size,used,available,capacity,health,altroot" 2115 * 2116 * List all pools in the system, whether or not they're healthy. Output space 2117 * statistics for each one, as well as health status summary. 2118 */ 2119 int 2120 zpool_do_list(int argc, char **argv) 2121 { 2122 int c; 2123 int ret; 2124 list_cbdata_t cb = { 0 }; 2125 static char default_props[] = 2126 "name,size,used,available,capacity,health,altroot"; 2127 char *props = default_props; 2128 2129 /* check options */ 2130 while ((c = getopt(argc, argv, ":Ho:")) != -1) { 2131 switch (c) { 2132 case 'H': 2133 cb.cb_scripted = B_TRUE; 2134 break; 2135 case 'o': 2136 props = optarg; 2137 break; 2138 case ':': 2139 (void) fprintf(stderr, gettext("missing argument for " 2140 "'%c' option\n"), optopt); 2141 usage(B_FALSE); 2142 break; 2143 case '?': 2144 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2145 optopt); 2146 usage(B_FALSE); 2147 } 2148 } 2149 2150 argc -= optind; 2151 argv += optind; 2152 2153 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 2154 usage(B_FALSE); 2155 2156 cb.cb_first = B_TRUE; 2157 2158 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 2159 list_callback, &cb); 2160 2161 zprop_free_list(cb.cb_proplist); 2162 2163 if (argc == 0 && cb.cb_first && !cb.cb_scripted) { 2164 (void) printf(gettext("no pools available\n")); 2165 return (0); 2166 } 2167 2168 return (ret); 2169 } 2170 2171 static nvlist_t * 2172 zpool_get_vdev_by_name(nvlist_t *nv, char *name) 2173 { 2174 nvlist_t **child; 2175 uint_t c, children; 2176 nvlist_t *match; 2177 char *path; 2178 2179 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2180 &child, &children) != 0) { 2181 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2182 if (strncmp(name, "/dev/dsk/", 9) == 0) 2183 name += 9; 2184 if (strncmp(path, "/dev/dsk/", 9) == 0) 2185 path += 9; 2186 if (strcmp(name, path) == 0) 2187 return (nv); 2188 return (NULL); 2189 } 2190 2191 for (c = 0; c < children; c++) 2192 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 2193 return (match); 2194 2195 return (NULL); 2196 } 2197 2198 static int 2199 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 2200 { 2201 boolean_t force = B_FALSE; 2202 int c; 2203 nvlist_t *nvroot; 2204 char *poolname, *old_disk, *new_disk; 2205 zpool_handle_t *zhp; 2206 int ret; 2207 2208 /* check options */ 2209 while ((c = getopt(argc, argv, "f")) != -1) { 2210 switch (c) { 2211 case 'f': 2212 force = B_TRUE; 2213 break; 2214 case '?': 2215 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2216 optopt); 2217 usage(B_FALSE); 2218 } 2219 } 2220 2221 argc -= optind; 2222 argv += optind; 2223 2224 /* get pool name and check number of arguments */ 2225 if (argc < 1) { 2226 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2227 usage(B_FALSE); 2228 } 2229 2230 poolname = argv[0]; 2231 2232 if (argc < 2) { 2233 (void) fprintf(stderr, 2234 gettext("missing <device> specification\n")); 2235 usage(B_FALSE); 2236 } 2237 2238 old_disk = argv[1]; 2239 2240 if (argc < 3) { 2241 if (!replacing) { 2242 (void) fprintf(stderr, 2243 gettext("missing <new_device> specification\n")); 2244 usage(B_FALSE); 2245 } 2246 new_disk = old_disk; 2247 argc -= 1; 2248 argv += 1; 2249 } else { 2250 new_disk = argv[2]; 2251 argc -= 2; 2252 argv += 2; 2253 } 2254 2255 if (argc > 1) { 2256 (void) fprintf(stderr, gettext("too many arguments\n")); 2257 usage(B_FALSE); 2258 } 2259 2260 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2261 return (1); 2262 2263 if (zpool_get_config(zhp, NULL) == NULL) { 2264 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 2265 poolname); 2266 zpool_close(zhp); 2267 return (1); 2268 } 2269 2270 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, argc, argv); 2271 if (nvroot == NULL) { 2272 zpool_close(zhp); 2273 return (1); 2274 } 2275 2276 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 2277 2278 nvlist_free(nvroot); 2279 zpool_close(zhp); 2280 2281 return (ret); 2282 } 2283 2284 /* 2285 * zpool replace [-f] <pool> <device> <new_device> 2286 * 2287 * -f Force attach, even if <new_device> appears to be in use. 2288 * 2289 * Replace <device> with <new_device>. 2290 */ 2291 /* ARGSUSED */ 2292 int 2293 zpool_do_replace(int argc, char **argv) 2294 { 2295 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 2296 } 2297 2298 /* 2299 * zpool attach [-f] <pool> <device> <new_device> 2300 * 2301 * -f Force attach, even if <new_device> appears to be in use. 2302 * 2303 * Attach <new_device> to the mirror containing <device>. If <device> is not 2304 * part of a mirror, then <device> will be transformed into a mirror of 2305 * <device> and <new_device>. In either case, <new_device> will begin life 2306 * with a DTL of [0, now], and will immediately begin to resilver itself. 2307 */ 2308 int 2309 zpool_do_attach(int argc, char **argv) 2310 { 2311 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 2312 } 2313 2314 /* 2315 * zpool detach [-f] <pool> <device> 2316 * 2317 * -f Force detach of <device>, even if DTLs argue against it 2318 * (not supported yet) 2319 * 2320 * Detach a device from a mirror. The operation will be refused if <device> 2321 * is the last device in the mirror, or if the DTLs indicate that this device 2322 * has the only valid copy of some data. 2323 */ 2324 /* ARGSUSED */ 2325 int 2326 zpool_do_detach(int argc, char **argv) 2327 { 2328 int c; 2329 char *poolname, *path; 2330 zpool_handle_t *zhp; 2331 int ret; 2332 2333 /* check options */ 2334 while ((c = getopt(argc, argv, "f")) != -1) { 2335 switch (c) { 2336 case 'f': 2337 case '?': 2338 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2339 optopt); 2340 usage(B_FALSE); 2341 } 2342 } 2343 2344 argc -= optind; 2345 argv += optind; 2346 2347 /* get pool name and check number of arguments */ 2348 if (argc < 1) { 2349 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2350 usage(B_FALSE); 2351 } 2352 2353 if (argc < 2) { 2354 (void) fprintf(stderr, 2355 gettext("missing <device> specification\n")); 2356 usage(B_FALSE); 2357 } 2358 2359 poolname = argv[0]; 2360 path = argv[1]; 2361 2362 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2363 return (1); 2364 2365 ret = zpool_vdev_detach(zhp, path); 2366 2367 zpool_close(zhp); 2368 2369 return (ret); 2370 } 2371 2372 /* 2373 * zpool online <pool> <device> ... 2374 */ 2375 int 2376 zpool_do_online(int argc, char **argv) 2377 { 2378 int c, i; 2379 char *poolname; 2380 zpool_handle_t *zhp; 2381 int ret = 0; 2382 vdev_state_t newstate; 2383 2384 /* check options */ 2385 while ((c = getopt(argc, argv, "t")) != -1) { 2386 switch (c) { 2387 case 't': 2388 case '?': 2389 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2390 optopt); 2391 usage(B_FALSE); 2392 } 2393 } 2394 2395 argc -= optind; 2396 argv += optind; 2397 2398 /* get pool name and check number of arguments */ 2399 if (argc < 1) { 2400 (void) fprintf(stderr, gettext("missing pool name\n")); 2401 usage(B_FALSE); 2402 } 2403 if (argc < 2) { 2404 (void) fprintf(stderr, gettext("missing device name\n")); 2405 usage(B_FALSE); 2406 } 2407 2408 poolname = argv[0]; 2409 2410 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2411 return (1); 2412 2413 for (i = 1; i < argc; i++) { 2414 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) { 2415 if (newstate != VDEV_STATE_HEALTHY) { 2416 (void) printf(gettext("warning: device '%s' " 2417 "onlined, but remains in faulted state\n"), 2418 argv[i]); 2419 if (newstate == VDEV_STATE_FAULTED) 2420 (void) printf(gettext("use 'zpool " 2421 "clear' to restore a faulted " 2422 "device\n")); 2423 else 2424 (void) printf(gettext("use 'zpool " 2425 "replace' to replace devices " 2426 "that are no longer present\n")); 2427 } 2428 } else { 2429 ret = 1; 2430 } 2431 } 2432 2433 zpool_close(zhp); 2434 2435 return (ret); 2436 } 2437 2438 /* 2439 * zpool offline [-ft] <pool> <device> ... 2440 * 2441 * -f Force the device into the offline state, even if doing 2442 * so would appear to compromise pool availability. 2443 * (not supported yet) 2444 * 2445 * -t Only take the device off-line temporarily. The offline 2446 * state will not be persistent across reboots. 2447 */ 2448 /* ARGSUSED */ 2449 int 2450 zpool_do_offline(int argc, char **argv) 2451 { 2452 int c, i; 2453 char *poolname; 2454 zpool_handle_t *zhp; 2455 int ret = 0; 2456 boolean_t istmp = B_FALSE; 2457 2458 /* check options */ 2459 while ((c = getopt(argc, argv, "ft")) != -1) { 2460 switch (c) { 2461 case 't': 2462 istmp = B_TRUE; 2463 break; 2464 case 'f': 2465 case '?': 2466 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2467 optopt); 2468 usage(B_FALSE); 2469 } 2470 } 2471 2472 argc -= optind; 2473 argv += optind; 2474 2475 /* get pool name and check number of arguments */ 2476 if (argc < 1) { 2477 (void) fprintf(stderr, gettext("missing pool name\n")); 2478 usage(B_FALSE); 2479 } 2480 if (argc < 2) { 2481 (void) fprintf(stderr, gettext("missing device name\n")); 2482 usage(B_FALSE); 2483 } 2484 2485 poolname = argv[0]; 2486 2487 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2488 return (1); 2489 2490 for (i = 1; i < argc; i++) { 2491 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 2492 ret = 1; 2493 } 2494 2495 zpool_close(zhp); 2496 2497 return (ret); 2498 } 2499 2500 /* 2501 * zpool clear <pool> [device] 2502 * 2503 * Clear all errors associated with a pool or a particular device. 2504 */ 2505 int 2506 zpool_do_clear(int argc, char **argv) 2507 { 2508 int ret = 0; 2509 zpool_handle_t *zhp; 2510 char *pool, *device; 2511 2512 if (argc < 2) { 2513 (void) fprintf(stderr, gettext("missing pool name\n")); 2514 usage(B_FALSE); 2515 } 2516 2517 if (argc > 3) { 2518 (void) fprintf(stderr, gettext("too many arguments\n")); 2519 usage(B_FALSE); 2520 } 2521 2522 pool = argv[1]; 2523 device = argc == 3 ? argv[2] : NULL; 2524 2525 if ((zhp = zpool_open(g_zfs, pool)) == NULL) 2526 return (1); 2527 2528 if (zpool_clear(zhp, device) != 0) 2529 ret = 1; 2530 2531 zpool_close(zhp); 2532 2533 return (ret); 2534 } 2535 2536 typedef struct scrub_cbdata { 2537 int cb_type; 2538 int cb_argc; 2539 char **cb_argv; 2540 } scrub_cbdata_t; 2541 2542 int 2543 scrub_callback(zpool_handle_t *zhp, void *data) 2544 { 2545 scrub_cbdata_t *cb = data; 2546 int err; 2547 2548 /* 2549 * Ignore faulted pools. 2550 */ 2551 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2552 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 2553 "currently unavailable\n"), zpool_get_name(zhp)); 2554 return (1); 2555 } 2556 2557 err = zpool_scrub(zhp, cb->cb_type); 2558 2559 return (err != 0); 2560 } 2561 2562 /* 2563 * zpool scrub [-s] <pool> ... 2564 * 2565 * -s Stop. Stops any in-progress scrub. 2566 */ 2567 int 2568 zpool_do_scrub(int argc, char **argv) 2569 { 2570 int c; 2571 scrub_cbdata_t cb; 2572 2573 cb.cb_type = POOL_SCRUB_EVERYTHING; 2574 2575 /* check options */ 2576 while ((c = getopt(argc, argv, "s")) != -1) { 2577 switch (c) { 2578 case 's': 2579 cb.cb_type = POOL_SCRUB_NONE; 2580 break; 2581 case '?': 2582 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2583 optopt); 2584 usage(B_FALSE); 2585 } 2586 } 2587 2588 cb.cb_argc = argc; 2589 cb.cb_argv = argv; 2590 argc -= optind; 2591 argv += optind; 2592 2593 if (argc < 1) { 2594 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2595 usage(B_FALSE); 2596 } 2597 2598 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 2599 } 2600 2601 typedef struct status_cbdata { 2602 int cb_count; 2603 boolean_t cb_allpools; 2604 boolean_t cb_verbose; 2605 boolean_t cb_explain; 2606 boolean_t cb_first; 2607 } status_cbdata_t; 2608 2609 /* 2610 * Print out detailed scrub status. 2611 */ 2612 void 2613 print_scrub_status(nvlist_t *nvroot) 2614 { 2615 vdev_stat_t *vs; 2616 uint_t vsc; 2617 time_t start, end, now; 2618 double fraction_done; 2619 uint64_t examined, total, minutes_left, minutes_taken; 2620 char *scrub_type; 2621 2622 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2623 (uint64_t **)&vs, &vsc) == 0); 2624 2625 /* 2626 * If there's never been a scrub, there's not much to say. 2627 */ 2628 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2629 (void) printf(gettext("none requested\n")); 2630 return; 2631 } 2632 2633 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2634 "resilver" : "scrub"; 2635 2636 start = vs->vs_scrub_start; 2637 end = vs->vs_scrub_end; 2638 now = time(NULL); 2639 examined = vs->vs_scrub_examined; 2640 total = vs->vs_alloc; 2641 2642 if (end != 0) { 2643 minutes_taken = (uint64_t)((end - start) / 60); 2644 2645 (void) printf(gettext("%s %s after %lluh%um with %llu errors " 2646 "on %s"), 2647 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 2648 (u_longlong_t)(minutes_taken / 60), 2649 (uint_t)(minutes_taken % 60), 2650 (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2651 return; 2652 } 2653 2654 if (examined == 0) 2655 examined = 1; 2656 if (examined > total) 2657 total = examined; 2658 2659 fraction_done = (double)examined / total; 2660 minutes_left = (uint64_t)((now - start) * 2661 (1 - fraction_done) / fraction_done / 60); 2662 minutes_taken = (uint64_t)((now - start) / 60); 2663 2664 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, " 2665 "%lluh%um to go\n"), 2666 scrub_type, (u_longlong_t)(minutes_taken / 60), 2667 (uint_t)(minutes_taken % 60), 100 * fraction_done, 2668 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2669 } 2670 2671 typedef struct spare_cbdata { 2672 uint64_t cb_guid; 2673 zpool_handle_t *cb_zhp; 2674 } spare_cbdata_t; 2675 2676 static boolean_t 2677 find_vdev(nvlist_t *nv, uint64_t search) 2678 { 2679 uint64_t guid; 2680 nvlist_t **child; 2681 uint_t c, children; 2682 2683 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 2684 search == guid) 2685 return (B_TRUE); 2686 2687 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2688 &child, &children) == 0) { 2689 for (c = 0; c < children; c++) 2690 if (find_vdev(child[c], search)) 2691 return (B_TRUE); 2692 } 2693 2694 return (B_FALSE); 2695 } 2696 2697 static int 2698 find_spare(zpool_handle_t *zhp, void *data) 2699 { 2700 spare_cbdata_t *cbp = data; 2701 nvlist_t *config, *nvroot; 2702 2703 config = zpool_get_config(zhp, NULL); 2704 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2705 &nvroot) == 0); 2706 2707 if (find_vdev(nvroot, cbp->cb_guid)) { 2708 cbp->cb_zhp = zhp; 2709 return (1); 2710 } 2711 2712 zpool_close(zhp); 2713 return (0); 2714 } 2715 2716 /* 2717 * Print out configuration state as requested by status_callback. 2718 */ 2719 void 2720 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 2721 int namewidth, int depth, boolean_t isspare, boolean_t print_logs) 2722 { 2723 nvlist_t **child; 2724 uint_t c, children; 2725 vdev_stat_t *vs; 2726 char rbuf[6], wbuf[6], cbuf[6], repaired[7]; 2727 char *vname; 2728 uint64_t notpresent; 2729 spare_cbdata_t cb; 2730 char *state; 2731 2732 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 2733 (uint64_t **)&vs, &c) == 0); 2734 2735 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2736 &child, &children) != 0) 2737 children = 0; 2738 2739 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2740 if (isspare) { 2741 /* 2742 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 2743 * online drives. 2744 */ 2745 if (vs->vs_aux == VDEV_AUX_SPARED) 2746 state = "INUSE"; 2747 else if (vs->vs_state == VDEV_STATE_HEALTHY) 2748 state = "AVAIL"; 2749 } 2750 2751 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 2752 name, state); 2753 2754 if (!isspare) { 2755 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2756 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2757 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 2758 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 2759 } 2760 2761 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 2762 ¬present) == 0) { 2763 char *path; 2764 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2765 (void) printf(" was %s", path); 2766 } else if (vs->vs_aux != 0) { 2767 (void) printf(" "); 2768 2769 switch (vs->vs_aux) { 2770 case VDEV_AUX_OPEN_FAILED: 2771 (void) printf(gettext("cannot open")); 2772 break; 2773 2774 case VDEV_AUX_BAD_GUID_SUM: 2775 (void) printf(gettext("missing device")); 2776 break; 2777 2778 case VDEV_AUX_NO_REPLICAS: 2779 (void) printf(gettext("insufficient replicas")); 2780 break; 2781 2782 case VDEV_AUX_VERSION_NEWER: 2783 (void) printf(gettext("newer version")); 2784 break; 2785 2786 case VDEV_AUX_SPARED: 2787 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 2788 &cb.cb_guid) == 0); 2789 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 2790 if (strcmp(zpool_get_name(cb.cb_zhp), 2791 zpool_get_name(zhp)) == 0) 2792 (void) printf(gettext("currently in " 2793 "use")); 2794 else 2795 (void) printf(gettext("in use by " 2796 "pool '%s'"), 2797 zpool_get_name(cb.cb_zhp)); 2798 zpool_close(cb.cb_zhp); 2799 } else { 2800 (void) printf(gettext("currently in use")); 2801 } 2802 break; 2803 2804 case VDEV_AUX_ERR_EXCEEDED: 2805 (void) printf(gettext("too many errors")); 2806 break; 2807 2808 case VDEV_AUX_IO_FAILURE: 2809 (void) printf(gettext("experienced I/O failures")); 2810 break; 2811 2812 default: 2813 (void) printf(gettext("corrupted data")); 2814 break; 2815 } 2816 } else if (vs->vs_scrub_repaired != 0 && children == 0) { 2817 /* 2818 * Report bytes resilvered/repaired on leaf devices. 2819 */ 2820 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 2821 (void) printf(gettext(" %s %s"), repaired, 2822 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2823 "resilvered" : "repaired"); 2824 } 2825 2826 (void) printf("\n"); 2827 2828 for (c = 0; c < children; c++) { 2829 uint64_t is_log = B_FALSE; 2830 2831 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2832 &is_log); 2833 if ((is_log && !print_logs) || (!is_log && print_logs)) 2834 continue; 2835 vname = zpool_vdev_name(g_zfs, zhp, child[c]); 2836 print_status_config(zhp, vname, child[c], 2837 namewidth, depth + 2, isspare, B_FALSE); 2838 free(vname); 2839 } 2840 } 2841 2842 static void 2843 print_error_log(zpool_handle_t *zhp) 2844 { 2845 nvlist_t *nverrlist = NULL; 2846 nvpair_t *elem; 2847 char *pathname; 2848 size_t len = MAXPATHLEN * 2; 2849 2850 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 2851 (void) printf("errors: List of errors unavailable " 2852 "(insufficient privileges)\n"); 2853 return; 2854 } 2855 2856 (void) printf("errors: Permanent errors have been " 2857 "detected in the following files:\n\n"); 2858 2859 pathname = safe_malloc(len); 2860 elem = NULL; 2861 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 2862 nvlist_t *nv; 2863 uint64_t dsobj, obj; 2864 2865 verify(nvpair_value_nvlist(elem, &nv) == 0); 2866 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 2867 &dsobj) == 0); 2868 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 2869 &obj) == 0); 2870 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 2871 (void) printf("%7s %s\n", "", pathname); 2872 } 2873 free(pathname); 2874 nvlist_free(nverrlist); 2875 } 2876 2877 static void 2878 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 2879 int namewidth) 2880 { 2881 uint_t i; 2882 char *name; 2883 2884 if (nspares == 0) 2885 return; 2886 2887 (void) printf(gettext("\tspares\n")); 2888 2889 for (i = 0; i < nspares; i++) { 2890 name = zpool_vdev_name(g_zfs, zhp, spares[i]); 2891 print_status_config(zhp, name, spares[i], 2892 namewidth, 2, B_TRUE, B_FALSE); 2893 free(name); 2894 } 2895 } 2896 2897 static void 2898 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 2899 int namewidth) 2900 { 2901 uint_t i; 2902 char *name; 2903 2904 if (nl2cache == 0) 2905 return; 2906 2907 (void) printf(gettext("\tcache\n")); 2908 2909 for (i = 0; i < nl2cache; i++) { 2910 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]); 2911 print_status_config(zhp, name, l2cache[i], 2912 namewidth, 2, B_FALSE, B_FALSE); 2913 free(name); 2914 } 2915 } 2916 2917 /* 2918 * Display a summary of pool status. Displays a summary such as: 2919 * 2920 * pool: tank 2921 * status: DEGRADED 2922 * reason: One or more devices ... 2923 * see: http://www.sun.com/msg/ZFS-xxxx-01 2924 * config: 2925 * mirror DEGRADED 2926 * c1t0d0 OK 2927 * c2t0d0 UNAVAIL 2928 * 2929 * When given the '-v' option, we print out the complete config. If the '-e' 2930 * option is specified, then we print out error rate information as well. 2931 */ 2932 int 2933 status_callback(zpool_handle_t *zhp, void *data) 2934 { 2935 status_cbdata_t *cbp = data; 2936 nvlist_t *config, *nvroot; 2937 char *msgid; 2938 int reason; 2939 const char *health; 2940 uint_t c; 2941 vdev_stat_t *vs; 2942 2943 config = zpool_get_config(zhp, NULL); 2944 reason = zpool_get_status(zhp, &msgid); 2945 2946 cbp->cb_count++; 2947 2948 /* 2949 * If we were given 'zpool status -x', only report those pools with 2950 * problems. 2951 */ 2952 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) { 2953 if (!cbp->cb_allpools) { 2954 (void) printf(gettext("pool '%s' is healthy\n"), 2955 zpool_get_name(zhp)); 2956 if (cbp->cb_first) 2957 cbp->cb_first = B_FALSE; 2958 } 2959 return (0); 2960 } 2961 2962 if (cbp->cb_first) 2963 cbp->cb_first = B_FALSE; 2964 else 2965 (void) printf("\n"); 2966 2967 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2968 &nvroot) == 0); 2969 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2970 (uint64_t **)&vs, &c) == 0); 2971 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2972 2973 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 2974 (void) printf(gettext(" state: %s\n"), health); 2975 2976 switch (reason) { 2977 case ZPOOL_STATUS_MISSING_DEV_R: 2978 (void) printf(gettext("status: One or more devices could not " 2979 "be opened. Sufficient replicas exist for\n\tthe pool to " 2980 "continue functioning in a degraded state.\n")); 2981 (void) printf(gettext("action: Attach the missing device and " 2982 "online it using 'zpool online'.\n")); 2983 break; 2984 2985 case ZPOOL_STATUS_MISSING_DEV_NR: 2986 (void) printf(gettext("status: One or more devices could not " 2987 "be opened. There are insufficient\n\treplicas for the " 2988 "pool to continue functioning.\n")); 2989 (void) printf(gettext("action: Attach the missing device and " 2990 "online it using 'zpool online'.\n")); 2991 break; 2992 2993 case ZPOOL_STATUS_CORRUPT_LABEL_R: 2994 (void) printf(gettext("status: One or more devices could not " 2995 "be used because the label is missing or\n\tinvalid. " 2996 "Sufficient replicas exist for the pool to continue\n\t" 2997 "functioning in a degraded state.\n")); 2998 (void) printf(gettext("action: Replace the device using " 2999 "'zpool replace'.\n")); 3000 break; 3001 3002 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 3003 (void) printf(gettext("status: One or more devices could not " 3004 "be used because the label is missing \n\tor invalid. " 3005 "There are insufficient replicas for the pool to " 3006 "continue\n\tfunctioning.\n")); 3007 (void) printf(gettext("action: Destroy and re-create the pool " 3008 "from a backup source.\n")); 3009 break; 3010 3011 case ZPOOL_STATUS_FAILING_DEV: 3012 (void) printf(gettext("status: One or more devices has " 3013 "experienced an unrecoverable error. An\n\tattempt was " 3014 "made to correct the error. Applications are " 3015 "unaffected.\n")); 3016 (void) printf(gettext("action: Determine if the device needs " 3017 "to be replaced, and clear the errors\n\tusing " 3018 "'zpool clear' or replace the device with 'zpool " 3019 "replace'.\n")); 3020 break; 3021 3022 case ZPOOL_STATUS_OFFLINE_DEV: 3023 (void) printf(gettext("status: One or more devices has " 3024 "been taken offline by the administrator.\n\tSufficient " 3025 "replicas exist for the pool to continue functioning in " 3026 "a\n\tdegraded state.\n")); 3027 (void) printf(gettext("action: Online the device using " 3028 "'zpool online' or replace the device with\n\t'zpool " 3029 "replace'.\n")); 3030 break; 3031 3032 case ZPOOL_STATUS_RESILVERING: 3033 (void) printf(gettext("status: One or more devices is " 3034 "currently being resilvered. The pool will\n\tcontinue " 3035 "to function, possibly in a degraded state.\n")); 3036 (void) printf(gettext("action: Wait for the resilver to " 3037 "complete.\n")); 3038 break; 3039 3040 case ZPOOL_STATUS_CORRUPT_DATA: 3041 (void) printf(gettext("status: One or more devices has " 3042 "experienced an error resulting in data\n\tcorruption. " 3043 "Applications may be affected.\n")); 3044 (void) printf(gettext("action: Restore the file in question " 3045 "if possible. Otherwise restore the\n\tentire pool from " 3046 "backup.\n")); 3047 break; 3048 3049 case ZPOOL_STATUS_CORRUPT_POOL: 3050 (void) printf(gettext("status: The pool metadata is corrupted " 3051 "and the pool cannot be opened.\n")); 3052 (void) printf(gettext("action: Destroy and re-create the pool " 3053 "from a backup source.\n")); 3054 break; 3055 3056 case ZPOOL_STATUS_VERSION_OLDER: 3057 (void) printf(gettext("status: The pool is formatted using an " 3058 "older on-disk format. The pool can\n\tstill be used, but " 3059 "some features are unavailable.\n")); 3060 (void) printf(gettext("action: Upgrade the pool using 'zpool " 3061 "upgrade'. Once this is done, the\n\tpool will no longer " 3062 "be accessible on older software versions.\n")); 3063 break; 3064 3065 case ZPOOL_STATUS_VERSION_NEWER: 3066 (void) printf(gettext("status: The pool has been upgraded to a " 3067 "newer, incompatible on-disk version.\n\tThe pool cannot " 3068 "be accessed on this system.\n")); 3069 (void) printf(gettext("action: Access the pool from a system " 3070 "running more recent software, or\n\trestore the pool from " 3071 "backup.\n")); 3072 break; 3073 3074 case ZPOOL_STATUS_FAULTED_DEV_R: 3075 (void) printf(gettext("status: One or more devices are " 3076 "faulted in response to persistent errors.\n\tSufficient " 3077 "replicas exist for the pool to continue functioning " 3078 "in a\n\tdegraded state.\n")); 3079 (void) printf(gettext("action: Replace the faulted device, " 3080 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 3081 break; 3082 3083 case ZPOOL_STATUS_FAULTED_DEV_NR: 3084 (void) printf(gettext("status: One or more devices are " 3085 "faulted in response to persistent errors. There are " 3086 "insufficient replicas for the pool to\n\tcontinue " 3087 "functioning.\n")); 3088 (void) printf(gettext("action: Destroy and re-create the pool " 3089 "from a backup source. Manually marking the device\n" 3090 "\trepaired using 'zpool clear' may allow some data " 3091 "to be recovered.\n")); 3092 break; 3093 3094 case ZPOOL_STATUS_IO_FAILURE_WAIT: 3095 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 3096 (void) printf(gettext("status: One or more devices are " 3097 "faulted in response to IO failures.\n")); 3098 (void) printf(gettext("action: Make sure the affected devices " 3099 "are connected, then run 'zpool clear'.\n")); 3100 break; 3101 3102 default: 3103 /* 3104 * The remaining errors can't actually be generated, yet. 3105 */ 3106 assert(reason == ZPOOL_STATUS_OK); 3107 } 3108 3109 if (msgid != NULL) 3110 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 3111 msgid); 3112 3113 if (config != NULL) { 3114 int namewidth; 3115 uint64_t nerr; 3116 nvlist_t **spares, **l2cache; 3117 uint_t nspares, nl2cache; 3118 3119 3120 (void) printf(gettext(" scrub: ")); 3121 print_scrub_status(nvroot); 3122 3123 namewidth = max_width(zhp, nvroot, 0, 0); 3124 if (namewidth < 10) 3125 namewidth = 10; 3126 3127 (void) printf(gettext("config:\n\n")); 3128 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 3129 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 3130 print_status_config(zhp, zpool_get_name(zhp), nvroot, 3131 namewidth, 0, B_FALSE, B_FALSE); 3132 if (num_logs(nvroot) > 0) 3133 print_status_config(zhp, "logs", nvroot, namewidth, 0, 3134 B_FALSE, B_TRUE); 3135 3136 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 3137 &l2cache, &nl2cache) == 0) 3138 print_l2cache(zhp, l2cache, nl2cache, namewidth); 3139 3140 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 3141 &spares, &nspares) == 0) 3142 print_spares(zhp, spares, nspares, namewidth); 3143 3144 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 3145 &nerr) == 0) { 3146 nvlist_t *nverrlist = NULL; 3147 3148 /* 3149 * If the approximate error count is small, get a 3150 * precise count by fetching the entire log and 3151 * uniquifying the results. 3152 */ 3153 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 3154 zpool_get_errlog(zhp, &nverrlist) == 0) { 3155 nvpair_t *elem; 3156 3157 elem = NULL; 3158 nerr = 0; 3159 while ((elem = nvlist_next_nvpair(nverrlist, 3160 elem)) != NULL) { 3161 nerr++; 3162 } 3163 } 3164 nvlist_free(nverrlist); 3165 3166 (void) printf("\n"); 3167 3168 if (nerr == 0) 3169 (void) printf(gettext("errors: No known data " 3170 "errors\n")); 3171 else if (!cbp->cb_verbose) 3172 (void) printf(gettext("errors: %llu data " 3173 "errors, use '-v' for a list\n"), 3174 (u_longlong_t)nerr); 3175 else 3176 print_error_log(zhp); 3177 } 3178 } else { 3179 (void) printf(gettext("config: The configuration cannot be " 3180 "determined.\n")); 3181 } 3182 3183 return (0); 3184 } 3185 3186 /* 3187 * zpool status [-vx] [pool] ... 3188 * 3189 * -v Display complete error logs 3190 * -x Display only pools with potential problems 3191 * 3192 * Describes the health status of all pools or some subset. 3193 */ 3194 int 3195 zpool_do_status(int argc, char **argv) 3196 { 3197 int c; 3198 int ret; 3199 status_cbdata_t cb = { 0 }; 3200 3201 /* check options */ 3202 while ((c = getopt(argc, argv, "vx")) != -1) { 3203 switch (c) { 3204 case 'v': 3205 cb.cb_verbose = B_TRUE; 3206 break; 3207 case 'x': 3208 cb.cb_explain = B_TRUE; 3209 break; 3210 case '?': 3211 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3212 optopt); 3213 usage(B_FALSE); 3214 } 3215 } 3216 3217 argc -= optind; 3218 argv += optind; 3219 3220 cb.cb_first = B_TRUE; 3221 3222 if (argc == 0) 3223 cb.cb_allpools = B_TRUE; 3224 3225 ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb); 3226 3227 if (argc == 0 && cb.cb_count == 0) 3228 (void) printf(gettext("no pools available\n")); 3229 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 3230 (void) printf(gettext("all pools are healthy\n")); 3231 3232 return (ret); 3233 } 3234 3235 typedef struct upgrade_cbdata { 3236 int cb_all; 3237 int cb_first; 3238 int cb_newer; 3239 int cb_argc; 3240 uint64_t cb_version; 3241 char **cb_argv; 3242 } upgrade_cbdata_t; 3243 3244 static int 3245 upgrade_cb(zpool_handle_t *zhp, void *arg) 3246 { 3247 upgrade_cbdata_t *cbp = arg; 3248 nvlist_t *config; 3249 uint64_t version; 3250 int ret = 0; 3251 3252 config = zpool_get_config(zhp, NULL); 3253 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 3254 &version) == 0); 3255 3256 if (!cbp->cb_newer && version < SPA_VERSION) { 3257 if (!cbp->cb_all) { 3258 if (cbp->cb_first) { 3259 (void) printf(gettext("The following pools are " 3260 "out of date, and can be upgraded. After " 3261 "being\nupgraded, these pools will no " 3262 "longer be accessible by older software " 3263 "versions.\n\n")); 3264 (void) printf(gettext("VER POOL\n")); 3265 (void) printf(gettext("--- ------------\n")); 3266 cbp->cb_first = B_FALSE; 3267 } 3268 3269 (void) printf("%2llu %s\n", (u_longlong_t)version, 3270 zpool_get_name(zhp)); 3271 } else { 3272 cbp->cb_first = B_FALSE; 3273 ret = zpool_upgrade(zhp, cbp->cb_version); 3274 if (!ret) { 3275 (void) printf(gettext("Successfully upgraded " 3276 "'%s'\n\n"), zpool_get_name(zhp)); 3277 } 3278 } 3279 } else if (cbp->cb_newer && version > SPA_VERSION) { 3280 assert(!cbp->cb_all); 3281 3282 if (cbp->cb_first) { 3283 (void) printf(gettext("The following pools are " 3284 "formatted using a newer software version and\n" 3285 "cannot be accessed on the current system.\n\n")); 3286 (void) printf(gettext("VER POOL\n")); 3287 (void) printf(gettext("--- ------------\n")); 3288 cbp->cb_first = B_FALSE; 3289 } 3290 3291 (void) printf("%2llu %s\n", (u_longlong_t)version, 3292 zpool_get_name(zhp)); 3293 } 3294 3295 zpool_close(zhp); 3296 return (ret); 3297 } 3298 3299 /* ARGSUSED */ 3300 static int 3301 upgrade_one(zpool_handle_t *zhp, void *data) 3302 { 3303 upgrade_cbdata_t *cbp = data; 3304 uint64_t cur_version; 3305 int ret; 3306 3307 if (strcmp("log", zpool_get_name(zhp)) == 0) { 3308 (void) printf(gettext("'log' is now a reserved word\n" 3309 "Pool 'log' must be renamed using export and import" 3310 " to upgrade.\n")); 3311 return (1); 3312 } 3313 3314 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 3315 if (cur_version > cbp->cb_version) { 3316 (void) printf(gettext("Pool '%s' is already formatted " 3317 "using more current version '%llu'.\n"), 3318 zpool_get_name(zhp), cur_version); 3319 return (0); 3320 } 3321 if (cur_version == cbp->cb_version) { 3322 (void) printf(gettext("Pool '%s' is already formatted " 3323 "using the current version.\n"), zpool_get_name(zhp)); 3324 return (0); 3325 } 3326 3327 ret = zpool_upgrade(zhp, cbp->cb_version); 3328 3329 if (!ret) { 3330 (void) printf(gettext("Successfully upgraded '%s' " 3331 "from version %llu to version %llu\n\n"), 3332 zpool_get_name(zhp), (u_longlong_t)cur_version, 3333 (u_longlong_t)cbp->cb_version); 3334 } 3335 3336 return (ret != 0); 3337 } 3338 3339 /* 3340 * zpool upgrade 3341 * zpool upgrade -v 3342 * zpool upgrade [-V version] <-a | pool ...> 3343 * 3344 * With no arguments, display downrev'd ZFS pool available for upgrade. 3345 * Individual pools can be upgraded by specifying the pool, and '-a' will 3346 * upgrade all pools. 3347 */ 3348 int 3349 zpool_do_upgrade(int argc, char **argv) 3350 { 3351 int c; 3352 upgrade_cbdata_t cb = { 0 }; 3353 int ret = 0; 3354 boolean_t showversions = B_FALSE; 3355 char *end; 3356 3357 3358 /* check options */ 3359 while ((c = getopt(argc, argv, "avV:")) != -1) { 3360 switch (c) { 3361 case 'a': 3362 cb.cb_all = B_TRUE; 3363 break; 3364 case 'v': 3365 showversions = B_TRUE; 3366 break; 3367 case 'V': 3368 cb.cb_version = strtoll(optarg, &end, 10); 3369 if (*end != '\0' || cb.cb_version > SPA_VERSION || 3370 cb.cb_version < SPA_VERSION_1) { 3371 (void) fprintf(stderr, 3372 gettext("invalid version '%s'\n"), optarg); 3373 usage(B_FALSE); 3374 } 3375 break; 3376 case '?': 3377 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3378 optopt); 3379 usage(B_FALSE); 3380 } 3381 } 3382 3383 cb.cb_argc = argc; 3384 cb.cb_argv = argv; 3385 argc -= optind; 3386 argv += optind; 3387 3388 if (cb.cb_version == 0) { 3389 cb.cb_version = SPA_VERSION; 3390 } else if (!cb.cb_all && argc == 0) { 3391 (void) fprintf(stderr, gettext("-V option is " 3392 "incompatible with other arguments\n")); 3393 usage(B_FALSE); 3394 } 3395 3396 if (showversions) { 3397 if (cb.cb_all || argc != 0) { 3398 (void) fprintf(stderr, gettext("-v option is " 3399 "incompatible with other arguments\n")); 3400 usage(B_FALSE); 3401 } 3402 } else if (cb.cb_all) { 3403 if (argc != 0) { 3404 (void) fprintf(stderr, gettext("-a option should not " 3405 "be used along with a pool name\n")); 3406 usage(B_FALSE); 3407 } 3408 } 3409 3410 (void) printf(gettext("This system is currently running " 3411 "ZFS pool version %llu.\n\n"), SPA_VERSION); 3412 cb.cb_first = B_TRUE; 3413 if (showversions) { 3414 (void) printf(gettext("The following versions are " 3415 "supported:\n\n")); 3416 (void) printf(gettext("VER DESCRIPTION\n")); 3417 (void) printf("--- -----------------------------------------" 3418 "---------------\n"); 3419 (void) printf(gettext(" 1 Initial ZFS version\n")); 3420 (void) printf(gettext(" 2 Ditto blocks " 3421 "(replicated metadata)\n")); 3422 (void) printf(gettext(" 3 Hot spares and double parity " 3423 "RAID-Z\n")); 3424 (void) printf(gettext(" 4 zpool history\n")); 3425 (void) printf(gettext(" 5 Compression using the gzip " 3426 "algorithm\n")); 3427 (void) printf(gettext(" 6 bootfs pool property\n")); 3428 (void) printf(gettext(" 7 Separate intent log devices\n")); 3429 (void) printf(gettext(" 8 Delegated administration\n")); 3430 (void) printf(gettext(" 9 refquota and refreservation " 3431 "properties\n")); 3432 (void) printf(gettext(" 10 Cache devices\n")); 3433 (void) printf(gettext(" 11 Improved scrub performance\n")); 3434 (void) printf(gettext("For more information on a particular " 3435 "version, including supported releases, see:\n\n")); 3436 (void) printf("http://www.opensolaris.org/os/community/zfs/" 3437 "version/N\n\n"); 3438 (void) printf(gettext("Where 'N' is the version number.\n")); 3439 } else if (argc == 0) { 3440 int notfound; 3441 3442 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3443 notfound = cb.cb_first; 3444 3445 if (!cb.cb_all && ret == 0) { 3446 if (!cb.cb_first) 3447 (void) printf("\n"); 3448 cb.cb_first = B_TRUE; 3449 cb.cb_newer = B_TRUE; 3450 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3451 if (!cb.cb_first) { 3452 notfound = B_FALSE; 3453 (void) printf("\n"); 3454 } 3455 } 3456 3457 if (ret == 0) { 3458 if (notfound) 3459 (void) printf(gettext("All pools are formatted " 3460 "using this version.\n")); 3461 else if (!cb.cb_all) 3462 (void) printf(gettext("Use 'zpool upgrade -v' " 3463 "for a list of available versions and " 3464 "their associated\nfeatures.\n")); 3465 } 3466 } else { 3467 ret = for_each_pool(argc, argv, B_FALSE, NULL, 3468 upgrade_one, &cb); 3469 } 3470 3471 return (ret); 3472 } 3473 3474 typedef struct hist_cbdata { 3475 boolean_t first; 3476 int longfmt; 3477 int internal; 3478 } hist_cbdata_t; 3479 3480 char *hist_event_table[LOG_END] = { 3481 "invalid event", 3482 "pool create", 3483 "vdev add", 3484 "pool remove", 3485 "pool destroy", 3486 "pool export", 3487 "pool import", 3488 "vdev attach", 3489 "vdev replace", 3490 "vdev detach", 3491 "vdev online", 3492 "vdev offline", 3493 "vdev upgrade", 3494 "pool clear", 3495 "pool scrub", 3496 "pool property set", 3497 "create", 3498 "clone", 3499 "destroy", 3500 "destroy_begin_sync", 3501 "inherit", 3502 "property set", 3503 "quota set", 3504 "permission update", 3505 "permission remove", 3506 "permission who remove", 3507 "promote", 3508 "receive", 3509 "rename", 3510 "reservation set", 3511 "replay_inc_sync", 3512 "replay_full_sync", 3513 "rollback", 3514 "snapshot", 3515 "filesystem version upgrade", 3516 "refquota set", 3517 "refreservation set", 3518 "pool scrub done", 3519 }; 3520 3521 /* 3522 * Print out the command history for a specific pool. 3523 */ 3524 static int 3525 get_history_one(zpool_handle_t *zhp, void *data) 3526 { 3527 nvlist_t *nvhis; 3528 nvlist_t **records; 3529 uint_t numrecords; 3530 char *cmdstr; 3531 char *pathstr; 3532 uint64_t dst_time; 3533 time_t tsec; 3534 struct tm t; 3535 char tbuf[30]; 3536 int ret, i; 3537 uint64_t who; 3538 struct passwd *pwd; 3539 char *hostname; 3540 char *zonename; 3541 char internalstr[MAXPATHLEN]; 3542 hist_cbdata_t *cb = (hist_cbdata_t *)data; 3543 uint64_t txg; 3544 uint64_t ievent; 3545 3546 cb->first = B_FALSE; 3547 3548 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 3549 3550 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 3551 return (ret); 3552 3553 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 3554 &records, &numrecords) == 0); 3555 for (i = 0; i < numrecords; i++) { 3556 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, 3557 &dst_time) != 0) 3558 continue; 3559 3560 /* is it an internal event or a standard event? */ 3561 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, 3562 &cmdstr) != 0) { 3563 if (cb->internal == 0) 3564 continue; 3565 3566 if (nvlist_lookup_uint64(records[i], 3567 ZPOOL_HIST_INT_EVENT, &ievent) != 0) 3568 continue; 3569 verify(nvlist_lookup_uint64(records[i], 3570 ZPOOL_HIST_TXG, &txg) == 0); 3571 verify(nvlist_lookup_string(records[i], 3572 ZPOOL_HIST_INT_STR, &pathstr) == 0); 3573 if (ievent >= LOG_END) 3574 continue; 3575 (void) snprintf(internalstr, 3576 sizeof (internalstr), 3577 "[internal %s txg:%lld] %s", 3578 hist_event_table[ievent], txg, 3579 pathstr); 3580 cmdstr = internalstr; 3581 } 3582 tsec = dst_time; 3583 (void) localtime_r(&tsec, &t); 3584 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 3585 (void) printf("%s %s", tbuf, cmdstr); 3586 3587 if (!cb->longfmt) { 3588 (void) printf("\n"); 3589 continue; 3590 } 3591 (void) printf(" ["); 3592 if (nvlist_lookup_uint64(records[i], 3593 ZPOOL_HIST_WHO, &who) == 0) { 3594 pwd = getpwuid((uid_t)who); 3595 if (pwd) 3596 (void) printf("user %s on", 3597 pwd->pw_name); 3598 else 3599 (void) printf("user %d on", 3600 (int)who); 3601 } else { 3602 (void) printf(gettext("no info]\n")); 3603 continue; 3604 } 3605 if (nvlist_lookup_string(records[i], 3606 ZPOOL_HIST_HOST, &hostname) == 0) { 3607 (void) printf(" %s", hostname); 3608 } 3609 if (nvlist_lookup_string(records[i], 3610 ZPOOL_HIST_ZONE, &zonename) == 0) { 3611 (void) printf(":%s", zonename); 3612 } 3613 3614 (void) printf("]"); 3615 (void) printf("\n"); 3616 } 3617 (void) printf("\n"); 3618 nvlist_free(nvhis); 3619 3620 return (ret); 3621 } 3622 3623 /* 3624 * zpool history <pool> 3625 * 3626 * Displays the history of commands that modified pools. 3627 */ 3628 3629 3630 int 3631 zpool_do_history(int argc, char **argv) 3632 { 3633 hist_cbdata_t cbdata = { 0 }; 3634 int ret; 3635 int c; 3636 3637 cbdata.first = B_TRUE; 3638 /* check options */ 3639 while ((c = getopt(argc, argv, "li")) != -1) { 3640 switch (c) { 3641 case 'l': 3642 cbdata.longfmt = 1; 3643 break; 3644 case 'i': 3645 cbdata.internal = 1; 3646 break; 3647 case '?': 3648 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3649 optopt); 3650 usage(B_FALSE); 3651 } 3652 } 3653 argc -= optind; 3654 argv += optind; 3655 3656 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 3657 &cbdata); 3658 3659 if (argc == 0 && cbdata.first == B_TRUE) { 3660 (void) printf(gettext("no pools available\n")); 3661 return (0); 3662 } 3663 3664 return (ret); 3665 } 3666 3667 static int 3668 get_callback(zpool_handle_t *zhp, void *data) 3669 { 3670 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 3671 char value[MAXNAMELEN]; 3672 zprop_source_t srctype; 3673 zprop_list_t *pl; 3674 3675 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 3676 3677 /* 3678 * Skip the special fake placeholder. This will also skip 3679 * over the name property when 'all' is specified. 3680 */ 3681 if (pl->pl_prop == ZPOOL_PROP_NAME && 3682 pl == cbp->cb_proplist) 3683 continue; 3684 3685 if (zpool_get_prop(zhp, pl->pl_prop, 3686 value, sizeof (value), &srctype) != 0) 3687 continue; 3688 3689 zprop_print_one_property(zpool_get_name(zhp), cbp, 3690 zpool_prop_to_name(pl->pl_prop), value, srctype, NULL); 3691 } 3692 return (0); 3693 } 3694 3695 int 3696 zpool_do_get(int argc, char **argv) 3697 { 3698 zprop_get_cbdata_t cb = { 0 }; 3699 zprop_list_t fake_name = { 0 }; 3700 int ret; 3701 3702 if (argc < 3) 3703 usage(B_FALSE); 3704 3705 cb.cb_first = B_TRUE; 3706 cb.cb_sources = ZPROP_SRC_ALL; 3707 cb.cb_columns[0] = GET_COL_NAME; 3708 cb.cb_columns[1] = GET_COL_PROPERTY; 3709 cb.cb_columns[2] = GET_COL_VALUE; 3710 cb.cb_columns[3] = GET_COL_SOURCE; 3711 cb.cb_type = ZFS_TYPE_POOL; 3712 3713 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist, 3714 ZFS_TYPE_POOL) != 0) 3715 usage(B_FALSE); 3716 3717 if (cb.cb_proplist != NULL) { 3718 fake_name.pl_prop = ZPOOL_PROP_NAME; 3719 fake_name.pl_width = strlen(gettext("NAME")); 3720 fake_name.pl_next = cb.cb_proplist; 3721 cb.cb_proplist = &fake_name; 3722 } 3723 3724 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist, 3725 get_callback, &cb); 3726 3727 if (cb.cb_proplist == &fake_name) 3728 zprop_free_list(fake_name.pl_next); 3729 else 3730 zprop_free_list(cb.cb_proplist); 3731 3732 return (ret); 3733 } 3734 3735 typedef struct set_cbdata { 3736 char *cb_propname; 3737 char *cb_value; 3738 boolean_t cb_any_successful; 3739 } set_cbdata_t; 3740 3741 int 3742 set_callback(zpool_handle_t *zhp, void *data) 3743 { 3744 int error; 3745 set_cbdata_t *cb = (set_cbdata_t *)data; 3746 3747 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 3748 3749 if (!error) 3750 cb->cb_any_successful = B_TRUE; 3751 3752 return (error); 3753 } 3754 3755 int 3756 zpool_do_set(int argc, char **argv) 3757 { 3758 set_cbdata_t cb = { 0 }; 3759 int error; 3760 3761 if (argc > 1 && argv[1][0] == '-') { 3762 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3763 argv[1][1]); 3764 usage(B_FALSE); 3765 } 3766 3767 if (argc < 2) { 3768 (void) fprintf(stderr, gettext("missing property=value " 3769 "argument\n")); 3770 usage(B_FALSE); 3771 } 3772 3773 if (argc < 3) { 3774 (void) fprintf(stderr, gettext("missing pool name\n")); 3775 usage(B_FALSE); 3776 } 3777 3778 if (argc > 3) { 3779 (void) fprintf(stderr, gettext("too many pool names\n")); 3780 usage(B_FALSE); 3781 } 3782 3783 cb.cb_propname = argv[1]; 3784 cb.cb_value = strchr(cb.cb_propname, '='); 3785 if (cb.cb_value == NULL) { 3786 (void) fprintf(stderr, gettext("missing value in " 3787 "property=value argument\n")); 3788 usage(B_FALSE); 3789 } 3790 3791 *(cb.cb_value) = '\0'; 3792 cb.cb_value++; 3793 3794 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 3795 set_callback, &cb); 3796 3797 return (error); 3798 } 3799 3800 static int 3801 find_command_idx(char *command, int *idx) 3802 { 3803 int i; 3804 3805 for (i = 0; i < NCOMMAND; i++) { 3806 if (command_table[i].name == NULL) 3807 continue; 3808 3809 if (strcmp(command, command_table[i].name) == 0) { 3810 *idx = i; 3811 return (0); 3812 } 3813 } 3814 return (1); 3815 } 3816 3817 int 3818 main(int argc, char **argv) 3819 { 3820 int ret; 3821 int i; 3822 char *cmdname; 3823 3824 (void) setlocale(LC_ALL, ""); 3825 (void) textdomain(TEXT_DOMAIN); 3826 3827 if ((g_zfs = libzfs_init()) == NULL) { 3828 (void) fprintf(stderr, gettext("internal error: failed to " 3829 "initialize ZFS library\n")); 3830 return (1); 3831 } 3832 3833 libzfs_print_on_error(g_zfs, B_TRUE); 3834 3835 opterr = 0; 3836 3837 /* 3838 * Make sure the user has specified some command. 3839 */ 3840 if (argc < 2) { 3841 (void) fprintf(stderr, gettext("missing command\n")); 3842 usage(B_FALSE); 3843 } 3844 3845 cmdname = argv[1]; 3846 3847 /* 3848 * Special case '-?' 3849 */ 3850 if (strcmp(cmdname, "-?") == 0) 3851 usage(B_TRUE); 3852 3853 zpool_set_history_str("zpool", argc, argv, history_str); 3854 verify(zpool_stage_history(g_zfs, history_str) == 0); 3855 3856 /* 3857 * Run the appropriate command. 3858 */ 3859 if (find_command_idx(cmdname, &i) == 0) { 3860 current_command = &command_table[i]; 3861 ret = command_table[i].func(argc - 1, argv + 1); 3862 } else if (strchr(cmdname, '=')) { 3863 verify(find_command_idx("set", &i) == 0); 3864 current_command = &command_table[i]; 3865 ret = command_table[i].func(argc, argv); 3866 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 3867 /* 3868 * 'freeze' is a vile debugging abomination, so we treat 3869 * it as such. 3870 */ 3871 char buf[16384]; 3872 int fd = open(ZFS_DEV, O_RDWR); 3873 (void) strcpy((void *)buf, argv[2]); 3874 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 3875 } else { 3876 (void) fprintf(stderr, gettext("unrecognized " 3877 "command '%s'\n"), cmdname); 3878 usage(B_FALSE); 3879 } 3880 3881 libzfs_fini(g_zfs); 3882 3883 /* 3884 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 3885 * for the purposes of running ::findleaks. 3886 */ 3887 if (getenv("ZFS_ABORT") != NULL) { 3888 (void) printf("dumping core by request\n"); 3889 abort(); 3890 } 3891 3892 return (ret); 3893 } 3894