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