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