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 case ZPOOL_STATUS_HOSTID_MISMATCH: 1146 (void) printf(gettext("status: The pool was last accessed by " 1147 "another system.\n")); 1148 break; 1149 case ZPOOL_STATUS_FAULTED_DEV_R: 1150 case ZPOOL_STATUS_FAULTED_DEV_NR: 1151 (void) printf(gettext("status: One or more devices are " 1152 "faulted.\n")); 1153 break; 1154 1155 default: 1156 /* 1157 * No other status can be seen when importing pools. 1158 */ 1159 assert(reason == ZPOOL_STATUS_OK); 1160 } 1161 1162 /* 1163 * Print out an action according to the overall state of the pool. 1164 */ 1165 if (vs->vs_state == VDEV_STATE_HEALTHY) { 1166 if (reason == ZPOOL_STATUS_VERSION_OLDER) 1167 (void) printf(gettext("action: The pool can be " 1168 "imported using its name or numeric identifier, " 1169 "though\n\tsome features will not be available " 1170 "without an explicit 'zpool upgrade'.\n")); 1171 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) 1172 (void) printf(gettext("action: The pool can be " 1173 "imported using its name or numeric " 1174 "identifier and\n\tthe '-f' flag.\n")); 1175 else 1176 (void) printf(gettext("action: The pool can be " 1177 "imported using its name or numeric " 1178 "identifier.\n")); 1179 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1180 (void) printf(gettext("action: The pool can be imported " 1181 "despite missing or damaged devices. The\n\tfault " 1182 "tolerance of the pool may be compromised if imported.\n")); 1183 } else { 1184 switch (reason) { 1185 case ZPOOL_STATUS_VERSION_NEWER: 1186 (void) printf(gettext("action: The pool cannot be " 1187 "imported. Access the pool on a system running " 1188 "newer\n\tsoftware, or recreate the pool from " 1189 "backup.\n")); 1190 break; 1191 case ZPOOL_STATUS_MISSING_DEV_R: 1192 case ZPOOL_STATUS_MISSING_DEV_NR: 1193 case ZPOOL_STATUS_BAD_GUID_SUM: 1194 (void) printf(gettext("action: The pool cannot be " 1195 "imported. Attach the missing\n\tdevices and try " 1196 "again.\n")); 1197 break; 1198 default: 1199 (void) printf(gettext("action: The pool cannot be " 1200 "imported due to damaged devices or data.\n")); 1201 } 1202 } 1203 1204 /* 1205 * If the state is "closed" or "can't open", and the aux state 1206 * is "corrupt data": 1207 */ 1208 if (((vs->vs_state == VDEV_STATE_CLOSED) || 1209 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 1210 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1211 if (pool_state == POOL_STATE_DESTROYED) 1212 (void) printf(gettext("\tThe pool was destroyed, " 1213 "but can be imported using the '-Df' flags.\n")); 1214 else if (pool_state != POOL_STATE_EXPORTED) 1215 (void) printf(gettext("\tThe pool may be active on " 1216 "another system, but can be imported using\n\t" 1217 "the '-f' flag.\n")); 1218 } 1219 1220 if (msgid != NULL) 1221 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 1222 msgid); 1223 1224 (void) printf(gettext("config:\n\n")); 1225 1226 namewidth = max_width(NULL, nvroot, 0, 0); 1227 if (namewidth < 10) 1228 namewidth = 10; 1229 1230 print_import_config(name, nvroot, namewidth, 0, B_FALSE); 1231 if (num_logs(nvroot) > 0) { 1232 (void) printf(gettext("\tlogs\n")); 1233 print_import_config(name, nvroot, namewidth, 0, B_TRUE); 1234 } 1235 1236 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 1237 (void) printf(gettext("\n\tAdditional devices are known to " 1238 "be part of this pool, though their\n\texact " 1239 "configuration cannot be determined.\n")); 1240 } 1241 } 1242 1243 /* 1244 * Perform the import for the given configuration. This passes the heavy 1245 * lifting off to zpool_import_props(), and then mounts the datasets contained 1246 * within the pool. 1247 */ 1248 static int 1249 do_import(nvlist_t *config, const char *newname, const char *mntopts, 1250 int force, nvlist_t *props, boolean_t allowfaulted) 1251 { 1252 zpool_handle_t *zhp; 1253 char *name; 1254 uint64_t state; 1255 uint64_t version; 1256 int error = 0; 1257 1258 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1259 &name) == 0); 1260 1261 verify(nvlist_lookup_uint64(config, 1262 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1263 verify(nvlist_lookup_uint64(config, 1264 ZPOOL_CONFIG_VERSION, &version) == 0); 1265 if (version > SPA_VERSION) { 1266 (void) fprintf(stderr, gettext("cannot import '%s': pool " 1267 "is formatted using a newer ZFS version\n"), name); 1268 return (1); 1269 } else if (state != POOL_STATE_EXPORTED && !force) { 1270 uint64_t hostid; 1271 1272 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 1273 &hostid) == 0) { 1274 if ((unsigned long)hostid != gethostid()) { 1275 char *hostname; 1276 uint64_t timestamp; 1277 time_t t; 1278 1279 verify(nvlist_lookup_string(config, 1280 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 1281 verify(nvlist_lookup_uint64(config, 1282 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 1283 t = timestamp; 1284 (void) fprintf(stderr, gettext("cannot import " 1285 "'%s': pool may be in use from other " 1286 "system, it was last accessed by %s " 1287 "(hostid: 0x%lx) on %s"), name, hostname, 1288 (unsigned long)hostid, 1289 asctime(localtime(&t))); 1290 (void) fprintf(stderr, gettext("use '-f' to " 1291 "import anyway\n")); 1292 return (1); 1293 } 1294 } else { 1295 (void) fprintf(stderr, gettext("cannot import '%s': " 1296 "pool may be in use from other system\n"), name); 1297 (void) fprintf(stderr, gettext("use '-f' to import " 1298 "anyway\n")); 1299 return (1); 1300 } 1301 } 1302 1303 if (zpool_import_props(g_zfs, config, newname, props, 1304 allowfaulted) != 0) 1305 return (1); 1306 1307 if (newname != NULL) 1308 name = (char *)newname; 1309 1310 verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL); 1311 1312 if (zpool_enable_datasets(zhp, mntopts, 0) != 0) { 1313 zpool_close(zhp); 1314 return (1); 1315 } 1316 1317 zpool_close(zhp); 1318 return (error); 1319 } 1320 1321 /* 1322 * zpool import [-d dir] [-D] 1323 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1324 * [-d dir | -c cachefile] [-f] -a 1325 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1326 * [-d dir | -c cachefile] [-f] <pool | id> [newpool] 1327 * 1328 * -c Read pool information from a cachefile instead of searching 1329 * devices. 1330 * 1331 * -d Scan in a specific directory, other than /dev/dsk. More than 1332 * one directory can be specified using multiple '-d' options. 1333 * 1334 * -D Scan for previously destroyed pools or import all or only 1335 * specified destroyed pools. 1336 * 1337 * -R Temporarily import the pool, with all mountpoints relative to 1338 * the given root. The pool will remain exported when the machine 1339 * is rebooted. 1340 * 1341 * -f Force import, even if it appears that the pool is active. 1342 * 1343 * -F Import even in the presence of faulted vdevs. This is an 1344 * intentionally undocumented option for testing purposes, and 1345 * treats the pool configuration as complete, leaving any bad 1346 * vdevs in the FAULTED state. 1347 * 1348 * -a Import all pools found. 1349 * 1350 * -o Set property=value and/or temporary mount options (without '='). 1351 * 1352 * The import command scans for pools to import, and import pools based on pool 1353 * name and GUID. The pool can also be renamed as part of the import process. 1354 */ 1355 int 1356 zpool_do_import(int argc, char **argv) 1357 { 1358 char **searchdirs = NULL; 1359 int nsearch = 0; 1360 int c; 1361 int err; 1362 nvlist_t *pools = NULL; 1363 boolean_t do_all = B_FALSE; 1364 boolean_t do_destroyed = B_FALSE; 1365 char *mntopts = NULL; 1366 boolean_t do_force = B_FALSE; 1367 nvpair_t *elem; 1368 nvlist_t *config; 1369 uint64_t searchguid = 0; 1370 char *searchname = NULL; 1371 char *propval; 1372 nvlist_t *found_config; 1373 nvlist_t *props = NULL; 1374 boolean_t first; 1375 boolean_t allow_faulted = B_FALSE; 1376 uint64_t pool_state; 1377 char *cachefile = NULL; 1378 1379 /* check options */ 1380 while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) { 1381 switch (c) { 1382 case 'a': 1383 do_all = B_TRUE; 1384 break; 1385 case 'c': 1386 cachefile = optarg; 1387 break; 1388 case 'd': 1389 if (searchdirs == NULL) { 1390 searchdirs = safe_malloc(sizeof (char *)); 1391 } else { 1392 char **tmp = safe_malloc((nsearch + 1) * 1393 sizeof (char *)); 1394 bcopy(searchdirs, tmp, nsearch * 1395 sizeof (char *)); 1396 free(searchdirs); 1397 searchdirs = tmp; 1398 } 1399 searchdirs[nsearch++] = optarg; 1400 break; 1401 case 'D': 1402 do_destroyed = B_TRUE; 1403 break; 1404 case 'f': 1405 do_force = B_TRUE; 1406 break; 1407 case 'F': 1408 allow_faulted = B_TRUE; 1409 break; 1410 case 'o': 1411 if ((propval = strchr(optarg, '=')) != NULL) { 1412 *propval = '\0'; 1413 propval++; 1414 if (add_prop_list(optarg, propval, 1415 &props, B_TRUE)) 1416 goto error; 1417 } else { 1418 mntopts = optarg; 1419 } 1420 break; 1421 case 'R': 1422 if (add_prop_list(zpool_prop_to_name( 1423 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1424 goto error; 1425 if (nvlist_lookup_string(props, 1426 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 1427 &propval) == 0) 1428 break; 1429 if (add_prop_list(zpool_prop_to_name( 1430 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1431 goto error; 1432 break; 1433 case ':': 1434 (void) fprintf(stderr, gettext("missing argument for " 1435 "'%c' option\n"), optopt); 1436 usage(B_FALSE); 1437 break; 1438 case '?': 1439 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1440 optopt); 1441 usage(B_FALSE); 1442 } 1443 } 1444 1445 argc -= optind; 1446 argv += optind; 1447 1448 if (cachefile && nsearch != 0) { 1449 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 1450 usage(B_FALSE); 1451 } 1452 1453 if (searchdirs == NULL) { 1454 searchdirs = safe_malloc(sizeof (char *)); 1455 searchdirs[0] = "/dev/dsk"; 1456 nsearch = 1; 1457 } 1458 1459 /* check argument count */ 1460 if (do_all) { 1461 if (argc != 0) { 1462 (void) fprintf(stderr, gettext("too many arguments\n")); 1463 usage(B_FALSE); 1464 } 1465 } else { 1466 if (argc > 2) { 1467 (void) fprintf(stderr, gettext("too many arguments\n")); 1468 usage(B_FALSE); 1469 } 1470 1471 /* 1472 * Check for the SYS_CONFIG privilege. We do this explicitly 1473 * here because otherwise any attempt to discover pools will 1474 * silently fail. 1475 */ 1476 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 1477 (void) fprintf(stderr, gettext("cannot " 1478 "discover pools: permission denied\n")); 1479 free(searchdirs); 1480 return (1); 1481 } 1482 } 1483 1484 /* 1485 * Depending on the arguments given, we do one of the following: 1486 * 1487 * <none> Iterate through all pools and display information about 1488 * each one. 1489 * 1490 * -a Iterate through all pools and try to import each one. 1491 * 1492 * <id> Find the pool that corresponds to the given GUID/pool 1493 * name and import that one. 1494 * 1495 * -D Above options applies only to destroyed pools. 1496 */ 1497 if (argc != 0) { 1498 char *endptr; 1499 1500 errno = 0; 1501 searchguid = strtoull(argv[0], &endptr, 10); 1502 if (errno != 0 || *endptr != '\0') 1503 searchname = argv[0]; 1504 found_config = NULL; 1505 } 1506 1507 if (cachefile) { 1508 pools = zpool_find_import_cached(g_zfs, cachefile, searchname, 1509 searchguid); 1510 } else if (searchname != NULL) { 1511 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs, 1512 searchname); 1513 } else { 1514 /* 1515 * It's OK to search by guid even if searchguid is 0. 1516 */ 1517 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs, 1518 searchguid); 1519 } 1520 1521 if (pools == NULL) { 1522 if (argc != 0) { 1523 (void) fprintf(stderr, gettext("cannot import '%s': " 1524 "no such pool available\n"), argv[0]); 1525 } 1526 free(searchdirs); 1527 return (1); 1528 } 1529 1530 /* 1531 * At this point we have a list of import candidate configs. Even if 1532 * we were searching by pool name or guid, we still need to 1533 * post-process the list to deal with pool state and possible 1534 * duplicate names. 1535 */ 1536 err = 0; 1537 elem = NULL; 1538 first = B_TRUE; 1539 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1540 1541 verify(nvpair_value_nvlist(elem, &config) == 0); 1542 1543 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1544 &pool_state) == 0); 1545 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 1546 continue; 1547 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 1548 continue; 1549 1550 if (argc == 0) { 1551 if (first) 1552 first = B_FALSE; 1553 else if (!do_all) 1554 (void) printf("\n"); 1555 1556 if (do_all) 1557 err |= do_import(config, NULL, mntopts, 1558 do_force, props, allow_faulted); 1559 else 1560 show_import(config); 1561 } else if (searchname != NULL) { 1562 char *name; 1563 1564 /* 1565 * We are searching for a pool based on name. 1566 */ 1567 verify(nvlist_lookup_string(config, 1568 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 1569 1570 if (strcmp(name, searchname) == 0) { 1571 if (found_config != NULL) { 1572 (void) fprintf(stderr, gettext( 1573 "cannot import '%s': more than " 1574 "one matching pool\n"), searchname); 1575 (void) fprintf(stderr, gettext( 1576 "import by numeric ID instead\n")); 1577 err = B_TRUE; 1578 } 1579 found_config = config; 1580 } 1581 } else { 1582 uint64_t guid; 1583 1584 /* 1585 * Search for a pool by guid. 1586 */ 1587 verify(nvlist_lookup_uint64(config, 1588 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 1589 1590 if (guid == searchguid) 1591 found_config = config; 1592 } 1593 } 1594 1595 /* 1596 * If we were searching for a specific pool, verify that we found a 1597 * pool, and then do the import. 1598 */ 1599 if (argc != 0 && err == 0) { 1600 if (found_config == NULL) { 1601 (void) fprintf(stderr, gettext("cannot import '%s': " 1602 "no such pool available\n"), argv[0]); 1603 err = B_TRUE; 1604 } else { 1605 err |= do_import(found_config, argc == 1 ? NULL : 1606 argv[1], mntopts, do_force, props, allow_faulted); 1607 } 1608 } 1609 1610 /* 1611 * If we were just looking for pools, report an error if none were 1612 * found. 1613 */ 1614 if (argc == 0 && first) 1615 (void) fprintf(stderr, 1616 gettext("no pools available to import\n")); 1617 1618 error: 1619 nvlist_free(props); 1620 nvlist_free(pools); 1621 free(searchdirs); 1622 1623 return (err ? 1 : 0); 1624 } 1625 1626 typedef struct iostat_cbdata { 1627 zpool_list_t *cb_list; 1628 int cb_verbose; 1629 int cb_iteration; 1630 int cb_namewidth; 1631 } iostat_cbdata_t; 1632 1633 static void 1634 print_iostat_separator(iostat_cbdata_t *cb) 1635 { 1636 int i = 0; 1637 1638 for (i = 0; i < cb->cb_namewidth; i++) 1639 (void) printf("-"); 1640 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 1641 } 1642 1643 static void 1644 print_iostat_header(iostat_cbdata_t *cb) 1645 { 1646 (void) printf("%*s capacity operations bandwidth\n", 1647 cb->cb_namewidth, ""); 1648 (void) printf("%-*s used avail read write read write\n", 1649 cb->cb_namewidth, "pool"); 1650 print_iostat_separator(cb); 1651 } 1652 1653 /* 1654 * Display a single statistic. 1655 */ 1656 static void 1657 print_one_stat(uint64_t value) 1658 { 1659 char buf[64]; 1660 1661 zfs_nicenum(value, buf, sizeof (buf)); 1662 (void) printf(" %5s", buf); 1663 } 1664 1665 /* 1666 * Print out all the statistics for the given vdev. This can either be the 1667 * toplevel configuration, or called recursively. If 'name' is NULL, then this 1668 * is a verbose output, and we don't want to display the toplevel pool stats. 1669 */ 1670 void 1671 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 1672 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 1673 { 1674 nvlist_t **oldchild, **newchild; 1675 uint_t c, children; 1676 vdev_stat_t *oldvs, *newvs; 1677 vdev_stat_t zerovs = { 0 }; 1678 uint64_t tdelta; 1679 double scale; 1680 char *vname; 1681 1682 if (oldnv != NULL) { 1683 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS, 1684 (uint64_t **)&oldvs, &c) == 0); 1685 } else { 1686 oldvs = &zerovs; 1687 } 1688 1689 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS, 1690 (uint64_t **)&newvs, &c) == 0); 1691 1692 if (strlen(name) + depth > cb->cb_namewidth) 1693 (void) printf("%*s%s", depth, "", name); 1694 else 1695 (void) printf("%*s%s%*s", depth, "", name, 1696 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 1697 1698 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 1699 1700 if (tdelta == 0) 1701 scale = 1.0; 1702 else 1703 scale = (double)NANOSEC / tdelta; 1704 1705 /* only toplevel vdevs have capacity stats */ 1706 if (newvs->vs_space == 0) { 1707 (void) printf(" - -"); 1708 } else { 1709 print_one_stat(newvs->vs_alloc); 1710 print_one_stat(newvs->vs_space - newvs->vs_alloc); 1711 } 1712 1713 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 1714 oldvs->vs_ops[ZIO_TYPE_READ]))); 1715 1716 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 1717 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 1718 1719 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 1720 oldvs->vs_bytes[ZIO_TYPE_READ]))); 1721 1722 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 1723 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 1724 1725 (void) printf("\n"); 1726 1727 if (!cb->cb_verbose) 1728 return; 1729 1730 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 1731 &newchild, &children) != 0) 1732 return; 1733 1734 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 1735 &oldchild, &c) != 0) 1736 return; 1737 1738 for (c = 0; c < children; c++) { 1739 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]); 1740 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1741 newchild[c], cb, depth + 2); 1742 free(vname); 1743 } 1744 1745 /* 1746 * Include level 2 ARC devices in iostat output 1747 */ 1748 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 1749 &newchild, &children) != 0) 1750 return; 1751 1752 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 1753 &oldchild, &c) != 0) 1754 return; 1755 1756 if (children > 0) { 1757 (void) printf("%-*s - - - - - " 1758 "-\n", cb->cb_namewidth, "cache"); 1759 for (c = 0; c < children; c++) { 1760 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]); 1761 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1762 newchild[c], cb, depth + 2); 1763 free(vname); 1764 } 1765 } 1766 } 1767 1768 static int 1769 refresh_iostat(zpool_handle_t *zhp, void *data) 1770 { 1771 iostat_cbdata_t *cb = data; 1772 boolean_t missing; 1773 1774 /* 1775 * If the pool has disappeared, remove it from the list and continue. 1776 */ 1777 if (zpool_refresh_stats(zhp, &missing) != 0) 1778 return (-1); 1779 1780 if (missing) 1781 pool_list_remove(cb->cb_list, zhp); 1782 1783 return (0); 1784 } 1785 1786 /* 1787 * Callback to print out the iostats for the given pool. 1788 */ 1789 int 1790 print_iostat(zpool_handle_t *zhp, void *data) 1791 { 1792 iostat_cbdata_t *cb = data; 1793 nvlist_t *oldconfig, *newconfig; 1794 nvlist_t *oldnvroot, *newnvroot; 1795 1796 newconfig = zpool_get_config(zhp, &oldconfig); 1797 1798 if (cb->cb_iteration == 1) 1799 oldconfig = NULL; 1800 1801 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 1802 &newnvroot) == 0); 1803 1804 if (oldconfig == NULL) 1805 oldnvroot = NULL; 1806 else 1807 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 1808 &oldnvroot) == 0); 1809 1810 /* 1811 * Print out the statistics for the pool. 1812 */ 1813 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 1814 1815 if (cb->cb_verbose) 1816 print_iostat_separator(cb); 1817 1818 return (0); 1819 } 1820 1821 int 1822 get_namewidth(zpool_handle_t *zhp, void *data) 1823 { 1824 iostat_cbdata_t *cb = data; 1825 nvlist_t *config, *nvroot; 1826 1827 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 1828 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1829 &nvroot) == 0); 1830 if (!cb->cb_verbose) 1831 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 1832 else 1833 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); 1834 } 1835 1836 /* 1837 * The width must fall into the range [10,38]. The upper limit is the 1838 * maximum we can have and still fit in 80 columns. 1839 */ 1840 if (cb->cb_namewidth < 10) 1841 cb->cb_namewidth = 10; 1842 if (cb->cb_namewidth > 38) 1843 cb->cb_namewidth = 38; 1844 1845 return (0); 1846 } 1847 1848 /* 1849 * zpool iostat [-v] [pool] ... [interval [count]] 1850 * 1851 * -v Display statistics for individual vdevs 1852 * 1853 * This command can be tricky because we want to be able to deal with pool 1854 * creation/destruction as well as vdev configuration changes. The bulk of this 1855 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 1856 * on pool_list_update() to detect the addition of new pools. Configuration 1857 * changes are all handled within libzfs. 1858 */ 1859 int 1860 zpool_do_iostat(int argc, char **argv) 1861 { 1862 int c; 1863 int ret; 1864 int npools; 1865 unsigned long interval = 0, count = 0; 1866 zpool_list_t *list; 1867 boolean_t verbose = B_FALSE; 1868 iostat_cbdata_t cb; 1869 1870 /* check options */ 1871 while ((c = getopt(argc, argv, "v")) != -1) { 1872 switch (c) { 1873 case 'v': 1874 verbose = B_TRUE; 1875 break; 1876 case '?': 1877 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1878 optopt); 1879 usage(B_FALSE); 1880 } 1881 } 1882 1883 argc -= optind; 1884 argv += optind; 1885 1886 /* 1887 * Determine if the last argument is an integer or a pool name 1888 */ 1889 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1890 char *end; 1891 1892 errno = 0; 1893 interval = strtoul(argv[argc - 1], &end, 10); 1894 1895 if (*end == '\0' && errno == 0) { 1896 if (interval == 0) { 1897 (void) fprintf(stderr, gettext("interval " 1898 "cannot be zero\n")); 1899 usage(B_FALSE); 1900 } 1901 1902 /* 1903 * Ignore the last parameter 1904 */ 1905 argc--; 1906 } else { 1907 /* 1908 * If this is not a valid number, just plow on. The 1909 * user will get a more informative error message later 1910 * on. 1911 */ 1912 interval = 0; 1913 } 1914 } 1915 1916 /* 1917 * If the last argument is also an integer, then we have both a count 1918 * and an integer. 1919 */ 1920 if (argc > 0 && isdigit(argv[argc - 1][0])) { 1921 char *end; 1922 1923 errno = 0; 1924 count = interval; 1925 interval = strtoul(argv[argc - 1], &end, 10); 1926 1927 if (*end == '\0' && errno == 0) { 1928 if (interval == 0) { 1929 (void) fprintf(stderr, gettext("interval " 1930 "cannot be zero\n")); 1931 usage(B_FALSE); 1932 } 1933 1934 /* 1935 * Ignore the last parameter 1936 */ 1937 argc--; 1938 } else { 1939 interval = 0; 1940 } 1941 } 1942 1943 /* 1944 * Construct the list of all interesting pools. 1945 */ 1946 ret = 0; 1947 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 1948 return (1); 1949 1950 if (pool_list_count(list) == 0 && argc != 0) { 1951 pool_list_free(list); 1952 return (1); 1953 } 1954 1955 if (pool_list_count(list) == 0 && interval == 0) { 1956 pool_list_free(list); 1957 (void) fprintf(stderr, gettext("no pools available\n")); 1958 return (1); 1959 } 1960 1961 /* 1962 * Enter the main iostat loop. 1963 */ 1964 cb.cb_list = list; 1965 cb.cb_verbose = verbose; 1966 cb.cb_iteration = 0; 1967 cb.cb_namewidth = 0; 1968 1969 for (;;) { 1970 pool_list_update(list); 1971 1972 if ((npools = pool_list_count(list)) == 0) 1973 break; 1974 1975 /* 1976 * Refresh all statistics. This is done as an explicit step 1977 * before calculating the maximum name width, so that any 1978 * configuration changes are properly accounted for. 1979 */ 1980 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 1981 1982 /* 1983 * Iterate over all pools to determine the maximum width 1984 * for the pool / device name column across all pools. 1985 */ 1986 cb.cb_namewidth = 0; 1987 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 1988 1989 /* 1990 * If it's the first time, or verbose mode, print the header. 1991 */ 1992 if (++cb.cb_iteration == 1 || verbose) 1993 print_iostat_header(&cb); 1994 1995 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 1996 1997 /* 1998 * If there's more than one pool, and we're not in verbose mode 1999 * (which prints a separator for us), then print a separator. 2000 */ 2001 if (npools > 1 && !verbose) 2002 print_iostat_separator(&cb); 2003 2004 if (verbose) 2005 (void) printf("\n"); 2006 2007 /* 2008 * Flush the output so that redirection to a file isn't buffered 2009 * indefinitely. 2010 */ 2011 (void) fflush(stdout); 2012 2013 if (interval == 0) 2014 break; 2015 2016 if (count != 0 && --count == 0) 2017 break; 2018 2019 (void) sleep(interval); 2020 } 2021 2022 pool_list_free(list); 2023 2024 return (ret); 2025 } 2026 2027 typedef struct list_cbdata { 2028 boolean_t cb_scripted; 2029 boolean_t cb_first; 2030 zprop_list_t *cb_proplist; 2031 } list_cbdata_t; 2032 2033 /* 2034 * Given a list of columns to display, output appropriate headers for each one. 2035 */ 2036 static void 2037 print_header(zprop_list_t *pl) 2038 { 2039 const char *header; 2040 boolean_t first = B_TRUE; 2041 boolean_t right_justify; 2042 2043 for (; pl != NULL; pl = pl->pl_next) { 2044 if (pl->pl_prop == ZPROP_INVAL) 2045 continue; 2046 2047 if (!first) 2048 (void) printf(" "); 2049 else 2050 first = B_FALSE; 2051 2052 header = zpool_prop_column_name(pl->pl_prop); 2053 right_justify = zpool_prop_align_right(pl->pl_prop); 2054 2055 if (pl->pl_next == NULL && !right_justify) 2056 (void) printf("%s", header); 2057 else if (right_justify) 2058 (void) printf("%*s", pl->pl_width, header); 2059 else 2060 (void) printf("%-*s", pl->pl_width, header); 2061 } 2062 2063 (void) printf("\n"); 2064 } 2065 2066 /* 2067 * Given a pool and a list of properties, print out all the properties according 2068 * to the described layout. 2069 */ 2070 static void 2071 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted) 2072 { 2073 boolean_t first = B_TRUE; 2074 char property[ZPOOL_MAXPROPLEN]; 2075 char *propstr; 2076 boolean_t right_justify; 2077 int width; 2078 2079 for (; pl != NULL; pl = pl->pl_next) { 2080 if (!first) { 2081 if (scripted) 2082 (void) printf("\t"); 2083 else 2084 (void) printf(" "); 2085 } else { 2086 first = B_FALSE; 2087 } 2088 2089 right_justify = B_FALSE; 2090 if (pl->pl_prop != ZPROP_INVAL) { 2091 if (zpool_get_prop(zhp, pl->pl_prop, property, 2092 sizeof (property), NULL) != 0) 2093 propstr = "-"; 2094 else 2095 propstr = property; 2096 2097 right_justify = zpool_prop_align_right(pl->pl_prop); 2098 } else { 2099 propstr = "-"; 2100 } 2101 2102 width = pl->pl_width; 2103 2104 /* 2105 * If this is being called in scripted mode, or if this is the 2106 * last column and it is left-justified, don't include a width 2107 * format specifier. 2108 */ 2109 if (scripted || (pl->pl_next == NULL && !right_justify)) 2110 (void) printf("%s", propstr); 2111 else if (right_justify) 2112 (void) printf("%*s", width, propstr); 2113 else 2114 (void) printf("%-*s", width, propstr); 2115 } 2116 2117 (void) printf("\n"); 2118 } 2119 2120 /* 2121 * Generic callback function to list a pool. 2122 */ 2123 int 2124 list_callback(zpool_handle_t *zhp, void *data) 2125 { 2126 list_cbdata_t *cbp = data; 2127 2128 if (cbp->cb_first) { 2129 if (!cbp->cb_scripted) 2130 print_header(cbp->cb_proplist); 2131 cbp->cb_first = B_FALSE; 2132 } 2133 2134 print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted); 2135 2136 return (0); 2137 } 2138 2139 /* 2140 * zpool list [-H] [-o prop[,prop]*] [pool] ... 2141 * 2142 * -H Scripted mode. Don't display headers, and separate properties 2143 * by a single tab. 2144 * -o List of properties to display. Defaults to 2145 * "name,size,used,available,capacity,health,altroot" 2146 * 2147 * List all pools in the system, whether or not they're healthy. Output space 2148 * statistics for each one, as well as health status summary. 2149 */ 2150 int 2151 zpool_do_list(int argc, char **argv) 2152 { 2153 int c; 2154 int ret; 2155 list_cbdata_t cb = { 0 }; 2156 static char default_props[] = 2157 "name,size,used,available,capacity,health,altroot"; 2158 char *props = default_props; 2159 2160 /* check options */ 2161 while ((c = getopt(argc, argv, ":Ho:")) != -1) { 2162 switch (c) { 2163 case 'H': 2164 cb.cb_scripted = B_TRUE; 2165 break; 2166 case 'o': 2167 props = optarg; 2168 break; 2169 case ':': 2170 (void) fprintf(stderr, gettext("missing argument for " 2171 "'%c' option\n"), optopt); 2172 usage(B_FALSE); 2173 break; 2174 case '?': 2175 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2176 optopt); 2177 usage(B_FALSE); 2178 } 2179 } 2180 2181 argc -= optind; 2182 argv += optind; 2183 2184 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 2185 usage(B_FALSE); 2186 2187 cb.cb_first = B_TRUE; 2188 2189 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 2190 list_callback, &cb); 2191 2192 zprop_free_list(cb.cb_proplist); 2193 2194 if (argc == 0 && cb.cb_first && !cb.cb_scripted) { 2195 (void) printf(gettext("no pools available\n")); 2196 return (0); 2197 } 2198 2199 return (ret); 2200 } 2201 2202 static nvlist_t * 2203 zpool_get_vdev_by_name(nvlist_t *nv, char *name) 2204 { 2205 nvlist_t **child; 2206 uint_t c, children; 2207 nvlist_t *match; 2208 char *path; 2209 2210 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2211 &child, &children) != 0) { 2212 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2213 if (strncmp(name, "/dev/dsk/", 9) == 0) 2214 name += 9; 2215 if (strncmp(path, "/dev/dsk/", 9) == 0) 2216 path += 9; 2217 if (strcmp(name, path) == 0) 2218 return (nv); 2219 return (NULL); 2220 } 2221 2222 for (c = 0; c < children; c++) 2223 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 2224 return (match); 2225 2226 return (NULL); 2227 } 2228 2229 static int 2230 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 2231 { 2232 boolean_t force = B_FALSE; 2233 int c; 2234 nvlist_t *nvroot; 2235 char *poolname, *old_disk, *new_disk; 2236 zpool_handle_t *zhp; 2237 int ret; 2238 2239 /* check options */ 2240 while ((c = getopt(argc, argv, "f")) != -1) { 2241 switch (c) { 2242 case 'f': 2243 force = B_TRUE; 2244 break; 2245 case '?': 2246 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2247 optopt); 2248 usage(B_FALSE); 2249 } 2250 } 2251 2252 argc -= optind; 2253 argv += optind; 2254 2255 /* get pool name and check number of arguments */ 2256 if (argc < 1) { 2257 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2258 usage(B_FALSE); 2259 } 2260 2261 poolname = argv[0]; 2262 2263 if (argc < 2) { 2264 (void) fprintf(stderr, 2265 gettext("missing <device> specification\n")); 2266 usage(B_FALSE); 2267 } 2268 2269 old_disk = argv[1]; 2270 2271 if (argc < 3) { 2272 if (!replacing) { 2273 (void) fprintf(stderr, 2274 gettext("missing <new_device> specification\n")); 2275 usage(B_FALSE); 2276 } 2277 new_disk = old_disk; 2278 argc -= 1; 2279 argv += 1; 2280 } else { 2281 new_disk = argv[2]; 2282 argc -= 2; 2283 argv += 2; 2284 } 2285 2286 if (argc > 1) { 2287 (void) fprintf(stderr, gettext("too many arguments\n")); 2288 usage(B_FALSE); 2289 } 2290 2291 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2292 return (1); 2293 2294 if (zpool_get_config(zhp, NULL) == NULL) { 2295 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 2296 poolname); 2297 zpool_close(zhp); 2298 return (1); 2299 } 2300 2301 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, argc, argv); 2302 if (nvroot == NULL) { 2303 zpool_close(zhp); 2304 return (1); 2305 } 2306 2307 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 2308 2309 nvlist_free(nvroot); 2310 zpool_close(zhp); 2311 2312 return (ret); 2313 } 2314 2315 /* 2316 * zpool replace [-f] <pool> <device> <new_device> 2317 * 2318 * -f Force attach, even if <new_device> appears to be in use. 2319 * 2320 * Replace <device> with <new_device>. 2321 */ 2322 /* ARGSUSED */ 2323 int 2324 zpool_do_replace(int argc, char **argv) 2325 { 2326 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 2327 } 2328 2329 /* 2330 * zpool attach [-f] <pool> <device> <new_device> 2331 * 2332 * -f Force attach, even if <new_device> appears to be in use. 2333 * 2334 * Attach <new_device> to the mirror containing <device>. If <device> is not 2335 * part of a mirror, then <device> will be transformed into a mirror of 2336 * <device> and <new_device>. In either case, <new_device> will begin life 2337 * with a DTL of [0, now], and will immediately begin to resilver itself. 2338 */ 2339 int 2340 zpool_do_attach(int argc, char **argv) 2341 { 2342 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 2343 } 2344 2345 /* 2346 * zpool detach [-f] <pool> <device> 2347 * 2348 * -f Force detach of <device>, even if DTLs argue against it 2349 * (not supported yet) 2350 * 2351 * Detach a device from a mirror. The operation will be refused if <device> 2352 * is the last device in the mirror, or if the DTLs indicate that this device 2353 * has the only valid copy of some data. 2354 */ 2355 /* ARGSUSED */ 2356 int 2357 zpool_do_detach(int argc, char **argv) 2358 { 2359 int c; 2360 char *poolname, *path; 2361 zpool_handle_t *zhp; 2362 int ret; 2363 2364 /* check options */ 2365 while ((c = getopt(argc, argv, "f")) != -1) { 2366 switch (c) { 2367 case 'f': 2368 case '?': 2369 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2370 optopt); 2371 usage(B_FALSE); 2372 } 2373 } 2374 2375 argc -= optind; 2376 argv += optind; 2377 2378 /* get pool name and check number of arguments */ 2379 if (argc < 1) { 2380 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2381 usage(B_FALSE); 2382 } 2383 2384 if (argc < 2) { 2385 (void) fprintf(stderr, 2386 gettext("missing <device> specification\n")); 2387 usage(B_FALSE); 2388 } 2389 2390 poolname = argv[0]; 2391 path = argv[1]; 2392 2393 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2394 return (1); 2395 2396 ret = zpool_vdev_detach(zhp, path); 2397 2398 zpool_close(zhp); 2399 2400 return (ret); 2401 } 2402 2403 /* 2404 * zpool online <pool> <device> ... 2405 */ 2406 int 2407 zpool_do_online(int argc, char **argv) 2408 { 2409 int c, i; 2410 char *poolname; 2411 zpool_handle_t *zhp; 2412 int ret = 0; 2413 vdev_state_t newstate; 2414 2415 /* check options */ 2416 while ((c = getopt(argc, argv, "t")) != -1) { 2417 switch (c) { 2418 case 't': 2419 case '?': 2420 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2421 optopt); 2422 usage(B_FALSE); 2423 } 2424 } 2425 2426 argc -= optind; 2427 argv += optind; 2428 2429 /* get pool name and check number of arguments */ 2430 if (argc < 1) { 2431 (void) fprintf(stderr, gettext("missing pool name\n")); 2432 usage(B_FALSE); 2433 } 2434 if (argc < 2) { 2435 (void) fprintf(stderr, gettext("missing device name\n")); 2436 usage(B_FALSE); 2437 } 2438 2439 poolname = argv[0]; 2440 2441 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2442 return (1); 2443 2444 for (i = 1; i < argc; i++) { 2445 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) { 2446 if (newstate != VDEV_STATE_HEALTHY) { 2447 (void) printf(gettext("warning: device '%s' " 2448 "onlined, but remains in faulted state\n"), 2449 argv[i]); 2450 if (newstate == VDEV_STATE_FAULTED) 2451 (void) printf(gettext("use 'zpool " 2452 "clear' to restore a faulted " 2453 "device\n")); 2454 else 2455 (void) printf(gettext("use 'zpool " 2456 "replace' to replace devices " 2457 "that are no longer present\n")); 2458 } 2459 } else { 2460 ret = 1; 2461 } 2462 } 2463 2464 zpool_close(zhp); 2465 2466 return (ret); 2467 } 2468 2469 /* 2470 * zpool offline [-ft] <pool> <device> ... 2471 * 2472 * -f Force the device into the offline state, even if doing 2473 * so would appear to compromise pool availability. 2474 * (not supported yet) 2475 * 2476 * -t Only take the device off-line temporarily. The offline 2477 * state will not be persistent across reboots. 2478 */ 2479 /* ARGSUSED */ 2480 int 2481 zpool_do_offline(int argc, char **argv) 2482 { 2483 int c, i; 2484 char *poolname; 2485 zpool_handle_t *zhp; 2486 int ret = 0; 2487 boolean_t istmp = B_FALSE; 2488 2489 /* check options */ 2490 while ((c = getopt(argc, argv, "ft")) != -1) { 2491 switch (c) { 2492 case 't': 2493 istmp = B_TRUE; 2494 break; 2495 case 'f': 2496 case '?': 2497 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2498 optopt); 2499 usage(B_FALSE); 2500 } 2501 } 2502 2503 argc -= optind; 2504 argv += optind; 2505 2506 /* get pool name and check number of arguments */ 2507 if (argc < 1) { 2508 (void) fprintf(stderr, gettext("missing pool name\n")); 2509 usage(B_FALSE); 2510 } 2511 if (argc < 2) { 2512 (void) fprintf(stderr, gettext("missing device name\n")); 2513 usage(B_FALSE); 2514 } 2515 2516 poolname = argv[0]; 2517 2518 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2519 return (1); 2520 2521 for (i = 1; i < argc; i++) { 2522 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 2523 ret = 1; 2524 } 2525 2526 zpool_close(zhp); 2527 2528 return (ret); 2529 } 2530 2531 /* 2532 * zpool clear <pool> [device] 2533 * 2534 * Clear all errors associated with a pool or a particular device. 2535 */ 2536 int 2537 zpool_do_clear(int argc, char **argv) 2538 { 2539 int ret = 0; 2540 zpool_handle_t *zhp; 2541 char *pool, *device; 2542 2543 if (argc < 2) { 2544 (void) fprintf(stderr, gettext("missing pool name\n")); 2545 usage(B_FALSE); 2546 } 2547 2548 if (argc > 3) { 2549 (void) fprintf(stderr, gettext("too many arguments\n")); 2550 usage(B_FALSE); 2551 } 2552 2553 pool = argv[1]; 2554 device = argc == 3 ? argv[2] : NULL; 2555 2556 if ((zhp = zpool_open(g_zfs, pool)) == NULL) 2557 return (1); 2558 2559 if (zpool_clear(zhp, device) != 0) 2560 ret = 1; 2561 2562 zpool_close(zhp); 2563 2564 return (ret); 2565 } 2566 2567 typedef struct scrub_cbdata { 2568 int cb_type; 2569 int cb_argc; 2570 char **cb_argv; 2571 } scrub_cbdata_t; 2572 2573 int 2574 scrub_callback(zpool_handle_t *zhp, void *data) 2575 { 2576 scrub_cbdata_t *cb = data; 2577 int err; 2578 2579 /* 2580 * Ignore faulted pools. 2581 */ 2582 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2583 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 2584 "currently unavailable\n"), zpool_get_name(zhp)); 2585 return (1); 2586 } 2587 2588 err = zpool_scrub(zhp, cb->cb_type); 2589 2590 return (err != 0); 2591 } 2592 2593 /* 2594 * zpool scrub [-s] <pool> ... 2595 * 2596 * -s Stop. Stops any in-progress scrub. 2597 */ 2598 int 2599 zpool_do_scrub(int argc, char **argv) 2600 { 2601 int c; 2602 scrub_cbdata_t cb; 2603 2604 cb.cb_type = POOL_SCRUB_EVERYTHING; 2605 2606 /* check options */ 2607 while ((c = getopt(argc, argv, "s")) != -1) { 2608 switch (c) { 2609 case 's': 2610 cb.cb_type = POOL_SCRUB_NONE; 2611 break; 2612 case '?': 2613 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2614 optopt); 2615 usage(B_FALSE); 2616 } 2617 } 2618 2619 cb.cb_argc = argc; 2620 cb.cb_argv = argv; 2621 argc -= optind; 2622 argv += optind; 2623 2624 if (argc < 1) { 2625 (void) fprintf(stderr, gettext("missing pool name argument\n")); 2626 usage(B_FALSE); 2627 } 2628 2629 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 2630 } 2631 2632 typedef struct status_cbdata { 2633 int cb_count; 2634 boolean_t cb_allpools; 2635 boolean_t cb_verbose; 2636 boolean_t cb_explain; 2637 boolean_t cb_first; 2638 } status_cbdata_t; 2639 2640 /* 2641 * Print out detailed scrub status. 2642 */ 2643 void 2644 print_scrub_status(nvlist_t *nvroot) 2645 { 2646 vdev_stat_t *vs; 2647 uint_t vsc; 2648 time_t start, end, now; 2649 double fraction_done; 2650 uint64_t examined, total, minutes_left, minutes_taken; 2651 char *scrub_type; 2652 2653 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2654 (uint64_t **)&vs, &vsc) == 0); 2655 2656 /* 2657 * If there's never been a scrub, there's not much to say. 2658 */ 2659 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2660 (void) printf(gettext("none requested\n")); 2661 return; 2662 } 2663 2664 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2665 "resilver" : "scrub"; 2666 2667 start = vs->vs_scrub_start; 2668 end = vs->vs_scrub_end; 2669 now = time(NULL); 2670 examined = vs->vs_scrub_examined; 2671 total = vs->vs_alloc; 2672 2673 if (end != 0) { 2674 minutes_taken = (uint64_t)((end - start) / 60); 2675 2676 (void) printf(gettext("%s %s after %lluh%um with %llu errors " 2677 "on %s"), 2678 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 2679 (u_longlong_t)(minutes_taken / 60), 2680 (uint_t)(minutes_taken % 60), 2681 (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2682 return; 2683 } 2684 2685 if (examined == 0) 2686 examined = 1; 2687 if (examined > total) 2688 total = examined; 2689 2690 fraction_done = (double)examined / total; 2691 minutes_left = (uint64_t)((now - start) * 2692 (1 - fraction_done) / fraction_done / 60); 2693 minutes_taken = (uint64_t)((now - start) / 60); 2694 2695 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, " 2696 "%lluh%um to go\n"), 2697 scrub_type, (u_longlong_t)(minutes_taken / 60), 2698 (uint_t)(minutes_taken % 60), 100 * fraction_done, 2699 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2700 } 2701 2702 typedef struct spare_cbdata { 2703 uint64_t cb_guid; 2704 zpool_handle_t *cb_zhp; 2705 } spare_cbdata_t; 2706 2707 static boolean_t 2708 find_vdev(nvlist_t *nv, uint64_t search) 2709 { 2710 uint64_t guid; 2711 nvlist_t **child; 2712 uint_t c, children; 2713 2714 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 2715 search == guid) 2716 return (B_TRUE); 2717 2718 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2719 &child, &children) == 0) { 2720 for (c = 0; c < children; c++) 2721 if (find_vdev(child[c], search)) 2722 return (B_TRUE); 2723 } 2724 2725 return (B_FALSE); 2726 } 2727 2728 static int 2729 find_spare(zpool_handle_t *zhp, void *data) 2730 { 2731 spare_cbdata_t *cbp = data; 2732 nvlist_t *config, *nvroot; 2733 2734 config = zpool_get_config(zhp, NULL); 2735 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2736 &nvroot) == 0); 2737 2738 if (find_vdev(nvroot, cbp->cb_guid)) { 2739 cbp->cb_zhp = zhp; 2740 return (1); 2741 } 2742 2743 zpool_close(zhp); 2744 return (0); 2745 } 2746 2747 /* 2748 * Print out configuration state as requested by status_callback. 2749 */ 2750 void 2751 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 2752 int namewidth, int depth, boolean_t isspare, boolean_t print_logs) 2753 { 2754 nvlist_t **child; 2755 uint_t c, children; 2756 vdev_stat_t *vs; 2757 char rbuf[6], wbuf[6], cbuf[6], repaired[7]; 2758 char *vname; 2759 uint64_t notpresent; 2760 spare_cbdata_t cb; 2761 char *state; 2762 2763 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 2764 (uint64_t **)&vs, &c) == 0); 2765 2766 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2767 &child, &children) != 0) 2768 children = 0; 2769 2770 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2771 if (isspare) { 2772 /* 2773 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 2774 * online drives. 2775 */ 2776 if (vs->vs_aux == VDEV_AUX_SPARED) 2777 state = "INUSE"; 2778 else if (vs->vs_state == VDEV_STATE_HEALTHY) 2779 state = "AVAIL"; 2780 } 2781 2782 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 2783 name, state); 2784 2785 if (!isspare) { 2786 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2787 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2788 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 2789 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 2790 } 2791 2792 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 2793 ¬present) == 0) { 2794 char *path; 2795 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2796 (void) printf(" was %s", path); 2797 } else if (vs->vs_aux != 0) { 2798 (void) printf(" "); 2799 2800 switch (vs->vs_aux) { 2801 case VDEV_AUX_OPEN_FAILED: 2802 (void) printf(gettext("cannot open")); 2803 break; 2804 2805 case VDEV_AUX_BAD_GUID_SUM: 2806 (void) printf(gettext("missing device")); 2807 break; 2808 2809 case VDEV_AUX_NO_REPLICAS: 2810 (void) printf(gettext("insufficient replicas")); 2811 break; 2812 2813 case VDEV_AUX_VERSION_NEWER: 2814 (void) printf(gettext("newer version")); 2815 break; 2816 2817 case VDEV_AUX_SPARED: 2818 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 2819 &cb.cb_guid) == 0); 2820 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 2821 if (strcmp(zpool_get_name(cb.cb_zhp), 2822 zpool_get_name(zhp)) == 0) 2823 (void) printf(gettext("currently in " 2824 "use")); 2825 else 2826 (void) printf(gettext("in use by " 2827 "pool '%s'"), 2828 zpool_get_name(cb.cb_zhp)); 2829 zpool_close(cb.cb_zhp); 2830 } else { 2831 (void) printf(gettext("currently in use")); 2832 } 2833 break; 2834 2835 case VDEV_AUX_ERR_EXCEEDED: 2836 (void) printf(gettext("too many errors")); 2837 break; 2838 2839 case VDEV_AUX_IO_FAILURE: 2840 (void) printf(gettext("experienced I/O failures")); 2841 break; 2842 2843 default: 2844 (void) printf(gettext("corrupted data")); 2845 break; 2846 } 2847 } else if (vs->vs_scrub_repaired != 0 && children == 0) { 2848 /* 2849 * Report bytes resilvered/repaired on leaf devices. 2850 */ 2851 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 2852 (void) printf(gettext(" %s %s"), repaired, 2853 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2854 "resilvered" : "repaired"); 2855 } 2856 2857 (void) printf("\n"); 2858 2859 for (c = 0; c < children; c++) { 2860 uint64_t is_log = B_FALSE; 2861 2862 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2863 &is_log); 2864 if ((is_log && !print_logs) || (!is_log && print_logs)) 2865 continue; 2866 vname = zpool_vdev_name(g_zfs, zhp, child[c]); 2867 print_status_config(zhp, vname, child[c], 2868 namewidth, depth + 2, isspare, B_FALSE); 2869 free(vname); 2870 } 2871 } 2872 2873 static void 2874 print_error_log(zpool_handle_t *zhp) 2875 { 2876 nvlist_t *nverrlist = NULL; 2877 nvpair_t *elem; 2878 char *pathname; 2879 size_t len = MAXPATHLEN * 2; 2880 2881 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 2882 (void) printf("errors: List of errors unavailable " 2883 "(insufficient privileges)\n"); 2884 return; 2885 } 2886 2887 (void) printf("errors: Permanent errors have been " 2888 "detected in the following files:\n\n"); 2889 2890 pathname = safe_malloc(len); 2891 elem = NULL; 2892 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 2893 nvlist_t *nv; 2894 uint64_t dsobj, obj; 2895 2896 verify(nvpair_value_nvlist(elem, &nv) == 0); 2897 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 2898 &dsobj) == 0); 2899 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 2900 &obj) == 0); 2901 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 2902 (void) printf("%7s %s\n", "", pathname); 2903 } 2904 free(pathname); 2905 nvlist_free(nverrlist); 2906 } 2907 2908 static void 2909 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 2910 int namewidth) 2911 { 2912 uint_t i; 2913 char *name; 2914 2915 if (nspares == 0) 2916 return; 2917 2918 (void) printf(gettext("\tspares\n")); 2919 2920 for (i = 0; i < nspares; i++) { 2921 name = zpool_vdev_name(g_zfs, zhp, spares[i]); 2922 print_status_config(zhp, name, spares[i], 2923 namewidth, 2, B_TRUE, B_FALSE); 2924 free(name); 2925 } 2926 } 2927 2928 static void 2929 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 2930 int namewidth) 2931 { 2932 uint_t i; 2933 char *name; 2934 2935 if (nl2cache == 0) 2936 return; 2937 2938 (void) printf(gettext("\tcache\n")); 2939 2940 for (i = 0; i < nl2cache; i++) { 2941 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]); 2942 print_status_config(zhp, name, l2cache[i], 2943 namewidth, 2, B_FALSE, B_FALSE); 2944 free(name); 2945 } 2946 } 2947 2948 /* 2949 * Display a summary of pool status. Displays a summary such as: 2950 * 2951 * pool: tank 2952 * status: DEGRADED 2953 * reason: One or more devices ... 2954 * see: http://www.sun.com/msg/ZFS-xxxx-01 2955 * config: 2956 * mirror DEGRADED 2957 * c1t0d0 OK 2958 * c2t0d0 UNAVAIL 2959 * 2960 * When given the '-v' option, we print out the complete config. If the '-e' 2961 * option is specified, then we print out error rate information as well. 2962 */ 2963 int 2964 status_callback(zpool_handle_t *zhp, void *data) 2965 { 2966 status_cbdata_t *cbp = data; 2967 nvlist_t *config, *nvroot; 2968 char *msgid; 2969 int reason; 2970 const char *health; 2971 uint_t c; 2972 vdev_stat_t *vs; 2973 2974 config = zpool_get_config(zhp, NULL); 2975 reason = zpool_get_status(zhp, &msgid); 2976 2977 cbp->cb_count++; 2978 2979 /* 2980 * If we were given 'zpool status -x', only report those pools with 2981 * problems. 2982 */ 2983 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) { 2984 if (!cbp->cb_allpools) { 2985 (void) printf(gettext("pool '%s' is healthy\n"), 2986 zpool_get_name(zhp)); 2987 if (cbp->cb_first) 2988 cbp->cb_first = B_FALSE; 2989 } 2990 return (0); 2991 } 2992 2993 if (cbp->cb_first) 2994 cbp->cb_first = B_FALSE; 2995 else 2996 (void) printf("\n"); 2997 2998 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2999 &nvroot) == 0); 3000 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 3001 (uint64_t **)&vs, &c) == 0); 3002 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 3003 3004 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 3005 (void) printf(gettext(" state: %s\n"), health); 3006 3007 switch (reason) { 3008 case ZPOOL_STATUS_MISSING_DEV_R: 3009 (void) printf(gettext("status: One or more devices could not " 3010 "be opened. Sufficient replicas exist for\n\tthe pool to " 3011 "continue functioning in a degraded state.\n")); 3012 (void) printf(gettext("action: Attach the missing device and " 3013 "online it using 'zpool online'.\n")); 3014 break; 3015 3016 case ZPOOL_STATUS_MISSING_DEV_NR: 3017 (void) printf(gettext("status: One or more devices could not " 3018 "be opened. There are insufficient\n\treplicas for the " 3019 "pool to continue functioning.\n")); 3020 (void) printf(gettext("action: Attach the missing device and " 3021 "online it using 'zpool online'.\n")); 3022 break; 3023 3024 case ZPOOL_STATUS_CORRUPT_LABEL_R: 3025 (void) printf(gettext("status: One or more devices could not " 3026 "be used because the label is missing or\n\tinvalid. " 3027 "Sufficient replicas exist for the pool to continue\n\t" 3028 "functioning in a degraded state.\n")); 3029 (void) printf(gettext("action: Replace the device using " 3030 "'zpool replace'.\n")); 3031 break; 3032 3033 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 3034 (void) printf(gettext("status: One or more devices could not " 3035 "be used because the label is missing \n\tor invalid. " 3036 "There are insufficient replicas for the pool to " 3037 "continue\n\tfunctioning.\n")); 3038 (void) printf(gettext("action: Destroy and re-create the pool " 3039 "from a backup source.\n")); 3040 break; 3041 3042 case ZPOOL_STATUS_FAILING_DEV: 3043 (void) printf(gettext("status: One or more devices has " 3044 "experienced an unrecoverable error. An\n\tattempt was " 3045 "made to correct the error. Applications are " 3046 "unaffected.\n")); 3047 (void) printf(gettext("action: Determine if the device needs " 3048 "to be replaced, and clear the errors\n\tusing " 3049 "'zpool clear' or replace the device with 'zpool " 3050 "replace'.\n")); 3051 break; 3052 3053 case ZPOOL_STATUS_OFFLINE_DEV: 3054 (void) printf(gettext("status: One or more devices has " 3055 "been taken offline by the administrator.\n\tSufficient " 3056 "replicas exist for the pool to continue functioning in " 3057 "a\n\tdegraded state.\n")); 3058 (void) printf(gettext("action: Online the device using " 3059 "'zpool online' or replace the device with\n\t'zpool " 3060 "replace'.\n")); 3061 break; 3062 3063 case ZPOOL_STATUS_RESILVERING: 3064 (void) printf(gettext("status: One or more devices is " 3065 "currently being resilvered. The pool will\n\tcontinue " 3066 "to function, possibly in a degraded state.\n")); 3067 (void) printf(gettext("action: Wait for the resilver to " 3068 "complete.\n")); 3069 break; 3070 3071 case ZPOOL_STATUS_CORRUPT_DATA: 3072 (void) printf(gettext("status: One or more devices has " 3073 "experienced an error resulting in data\n\tcorruption. " 3074 "Applications may be affected.\n")); 3075 (void) printf(gettext("action: Restore the file in question " 3076 "if possible. Otherwise restore the\n\tentire pool from " 3077 "backup.\n")); 3078 break; 3079 3080 case ZPOOL_STATUS_CORRUPT_POOL: 3081 (void) printf(gettext("status: The pool metadata is corrupted " 3082 "and the pool cannot be opened.\n")); 3083 (void) printf(gettext("action: Destroy and re-create the pool " 3084 "from a backup source.\n")); 3085 break; 3086 3087 case ZPOOL_STATUS_VERSION_OLDER: 3088 (void) printf(gettext("status: The pool is formatted using an " 3089 "older on-disk format. The pool can\n\tstill be used, but " 3090 "some features are unavailable.\n")); 3091 (void) printf(gettext("action: Upgrade the pool using 'zpool " 3092 "upgrade'. Once this is done, the\n\tpool will no longer " 3093 "be accessible on older software versions.\n")); 3094 break; 3095 3096 case ZPOOL_STATUS_VERSION_NEWER: 3097 (void) printf(gettext("status: The pool has been upgraded to a " 3098 "newer, incompatible on-disk version.\n\tThe pool cannot " 3099 "be accessed on this system.\n")); 3100 (void) printf(gettext("action: Access the pool from a system " 3101 "running more recent software, or\n\trestore the pool from " 3102 "backup.\n")); 3103 break; 3104 3105 case ZPOOL_STATUS_FAULTED_DEV_R: 3106 (void) printf(gettext("status: One or more devices are " 3107 "faulted in response to persistent errors.\n\tSufficient " 3108 "replicas exist for the pool to continue functioning " 3109 "in a\n\tdegraded state.\n")); 3110 (void) printf(gettext("action: Replace the faulted device, " 3111 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 3112 break; 3113 3114 case ZPOOL_STATUS_FAULTED_DEV_NR: 3115 (void) printf(gettext("status: One or more devices are " 3116 "faulted in response to persistent errors. There are " 3117 "insufficient replicas for the pool to\n\tcontinue " 3118 "functioning.\n")); 3119 (void) printf(gettext("action: Destroy and re-create the pool " 3120 "from a backup source. Manually marking the device\n" 3121 "\trepaired using 'zpool clear' may allow some data " 3122 "to be recovered.\n")); 3123 break; 3124 3125 case ZPOOL_STATUS_IO_FAILURE_WAIT: 3126 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 3127 (void) printf(gettext("status: One or more devices are " 3128 "faulted in response to IO failures.\n")); 3129 (void) printf(gettext("action: Make sure the affected devices " 3130 "are connected, then run 'zpool clear'.\n")); 3131 break; 3132 3133 default: 3134 /* 3135 * The remaining errors can't actually be generated, yet. 3136 */ 3137 assert(reason == ZPOOL_STATUS_OK); 3138 } 3139 3140 if (msgid != NULL) 3141 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 3142 msgid); 3143 3144 if (config != NULL) { 3145 int namewidth; 3146 uint64_t nerr; 3147 nvlist_t **spares, **l2cache; 3148 uint_t nspares, nl2cache; 3149 3150 3151 (void) printf(gettext(" scrub: ")); 3152 print_scrub_status(nvroot); 3153 3154 namewidth = max_width(zhp, nvroot, 0, 0); 3155 if (namewidth < 10) 3156 namewidth = 10; 3157 3158 (void) printf(gettext("config:\n\n")); 3159 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 3160 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 3161 print_status_config(zhp, zpool_get_name(zhp), nvroot, 3162 namewidth, 0, B_FALSE, B_FALSE); 3163 if (num_logs(nvroot) > 0) 3164 print_status_config(zhp, "logs", nvroot, namewidth, 0, 3165 B_FALSE, B_TRUE); 3166 3167 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 3168 &l2cache, &nl2cache) == 0) 3169 print_l2cache(zhp, l2cache, nl2cache, namewidth); 3170 3171 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 3172 &spares, &nspares) == 0) 3173 print_spares(zhp, spares, nspares, namewidth); 3174 3175 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 3176 &nerr) == 0) { 3177 nvlist_t *nverrlist = NULL; 3178 3179 /* 3180 * If the approximate error count is small, get a 3181 * precise count by fetching the entire log and 3182 * uniquifying the results. 3183 */ 3184 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 3185 zpool_get_errlog(zhp, &nverrlist) == 0) { 3186 nvpair_t *elem; 3187 3188 elem = NULL; 3189 nerr = 0; 3190 while ((elem = nvlist_next_nvpair(nverrlist, 3191 elem)) != NULL) { 3192 nerr++; 3193 } 3194 } 3195 nvlist_free(nverrlist); 3196 3197 (void) printf("\n"); 3198 3199 if (nerr == 0) 3200 (void) printf(gettext("errors: No known data " 3201 "errors\n")); 3202 else if (!cbp->cb_verbose) 3203 (void) printf(gettext("errors: %llu data " 3204 "errors, use '-v' for a list\n"), 3205 (u_longlong_t)nerr); 3206 else 3207 print_error_log(zhp); 3208 } 3209 } else { 3210 (void) printf(gettext("config: The configuration cannot be " 3211 "determined.\n")); 3212 } 3213 3214 return (0); 3215 } 3216 3217 /* 3218 * zpool status [-vx] [pool] ... 3219 * 3220 * -v Display complete error logs 3221 * -x Display only pools with potential problems 3222 * 3223 * Describes the health status of all pools or some subset. 3224 */ 3225 int 3226 zpool_do_status(int argc, char **argv) 3227 { 3228 int c; 3229 int ret; 3230 status_cbdata_t cb = { 0 }; 3231 3232 /* check options */ 3233 while ((c = getopt(argc, argv, "vx")) != -1) { 3234 switch (c) { 3235 case 'v': 3236 cb.cb_verbose = B_TRUE; 3237 break; 3238 case 'x': 3239 cb.cb_explain = B_TRUE; 3240 break; 3241 case '?': 3242 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3243 optopt); 3244 usage(B_FALSE); 3245 } 3246 } 3247 3248 argc -= optind; 3249 argv += optind; 3250 3251 cb.cb_first = B_TRUE; 3252 3253 if (argc == 0) 3254 cb.cb_allpools = B_TRUE; 3255 3256 ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb); 3257 3258 if (argc == 0 && cb.cb_count == 0) 3259 (void) printf(gettext("no pools available\n")); 3260 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 3261 (void) printf(gettext("all pools are healthy\n")); 3262 3263 return (ret); 3264 } 3265 3266 typedef struct upgrade_cbdata { 3267 int cb_all; 3268 int cb_first; 3269 int cb_newer; 3270 int cb_argc; 3271 uint64_t cb_version; 3272 char **cb_argv; 3273 } upgrade_cbdata_t; 3274 3275 static int 3276 upgrade_cb(zpool_handle_t *zhp, void *arg) 3277 { 3278 upgrade_cbdata_t *cbp = arg; 3279 nvlist_t *config; 3280 uint64_t version; 3281 int ret = 0; 3282 3283 config = zpool_get_config(zhp, NULL); 3284 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 3285 &version) == 0); 3286 3287 if (!cbp->cb_newer && version < SPA_VERSION) { 3288 if (!cbp->cb_all) { 3289 if (cbp->cb_first) { 3290 (void) printf(gettext("The following pools are " 3291 "out of date, and can be upgraded. After " 3292 "being\nupgraded, these pools will no " 3293 "longer be accessible by older software " 3294 "versions.\n\n")); 3295 (void) printf(gettext("VER POOL\n")); 3296 (void) printf(gettext("--- ------------\n")); 3297 cbp->cb_first = B_FALSE; 3298 } 3299 3300 (void) printf("%2llu %s\n", (u_longlong_t)version, 3301 zpool_get_name(zhp)); 3302 } else { 3303 cbp->cb_first = B_FALSE; 3304 ret = zpool_upgrade(zhp, cbp->cb_version); 3305 if (!ret) { 3306 (void) printf(gettext("Successfully upgraded " 3307 "'%s'\n\n"), zpool_get_name(zhp)); 3308 } 3309 } 3310 } else if (cbp->cb_newer && version > SPA_VERSION) { 3311 assert(!cbp->cb_all); 3312 3313 if (cbp->cb_first) { 3314 (void) printf(gettext("The following pools are " 3315 "formatted using a newer software version and\n" 3316 "cannot be accessed on the current system.\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 } 3325 3326 zpool_close(zhp); 3327 return (ret); 3328 } 3329 3330 /* ARGSUSED */ 3331 static int 3332 upgrade_one(zpool_handle_t *zhp, void *data) 3333 { 3334 upgrade_cbdata_t *cbp = data; 3335 uint64_t cur_version; 3336 int ret; 3337 3338 if (strcmp("log", zpool_get_name(zhp)) == 0) { 3339 (void) printf(gettext("'log' is now a reserved word\n" 3340 "Pool 'log' must be renamed using export and import" 3341 " to upgrade.\n")); 3342 return (1); 3343 } 3344 3345 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 3346 if (cur_version > cbp->cb_version) { 3347 (void) printf(gettext("Pool '%s' is already formatted " 3348 "using more current version '%llu'.\n"), 3349 zpool_get_name(zhp), cur_version); 3350 return (0); 3351 } 3352 if (cur_version == cbp->cb_version) { 3353 (void) printf(gettext("Pool '%s' is already formatted " 3354 "using the current version.\n"), zpool_get_name(zhp)); 3355 return (0); 3356 } 3357 3358 ret = zpool_upgrade(zhp, cbp->cb_version); 3359 3360 if (!ret) { 3361 (void) printf(gettext("Successfully upgraded '%s' " 3362 "from version %llu to version %llu\n\n"), 3363 zpool_get_name(zhp), (u_longlong_t)cur_version, 3364 (u_longlong_t)cbp->cb_version); 3365 } 3366 3367 return (ret != 0); 3368 } 3369 3370 /* 3371 * zpool upgrade 3372 * zpool upgrade -v 3373 * zpool upgrade [-V version] <-a | pool ...> 3374 * 3375 * With no arguments, display downrev'd ZFS pool available for upgrade. 3376 * Individual pools can be upgraded by specifying the pool, and '-a' will 3377 * upgrade all pools. 3378 */ 3379 int 3380 zpool_do_upgrade(int argc, char **argv) 3381 { 3382 int c; 3383 upgrade_cbdata_t cb = { 0 }; 3384 int ret = 0; 3385 boolean_t showversions = B_FALSE; 3386 char *end; 3387 3388 3389 /* check options */ 3390 while ((c = getopt(argc, argv, "avV:")) != -1) { 3391 switch (c) { 3392 case 'a': 3393 cb.cb_all = B_TRUE; 3394 break; 3395 case 'v': 3396 showversions = B_TRUE; 3397 break; 3398 case 'V': 3399 cb.cb_version = strtoll(optarg, &end, 10); 3400 if (*end != '\0' || cb.cb_version > SPA_VERSION || 3401 cb.cb_version < SPA_VERSION_1) { 3402 (void) fprintf(stderr, 3403 gettext("invalid version '%s'\n"), optarg); 3404 usage(B_FALSE); 3405 } 3406 break; 3407 case '?': 3408 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3409 optopt); 3410 usage(B_FALSE); 3411 } 3412 } 3413 3414 cb.cb_argc = argc; 3415 cb.cb_argv = argv; 3416 argc -= optind; 3417 argv += optind; 3418 3419 if (cb.cb_version == 0) { 3420 cb.cb_version = SPA_VERSION; 3421 } else if (!cb.cb_all && argc == 0) { 3422 (void) fprintf(stderr, gettext("-V option is " 3423 "incompatible with other arguments\n")); 3424 usage(B_FALSE); 3425 } 3426 3427 if (showversions) { 3428 if (cb.cb_all || argc != 0) { 3429 (void) fprintf(stderr, gettext("-v option is " 3430 "incompatible with other arguments\n")); 3431 usage(B_FALSE); 3432 } 3433 } else if (cb.cb_all) { 3434 if (argc != 0) { 3435 (void) fprintf(stderr, gettext("-a option should not " 3436 "be used along with a pool name\n")); 3437 usage(B_FALSE); 3438 } 3439 } 3440 3441 (void) printf(gettext("This system is currently running " 3442 "ZFS pool version %llu.\n\n"), SPA_VERSION); 3443 cb.cb_first = B_TRUE; 3444 if (showversions) { 3445 (void) printf(gettext("The following versions are " 3446 "supported:\n\n")); 3447 (void) printf(gettext("VER DESCRIPTION\n")); 3448 (void) printf("--- -----------------------------------------" 3449 "---------------\n"); 3450 (void) printf(gettext(" 1 Initial ZFS version\n")); 3451 (void) printf(gettext(" 2 Ditto blocks " 3452 "(replicated metadata)\n")); 3453 (void) printf(gettext(" 3 Hot spares and double parity " 3454 "RAID-Z\n")); 3455 (void) printf(gettext(" 4 zpool history\n")); 3456 (void) printf(gettext(" 5 Compression using the gzip " 3457 "algorithm\n")); 3458 (void) printf(gettext(" 6 bootfs pool property\n")); 3459 (void) printf(gettext(" 7 Separate intent log devices\n")); 3460 (void) printf(gettext(" 8 Delegated administration\n")); 3461 (void) printf(gettext(" 9 refquota and refreservation " 3462 "properties\n")); 3463 (void) printf(gettext(" 10 Cache devices\n")); 3464 (void) printf(gettext(" 11 Improved scrub performance\n")); 3465 (void) printf(gettext(" 12 Snapshot properties\n")); 3466 (void) printf(gettext("For more information on a particular " 3467 "version, including supported releases, see:\n\n")); 3468 (void) printf("http://www.opensolaris.org/os/community/zfs/" 3469 "version/N\n\n"); 3470 (void) printf(gettext("Where 'N' is the version number.\n")); 3471 } else if (argc == 0) { 3472 int notfound; 3473 3474 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3475 notfound = cb.cb_first; 3476 3477 if (!cb.cb_all && ret == 0) { 3478 if (!cb.cb_first) 3479 (void) printf("\n"); 3480 cb.cb_first = B_TRUE; 3481 cb.cb_newer = B_TRUE; 3482 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3483 if (!cb.cb_first) { 3484 notfound = B_FALSE; 3485 (void) printf("\n"); 3486 } 3487 } 3488 3489 if (ret == 0) { 3490 if (notfound) 3491 (void) printf(gettext("All pools are formatted " 3492 "using this version.\n")); 3493 else if (!cb.cb_all) 3494 (void) printf(gettext("Use 'zpool upgrade -v' " 3495 "for a list of available versions and " 3496 "their associated\nfeatures.\n")); 3497 } 3498 } else { 3499 ret = for_each_pool(argc, argv, B_FALSE, NULL, 3500 upgrade_one, &cb); 3501 } 3502 3503 return (ret); 3504 } 3505 3506 typedef struct hist_cbdata { 3507 boolean_t first; 3508 int longfmt; 3509 int internal; 3510 } hist_cbdata_t; 3511 3512 char *hist_event_table[LOG_END] = { 3513 "invalid event", 3514 "pool create", 3515 "vdev add", 3516 "pool remove", 3517 "pool destroy", 3518 "pool export", 3519 "pool import", 3520 "vdev attach", 3521 "vdev replace", 3522 "vdev detach", 3523 "vdev online", 3524 "vdev offline", 3525 "vdev upgrade", 3526 "pool clear", 3527 "pool scrub", 3528 "pool property set", 3529 "create", 3530 "clone", 3531 "destroy", 3532 "destroy_begin_sync", 3533 "inherit", 3534 "property set", 3535 "quota set", 3536 "permission update", 3537 "permission remove", 3538 "permission who remove", 3539 "promote", 3540 "receive", 3541 "rename", 3542 "reservation set", 3543 "replay_inc_sync", 3544 "replay_full_sync", 3545 "rollback", 3546 "snapshot", 3547 "filesystem version upgrade", 3548 "refquota set", 3549 "refreservation set", 3550 "pool scrub done", 3551 }; 3552 3553 /* 3554 * Print out the command history for a specific pool. 3555 */ 3556 static int 3557 get_history_one(zpool_handle_t *zhp, void *data) 3558 { 3559 nvlist_t *nvhis; 3560 nvlist_t **records; 3561 uint_t numrecords; 3562 char *cmdstr; 3563 char *pathstr; 3564 uint64_t dst_time; 3565 time_t tsec; 3566 struct tm t; 3567 char tbuf[30]; 3568 int ret, i; 3569 uint64_t who; 3570 struct passwd *pwd; 3571 char *hostname; 3572 char *zonename; 3573 char internalstr[MAXPATHLEN]; 3574 hist_cbdata_t *cb = (hist_cbdata_t *)data; 3575 uint64_t txg; 3576 uint64_t ievent; 3577 3578 cb->first = B_FALSE; 3579 3580 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 3581 3582 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 3583 return (ret); 3584 3585 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 3586 &records, &numrecords) == 0); 3587 for (i = 0; i < numrecords; i++) { 3588 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, 3589 &dst_time) != 0) 3590 continue; 3591 3592 /* is it an internal event or a standard event? */ 3593 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, 3594 &cmdstr) != 0) { 3595 if (cb->internal == 0) 3596 continue; 3597 3598 if (nvlist_lookup_uint64(records[i], 3599 ZPOOL_HIST_INT_EVENT, &ievent) != 0) 3600 continue; 3601 verify(nvlist_lookup_uint64(records[i], 3602 ZPOOL_HIST_TXG, &txg) == 0); 3603 verify(nvlist_lookup_string(records[i], 3604 ZPOOL_HIST_INT_STR, &pathstr) == 0); 3605 if (ievent >= LOG_END) 3606 continue; 3607 (void) snprintf(internalstr, 3608 sizeof (internalstr), 3609 "[internal %s txg:%lld] %s", 3610 hist_event_table[ievent], txg, 3611 pathstr); 3612 cmdstr = internalstr; 3613 } 3614 tsec = dst_time; 3615 (void) localtime_r(&tsec, &t); 3616 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 3617 (void) printf("%s %s", tbuf, cmdstr); 3618 3619 if (!cb->longfmt) { 3620 (void) printf("\n"); 3621 continue; 3622 } 3623 (void) printf(" ["); 3624 if (nvlist_lookup_uint64(records[i], 3625 ZPOOL_HIST_WHO, &who) == 0) { 3626 pwd = getpwuid((uid_t)who); 3627 if (pwd) 3628 (void) printf("user %s on", 3629 pwd->pw_name); 3630 else 3631 (void) printf("user %d on", 3632 (int)who); 3633 } else { 3634 (void) printf(gettext("no info]\n")); 3635 continue; 3636 } 3637 if (nvlist_lookup_string(records[i], 3638 ZPOOL_HIST_HOST, &hostname) == 0) { 3639 (void) printf(" %s", hostname); 3640 } 3641 if (nvlist_lookup_string(records[i], 3642 ZPOOL_HIST_ZONE, &zonename) == 0) { 3643 (void) printf(":%s", zonename); 3644 } 3645 3646 (void) printf("]"); 3647 (void) printf("\n"); 3648 } 3649 (void) printf("\n"); 3650 nvlist_free(nvhis); 3651 3652 return (ret); 3653 } 3654 3655 /* 3656 * zpool history <pool> 3657 * 3658 * Displays the history of commands that modified pools. 3659 */ 3660 3661 3662 int 3663 zpool_do_history(int argc, char **argv) 3664 { 3665 hist_cbdata_t cbdata = { 0 }; 3666 int ret; 3667 int c; 3668 3669 cbdata.first = B_TRUE; 3670 /* check options */ 3671 while ((c = getopt(argc, argv, "li")) != -1) { 3672 switch (c) { 3673 case 'l': 3674 cbdata.longfmt = 1; 3675 break; 3676 case 'i': 3677 cbdata.internal = 1; 3678 break; 3679 case '?': 3680 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3681 optopt); 3682 usage(B_FALSE); 3683 } 3684 } 3685 argc -= optind; 3686 argv += optind; 3687 3688 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 3689 &cbdata); 3690 3691 if (argc == 0 && cbdata.first == B_TRUE) { 3692 (void) printf(gettext("no pools available\n")); 3693 return (0); 3694 } 3695 3696 return (ret); 3697 } 3698 3699 static int 3700 get_callback(zpool_handle_t *zhp, void *data) 3701 { 3702 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 3703 char value[MAXNAMELEN]; 3704 zprop_source_t srctype; 3705 zprop_list_t *pl; 3706 3707 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 3708 3709 /* 3710 * Skip the special fake placeholder. This will also skip 3711 * over the name property when 'all' is specified. 3712 */ 3713 if (pl->pl_prop == ZPOOL_PROP_NAME && 3714 pl == cbp->cb_proplist) 3715 continue; 3716 3717 if (zpool_get_prop(zhp, pl->pl_prop, 3718 value, sizeof (value), &srctype) != 0) 3719 continue; 3720 3721 zprop_print_one_property(zpool_get_name(zhp), cbp, 3722 zpool_prop_to_name(pl->pl_prop), value, srctype, NULL); 3723 } 3724 return (0); 3725 } 3726 3727 int 3728 zpool_do_get(int argc, char **argv) 3729 { 3730 zprop_get_cbdata_t cb = { 0 }; 3731 zprop_list_t fake_name = { 0 }; 3732 int ret; 3733 3734 if (argc < 3) 3735 usage(B_FALSE); 3736 3737 cb.cb_first = B_TRUE; 3738 cb.cb_sources = ZPROP_SRC_ALL; 3739 cb.cb_columns[0] = GET_COL_NAME; 3740 cb.cb_columns[1] = GET_COL_PROPERTY; 3741 cb.cb_columns[2] = GET_COL_VALUE; 3742 cb.cb_columns[3] = GET_COL_SOURCE; 3743 cb.cb_type = ZFS_TYPE_POOL; 3744 3745 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist, 3746 ZFS_TYPE_POOL) != 0) 3747 usage(B_FALSE); 3748 3749 if (cb.cb_proplist != NULL) { 3750 fake_name.pl_prop = ZPOOL_PROP_NAME; 3751 fake_name.pl_width = strlen(gettext("NAME")); 3752 fake_name.pl_next = cb.cb_proplist; 3753 cb.cb_proplist = &fake_name; 3754 } 3755 3756 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist, 3757 get_callback, &cb); 3758 3759 if (cb.cb_proplist == &fake_name) 3760 zprop_free_list(fake_name.pl_next); 3761 else 3762 zprop_free_list(cb.cb_proplist); 3763 3764 return (ret); 3765 } 3766 3767 typedef struct set_cbdata { 3768 char *cb_propname; 3769 char *cb_value; 3770 boolean_t cb_any_successful; 3771 } set_cbdata_t; 3772 3773 int 3774 set_callback(zpool_handle_t *zhp, void *data) 3775 { 3776 int error; 3777 set_cbdata_t *cb = (set_cbdata_t *)data; 3778 3779 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 3780 3781 if (!error) 3782 cb->cb_any_successful = B_TRUE; 3783 3784 return (error); 3785 } 3786 3787 int 3788 zpool_do_set(int argc, char **argv) 3789 { 3790 set_cbdata_t cb = { 0 }; 3791 int error; 3792 3793 if (argc > 1 && argv[1][0] == '-') { 3794 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3795 argv[1][1]); 3796 usage(B_FALSE); 3797 } 3798 3799 if (argc < 2) { 3800 (void) fprintf(stderr, gettext("missing property=value " 3801 "argument\n")); 3802 usage(B_FALSE); 3803 } 3804 3805 if (argc < 3) { 3806 (void) fprintf(stderr, gettext("missing pool name\n")); 3807 usage(B_FALSE); 3808 } 3809 3810 if (argc > 3) { 3811 (void) fprintf(stderr, gettext("too many pool names\n")); 3812 usage(B_FALSE); 3813 } 3814 3815 cb.cb_propname = argv[1]; 3816 cb.cb_value = strchr(cb.cb_propname, '='); 3817 if (cb.cb_value == NULL) { 3818 (void) fprintf(stderr, gettext("missing value in " 3819 "property=value argument\n")); 3820 usage(B_FALSE); 3821 } 3822 3823 *(cb.cb_value) = '\0'; 3824 cb.cb_value++; 3825 3826 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 3827 set_callback, &cb); 3828 3829 return (error); 3830 } 3831 3832 static int 3833 find_command_idx(char *command, int *idx) 3834 { 3835 int i; 3836 3837 for (i = 0; i < NCOMMAND; i++) { 3838 if (command_table[i].name == NULL) 3839 continue; 3840 3841 if (strcmp(command, command_table[i].name) == 0) { 3842 *idx = i; 3843 return (0); 3844 } 3845 } 3846 return (1); 3847 } 3848 3849 int 3850 main(int argc, char **argv) 3851 { 3852 int ret; 3853 int i; 3854 char *cmdname; 3855 3856 (void) setlocale(LC_ALL, ""); 3857 (void) textdomain(TEXT_DOMAIN); 3858 3859 if ((g_zfs = libzfs_init()) == NULL) { 3860 (void) fprintf(stderr, gettext("internal error: failed to " 3861 "initialize ZFS library\n")); 3862 return (1); 3863 } 3864 3865 libzfs_print_on_error(g_zfs, B_TRUE); 3866 3867 opterr = 0; 3868 3869 /* 3870 * Make sure the user has specified some command. 3871 */ 3872 if (argc < 2) { 3873 (void) fprintf(stderr, gettext("missing command\n")); 3874 usage(B_FALSE); 3875 } 3876 3877 cmdname = argv[1]; 3878 3879 /* 3880 * Special case '-?' 3881 */ 3882 if (strcmp(cmdname, "-?") == 0) 3883 usage(B_TRUE); 3884 3885 zpool_set_history_str("zpool", argc, argv, history_str); 3886 verify(zpool_stage_history(g_zfs, history_str) == 0); 3887 3888 /* 3889 * Run the appropriate command. 3890 */ 3891 if (find_command_idx(cmdname, &i) == 0) { 3892 current_command = &command_table[i]; 3893 ret = command_table[i].func(argc - 1, argv + 1); 3894 } else if (strchr(cmdname, '=')) { 3895 verify(find_command_idx("set", &i) == 0); 3896 current_command = &command_table[i]; 3897 ret = command_table[i].func(argc, argv); 3898 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 3899 /* 3900 * 'freeze' is a vile debugging abomination, so we treat 3901 * it as such. 3902 */ 3903 char buf[16384]; 3904 int fd = open(ZFS_DEV, O_RDWR); 3905 (void) strcpy((void *)buf, argv[2]); 3906 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 3907 } else { 3908 (void) fprintf(stderr, gettext("unrecognized " 3909 "command '%s'\n"), cmdname); 3910 usage(B_FALSE); 3911 } 3912 3913 libzfs_fini(g_zfs); 3914 3915 /* 3916 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 3917 * for the purposes of running ::findleaks. 3918 */ 3919 if (getenv("ZFS_ABORT") != NULL) { 3920 (void) printf("dumping core by request\n"); 3921 abort(); 3922 } 3923 3924 return (ret); 3925 } 3926