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