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