1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <assert.h> 30 #include <ctype.h> 31 #include <dirent.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <libgen.h> 35 #include <libintl.h> 36 #include <libuutil.h> 37 #include <locale.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <strings.h> 42 #include <unistd.h> 43 #include <priv.h> 44 #include <pwd.h> 45 #include <zone.h> 46 #include <sys/fs/zfs.h> 47 48 #include <sys/stat.h> 49 50 #include <libzfs.h> 51 52 #include "zpool_util.h" 53 #include "zfs_comutil.h" 54 55 static int zpool_do_create(int, char **); 56 static int zpool_do_destroy(int, char **); 57 58 static int zpool_do_add(int, char **); 59 static int zpool_do_remove(int, char **); 60 61 static int zpool_do_list(int, char **); 62 static int zpool_do_iostat(int, char **); 63 static int zpool_do_status(int, char **); 64 65 static int zpool_do_online(int, char **); 66 static int zpool_do_offline(int, char **); 67 static int zpool_do_clear(int, char **); 68 69 static int zpool_do_attach(int, char **); 70 static int zpool_do_detach(int, char **); 71 static int zpool_do_replace(int, char **); 72 73 static int zpool_do_scrub(int, char **); 74 75 static int zpool_do_import(int, char **); 76 static int zpool_do_export(int, char **); 77 78 static int zpool_do_upgrade(int, char **); 79 80 static int zpool_do_history(int, char **); 81 82 static int zpool_do_get(int, char **); 83 static int zpool_do_set(int, char **); 84 85 /* 86 * These libumem hooks provide a reasonable set of defaults for the allocator's 87 * debugging facilities. 88 */ 89 90 #ifdef DEBUG 91 const char * 92 _umem_debug_init(void) 93 { 94 return ("default,verbose"); /* $UMEM_DEBUG setting */ 95 } 96 97 const char * 98 _umem_logging_init(void) 99 { 100 return ("fail,contents"); /* $UMEM_LOGGING setting */ 101 } 102 #endif 103 104 typedef enum { 105 HELP_ADD, 106 HELP_ATTACH, 107 HELP_CLEAR, 108 HELP_CREATE, 109 HELP_DESTROY, 110 HELP_DETACH, 111 HELP_EXPORT, 112 HELP_HISTORY, 113 HELP_IMPORT, 114 HELP_IOSTAT, 115 HELP_LIST, 116 HELP_OFFLINE, 117 HELP_ONLINE, 118 HELP_REPLACE, 119 HELP_REMOVE, 120 HELP_SCRUB, 121 HELP_STATUS, 122 HELP_UPGRADE, 123 HELP_GET, 124 HELP_SET 125 } zpool_help_t; 126 127 128 typedef struct zpool_command { 129 const char *name; 130 int (*func)(int, char **); 131 zpool_help_t usage; 132 } zpool_command_t; 133 134 /* 135 * Master command table. Each ZFS command has a name, associated function, and 136 * usage message. The usage messages need to be internationalized, so we have 137 * to have a function to return the usage message based on a command index. 138 * 139 * These commands are organized according to how they are displayed in the usage 140 * message. An empty command (one with a NULL name) indicates an empty line in 141 * the generic usage message. 142 */ 143 static zpool_command_t command_table[] = { 144 { "create", zpool_do_create, HELP_CREATE }, 145 { "destroy", zpool_do_destroy, HELP_DESTROY }, 146 { NULL }, 147 { "add", zpool_do_add, HELP_ADD }, 148 { "remove", zpool_do_remove, HELP_REMOVE }, 149 { NULL }, 150 { "list", zpool_do_list, HELP_LIST }, 151 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 152 { "status", zpool_do_status, HELP_STATUS }, 153 { NULL }, 154 { "online", zpool_do_online, HELP_ONLINE }, 155 { "offline", zpool_do_offline, HELP_OFFLINE }, 156 { "clear", zpool_do_clear, HELP_CLEAR }, 157 { NULL }, 158 { "attach", zpool_do_attach, HELP_ATTACH }, 159 { "detach", zpool_do_detach, HELP_DETACH }, 160 { "replace", zpool_do_replace, HELP_REPLACE }, 161 { NULL }, 162 { "scrub", zpool_do_scrub, HELP_SCRUB }, 163 { NULL }, 164 { "import", zpool_do_import, HELP_IMPORT }, 165 { "export", zpool_do_export, HELP_EXPORT }, 166 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 167 { NULL }, 168 { "history", zpool_do_history, HELP_HISTORY }, 169 { "get", zpool_do_get, HELP_GET }, 170 { "set", zpool_do_set, HELP_SET }, 171 }; 172 173 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 174 175 zpool_command_t *current_command; 176 static char history_str[HIS_MAX_RECORD_LEN]; 177 178 static const char * 179 get_usage(zpool_help_t idx) { 180 switch (idx) { 181 case HELP_ADD: 182 return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 183 case HELP_ATTACH: 184 return (gettext("\tattach [-f] <pool> <device> " 185 "<new-device>\n")); 186 case HELP_CLEAR: 187 return (gettext("\tclear <pool> [device]\n")); 188 case HELP_CREATE: 189 return (gettext("\tcreate [-fn] [-o property=value] ... \n" 190 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 191 case HELP_DESTROY: 192 return (gettext("\tdestroy [-f] <pool>\n")); 193 case HELP_DETACH: 194 return (gettext("\tdetach <pool> <device>\n")); 195 case HELP_EXPORT: 196 return (gettext("\texport [-f] <pool> ...\n")); 197 case HELP_HISTORY: 198 return (gettext("\thistory [-il] [<pool>] ...\n")); 199 case HELP_IMPORT: 200 return (gettext("\timport [-d dir] [-D]\n" 201 "\timport [-o mntopts] [-o property=value] ... \n" 202 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n" 203 "\timport [-o mntopts] [-o property=value] ... \n" 204 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] " 205 "<pool | id> [newpool]\n")); 206 case HELP_IOSTAT: 207 return (gettext("\tiostat [-v] [pool] ... [interval " 208 "[count]]\n")); 209 case HELP_LIST: 210 return (gettext("\tlist [-H] [-o property[,...]] " 211 "[pool] ...\n")); 212 case HELP_OFFLINE: 213 return (gettext("\toffline [-t] <pool> <device> ...\n")); 214 case HELP_ONLINE: 215 return (gettext("\tonline <pool> <device> ...\n")); 216 case HELP_REPLACE: 217 return (gettext("\treplace [-f] <pool> <device> " 218 "[new-device]\n")); 219 case HELP_REMOVE: 220 return (gettext("\tremove <pool> <device> ...\n")); 221 case HELP_SCRUB: 222 return (gettext("\tscrub [-s] <pool> ...\n")); 223 case HELP_STATUS: 224 return (gettext("\tstatus [-vx] [pool] ...\n")); 225 case HELP_UPGRADE: 226 return (gettext("\tupgrade\n" 227 "\tupgrade -v\n" 228 "\tupgrade [-V version] <-a | pool ...>\n")); 229 case HELP_GET: 230 return (gettext("\tget <\"all\" | property[,...]> " 231 "<pool> ...\n")); 232 case HELP_SET: 233 return (gettext("\tset <property=value> <pool> \n")); 234 } 235 236 abort(); 237 /* NOTREACHED */ 238 } 239 240 241 /* 242 * Callback routine that will print out a pool property value. 243 */ 244 static int 245 print_prop_cb(int prop, void *cb) 246 { 247 FILE *fp = cb; 248 249 (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop)); 250 251 if (zpool_prop_readonly(prop)) 252 (void) fprintf(fp, " NO "); 253 else 254 (void) fprintf(fp, " YES "); 255 256 if (zpool_prop_values(prop) == NULL) 257 (void) fprintf(fp, "-\n"); 258 else 259 (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 260 261 return (ZPROP_CONT); 262 } 263 264 /* 265 * Display usage message. If we're inside a command, display only the usage for 266 * that command. Otherwise, iterate over the entire command table and display 267 * a complete usage message. 268 */ 269 void 270 usage(boolean_t requested) 271 { 272 FILE *fp = requested ? stdout : stderr; 273 274 if (current_command == NULL) { 275 int i; 276 277 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 278 (void) fprintf(fp, 279 gettext("where 'command' is one of the following:\n\n")); 280 281 for (i = 0; i < NCOMMAND; i++) { 282 if (command_table[i].name == NULL) 283 (void) fprintf(fp, "\n"); 284 else 285 (void) fprintf(fp, "%s", 286 get_usage(command_table[i].usage)); 287 } 288 } else { 289 (void) fprintf(fp, gettext("usage:\n")); 290 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 291 } 292 293 if (current_command != NULL && 294 ((strcmp(current_command->name, "set") == 0) || 295 (strcmp(current_command->name, "get") == 0) || 296 (strcmp(current_command->name, "list") == 0))) { 297 298 (void) fprintf(fp, 299 gettext("\nthe following properties are supported:\n")); 300 301 (void) fprintf(fp, "\n\t%-13s %s %s\n\n", 302 "PROPERTY", "EDIT", "VALUES"); 303 304 /* Iterate over all properties */ 305 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 306 ZFS_TYPE_POOL); 307 } 308 309 /* 310 * See comments at end of main(). 311 */ 312 if (getenv("ZFS_ABORT") != NULL) { 313 (void) printf("dumping core by request\n"); 314 abort(); 315 } 316 317 exit(requested ? 0 : 2); 318 } 319 320 void 321 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 322 boolean_t print_logs) 323 { 324 nvlist_t **child; 325 uint_t c, children; 326 char *vname; 327 328 if (name != NULL) 329 (void) printf("\t%*s%s\n", indent, "", name); 330 331 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 332 &child, &children) != 0) 333 return; 334 335 for (c = 0; c < children; c++) { 336 uint64_t is_log = B_FALSE; 337 338 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 339 &is_log); 340 if ((is_log && !print_logs) || (!is_log && print_logs)) 341 continue; 342 343 vname = zpool_vdev_name(g_zfs, zhp, child[c]); 344 print_vdev_tree(zhp, vname, child[c], indent + 2, 345 B_FALSE); 346 free(vname); 347 } 348 } 349 350 /* 351 * Add a property pair (name, string-value) into a property nvlist. 352 */ 353 static int 354 add_prop_list(const char *propname, char *propval, nvlist_t **props) 355 { 356 char *strval; 357 nvlist_t *proplist; 358 zpool_prop_t prop; 359 360 if (*props == NULL && 361 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 362 (void) fprintf(stderr, 363 gettext("internal error: out of memory\n")); 364 return (1); 365 } 366 367 proplist = *props; 368 369 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { 370 (void) fprintf(stderr, gettext("property '%s' is " 371 "not a valid pool property\n"), propname); 372 return (2); 373 } 374 375 /* Use normalized property name for nvlist operations */ 376 if (nvlist_lookup_string(proplist, zpool_prop_to_name(prop), 377 &strval) == 0 && prop != ZPOOL_PROP_CACHEFILE) { 378 (void) fprintf(stderr, gettext("property '%s' " 379 "specified multiple times\n"), propname); 380 return (2); 381 } 382 383 if (nvlist_add_string(proplist, zpool_prop_to_name(prop), 384 propval) != 0) { 385 (void) fprintf(stderr, gettext("internal " 386 "error: out of memory\n")); 387 return (1); 388 } 389 390 return (0); 391 } 392 393 /* 394 * zpool add [-fn] <pool> <vdev> ... 395 * 396 * -f Force addition of devices, even if they appear in use 397 * -n Do not add the devices, but display the resulting layout if 398 * they were to be added. 399 * 400 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 401 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 402 * libzfs. 403 */ 404 int 405 zpool_do_add(int argc, char **argv) 406 { 407 boolean_t force = B_FALSE; 408 boolean_t dryrun = B_FALSE; 409 int c; 410 nvlist_t *nvroot; 411 char *poolname; 412 int ret; 413 zpool_handle_t *zhp; 414 nvlist_t *config; 415 416 /* check options */ 417 while ((c = getopt(argc, argv, "fn")) != -1) { 418 switch (c) { 419 case 'f': 420 force = B_TRUE; 421 break; 422 case 'n': 423 dryrun = B_TRUE; 424 break; 425 case '?': 426 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 427 optopt); 428 usage(B_FALSE); 429 } 430 } 431 432 argc -= optind; 433 argv += optind; 434 435 /* get pool name and check number of arguments */ 436 if (argc < 1) { 437 (void) fprintf(stderr, gettext("missing pool name argument\n")); 438 usage(B_FALSE); 439 } 440 if (argc < 2) { 441 (void) fprintf(stderr, gettext("missing vdev specification\n")); 442 usage(B_FALSE); 443 } 444 445 poolname = argv[0]; 446 447 argc--; 448 argv++; 449 450 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 451 return (1); 452 453 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 454 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 455 poolname); 456 zpool_close(zhp); 457 return (1); 458 } 459 460 /* pass off to get_vdev_spec for processing */ 461 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, argc, argv); 462 if (nvroot == NULL) { 463 zpool_close(zhp); 464 return (1); 465 } 466 467 if (dryrun) { 468 nvlist_t *poolnvroot; 469 470 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 471 &poolnvroot) == 0); 472 473 (void) printf(gettext("would update '%s' to the following " 474 "configuration:\n"), zpool_get_name(zhp)); 475 476 /* print original main pool and new tree */ 477 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 478 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 479 480 /* Do the same for the logs */ 481 if (num_logs(poolnvroot) > 0) { 482 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 483 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 484 } else if (num_logs(nvroot) > 0) { 485 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 486 } 487 488 ret = 0; 489 } else { 490 ret = (zpool_add(zhp, nvroot) != 0); 491 } 492 493 nvlist_free(nvroot); 494 zpool_close(zhp); 495 496 return (ret); 497 } 498 499 /* 500 * zpool remove <pool> <vdev> ... 501 * 502 * Removes the given vdev from the pool. Currently, this only supports removing 503 * spares and cache devices from the pool. Eventually, we'll want to support 504 * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs. 505 */ 506 int 507 zpool_do_remove(int argc, char **argv) 508 { 509 char *poolname; 510 int i, ret = 0; 511 zpool_handle_t *zhp; 512 513 argc--; 514 argv++; 515 516 /* get pool name and check number of arguments */ 517 if (argc < 1) { 518 (void) fprintf(stderr, gettext("missing pool name argument\n")); 519 usage(B_FALSE); 520 } 521 if (argc < 2) { 522 (void) fprintf(stderr, gettext("missing device\n")); 523 usage(B_FALSE); 524 } 525 526 poolname = argv[0]; 527 528 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 529 return (1); 530 531 for (i = 1; i < argc; i++) { 532 if (zpool_vdev_remove(zhp, argv[i]) != 0) 533 ret = 1; 534 } 535 536 return (ret); 537 } 538 539 /* 540 * zpool create [-fn] [-o property=value] ... [-R root] [-m mountpoint] 541 * <pool> <dev> ... 542 * 543 * -f Force creation, even if devices appear in use 544 * -n Do not create the pool, but display the resulting layout if it 545 * were to be created. 546 * -R Create a pool under an alternate root 547 * -m Set default mountpoint for the root dataset. By default it's 548 * '/<pool>' 549 * -o Set property=value. 550 * 551 * Creates the named pool according to the given vdev specification. The 552 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 553 * we get the nvlist back from get_vdev_spec(), we either print out the contents 554 * (if '-n' was specified), or pass it to libzfs to do the creation. 555 */ 556 int 557 zpool_do_create(int argc, char **argv) 558 { 559 boolean_t force = B_FALSE; 560 boolean_t dryrun = B_FALSE; 561 int c; 562 nvlist_t *nvroot = NULL; 563 char *poolname; 564 int ret = 1; 565 char *altroot = NULL; 566 char *mountpoint = NULL; 567 nvlist_t *props = NULL; 568 char *propval; 569 570 /* check options */ 571 while ((c = getopt(argc, argv, ":fnR:m:o:")) != -1) { 572 switch (c) { 573 case 'f': 574 force = B_TRUE; 575 break; 576 case 'n': 577 dryrun = B_TRUE; 578 break; 579 case 'R': 580 altroot = optarg; 581 if (add_prop_list(zpool_prop_to_name( 582 ZPOOL_PROP_ALTROOT), optarg, &props)) 583 goto errout; 584 if (nvlist_lookup_string(props, 585 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 586 &propval) == 0) 587 break; 588 if (add_prop_list(zpool_prop_to_name( 589 ZPOOL_PROP_CACHEFILE), "none", &props)) 590 goto errout; 591 break; 592 case 'm': 593 mountpoint = optarg; 594 break; 595 case 'o': 596 if ((propval = strchr(optarg, '=')) == NULL) { 597 (void) fprintf(stderr, gettext("missing " 598 "'=' for -o option\n")); 599 goto errout; 600 } 601 *propval = '\0'; 602 propval++; 603 604 if (add_prop_list(optarg, propval, &props)) 605 goto errout; 606 break; 607 case ':': 608 (void) fprintf(stderr, gettext("missing argument for " 609 "'%c' option\n"), optopt); 610 goto badusage; 611 case '?': 612 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 613 optopt); 614 goto badusage; 615 } 616 } 617 618 argc -= optind; 619 argv += optind; 620 621 /* get pool name and check number of arguments */ 622 if (argc < 1) { 623 (void) fprintf(stderr, gettext("missing pool name argument\n")); 624 goto badusage; 625 } 626 if (argc < 2) { 627 (void) fprintf(stderr, gettext("missing vdev specification\n")); 628 goto badusage; 629 } 630 631 poolname = argv[0]; 632 633 /* 634 * As a special case, check for use of '/' in the name, and direct the 635 * user to use 'zfs create' instead. 636 */ 637 if (strchr(poolname, '/') != NULL) { 638 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 639 "character '/' in pool name\n"), poolname); 640 (void) fprintf(stderr, gettext("use 'zfs create' to " 641 "create a dataset\n")); 642 goto errout; 643 } 644 645 /* pass off to get_vdev_spec for bulk processing */ 646 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1, 647 argv + 1); 648 if (nvroot == NULL) 649 return (1); 650 651 /* make_root_vdev() allows 0 toplevel children if there are spares */ 652 if (!zfs_allocatable_devs(nvroot)) { 653 (void) fprintf(stderr, gettext("invalid vdev " 654 "specification: at least one toplevel vdev must be " 655 "specified\n")); 656 goto errout; 657 } 658 659 660 if (altroot != NULL && altroot[0] != '/') { 661 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 662 "must be an absolute path\n"), altroot); 663 goto errout; 664 } 665 666 /* 667 * Check the validity of the mountpoint and direct the user to use the 668 * '-m' mountpoint option if it looks like its in use. 669 */ 670 if (mountpoint == NULL || 671 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 672 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 673 char buf[MAXPATHLEN]; 674 DIR *dirp; 675 676 if (mountpoint && mountpoint[0] != '/') { 677 (void) fprintf(stderr, gettext("invalid mountpoint " 678 "'%s': must be an absolute path, 'legacy', or " 679 "'none'\n"), mountpoint); 680 goto errout; 681 } 682 683 if (mountpoint == NULL) { 684 if (altroot != NULL) 685 (void) snprintf(buf, sizeof (buf), "%s/%s", 686 altroot, poolname); 687 else 688 (void) snprintf(buf, sizeof (buf), "/%s", 689 poolname); 690 } else { 691 if (altroot != NULL) 692 (void) snprintf(buf, sizeof (buf), "%s%s", 693 altroot, mountpoint); 694 else 695 (void) snprintf(buf, sizeof (buf), "%s", 696 mountpoint); 697 } 698 699 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 700 (void) fprintf(stderr, gettext("mountpoint '%s' : " 701 "%s\n"), buf, strerror(errno)); 702 (void) fprintf(stderr, gettext("use '-m' " 703 "option to provide a different default\n")); 704 goto errout; 705 } else if (dirp) { 706 int count = 0; 707 708 while (count < 3 && readdir(dirp) != NULL) 709 count++; 710 (void) closedir(dirp); 711 712 if (count > 2) { 713 (void) fprintf(stderr, gettext("mountpoint " 714 "'%s' exists and is not empty\n"), buf); 715 (void) fprintf(stderr, gettext("use '-m' " 716 "option to provide a " 717 "different default\n")); 718 goto errout; 719 } 720 } 721 } 722 723 if (dryrun) { 724 /* 725 * For a dry run invocation, print out a basic message and run 726 * through all the vdevs in the list and print out in an 727 * appropriate hierarchy. 728 */ 729 (void) printf(gettext("would create '%s' with the " 730 "following layout:\n\n"), poolname); 731 732 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 733 if (num_logs(nvroot) > 0) 734 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 735 736 ret = 0; 737 } else { 738 /* 739 * Hand off to libzfs. 740 */ 741 if (zpool_create(g_zfs, poolname, nvroot, props) == 0) { 742 zfs_handle_t *pool = zfs_open(g_zfs, poolname, 743 ZFS_TYPE_FILESYSTEM); 744 if (pool != NULL) { 745 if (mountpoint != NULL) 746 verify(zfs_prop_set(pool, 747 zfs_prop_to_name( 748 ZFS_PROP_MOUNTPOINT), 749 mountpoint) == 0); 750 if (zfs_mount(pool, NULL, 0) == 0) 751 ret = zfs_shareall(pool); 752 zfs_close(pool); 753 } 754 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 755 (void) fprintf(stderr, gettext("pool name may have " 756 "been omitted\n")); 757 } 758 } 759 760 errout: 761 nvlist_free(nvroot); 762 nvlist_free(props); 763 return (ret); 764 badusage: 765 nvlist_free(props); 766 usage(B_FALSE); 767 return (2); 768 } 769 770 /* 771 * zpool destroy <pool> 772 * 773 * -f Forcefully unmount any datasets 774 * 775 * Destroy the given pool. Automatically unmounts any datasets in the pool. 776 */ 777 int 778 zpool_do_destroy(int argc, char **argv) 779 { 780 boolean_t force = B_FALSE; 781 int c; 782 char *pool; 783 zpool_handle_t *zhp; 784 int ret; 785 786 /* check options */ 787 while ((c = getopt(argc, argv, "f")) != -1) { 788 switch (c) { 789 case 'f': 790 force = B_TRUE; 791 break; 792 case '?': 793 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 794 optopt); 795 usage(B_FALSE); 796 } 797 } 798 799 argc -= optind; 800 argv += optind; 801 802 /* check arguments */ 803 if (argc < 1) { 804 (void) fprintf(stderr, gettext("missing pool argument\n")); 805 usage(B_FALSE); 806 } 807 if (argc > 1) { 808 (void) fprintf(stderr, gettext("too many arguments\n")); 809 usage(B_FALSE); 810 } 811 812 pool = argv[0]; 813 814 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 815 /* 816 * As a special case, check for use of '/' in the name, and 817 * direct the user to use 'zfs destroy' instead. 818 */ 819 if (strchr(pool, '/') != NULL) 820 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 821 "destroy a dataset\n")); 822 return (1); 823 } 824 825 if (zpool_disable_datasets(zhp, force) != 0) { 826 (void) fprintf(stderr, gettext("could not destroy '%s': " 827 "could not unmount datasets\n"), zpool_get_name(zhp)); 828 return (1); 829 } 830 831 ret = (zpool_destroy(zhp) != 0); 832 833 zpool_close(zhp); 834 835 return (ret); 836 } 837 838 /* 839 * zpool export [-f] <pool> ... 840 * 841 * -f Forcefully unmount datasets 842 * 843 * Export the given pools. By default, the command will attempt to cleanly 844 * unmount any active datasets within the pool. If the '-f' flag is specified, 845 * then the datasets will be forcefully unmounted. 846 */ 847 int 848 zpool_do_export(int argc, char **argv) 849 { 850 boolean_t force = B_FALSE; 851 int c; 852 zpool_handle_t *zhp; 853 int ret; 854 int i; 855 856 /* check options */ 857 while ((c = getopt(argc, argv, "f")) != -1) { 858 switch (c) { 859 case 'f': 860 force = B_TRUE; 861 break; 862 case '?': 863 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 864 optopt); 865 usage(B_FALSE); 866 } 867 } 868 869 argc -= optind; 870 argv += optind; 871 872 /* check arguments */ 873 if (argc < 1) { 874 (void) fprintf(stderr, gettext("missing pool argument\n")); 875 usage(B_FALSE); 876 } 877 878 ret = 0; 879 for (i = 0; i < argc; i++) { 880 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 881 ret = 1; 882 continue; 883 } 884 885 if (zpool_disable_datasets(zhp, force) != 0) { 886 ret = 1; 887 zpool_close(zhp); 888 continue; 889 } 890 891 if (zpool_export(zhp) != 0) 892 ret = 1; 893 894 zpool_close(zhp); 895 } 896 897 return (ret); 898 } 899 900 /* 901 * Given a vdev configuration, determine the maximum width needed for the device 902 * name column. 903 */ 904 static int 905 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 906 { 907 char *name = zpool_vdev_name(g_zfs, zhp, nv); 908 nvlist_t **child; 909 uint_t c, children; 910 int ret; 911 912 if (strlen(name) + depth > max) 913 max = strlen(name) + depth; 914 915 free(name); 916 917 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 918 &child, &children) == 0) { 919 for (c = 0; c < children; c++) 920 if ((ret = max_width(zhp, child[c], depth + 2, 921 max)) > max) 922 max = ret; 923 } 924 925 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 926 &child, &children) == 0) { 927 for (c = 0; c < children; c++) 928 if ((ret = max_width(zhp, child[c], depth + 2, 929 max)) > max) 930 max = ret; 931 } 932 933 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 934 &child, &children) == 0) { 935 for (c = 0; c < children; c++) 936 if ((ret = max_width(zhp, child[c], depth + 2, 937 max)) > max) 938 max = ret; 939 } 940 941 942 return (max); 943 } 944 945 946 /* 947 * Print the configuration of an exported pool. Iterate over all vdevs in the 948 * pool, printing out the name and status for each one. 949 */ 950 void 951 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth, 952 boolean_t print_logs) 953 { 954 nvlist_t **child; 955 uint_t c, children; 956 vdev_stat_t *vs; 957 char *type, *vname; 958 959 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 960 if (strcmp(type, VDEV_TYPE_MISSING) == 0) 961 return; 962 963 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 964 (uint64_t **)&vs, &c) == 0); 965 966 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 967 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 968 969 if (vs->vs_aux != 0) { 970 (void) printf(" "); 971 972 switch (vs->vs_aux) { 973 case VDEV_AUX_OPEN_FAILED: 974 (void) printf(gettext("cannot open")); 975 break; 976 977 case VDEV_AUX_BAD_GUID_SUM: 978 (void) printf(gettext("missing device")); 979 break; 980 981 case VDEV_AUX_NO_REPLICAS: 982 (void) printf(gettext("insufficient replicas")); 983 break; 984 985 case VDEV_AUX_VERSION_NEWER: 986 (void) printf(gettext("newer version")); 987 break; 988 989 case VDEV_AUX_ERR_EXCEEDED: 990 (void) printf(gettext("too many errors")); 991 break; 992 993 default: 994 (void) printf(gettext("corrupted data")); 995 break; 996 } 997 } 998 (void) printf("\n"); 999 1000 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1001 &child, &children) != 0) 1002 return; 1003 1004 for (c = 0; c < children; c++) { 1005 uint64_t is_log = B_FALSE; 1006 1007 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1008 &is_log); 1009 if ((is_log && !print_logs) || (!is_log && print_logs)) 1010 continue; 1011 1012 vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1013 print_import_config(vname, child[c], 1014 namewidth, depth + 2, B_FALSE); 1015 free(vname); 1016 } 1017 1018 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1019 &child, &children) == 0) { 1020 (void) printf(gettext("\tcache\n")); 1021 for (c = 0; c < children; c++) { 1022 vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1023 (void) printf("\t %s\n", vname); 1024 free(vname); 1025 } 1026 } 1027 1028 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1029 &child, &children) == 0) { 1030 (void) printf(gettext("\tspares\n")); 1031 for (c = 0; c < children; c++) { 1032 vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1033 (void) printf("\t %s\n", vname); 1034 free(vname); 1035 } 1036 } 1037 } 1038 1039 /* 1040 * Display the status for the given pool. 1041 */ 1042 static void 1043 show_import(nvlist_t *config) 1044 { 1045 uint64_t pool_state; 1046 vdev_stat_t *vs; 1047 char *name; 1048 uint64_t guid; 1049 char *msgid; 1050 nvlist_t *nvroot; 1051 int reason; 1052 const char *health; 1053 uint_t vsc; 1054 int namewidth; 1055 1056 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1057 &name) == 0); 1058 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1059 &guid) == 0); 1060 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1061 &pool_state) == 0); 1062 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1063 &nvroot) == 0); 1064 1065 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 1066 (uint64_t **)&vs, &vsc) == 0); 1067 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1068 1069 reason = zpool_import_status(config, &msgid); 1070 1071 (void) printf(gettext(" pool: %s\n"), name); 1072 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1073 (void) printf(gettext(" state: %s"), health); 1074 if (pool_state == POOL_STATE_DESTROYED) 1075 (void) printf(gettext(" (DESTROYED)")); 1076 (void) printf("\n"); 1077 1078 switch (reason) { 1079 case ZPOOL_STATUS_MISSING_DEV_R: 1080 case ZPOOL_STATUS_MISSING_DEV_NR: 1081 case ZPOOL_STATUS_BAD_GUID_SUM: 1082 (void) printf(gettext("status: One or more devices are missing " 1083 "from the system.\n")); 1084 break; 1085 1086 case ZPOOL_STATUS_CORRUPT_LABEL_R: 1087 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1088 (void) printf(gettext("status: One or more devices contains " 1089 "corrupted data.\n")); 1090 break; 1091 1092 case ZPOOL_STATUS_CORRUPT_DATA: 1093 (void) printf(gettext("status: The pool data is corrupted.\n")); 1094 break; 1095 1096 case ZPOOL_STATUS_OFFLINE_DEV: 1097 (void) printf(gettext("status: One or more devices " 1098 "are offlined.\n")); 1099 break; 1100 1101 case ZPOOL_STATUS_CORRUPT_POOL: 1102 (void) printf(gettext("status: The pool metadata is " 1103 "corrupted.\n")); 1104 break; 1105 1106 case ZPOOL_STATUS_VERSION_OLDER: 1107 (void) printf(gettext("status: The pool is formatted using an " 1108 "older on-disk version.\n")); 1109 break; 1110 1111 case ZPOOL_STATUS_VERSION_NEWER: 1112 (void) printf(gettext("status: The pool is formatted using an " 1113 "incompatible version.\n")); 1114 break; 1115 case ZPOOL_STATUS_HOSTID_MISMATCH: 1116 (void) printf(gettext("status: The pool was last accessed by " 1117 "another system.\n")); 1118 break; 1119 case ZPOOL_STATUS_FAULTED_DEV_R: 1120 case ZPOOL_STATUS_FAULTED_DEV_NR: 1121 (void) printf(gettext("status: One or more devices are " 1122 "fa