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