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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2011, 2016 by Delphix. All rights reserved. 25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved. 26 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved. 27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>. 28 * Copyright 2016 Nexenta Systems, Inc. 29 * Copyright (c) 2017 Datto Inc. 30 */ 31 32 #include <assert.h> 33 #include <ctype.h> 34 #include <dirent.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <libgen.h> 38 #include <libintl.h> 39 #include <libuutil.h> 40 #include <locale.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <strings.h> 45 #include <unistd.h> 46 #include <priv.h> 47 #include <pwd.h> 48 #include <zone.h> 49 #include <zfs_prop.h> 50 #include <sys/fs/zfs.h> 51 #include <sys/stat.h> 52 53 #include <libzfs.h> 54 55 #include "zpool_util.h" 56 #include "zfs_comutil.h" 57 #include "zfeature_common.h" 58 59 #include "statcommon.h" 60 61 static int zpool_do_create(int, char **); 62 static int zpool_do_destroy(int, char **); 63 64 static int zpool_do_add(int, char **); 65 static int zpool_do_remove(int, char **); 66 static int zpool_do_labelclear(int, char **); 67 68 static int zpool_do_list(int, char **); 69 static int zpool_do_iostat(int, char **); 70 static int zpool_do_status(int, char **); 71 72 static int zpool_do_online(int, char **); 73 static int zpool_do_offline(int, char **); 74 static int zpool_do_clear(int, char **); 75 static int zpool_do_reopen(int, char **); 76 77 static int zpool_do_reguid(int, char **); 78 79 static int zpool_do_attach(int, char **); 80 static int zpool_do_detach(int, char **); 81 static int zpool_do_replace(int, char **); 82 static int zpool_do_split(int, char **); 83 84 static int zpool_do_scrub(int, char **); 85 86 static int zpool_do_import(int, char **); 87 static int zpool_do_export(int, char **); 88 89 static int zpool_do_upgrade(int, char **); 90 91 static int zpool_do_history(int, char **); 92 93 static int zpool_do_get(int, char **); 94 static int zpool_do_set(int, char **); 95 96 /* 97 * These libumem hooks provide a reasonable set of defaults for the allocator's 98 * debugging facilities. 99 */ 100 101 #ifdef DEBUG 102 const char * 103 _umem_debug_init(void) 104 { 105 return ("default,verbose"); /* $UMEM_DEBUG setting */ 106 } 107 108 const char * 109 _umem_logging_init(void) 110 { 111 return ("fail,contents"); /* $UMEM_LOGGING setting */ 112 } 113 #endif 114 115 typedef enum { 116 HELP_ADD, 117 HELP_ATTACH, 118 HELP_CLEAR, 119 HELP_CREATE, 120 HELP_DESTROY, 121 HELP_DETACH, 122 HELP_EXPORT, 123 HELP_HISTORY, 124 HELP_IMPORT, 125 HELP_IOSTAT, 126 HELP_LABELCLEAR, 127 HELP_LIST, 128 HELP_OFFLINE, 129 HELP_ONLINE, 130 HELP_REPLACE, 131 HELP_REMOVE, 132 HELP_SCRUB, 133 HELP_STATUS, 134 HELP_UPGRADE, 135 HELP_GET, 136 HELP_SET, 137 HELP_SPLIT, 138 HELP_REGUID, 139 HELP_REOPEN 140 } zpool_help_t; 141 142 143 typedef struct zpool_command { 144 const char *name; 145 int (*func)(int, char **); 146 zpool_help_t usage; 147 } zpool_command_t; 148 149 /* 150 * Master command table. Each ZFS command has a name, associated function, and 151 * usage message. The usage messages need to be internationalized, so we have 152 * to have a function to return the usage message based on a command index. 153 * 154 * These commands are organized according to how they are displayed in the usage 155 * message. An empty command (one with a NULL name) indicates an empty line in 156 * the generic usage message. 157 */ 158 static zpool_command_t command_table[] = { 159 { "create", zpool_do_create, HELP_CREATE }, 160 { "destroy", zpool_do_destroy, HELP_DESTROY }, 161 { NULL }, 162 { "add", zpool_do_add, HELP_ADD }, 163 { "remove", zpool_do_remove, HELP_REMOVE }, 164 { NULL }, 165 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 166 { NULL }, 167 { "list", zpool_do_list, HELP_LIST }, 168 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 169 { "status", zpool_do_status, HELP_STATUS }, 170 { NULL }, 171 { "online", zpool_do_online, HELP_ONLINE }, 172 { "offline", zpool_do_offline, HELP_OFFLINE }, 173 { "clear", zpool_do_clear, HELP_CLEAR }, 174 { "reopen", zpool_do_reopen, HELP_REOPEN }, 175 { NULL }, 176 { "attach", zpool_do_attach, HELP_ATTACH }, 177 { "detach", zpool_do_detach, HELP_DETACH }, 178 { "replace", zpool_do_replace, HELP_REPLACE }, 179 { "split", zpool_do_split, HELP_SPLIT }, 180 { NULL }, 181 { "scrub", zpool_do_scrub, HELP_SCRUB }, 182 { NULL }, 183 { "import", zpool_do_import, HELP_IMPORT }, 184 { "export", zpool_do_export, HELP_EXPORT }, 185 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 186 { "reguid", zpool_do_reguid, HELP_REGUID }, 187 { NULL }, 188 { "history", zpool_do_history, HELP_HISTORY }, 189 { "get", zpool_do_get, HELP_GET }, 190 { "set", zpool_do_set, HELP_SET }, 191 }; 192 193 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 194 195 static zpool_command_t *current_command; 196 static char history_str[HIS_MAX_RECORD_LEN]; 197 static boolean_t log_history = B_TRUE; 198 static uint_t timestamp_fmt = NODATE; 199 200 static const char * 201 get_usage(zpool_help_t idx) 202 { 203 switch (idx) { 204 case HELP_ADD: 205 return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 206 case HELP_ATTACH: 207 return (gettext("\tattach [-f] <pool> <device> " 208 "<new-device>\n")); 209 case HELP_CLEAR: 210 return (gettext("\tclear [-nF] <pool> [device]\n")); 211 case HELP_CREATE: 212 return (gettext("\tcreate [-fnd] [-B] " 213 "[-o property=value] ... \n" 214 "\t [-O file-system-property=value] ... \n" 215 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 216 case HELP_DESTROY: 217 return (gettext("\tdestroy [-f] <pool>\n")); 218 case HELP_DETACH: 219 return (gettext("\tdetach <pool> <device>\n")); 220 case HELP_EXPORT: 221 return (gettext("\texport [-f] <pool> ...\n")); 222 case HELP_HISTORY: 223 return (gettext("\thistory [-il] [<pool>] ...\n")); 224 case HELP_IMPORT: 225 return (gettext("\timport [-d dir] [-D]\n" 226 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n" 227 "\timport [-o mntopts] [-o property=value] ... \n" 228 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 229 "[-R root] [-F [-n]] -a\n" 230 "\timport [-o mntopts] [-o property=value] ... \n" 231 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 232 "[-R root] [-F [-n]]\n" 233 "\t <pool | id> [newpool]\n")); 234 case HELP_IOSTAT: 235 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " 236 "[count]]\n")); 237 case HELP_LABELCLEAR: 238 return (gettext("\tlabelclear [-f] <vdev>\n")); 239 case HELP_LIST: 240 return (gettext("\tlist [-Hp] [-o property[,...]] " 241 "[-T d|u] [pool] ... [interval [count]]\n")); 242 case HELP_OFFLINE: 243 return (gettext("\toffline [-t] <pool> <device> ...\n")); 244 case HELP_ONLINE: 245 return (gettext("\tonline <pool> <device> ...\n")); 246 case HELP_REPLACE: 247 return (gettext("\treplace [-f] <pool> <device> " 248 "[new-device]\n")); 249 case HELP_REMOVE: 250 return (gettext("\tremove <pool> <device> ...\n")); 251 case HELP_REOPEN: 252 return (gettext("\treopen <pool>\n")); 253 case HELP_SCRUB: 254 return (gettext("\tscrub [-s | -p] <pool> ...\n")); 255 case HELP_STATUS: 256 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval " 257 "[count]]\n")); 258 case HELP_UPGRADE: 259 return (gettext("\tupgrade\n" 260 "\tupgrade -v\n" 261 "\tupgrade [-V version] <-a | pool ...>\n")); 262 case HELP_GET: 263 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 264 "<\"all\" | property[,...]> <pool> ...\n")); 265 case HELP_SET: 266 return (gettext("\tset <property=value> <pool> \n")); 267 case HELP_SPLIT: 268 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" 269 "\t [-o property=value] <pool> <newpool> " 270 "[<device> ...]\n")); 271 case HELP_REGUID: 272 return (gettext("\treguid <pool>\n")); 273 } 274 275 abort(); 276 /* NOTREACHED */ 277 } 278 279 280 /* 281 * Callback routine that will print out a pool property value. 282 */ 283 static int 284 print_prop_cb(int prop, void *cb) 285 { 286 FILE *fp = cb; 287 288 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop)); 289 290 if (zpool_prop_readonly(prop)) 291 (void) fprintf(fp, " NO "); 292 else 293 (void) fprintf(fp, " YES "); 294 295 if (zpool_prop_values(prop) == NULL) 296 (void) fprintf(fp, "-\n"); 297 else 298 (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 299 300 return (ZPROP_CONT); 301 } 302 303 /* 304 * Display usage message. If we're inside a command, display only the usage for 305 * that command. Otherwise, iterate over the entire command table and display 306 * a complete usage message. 307 */ 308 void 309 usage(boolean_t requested) 310 { 311 FILE *fp = requested ? stdout : stderr; 312 313 if (current_command == NULL) { 314 int i; 315 316 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 317 (void) fprintf(fp, 318 gettext("where 'command' is one of the following:\n\n")); 319 320 for (i = 0; i < NCOMMAND; i++) { 321 if (command_table[i].name == NULL) 322 (void) fprintf(fp, "\n"); 323 else 324 (void) fprintf(fp, "%s", 325 get_usage(command_table[i].usage)); 326 } 327 } else { 328 (void) fprintf(fp, gettext("usage:\n")); 329 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 330 } 331 332 if (current_command != NULL && 333 ((strcmp(current_command->name, "set") == 0) || 334 (strcmp(current_command->name, "get") == 0) || 335 (strcmp(current_command->name, "list") == 0))) { 336 337 (void) fprintf(fp, 338 gettext("\nthe following properties are supported:\n")); 339 340 (void) fprintf(fp, "\n\t%-15s %s %s\n\n", 341 "PROPERTY", "EDIT", "VALUES"); 342 343 /* Iterate over all properties */ 344 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 345 ZFS_TYPE_POOL); 346 347 (void) fprintf(fp, "\t%-15s ", "feature@..."); 348 (void) fprintf(fp, "YES disabled | enabled | active\n"); 349 350 (void) fprintf(fp, gettext("\nThe feature@ properties must be " 351 "appended with a feature name.\nSee zpool-features(5).\n")); 352 } 353 354 /* 355 * See comments at end of main(). 356 */ 357 if (getenv("ZFS_ABORT") != NULL) { 358 (void) printf("dumping core by request\n"); 359 abort(); 360 } 361 362 exit(requested ? 0 : 2); 363 } 364 365 void 366 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 367 boolean_t print_logs) 368 { 369 nvlist_t **child; 370 uint_t c, children; 371 char *vname; 372 373 if (name != NULL) 374 (void) printf("\t%*s%s\n", indent, "", name); 375 376 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 377 &child, &children) != 0) 378 return; 379 380 for (c = 0; c < children; c++) { 381 uint64_t is_log = B_FALSE; 382 383 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 384 &is_log); 385 if ((is_log && !print_logs) || (!is_log && print_logs)) 386 continue; 387 388 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 389 print_vdev_tree(zhp, vname, child[c], indent + 2, 390 B_FALSE); 391 free(vname); 392 } 393 } 394 395 static boolean_t 396 prop_list_contains_feature(nvlist_t *proplist) 397 { 398 nvpair_t *nvp; 399 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 400 nvp = nvlist_next_nvpair(proplist, nvp)) { 401 if (zpool_prop_feature(nvpair_name(nvp))) 402 return (B_TRUE); 403 } 404 return (B_FALSE); 405 } 406 407 /* 408 * Add a property pair (name, string-value) into a property nvlist. 409 */ 410 static int 411 add_prop_list(const char *propname, char *propval, nvlist_t **props, 412 boolean_t poolprop) 413 { 414 zpool_prop_t prop = ZPROP_INVAL; 415 zfs_prop_t fprop; 416 nvlist_t *proplist; 417 const char *normnm; 418 char *strval; 419 420 if (*props == NULL && 421 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 422 (void) fprintf(stderr, 423 gettext("internal error: out of memory\n")); 424 return (1); 425 } 426 427 proplist = *props; 428 429 if (poolprop) { 430 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 431 432 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL && 433 !zpool_prop_feature(propname)) { 434 (void) fprintf(stderr, gettext("property '%s' is " 435 "not a valid pool property\n"), propname); 436 return (2); 437 } 438 439 /* 440 * feature@ properties and version should not be specified 441 * at the same time. 442 */ 443 if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) && 444 nvlist_exists(proplist, vname)) || 445 (prop == ZPOOL_PROP_VERSION && 446 prop_list_contains_feature(proplist))) { 447 (void) fprintf(stderr, gettext("'feature@' and " 448 "'version' properties cannot be specified " 449 "together\n")); 450 return (2); 451 } 452 453 454 if (zpool_prop_feature(propname)) 455 normnm = propname; 456 else 457 normnm = zpool_prop_to_name(prop); 458 } else { 459 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 460 normnm = zfs_prop_to_name(fprop); 461 } else { 462 normnm = propname; 463 } 464 } 465 466 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 467 prop != ZPOOL_PROP_CACHEFILE) { 468 (void) fprintf(stderr, gettext("property '%s' " 469 "specified multiple times\n"), propname); 470 return (2); 471 } 472 473 if (nvlist_add_string(proplist, normnm, propval) != 0) { 474 (void) fprintf(stderr, gettext("internal " 475 "error: out of memory\n")); 476 return (1); 477 } 478 479 return (0); 480 } 481 482 /* 483 * zpool add [-fn] <pool> <vdev> ... 484 * 485 * -f Force addition of devices, even if they appear in use 486 * -n Do not add the devices, but display the resulting layout if 487 * they were to be added. 488 * 489 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 490 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 491 * libzfs. 492 */ 493 int 494 zpool_do_add(int argc, char **argv) 495 { 496 boolean_t force = B_FALSE; 497 boolean_t dryrun = B_FALSE; 498 int c; 499 nvlist_t *nvroot; 500 char *poolname; 501 zpool_boot_label_t boot_type; 502 uint64_t boot_size; 503 int ret; 504 zpool_handle_t *zhp; 505 nvlist_t *config; 506 507 /* check options */ 508 while ((c = getopt(argc, argv, "fn")) != -1) { 509 switch (c) { 510 case 'f': 511 force = B_TRUE; 512 break; 513 case 'n': 514 dryrun = B_TRUE; 515 break; 516 case '?': 517 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 518 optopt); 519 usage(B_FALSE); 520 } 521 } 522 523 argc -= optind; 524 argv += optind; 525 526 /* get pool name and check number of arguments */ 527 if (argc < 1) { 528 (void) fprintf(stderr, gettext("missing pool name argument\n")); 529 usage(B_FALSE); 530 } 531 if (argc < 2) { 532 (void) fprintf(stderr, gettext("missing vdev specification\n")); 533 usage(B_FALSE); 534 } 535 536 poolname = argv[0]; 537 538 argc--; 539 argv++; 540 541 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 542 return (1); 543 544 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 545 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 546 poolname); 547 zpool_close(zhp); 548 return (1); 549 } 550 551 if (zpool_is_bootable(zhp)) 552 boot_type = ZPOOL_COPY_BOOT_LABEL; 553 else 554 boot_type = ZPOOL_NO_BOOT_LABEL; 555 556 /* pass off to get_vdev_spec for processing */ 557 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 558 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 559 boot_type, boot_size, argc, argv); 560 if (nvroot == NULL) { 561 zpool_close(zhp); 562 return (1); 563 } 564 565 if (dryrun) { 566 nvlist_t *poolnvroot; 567 568 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 569 &poolnvroot) == 0); 570 571 (void) printf(gettext("would update '%s' to the following " 572 "configuration:\n"), zpool_get_name(zhp)); 573 574 /* print original main pool and new tree */ 575 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 576 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 577 578 /* Do the same for the logs */ 579 if (num_logs(poolnvroot) > 0) { 580 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 581 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 582 } else if (num_logs(nvroot) > 0) { 583 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 584 } 585 586 ret = 0; 587 } else { 588 ret = (zpool_add(zhp, nvroot) != 0); 589 } 590 591 nvlist_free(nvroot); 592 zpool_close(zhp); 593 594 return (ret); 595 } 596 597 /* 598 * zpool remove <pool> <vdev> ... 599 * 600 * Removes the given vdev from the pool. Currently, this supports removing 601 * spares, cache, and log devices from the pool. 602 */ 603 int 604 zpool_do_remove(int argc, char **argv) 605 { 606 char *poolname; 607 int i, ret = 0; 608 zpool_handle_t *zhp; 609 610 argc--; 611 argv++; 612 613 /* get pool name and check number of arguments */ 614 if (argc < 1) { 615 (void) fprintf(stderr, gettext("missing pool name argument\n")); 616 usage(B_FALSE); 617 } 618 if (argc < 2) { 619 (void) fprintf(stderr, gettext("missing device\n")); 620 usage(B_FALSE); 621 } 622 623 poolname = argv[0]; 624 625 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 626 return (1); 627 628 for (i = 1; i < argc; i++) { 629 if (zpool_vdev_remove(zhp, argv[i]) != 0) 630 ret = 1; 631 } 632 633 return (ret); 634 } 635 636 /* 637 * zpool labelclear [-f] <vdev> 638 * 639 * -f Force clearing the label for the vdevs which are members of 640 * the exported or foreign pools. 641 * 642 * Verifies that the vdev is not active and zeros out the label information 643 * on the device. 644 */ 645 int 646 zpool_do_labelclear(int argc, char **argv) 647 { 648 char vdev[MAXPATHLEN]; 649 char *name = NULL; 650 struct stat st; 651 int c, fd, ret = 0; 652 nvlist_t *config; 653 pool_state_t state; 654 boolean_t inuse = B_FALSE; 655 boolean_t force = B_FALSE; 656 657 /* check options */ 658 while ((c = getopt(argc, argv, "f")) != -1) { 659 switch (c) { 660 case 'f': 661 force = B_TRUE; 662 break; 663 default: 664 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 665 optopt); 666 usage(B_FALSE); 667 } 668 } 669 670 argc -= optind; 671 argv += optind; 672 673 /* get vdev name */ 674 if (argc < 1) { 675 (void) fprintf(stderr, gettext("missing vdev name\n")); 676 usage(B_FALSE); 677 } 678 if (argc > 1) { 679 (void) fprintf(stderr, gettext("too many arguments\n")); 680 usage(B_FALSE); 681 } 682 683 /* 684 * Check if we were given absolute path and use it as is. 685 * Otherwise if the provided vdev name doesn't point to a file, 686 * try prepending dsk path and appending s0. 687 */ 688 (void) strlcpy(vdev, argv[0], sizeof (vdev)); 689 if (vdev[0] != '/' && stat(vdev, &st) != 0) { 690 char *s; 691 692 (void) snprintf(vdev, sizeof (vdev), "%s/%s", 693 ZFS_DISK_ROOT, argv[0]); 694 if ((s = strrchr(argv[0], 's')) == NULL || 695 !isdigit(*(s + 1))) 696 (void) strlcat(vdev, "s0", sizeof (vdev)); 697 if (stat(vdev, &st) != 0) { 698 (void) fprintf(stderr, gettext( 699 "failed to find device %s, try specifying absolute " 700 "path instead\n"), argv[0]); 701 return (1); 702 } 703 } 704 705 if ((fd = open(vdev, O_RDWR)) < 0) { 706 (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 707 vdev, strerror(errno)); 708 return (1); 709 } 710 711 if (zpool_read_label(fd, &config) != 0) { 712 (void) fprintf(stderr, 713 gettext("failed to read label from %s\n"), vdev); 714 return (1); 715 } 716 nvlist_free(config); 717 718 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 719 if (ret != 0) { 720 (void) fprintf(stderr, 721 gettext("failed to check state for %s\n"), vdev); 722 return (1); 723 } 724 725 if (!inuse) 726 goto wipe_label; 727 728 switch (state) { 729 default: 730 case POOL_STATE_ACTIVE: 731 case POOL_STATE_SPARE: 732 case POOL_STATE_L2CACHE: 733 (void) fprintf(stderr, gettext( 734 "%s is a member (%s) of pool \"%s\"\n"), 735 vdev, zpool_pool_state_to_name(state), name); 736 ret = 1; 737 goto errout; 738 739 case POOL_STATE_EXPORTED: 740 if (force) 741 break; 742 (void) fprintf(stderr, gettext( 743 "use '-f' to override the following error:\n" 744 "%s is a member of exported pool \"%s\"\n"), 745 vdev, name); 746 ret = 1; 747 goto errout; 748 749 case POOL_STATE_POTENTIALLY_ACTIVE: 750 if (force) 751 break; 752 (void) fprintf(stderr, gettext( 753 "use '-f' to override the following error:\n" 754 "%s is a member of potentially active pool \"%s\"\n"), 755 vdev, name); 756 ret = 1; 757 goto errout; 758 759 case POOL_STATE_DESTROYED: 760 /* inuse should never be set for a destroyed pool */ 761 assert(0); 762 break; 763 } 764 765 wipe_label: 766 ret = zpool_clear_label(fd); 767 if (ret != 0) { 768 (void) fprintf(stderr, 769 gettext("failed to clear label for %s\n"), vdev); 770 } 771 772 errout: 773 free(name); 774 (void) close(fd); 775 776 return (ret); 777 } 778 779 /* 780 * zpool create [-fnd] [-B] [-o property=value] ... 781 * [-O file-system-property=value] ... 782 * [-R root] [-m mountpoint] <pool> <dev> ... 783 * 784 * -B Create boot partition. 785 * -f Force creation, even if devices appear in use 786 * -n Do not create the pool, but display the resulting layout if it 787 * were to be created. 788 * -R Create a pool under an alternate root 789 * -m Set default mountpoint for the root dataset. By default it's 790 * '/<pool>' 791 * -o Set property=value. 792 * -d Don't automatically enable all supported pool features 793 * (individual features can be enabled with -o). 794 * -O Set fsproperty=value in the pool's root file system 795 * 796 * Creates the named pool according to the given vdev specification. The 797 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 798 * we get the nvlist back from get_vdev_spec(), we either print out the contents 799 * (if '-n' was specified), or pass it to libzfs to do the creation. 800 */ 801 802 #define SYSTEM256 (256 * 1024 * 1024) 803 int 804 zpool_do_create(int argc, char **argv) 805 { 806 boolean_t force = B_FALSE; 807 boolean_t dryrun = B_FALSE; 808 boolean_t enable_all_pool_feat = B_TRUE; 809 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 810 uint64_t boot_size = 0; 811 int c; 812 nvlist_t *nvroot = NULL; 813 char *poolname; 814 int ret = 1; 815 char *altroot = NULL; 816 char *mountpoint = NULL; 817 nvlist_t *fsprops = NULL; 818 nvlist_t *props = NULL; 819 char *propval; 820 821 /* check options */ 822 while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) { 823 switch (c) { 824 case 'f': 825 force = B_TRUE; 826 break; 827 case 'n': 828 dryrun = B_TRUE; 829 break; 830 case 'd': 831 enable_all_pool_feat = B_FALSE; 832 break; 833 case 'B': 834 /* 835 * We should create the system partition. 836 * Also make sure the size is set. 837 */ 838 boot_type = ZPOOL_CREATE_BOOT_LABEL; 839 if (boot_size == 0) 840 boot_size = SYSTEM256; 841 break; 842 case 'R': 843 altroot = optarg; 844 if (add_prop_list(zpool_prop_to_name( 845 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 846 goto errout; 847 if (nvlist_lookup_string(props, 848 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 849 &propval) == 0) 850 break; 851 if (add_prop_list(zpool_prop_to_name( 852 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 853 goto errout; 854 break; 855 case 'm': 856 /* Equivalent to -O mountpoint=optarg */ 857 mountpoint = optarg; 858 break; 859 case 'o': 860 if ((propval = strchr(optarg, '=')) == NULL) { 861 (void) fprintf(stderr, gettext("missing " 862 "'=' for -o option\n")); 863 goto errout; 864 } 865 *propval = '\0'; 866 propval++; 867 868 if (add_prop_list(optarg, propval, &props, B_TRUE)) 869 goto errout; 870 871 /* 872 * Get bootsize value for make_root_vdev(). 873 */ 874 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 875 if (zfs_nicestrtonum(g_zfs, propval, 876 &boot_size) < 0 || boot_size == 0) { 877 (void) fprintf(stderr, 878 gettext("bad boot partition size " 879 "'%s': %s\n"), propval, 880 libzfs_error_description(g_zfs)); 881 goto errout; 882 } 883 } 884 885 /* 886 * If the user is creating a pool that doesn't support 887 * feature flags, don't enable any features. 888 */ 889 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 890 char *end; 891 u_longlong_t ver; 892 893 ver = strtoull(propval, &end, 10); 894 if (*end == '\0' && 895 ver < SPA_VERSION_FEATURES) { 896 enable_all_pool_feat = B_FALSE; 897 } 898 } 899 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 900 altroot = propval; 901 break; 902 case 'O': 903 if ((propval = strchr(optarg, '=')) == NULL) { 904 (void) fprintf(stderr, gettext("missing " 905 "'=' for -O option\n")); 906 goto errout; 907 } 908 *propval = '\0'; 909 propval++; 910 911 /* 912 * Mountpoints are checked and then added later. 913 * Uniquely among properties, they can be specified 914 * more than once, to avoid conflict with -m. 915 */ 916 if (0 == strcmp(optarg, 917 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 918 mountpoint = propval; 919 } else if (add_prop_list(optarg, propval, &fsprops, 920 B_FALSE)) { 921 goto errout; 922 } 923 break; 924 case ':': 925 (void) fprintf(stderr, gettext("missing argument for " 926 "'%c' option\n"), optopt); 927 goto badusage; 928 case '?': 929 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 930 optopt); 931 goto badusage; 932 } 933 } 934 935 argc -= optind; 936 argv += optind; 937 938 /* get pool name and check number of arguments */ 939 if (argc < 1) { 940 (void) fprintf(stderr, gettext("missing pool name argument\n")); 941 goto badusage; 942 } 943 if (argc < 2) { 944 (void) fprintf(stderr, gettext("missing vdev specification\n")); 945 goto badusage; 946 } 947 948 poolname = argv[0]; 949 950 /* 951 * As a special case, check for use of '/' in the name, and direct the 952 * user to use 'zfs create' instead. 953 */ 954 if (strchr(poolname, '/') != NULL) { 955 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 956 "character '/' in pool name\n"), poolname); 957 (void) fprintf(stderr, gettext("use 'zfs create' to " 958 "create a dataset\n")); 959 goto errout; 960 } 961 962 /* 963 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 964 * and not set otherwise. 965 */ 966 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 967 const char *propname; 968 char *strptr, *buf = NULL; 969 int rv; 970 971 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 972 if (nvlist_lookup_string(props, propname, &strptr) != 0) { 973 (void) asprintf(&buf, "%" PRIu64, boot_size); 974 if (buf == NULL) { 975 (void) fprintf(stderr, 976 gettext("internal error: out of memory\n")); 977 goto errout; 978 } 979 rv = add_prop_list(propname, buf, &props, B_TRUE); 980 free(buf); 981 if (rv != 0) 982 goto errout; 983 } 984 } else { 985 const char *propname; 986 char *strptr; 987 988 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 989 if (nvlist_lookup_string(props, propname, &strptr) == 0) { 990 (void) fprintf(stderr, gettext("error: setting boot " 991 "partition size requires option '-B'\n")); 992 goto errout; 993 } 994 } 995 996 /* pass off to get_vdev_spec for bulk processing */ 997 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 998 boot_type, boot_size, argc - 1, argv + 1); 999 if (nvroot == NULL) 1000 goto errout; 1001 1002 /* make_root_vdev() allows 0 toplevel children if there are spares */ 1003 if (!zfs_allocatable_devs(nvroot)) { 1004 (void) fprintf(stderr, gettext("invalid vdev " 1005 "specification: at least one toplevel vdev must be " 1006 "specified\n")); 1007 goto errout; 1008 } 1009 1010 if (altroot != NULL && altroot[0] != '/') { 1011 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1012 "must be an absolute path\n"), altroot); 1013 goto errout; 1014 } 1015 1016 /* 1017 * Check the validity of the mountpoint and direct the user to use the 1018 * '-m' mountpoint option if it looks like its in use. 1019 */ 1020 if (mountpoint == NULL || 1021 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1022 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 1023 char buf[MAXPATHLEN]; 1024 DIR *dirp; 1025 1026 if (mountpoint && mountpoint[0] != '/') { 1027 (void) fprintf(stderr, gettext("invalid mountpoint " 1028 "'%s': must be an absolute path, 'legacy', or " 1029 "'none'\n"), mountpoint); 1030 goto errout; 1031 } 1032 1033 if (mountpoint == NULL) { 1034 if (altroot != NULL) 1035 (void) snprintf(buf, sizeof (buf), "%s/%s", 1036 altroot, poolname); 1037 else 1038 (void) snprintf(buf, sizeof (buf), "/%s", 1039 poolname); 1040 } else { 1041 if (altroot != NULL) 1042 (void) snprintf(buf, sizeof (buf), "%s%s", 1043 altroot, mountpoint); 1044 else 1045 (void) snprintf(buf, sizeof (buf), "%s", 1046 mountpoint); 1047 } 1048 1049 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 1050 (void) fprintf(stderr, gettext("mountpoint '%s' : " 1051 "%s\n"), buf, strerror(errno)); 1052 (void) fprintf(stderr, gettext("use '-m' " 1053 "option to provide a different default\n")); 1054 goto errout; 1055 } else if (dirp) { 1056 int count = 0; 1057 1058 while (count < 3 && readdir(dirp) != NULL) 1059 count++; 1060 (void) closedir(dirp); 1061 1062 if (count > 2) { 1063 (void) fprintf(stderr, gettext("mountpoint " 1064 "'%s' exists and is not empty\n"), buf); 1065 (void) fprintf(stderr, gettext("use '-m' " 1066 "option to provide a " 1067 "different default\n")); 1068 goto errout; 1069 } 1070 } 1071 } 1072 1073 /* 1074 * Now that the mountpoint's validity has been checked, ensure that 1075 * the property is set appropriately prior to creating the pool. 1076 */ 1077 if (mountpoint != NULL) { 1078 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1079 mountpoint, &fsprops, B_FALSE); 1080 if (ret != 0) 1081 goto errout; 1082 } 1083 1084 ret = 1; 1085 if (dryrun) { 1086 /* 1087 * For a dry run invocation, print out a basic message and run 1088 * through all the vdevs in the list and print out in an 1089 * appropriate hierarchy. 1090 */ 1091 (void) printf(gettext("would create '%s' with the " 1092 "following layout:\n\n"), poolname); 1093 1094 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 1095 if (num_logs(nvroot) > 0) 1096 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 1097 1098 ret = 0; 1099 } else { 1100 /* 1101 * Hand off to libzfs. 1102 */ 1103 if (enable_all_pool_feat) { 1104 spa_feature_t i; 1105 for (i = 0; i < SPA_FEATURES; i++) { 1106 char propname[MAXPATHLEN]; 1107 zfeature_info_t *feat = &spa_feature_table[i]; 1108 1109 (void) snprintf(propname, sizeof (propname), 1110 "feature@%s", feat->fi_uname); 1111 1112 /* 1113 * Skip feature if user specified it manually 1114 * on the command line. 1115 */ 1116 if (nvlist_exists(props, propname)) 1117 continue; 1118 1119 ret = add_prop_list(propname, 1120 ZFS_FEATURE_ENABLED, &props, B_TRUE); 1121 if (ret != 0) 1122 goto errout; 1123 } 1124 } 1125 1126 ret = 1; 1127 if (zpool_create(g_zfs, poolname, 1128 nvroot, props, fsprops) == 0) { 1129 zfs_handle_t *pool = zfs_open(g_zfs, poolname, 1130 ZFS_TYPE_FILESYSTEM); 1131 if (pool != NULL) { 1132 if (zfs_mount(pool, NULL, 0) == 0) 1133 ret = zfs_shareall(pool); 1134 zfs_close(pool); 1135 } 1136 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 1137 (void) fprintf(stderr, gettext("pool name may have " 1138 "been omitted\n")); 1139 } 1140 } 1141 1142 errout: 1143 nvlist_free(nvroot); 1144 nvlist_free(fsprops); 1145 nvlist_free(props); 1146 return (ret); 1147 badusage: 1148 nvlist_free(fsprops); 1149 nvlist_free(props); 1150 usage(B_FALSE); 1151 return (2); 1152 } 1153 1154 /* 1155 * zpool destroy <pool> 1156 * 1157 * -f Forcefully unmount any datasets 1158 * 1159 * Destroy the given pool. Automatically unmounts any datasets in the pool. 1160 */ 1161 int 1162 zpool_do_destroy(int argc, char **argv) 1163 { 1164 boolean_t force = B_FALSE; 1165 int c; 1166 char *pool; 1167 zpool_handle_t *zhp; 1168 int ret; 1169 1170 /* check options */ 1171 while ((c = getopt(argc, argv, "f")) != -1) { 1172 switch (c) { 1173 case 'f': 1174 force = B_TRUE; 1175 break; 1176 case '?': 1177 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1178 optopt); 1179 usage(B_FALSE); 1180 } 1181 } 1182 1183 argc -= optind; 1184 argv += optind; 1185 1186 /* check arguments */ 1187 if (argc < 1) { 1188 (void) fprintf(stderr, gettext("missing pool argument\n")); 1189 usage(B_FALSE); 1190 } 1191 if (argc > 1) { 1192 (void) fprintf(stderr, gettext("too many arguments\n")); 1193 usage(B_FALSE); 1194 } 1195 1196 pool = argv[0]; 1197 1198 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1199 /* 1200 * As a special case, check for use of '/' in the name, and 1201 * direct the user to use 'zfs destroy' instead. 1202 */ 1203 if (strchr(pool, '/') != NULL) 1204 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1205 "destroy a dataset\n")); 1206 return (1); 1207 } 1208 1209 if (zpool_disable_datasets(zhp, force) != 0) { 1210 (void) fprintf(stderr, gettext("could not destroy '%s': " 1211 "could not unmount datasets\n"), zpool_get_name(zhp)); 1212 return (1); 1213 } 1214 1215 /* The history must be logged as part of the export */ 1216 log_history = B_FALSE; 1217 1218 ret = (zpool_destroy(zhp, history_str) != 0); 1219 1220 zpool_close(zhp); 1221 1222 return (ret); 1223 } 1224 1225 /* 1226 * zpool export [-f] <pool> ... 1227 * 1228 * -f Forcefully unmount datasets 1229 * 1230 * Export the given pools. By default, the command will attempt to cleanly 1231 * unmount any active datasets within the pool. If the '-f' flag is specified, 1232 * then the datasets will be forcefully unmounted. 1233 */ 1234 int 1235 zpool_do_export(int argc, char **argv) 1236 { 1237 boolean_t force = B_FALSE; 1238 boolean_t hardforce = B_FALSE; 1239 int c; 1240 zpool_handle_t *zhp; 1241 int ret; 1242 int i; 1243 1244 /* check options */ 1245 while ((c = getopt(argc, argv, "fF")) != -1) { 1246 switch (c) { 1247 case 'f': 1248 force = B_TRUE; 1249 break; 1250 case 'F': 1251 hardforce = B_TRUE; 1252 break; 1253 case '?': 1254 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1255 optopt); 1256 usage(B_FALSE); 1257 } 1258 } 1259 1260 argc -= optind; 1261 argv += optind; 1262 1263 /* check arguments */ 1264 if (argc < 1) { 1265 (void) fprintf(stderr, gettext("missing pool argument\n")); 1266 usage(B_FALSE); 1267 } 1268 1269 ret = 0; 1270 for (i = 0; i < argc; i++) { 1271 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1272 ret = 1; 1273 continue; 1274 } 1275 1276 if (zpool_disable_datasets(zhp, force) != 0) { 1277 ret = 1; 1278 zpool_close(zhp); 1279 continue; 1280 } 1281 1282 /* The history must be logged as part of the export */ 1283 log_history = B_FALSE; 1284 1285 if (hardforce) { 1286 if (zpool_export_force(zhp, history_str) != 0) 1287 ret = 1; 1288 } else if (zpool_export(zhp, force, history_str) != 0) { 1289 ret = 1; 1290 } 1291 1292 zpool_close(zhp); 1293 } 1294 1295 return (ret); 1296 } 1297 1298 /* 1299 * Given a vdev configuration, determine the maximum width needed for the device 1300 * name column. 1301 */ 1302 static int 1303 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 1304 { 1305 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); 1306 nvlist_t **child; 1307 uint_t c, children; 1308 int ret; 1309 1310 if (strlen(name) + depth > max) 1311 max = strlen(name) + depth; 1312 1313 free(name); 1314 1315 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1316 &child, &children) == 0) { 1317 for (c = 0; c < children; c++) 1318 if ((ret = max_width(zhp, child[c], depth + 2, 1319 max)) > max) 1320 max = ret; 1321 } 1322 1323 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1324 &child, &children) == 0) { 1325 for (c = 0; c < children; c++) 1326 if ((ret = max_width(zhp, child[c], depth + 2, 1327 max)) > max) 1328 max = ret; 1329 } 1330 1331 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1332 &child, &children) == 0) { 1333 for (c = 0; c < children; c++) 1334 if ((ret = max_width(zhp, child[c], depth + 2, 1335 max)) > max) 1336 max = ret; 1337 } 1338 1339 1340 return (max); 1341 } 1342 1343 typedef struct spare_cbdata { 1344 uint64_t cb_guid; 1345 zpool_handle_t *cb_zhp; 1346 } spare_cbdata_t; 1347 1348 static boolean_t 1349 find_vdev(nvlist_t *nv, uint64_t search) 1350 { 1351 uint64_t guid; 1352 nvlist_t **child; 1353 uint_t c, children; 1354 1355 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1356 search == guid) 1357 return (B_TRUE); 1358 1359 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1360 &child, &children) == 0) { 1361 for (c = 0; c < children; c++) 1362 if (find_vdev(child[c], search)) 1363 return (B_TRUE); 1364 } 1365 1366 return (B_FALSE); 1367 } 1368 1369 static int 1370 find_spare(zpool_handle_t *zhp, void *data) 1371 { 1372 spare_cbdata_t *cbp = data; 1373 nvlist_t *config, *nvroot; 1374 1375 config = zpool_get_config(zhp, NULL); 1376 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1377 &nvroot) == 0); 1378 1379 if (find_vdev(nvroot, cbp->cb_guid)) { 1380 cbp->cb_zhp = zhp; 1381 return (1); 1382 } 1383 1384 zpool_close(zhp); 1385 return (0); 1386 } 1387 1388 /* 1389 * Print out configuration state as requested by status_callback. 1390 */ 1391 void 1392 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1393 int namewidth, int depth, boolean_t isspare) 1394 { 1395 nvlist_t **child; 1396 uint_t c, children; 1397 pool_scan_stat_t *ps = NULL; 1398 vdev_stat_t *vs; 1399 char rbuf[6], wbuf[6], cbuf[6]; 1400 char *vname; 1401 uint64_t notpresent; 1402 spare_cbdata_t cb; 1403 const char *state; 1404 1405 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1406 &child, &children) != 0) 1407 children = 0; 1408 1409 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1410 (uint64_t **)&vs, &c) == 0); 1411 1412 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1413 if (isspare) { 1414 /* 1415 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1416 * online drives. 1417 */ 1418 if (vs->vs_aux == VDEV_AUX_SPARED) 1419 state = "INUSE"; 1420 else if (vs->vs_state == VDEV_STATE_HEALTHY) 1421 state = "AVAIL"; 1422 } 1423 1424 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1425 name, state); 1426 1427 if (!isspare) { 1428 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1429 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1430 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1431 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1432 } 1433 1434 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1435 ¬present) == 0) { 1436 char *path; 1437 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1438 (void) printf(" was %s", path); 1439 } else if (vs->vs_aux != 0) { 1440 (void) printf(" "); 1441 1442 switch (vs->vs_aux) { 1443 case VDEV_AUX_OPEN_FAILED: 1444 (void) printf(gettext("cannot open")); 1445 break; 1446 1447 case VDEV_AUX_BAD_GUID_SUM: 1448 (void) printf(gettext("missing device")); 1449 break; 1450 1451 case VDEV_AUX_NO_REPLICAS: 1452 (void) printf(gettext("insufficient replicas")); 1453 break; 1454 1455 case VDEV_AUX_VERSION_NEWER: 1456 (void) printf(gettext("newer version")); 1457 break; 1458 1459 case VDEV_AUX_UNSUP_FEAT: 1460 (void) printf(gettext("unsupported feature(s)")); 1461 break; 1462 1463 case VDEV_AUX_SPARED: 1464 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1465 &cb.cb_guid) == 0); 1466 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1467 if (strcmp(zpool_get_name(cb.cb_zhp), 1468 zpool_get_name(zhp)) == 0) 1469 (void) printf(gettext("currently in " 1470 "use")); 1471 else 1472 (void) printf(gettext("in use by " 1473 "pool '%s'"), 1474 zpool_get_name(cb.cb_zhp)); 1475 zpool_close(cb.cb_zhp); 1476 } else { 1477 (void) printf(gettext("currently in use")); 1478 } 1479 break; 1480 1481 case VDEV_AUX_ERR_EXCEEDED: 1482 (void) printf(gettext("too many errors")); 1483 break; 1484 1485 case VDEV_AUX_IO_FAILURE: 1486 (void) printf(gettext("experienced I/O failures")); 1487 break; 1488 1489 case VDEV_AUX_BAD_LOG: 1490 (void) printf(gettext("bad intent log")); 1491 break; 1492 1493 case VDEV_AUX_EXTERNAL: 1494 (void) printf(gettext("external device fault")); 1495 break; 1496 1497 case VDEV_AUX_SPLIT_POOL: 1498 (void) printf(gettext("split into new pool")); 1499 break; 1500 1501 default: 1502 (void) printf(gettext("corrupted data")); 1503 break; 1504 } 1505 } 1506 1507 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, 1508 (uint64_t **)&ps, &c); 1509 1510 if (ps && ps->pss_state == DSS_SCANNING && 1511 vs->vs_scan_processed != 0 && children == 0) { 1512 (void) printf(gettext(" (%s)"), 1513 (ps->pss_func == POOL_SCAN_RESILVER) ? 1514 "resilvering" : "repairing"); 1515 } 1516 1517 (void) printf("\n"); 1518 1519 for (c = 0; c < children; c++) { 1520 uint64_t islog = B_FALSE, ishole = B_FALSE; 1521 1522 /* Don't print logs or holes here */ 1523 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1524 &islog); 1525 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 1526 &ishole); 1527 if (islog || ishole) 1528 continue; 1529 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1530 print_status_config(zhp, vname, child[c], 1531 namewidth, depth + 2, isspare); 1532 free(vname); 1533 } 1534 } 1535 1536 1537 /* 1538 * Print the configuration of an exported pool. Iterate over all vdevs in the 1539 * pool, printing out the name and status for each one. 1540 */ 1541 void 1542 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1543 { 1544 nvlist_t **child; 1545 uint_t c, children; 1546 vdev_stat_t *vs; 1547 char *type, *vname; 1548 1549 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1550 if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 1551 strcmp(type, VDEV_TYPE_HOLE) == 0) 1552 return; 1553 1554 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1555 (uint64_t **)&vs, &c) == 0); 1556 1557 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1558 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1559 1560 if (vs->vs_aux != 0) { 1561 (void) printf(" "); 1562 1563 switch (vs->vs_aux) { 1564 case VDEV_AUX_OPEN_FAILED: 1565 (void) printf(gettext("cannot open")); 1566 break; 1567 1568 case VDEV_AUX_BAD_GUID_SUM: 1569 (void) printf(gettext("missing device")); 1570 break; 1571 1572 case VDEV_AUX_NO_REPLICAS: 1573 (void) printf(gettext("insufficient replicas")); 1574 break; 1575 1576 case VDEV_AUX_VERSION_NEWER: 1577 (void) printf(gettext("newer version")); 1578 break; 1579 1580 case VDEV_AUX_UNSUP_FEAT: 1581 (void) printf(gettext("unsupported feature(s)")); 1582 break; 1583 1584 case VDEV_AUX_ERR_EXCEEDED: 1585 (void) printf(gettext("too many errors")); 1586 break; 1587 1588 default: 1589 (void) printf(gettext("corrupted data")); 1590 break; 1591 } 1592 } 1593 (void) printf("\n"); 1594 1595 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1596 &child, &children) != 0) 1597 return; 1598 1599 for (c = 0; c < children; c++) { 1600 uint64_t is_log = B_FALSE; 1601 1602 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1603 &is_log); 1604 if (is_log) 1605 continue; 1606 1607 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE); 1608 print_import_config(vname, child[c], namewidth, depth + 2); 1609 free(vname); 1610 } 1611 1612 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1613 &child, &children) == 0) { 1614 (void) printf(gettext("\tcache\n")); 1615 for (c = 0; c < children; c++) { 1616 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1617 (void) printf("\t %s\n", vname); 1618 free(vname); 1619 } 1620 } 1621 1622 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1623 &child, &children) == 0) { 1624 (void) printf(gettext("\tspares\n")); 1625 for (c = 0; c < children; c++) { 1626 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1627 (void) printf("\t %s\n", vname); 1628 free(vname); 1629 } 1630 } 1631 } 1632 1633 /* 1634 * Print log vdevs. 1635 * Logs are recorded as top level vdevs in the main pool child array 1636 * but with "is_log" set to 1. We use either print_status_config() or 1637 * print_import_config() to print the top level logs then any log 1638 * children (eg mirrored slogs) are printed recursively - which 1639 * works because only the top level vdev is marked "is_log" 1640 */ 1641 static void 1642 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1643 { 1644 uint_t c, children; 1645 nvlist_t **child; 1646 1647 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1648 &children) != 0) 1649 return; 1650 1651 (void) printf(gettext("\tlogs\n")); 1652 1653 for (c = 0; c < children; c++) { 1654 uint64_t is_log = B_FALSE; 1655 char *name; 1656 1657 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1658 &is_log); 1659 if (!is_log) 1660 continue; 1661 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1662 if (verbose) 1663 print_status_config(zhp, name, child[c], namewidth, 1664 2, B_FALSE); 1665 else 1666 print_import_config(name, child[c], namewidth, 2); 1667 free(name); 1668 } 1669 } 1670 1671 /* 1672 * Display the status for the given pool. 1673 */ 1674 static void 1675 show_import(nvlist_t *config) 1676 { 1677 uint64_t pool_state; 1678 vdev_stat_t *vs; 1679 char *name; 1680 uint64_t guid; 1681 char *msgid; 1682 nvlist_t *nvroot; 1683 int reason; 1684 const char *health; 1685 uint_t vsc; 1686 int namewidth; 1687 char *comment; 1688 1689 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1690 &name) == 0); 1691 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1692 &guid) == 0); 1693 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1694 &pool_state) == 0); 1695 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1696 &nvroot) == 0); 1697 1698 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 1699 (uint64_t **)&vs, &vsc) == 0); 1700 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1701 1702 reason = zpool_import_status(config, &msgid); 1703 1704 (void) printf(gettext(" pool: %s\n"), name); 1705 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1706 (void) printf(gettext(" state: %s"), health); 1707 if (pool_state == POOL_STATE_DESTROYED) 1708 (void) printf(gettext(" (DESTROYED)")); 1709 (void) printf("\n"); 1710 1711 switch (reason) { 1712 case ZPOOL_STATUS_MISSING_DEV_R: 1713 case ZPOOL_STATUS_MISSING_DEV_NR: 1714 case ZPOOL_STATUS_BAD_GUID_SUM: 1715 (void) printf(gettext(" status: One or more devices are " 1716 "missing from the system.\n")); 1717 break; 1718 1719 case ZPOOL_STATUS_CORRUPT_LABEL_R: 1720 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1721 (void) printf(gettext(" status: One or more devices contains " 1722 "corrupted data.\n")); 1723 break; 1724 1725 case ZPOOL_STATUS_CORRUPT_DATA: 1726 (void) printf( 1727 gettext(" status: The pool data is corrupted.\n")); 1728 break; 1729 1730 case ZPOOL_STATUS_OFFLINE_DEV: 1731 (void) printf(gettext(" status: One or more devices " 1732 "are offlined.\n")); 1733 break; 1734 1735 case ZPOOL_STATUS_CORRUPT_POOL: 1736 (void) printf(gettext(" status: The pool metadata is " 1737 "corrupted.\n")); 1738 break; 1739 1740 case ZPOOL_STATUS_VERSION_OLDER: 1741 (void) printf(gettext(" status: The pool is formatted using a " 1742 "legacy on-disk version.\n")); 1743 break; 1744 1745 case ZPOOL_STATUS_VERSION_NEWER: 1746 (void) printf(gettext(" status: The pool is formatted using an " 1747 "incompatible version.\n")); 1748 break; 1749 1750 case ZPOOL_STATUS_FEAT_DISABLED: 1751 (void) printf(gettext(" status: Some supported features are " 1752 "not enabled on the pool.\n")); 1753 break; 1754 1755 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1756 (void) printf(gettext("status: The pool uses the following " 1757 "feature(s) not supported on this sytem:\n")); 1758 zpool_print_unsup_feat(config); 1759 break; 1760 1761 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1762 (void) printf(gettext("status: The pool can only be accessed " 1763 "in read-only mode on this system. It\n\tcannot be " 1764 "accessed in read-write mode because it uses the " 1765 "following\n\tfeature(s) not supported on this system:\n")); 1766 zpool_print_unsup_feat(config); 1767 break; 1768 1769 case ZPOOL_STATUS_HOSTID_MISMATCH: 1770 (void) printf(gettext(" status: The pool was last accessed by " 1771 "another system.\n")); 1772 break; 1773 1774 case ZPOOL_STATUS_FAULTED_DEV_R: 1775 case ZPOOL_STATUS_FAULTED_DEV_NR: 1776 (void) printf(gettext(" status: One or more devices are " 1777 "faulted.\n")); 1778 break; 1779 1780 case ZPOOL_STATUS_BAD_LOG: 1781 (void) printf(gettext(" status: An intent log record cannot be " 1782 "read.\n")); 1783 break; 1784 1785 case ZPOOL_STATUS_RESILVERING: 1786 (void) printf(gettext(" status: One or more devices were being " 1787 "resilvered.\n")); 1788 break; 1789 1790 default: 1791 /* 1792 * No other status can be seen when importing pools. 1793 */ 1794 assert(reason == ZPOOL_STATUS_OK); 1795 } 1796 1797 /* 1798 * Print out an action according to the overall state of the pool. 1799 */ 1800 if (vs->vs_state == VDEV_STATE_HEALTHY) { 1801 if (reason == ZPOOL_STATUS_VERSION_OLDER || 1802 reason == ZPOOL_STATUS_FEAT_DISABLED) { 1803 (void) printf(gettext(" action: The pool can be " 1804 "imported using its name or numeric identifier, " 1805 "though\n\tsome features will not be available " 1806 "without an explicit 'zpool upgrade'.\n")); 1807 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 1808 (void) printf(gettext(" action: The pool can be " 1809 "imported using its name or numeric " 1810 "identifier and\n\tthe '-f' flag.\n")); 1811 } else { 1812 (void) printf(gettext(" action: The pool can be " 1813 "imported using its name or numeric " 1814 "identifier.\n")); 1815 } 1816 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1817 (void) printf(gettext(" action: The pool can be imported " 1818 "despite missing or damaged devices. The\n\tfault " 1819 "tolerance of the pool may be compromised if imported.\n")); 1820 } else { 1821 switch (reason) { 1822 case ZPOOL_STATUS_VERSION_NEWER: 1823 (void) printf(gettext(" action: The pool cannot be " 1824 "imported. Access the pool on a system running " 1825 "newer\n\tsoftware, or recreate the pool from " 1826 "backup.\n")); 1827 break; 1828 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1829 (void) printf(gettext("action: The pool cannot be " 1830 "imported. Access the pool on a system that " 1831 "supports\n\tthe required feature(s), or recreate " 1832 "the pool from backup.\n")); 1833 break; 1834 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1835 (void) printf(gettext("action: The pool cannot be " 1836 "imported in read-write mode. Import the pool " 1837 "with\n" 1838 "\t\"-o readonly=on\", access the pool on a system " 1839 "that supports the\n\trequired feature(s), or " 1840 "recreate the pool from backup.\n")); 1841 break; 1842 case ZPOOL_STATUS_MISSING_DEV_R: 1843 case ZPOOL_STATUS_MISSING_DEV_NR: 1844 case ZPOOL_STATUS_BAD_GUID_SUM: 1845 (void) printf(gettext(" action: The pool cannot be " 1846 "imported. Attach the missing\n\tdevices and try " 1847 "again.\n")); 1848 break; 1849 default: 1850 (void) printf(gettext(" action: The pool cannot be " 1851 "imported due to damaged devices or data.\n")); 1852 } 1853 } 1854 1855 /* Print the comment attached to the pool. */ 1856 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 1857 (void) printf(gettext("comment: %s\n"), comment); 1858 1859 /* 1860 * If the state is "closed" or "can't open", and the aux state 1861 * is "corrupt data": 1862 */ 1863 if (((vs->vs_state == VDEV_STATE_CLOSED) || 1864 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 1865 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1866 if (pool_state == POOL_STATE_DESTROYED) 1867 (void) printf(gettext("\tThe pool was destroyed, " 1868 "but can be imported using the '-Df' flags.\n")); 1869 else if (pool_state != POOL_STATE_EXPORTED) 1870 (void) printf(gettext("\tThe pool may be active on " 1871 "another system, but can be imported using\n\t" 1872 "the '-f' flag.\n")); 1873 } 1874 1875 if (msgid != NULL) 1876 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 1877 msgid); 1878 1879 (void) printf(gettext(" config:\n\n")); 1880 1881 namewidth = max_width(NULL, nvroot, 0, 0); 1882 if (namewidth < 10) 1883 namewidth = 10; 1884 1885 print_import_config(name, nvroot, namewidth, 0); 1886 if (num_logs(nvroot) > 0) 1887 print_logs(NULL, nvroot, namewidth, B_FALSE); 1888 1889 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 1890 (void) printf(gettext("\n\tAdditional devices are known to " 1891 "be part of this pool, though their\n\texact " 1892 "configuration cannot be determined.\n")); 1893 } 1894 } 1895 1896 /* 1897 * Perform the import for the given configuration. This passes the heavy 1898 * lifting off to zpool_import_props(), and then mounts the datasets contained 1899 * within the pool. 1900 */ 1901 static int 1902 do_import(nvlist_t *config, const char *newname, const char *mntopts, 1903 nvlist_t *props, int flags) 1904 { 1905 zpool_handle_t *zhp; 1906 char *name; 1907 uint64_t state; 1908 uint64_t version; 1909 1910 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1911 &name) == 0); 1912 1913 verify(nvlist_lookup_uint64(config, 1914 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1915 verify(nvlist_lookup_uint64(config, 1916 ZPOOL_CONFIG_VERSION, &version) == 0); 1917 if (!SPA_VERSION_IS_SUPPORTED(version)) { 1918 (void) fprintf(stderr, gettext("cannot import '%s': pool " 1919 "is formatted using an unsupported ZFS version\n"), name); 1920 return (1); 1921 } else if (state != POOL_STATE_EXPORTED && 1922 !(flags & ZFS_IMPORT_ANY_HOST)) { 1923 uint64_t hostid; 1924 1925 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 1926 &hostid) == 0) { 1927 if ((unsigned long)hostid != gethostid()) { 1928 char *hostname; 1929 uint64_t timestamp; 1930 time_t t; 1931 1932 verify(nvlist_lookup_string(config, 1933 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 1934 verify(nvlist_lookup_uint64(config, 1935 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 1936 t = timestamp; 1937 (void) fprintf(stderr, gettext("cannot import " 1938 "'%s': pool may be in use from other " 1939 "system, it was last accessed by %s " 1940 "(hostid: 0x%lx) on %s"), name, hostname, 1941 (unsigned long)hostid, 1942 asctime(localtime(&t))); 1943 (void) fprintf(stderr, gettext("use '-f' to " 1944 "import anyway\n")); 1945 return (1); 1946 } 1947 } else { 1948 (void) fprintf(stderr, gettext("cannot import '%s': " 1949 "pool may be in use from other system\n"), name); 1950 (void) fprintf(stderr, gettext("use '-f' to import " 1951 "anyway\n")); 1952 return (1); 1953 } 1954 } 1955 1956 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 1957 return (1); 1958 1959 if (newname != NULL) 1960 name = (char *)newname; 1961 1962 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 1963 return (1); 1964 1965 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 1966 !(flags & ZFS_IMPORT_ONLY) && 1967 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 1968 zpool_close(zhp); 1969 return (1); 1970 } 1971 1972 zpool_close(zhp); 1973 return (0); 1974 } 1975 1976 /* 1977 * zpool import [-d dir] [-D] 1978 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1979 * [-d dir | -c cachefile] [-f] -a 1980 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1981 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool] 1982 * 1983 * -c Read pool information from a cachefile instead of searching 1984 * devices. 1985 * 1986 * -d Scan in a specific directory, other than /dev/dsk. More than 1987 * one directory can be specified using multiple '-d' options. 1988 * 1989 * -D Scan for previously destroyed pools or import all or only 1990 * specified destroyed pools. 1991 * 1992 * -R Temporarily import the pool, with all mountpoints relative to 1993 * the given root. The pool will remain exported when the machine 1994 * is rebooted. 1995 * 1996 * -V Import even in the presence of faulted vdevs. This is an 1997 * intentionally undocumented option for testing purposes, and 1998 * treats the pool configuration as complete, leaving any bad 1999 * vdevs in the FAULTED state. In other words, it does verbatim 2000 * import. 2001 * 2002 * -f Force import, even if it appears that the pool is active. 2003 * 2004 * -F Attempt rewind if necessary. 2005 * 2006 * -n See if rewind would work, but don't actually rewind. 2007 * 2008 * -N Import the pool but don't mount datasets. 2009 * 2010 * -T Specify a starting txg to use for import. This option is 2011 * intentionally undocumented option for testing purposes. 2012 * 2013 * -a Import all pools found. 2014 * 2015 * -o Set property=value and/or temporary mount options (without '='). 2016 * 2017 * The import command scans for pools to import, and import pools based on pool 2018 * name and GUID. The pool can also be renamed as part of the import process. 2019 */ 2020 int 2021 zpool_do_import(int argc, char **argv) 2022 { 2023 char **searchdirs = NULL; 2024 int nsearch = 0; 2025 int c; 2026 int err = 0; 2027 nvlist_t *pools = NULL; 2028 boolean_t do_all = B_FALSE; 2029 boolean_t do_destroyed = B_FALSE; 2030 char *mntopts = NULL; 2031 nvpair_t *elem; 2032 nvlist_t *config; 2033 uint64_t searchguid = 0; 2034 char *searchname = NULL; 2035 char *propval; 2036 nvlist_t *found_config; 2037 nvlist_t *policy = NULL; 2038 nvlist_t *props = NULL; 2039 boolean_t first; 2040 int flags = ZFS_IMPORT_NORMAL; 2041 uint32_t rewind_policy = ZPOOL_NO_REWIND; 2042 boolean_t dryrun = B_FALSE; 2043 boolean_t do_rewind = B_FALSE; 2044 boolean_t xtreme_rewind = B_FALSE; 2045 uint64_t pool_state, txg = -1ULL; 2046 char *cachefile = NULL; 2047 importargs_t idata = { 0 }; 2048 char *endptr; 2049 2050 /* check options */ 2051 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) { 2052 switch (c) { 2053 case 'a': 2054 do_all = B_TRUE; 2055 break; 2056 case 'c': 2057 cachefile = optarg; 2058 break; 2059 case 'd': 2060 if (searchdirs == NULL) { 2061 searchdirs = safe_malloc(sizeof (char *)); 2062 } else { 2063 char **tmp = safe_malloc((nsearch + 1) * 2064 sizeof (char *)); 2065 bcopy(searchdirs, tmp, nsearch * 2066 sizeof (char *)); 2067 free(searchdirs); 2068 searchdirs = tmp; 2069 } 2070 searchdirs[nsearch++] = optarg; 2071 break; 2072 case 'D': 2073 do_destroyed = B_TRUE; 2074 break; 2075 case 'f': 2076 flags |= ZFS_IMPORT_ANY_HOST; 2077 break; 2078 case 'F': 2079 do_rewind = B_TRUE; 2080 break; 2081 case 'm': 2082 flags |= ZFS_IMPORT_MISSING_LOG; 2083 break; 2084 case 'n': 2085 dryrun = B_TRUE; 2086 break; 2087 case 'N': 2088 flags |= ZFS_IMPORT_ONLY; 2089 break; 2090 case 'o': 2091 if ((propval = strchr(optarg, '=')) != NULL) { 2092 *propval = '\0'; 2093 propval++; 2094 if (add_prop_list(optarg, propval, 2095 &props, B_TRUE)) 2096 goto error; 2097 } else { 2098 mntopts = optarg; 2099 } 2100 break; 2101 case 'R': 2102 if (add_prop_list(zpool_prop_to_name( 2103 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2104 goto error; 2105 if (nvlist_lookup_string(props, 2106 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 2107 &propval) == 0) 2108 break; 2109 if (add_prop_list(zpool_prop_to_name( 2110 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2111 goto error; 2112 break; 2113 case 'T': 2114 errno = 0; 2115 txg = strtoull(optarg, &endptr, 0); 2116 if (errno != 0 || *endptr != '\0') { 2117 (void) fprintf(stderr, 2118 gettext("invalid txg value\n")); 2119 usage(B_FALSE); 2120 } 2121 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2122 break; 2123 case 'V': 2124 flags |= ZFS_IMPORT_VERBATIM; 2125 break; 2126 case 'X': 2127 xtreme_rewind = B_TRUE; 2128 break; 2129 case ':': 2130 (void) fprintf(stderr, gettext("missing argument for " 2131 "'%c' option\n"), optopt); 2132 usage(B_FALSE); 2133 break; 2134 case '?': 2135 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2136 optopt); 2137 usage(B_FALSE); 2138 } 2139 } 2140 2141 argc -= optind; 2142 argv += optind; 2143 2144 if (cachefile && nsearch != 0) { 2145 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 2146 usage(B_FALSE); 2147 } 2148 2149 if ((dryrun || xtreme_rewind) && !do_rewind) { 2150 (void) fprintf(stderr, 2151 gettext("-n or -X only meaningful with -F\n")); 2152 usage(B_FALSE); 2153 } 2154 if (dryrun) 2155 rewind_policy = ZPOOL_TRY_REWIND; 2156 else if (do_rewind) 2157 rewind_policy = ZPOOL_DO_REWIND; 2158 if (xtreme_rewind) 2159 rewind_policy |= ZPOOL_EXTREME_REWIND; 2160 2161 /* In the future, we can capture further policy and include it here */ 2162 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 2163 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 || 2164 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 2165 goto error; 2166 2167 if (searchdirs == NULL) { 2168 searchdirs = safe_malloc(sizeof (char *)); 2169 searchdirs[0] = ZFS_DISK_ROOT; 2170 nsearch = 1; 2171 } 2172 2173 /* check argument count */ 2174 if (do_all) { 2175 if (argc != 0) { 2176 (void) fprintf(stderr, gettext("too many arguments\n")); 2177 usage(B_FALSE); 2178 } 2179 } else { 2180 if (argc > 2) { 2181 (void) fprintf(stderr, gettext("too many arguments\n")); 2182 usage(B_FALSE); 2183 } 2184 2185 /* 2186 * Check for the SYS_CONFIG privilege. We do this explicitly 2187 * here because otherwise any attempt to discover pools will 2188 * silently fail. 2189 */ 2190 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2191 (void) fprintf(stderr, gettext("cannot " 2192 "discover pools: permission denied\n")); 2193 free(searchdirs); 2194 nvlist_free(policy); 2195 return (1); 2196 } 2197 } 2198 2199 /* 2200 * Depending on the arguments given, we do one of the following: 2201 * 2202 * <none> Iterate through all pools and display information about 2203 * each one. 2204 * 2205 * -a Iterate through all pools and try to import each one. 2206 * 2207 * <id> Find the pool that corresponds to the given GUID/pool 2208 * name and import that one. 2209 * 2210 * -D Above options applies only to destroyed pools. 2211 */ 2212 if (argc != 0) { 2213 char *endptr; 2214 2215 errno = 0; 2216 searchguid = strtoull(argv[0], &endptr, 10); 2217 if (errno != 0 || *endptr != '\0') { 2218 searchname = argv[0]; 2219 searchguid = 0; 2220 } 2221 found_config = NULL; 2222 2223 /* 2224 * User specified a name or guid. Ensure it's unique. 2225 */ 2226 idata.unique = B_TRUE; 2227 } 2228 2229 2230 idata.path = searchdirs; 2231 idata.paths = nsearch; 2232 idata.poolname = searchname; 2233 idata.guid = searchguid; 2234 idata.cachefile = cachefile; 2235 2236 pools = zpool_search_import(g_zfs, &idata); 2237 2238 if (pools != NULL && idata.exists && 2239 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2240 (void) fprintf(stderr, gettext("cannot import '%s': " 2241 "a pool with that name already exists\n"), 2242 argv[0]); 2243 (void) fprintf(stderr, gettext("use the form '%s " 2244 "<pool | id> <newpool>' to give it a new name\n"), 2245 "zpool import"); 2246 err = 1; 2247 } else if (pools == NULL && idata.exists) { 2248 (void) fprintf(stderr, gettext("cannot import '%s': " 2249 "a pool with that name is already created/imported,\n"), 2250 argv[0]); 2251 (void) fprintf(stderr, gettext("and no additional pools " 2252 "with that name were found\n")); 2253 err = 1; 2254 } else if (pools == NULL) { 2255 if (argc != 0) { 2256 (void) fprintf(stderr, gettext("cannot import '%s': " 2257 "no such pool available\n"), argv[0]); 2258 } 2259 err = 1; 2260 } 2261 2262 if (err == 1) { 2263 free(searchdirs); 2264 nvlist_free(policy); 2265 return (1); 2266 } 2267 2268 /* 2269 * At this point we have a list of import candidate configs. Even if 2270 * we were searching by pool name or guid, we still need to 2271 * post-process the list to deal with pool state and possible 2272 * duplicate names. 2273 */ 2274 err = 0; 2275 elem = NULL; 2276 first = B_TRUE; 2277 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2278 2279 verify(nvpair_value_nvlist(elem, &config) == 0); 2280 2281 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2282 &pool_state) == 0); 2283 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 2284 continue; 2285 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 2286 continue; 2287 2288 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY, 2289 policy) == 0); 2290 2291 if (argc == 0) { 2292 if (first) 2293 first = B_FALSE; 2294 else if (!do_all) 2295 (void) printf("\n"); 2296 2297 if (do_all) { 2298 err |= do_import(config, NULL, mntopts, 2299 props, flags); 2300 } else { 2301 show_import(config); 2302 } 2303 } else if (searchname != NULL) { 2304 char *name; 2305 2306 /* 2307 * We are searching for a pool based on name. 2308 */ 2309 verify(nvlist_lookup_string(config, 2310 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2311 2312 if (strcmp(name, searchname) == 0) { 2313 if (found_config != NULL) { 2314 (void) fprintf(stderr, gettext( 2315 "cannot import '%s': more than " 2316 "one matching pool\n"), searchname); 2317 (void) fprintf(stderr, gettext( 2318 "import by numeric ID instead\n")); 2319 err = B_TRUE; 2320 } 2321 found_config = config; 2322 } 2323 } else { 2324 uint64_t guid; 2325 2326 /* 2327 * Search for a pool by guid. 2328 */ 2329 verify(nvlist_lookup_uint64(config, 2330 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 2331 2332 if (guid == searchguid) 2333 found_config = config; 2334 } 2335 } 2336 2337 /* 2338 * If we were searching for a specific pool, verify that we found a 2339 * pool, and then do the import. 2340 */ 2341 if (argc != 0 && err == 0) { 2342 if (found_config == NULL) { 2343 (void) fprintf(stderr, gettext("cannot import '%s': " 2344 "no such pool available\n"), argv[0]); 2345 err = B_TRUE; 2346 } else { 2347 err |= do_import(found_config, argc == 1 ? NULL : 2348 argv[1], mntopts, props, flags); 2349 } 2350 } 2351 2352 /* 2353 * If we were just looking for pools, report an error if none were 2354 * found. 2355 */ 2356 if (argc == 0 && first) 2357 (void) fprintf(stderr, 2358 gettext("no pools available to import\n")); 2359 2360 error: 2361 nvlist_free(props); 2362 nvlist_free(pools); 2363 nvlist_free(policy); 2364 free(searchdirs); 2365 2366 return (err ? 1 : 0); 2367 } 2368 2369 typedef struct iostat_cbdata { 2370 boolean_t cb_verbose; 2371 int cb_namewidth; 2372 int cb_iteration; 2373 zpool_list_t *cb_list; 2374 } iostat_cbdata_t; 2375 2376 static void 2377 print_iostat_separator(iostat_cbdata_t *cb) 2378 { 2379 int i = 0; 2380 2381 for (i = 0; i < cb->cb_namewidth; i++) 2382 (void) printf("-"); 2383 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 2384 } 2385 2386 static void 2387 print_iostat_header(iostat_cbdata_t *cb) 2388 { 2389 (void) printf("%*s capacity operations bandwidth\n", 2390 cb->cb_namewidth, ""); 2391 (void) printf("%-*s alloc free read write read write\n", 2392 cb->cb_namewidth, "pool"); 2393 print_iostat_separator(cb); 2394 } 2395 2396 /* 2397 * Display a single statistic. 2398 */ 2399 static void 2400 print_one_stat(uint64_t value) 2401 { 2402 char buf[64]; 2403 2404 zfs_nicenum(value, buf, sizeof (buf)); 2405 (void) printf(" %5s", buf); 2406 } 2407 2408 /* 2409 * Print out all the statistics for the given vdev. This can either be the 2410 * toplevel configuration, or called recursively. If 'name' is NULL, then this 2411 * is a verbose output, and we don't want to display the toplevel pool stats. 2412 */ 2413 void 2414 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 2415 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 2416 { 2417 nvlist_t **oldchild, **newchild; 2418 uint_t c, children; 2419 vdev_stat_t *oldvs, *newvs; 2420 vdev_stat_t zerovs = { 0 }; 2421 uint64_t tdelta; 2422 double scale; 2423 char *vname; 2424 2425 if (oldnv != NULL) { 2426 verify(nvlist_lookup_uint64_array(oldnv, 2427 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 2428 } else { 2429 oldvs = &zerovs; 2430 } 2431 2432 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 2433 (uint64_t **)&newvs, &c) == 0); 2434 2435 if (strlen(name) + depth > cb->cb_namewidth) 2436 (void) printf("%*s%s", depth, "", name); 2437 else 2438 (void) printf("%*s%s%*s", depth, "", name, 2439 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 2440 2441 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 2442 2443 if (tdelta == 0) 2444 scale = 1.0; 2445 else 2446 scale = (double)NANOSEC / tdelta; 2447 2448 /* only toplevel vdevs have capacity stats */ 2449 if (newvs->vs_space == 0) { 2450 (void) printf(" - -"); 2451 } else { 2452 print_one_stat(newvs->vs_alloc); 2453 print_one_stat(newvs->vs_space - newvs->vs_alloc); 2454 } 2455 2456 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 2457 oldvs->vs_ops[ZIO_TYPE_READ]))); 2458 2459 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 2460 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 2461 2462 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 2463 oldvs->vs_bytes[ZIO_TYPE_READ]))); 2464 2465 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 2466 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 2467 2468 (void) printf("\n"); 2469 2470 if (!cb->cb_verbose) 2471 return; 2472 2473 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 2474 &newchild, &children) != 0) 2475 return; 2476 2477 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 2478 &oldchild, &c) != 0) 2479 return; 2480 2481 for (c = 0; c < children; c++) { 2482 uint64_t ishole = B_FALSE, islog = B_FALSE; 2483 2484 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 2485 &ishole); 2486 2487 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 2488 &islog); 2489 2490 if (ishole || islog) 2491 continue; 2492 2493 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); 2494 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2495 newchild[c], cb, depth + 2); 2496 free(vname); 2497 } 2498 2499 /* 2500 * Log device section 2501 */ 2502 2503 if (num_logs(newnv) > 0) { 2504 (void) printf("%-*s - - - - - " 2505 "-\n", cb->cb_namewidth, "logs"); 2506 2507 for (c = 0; c < children; c++) { 2508 uint64_t islog = B_FALSE; 2509 (void) nvlist_lookup_uint64(newchild[c], 2510 ZPOOL_CONFIG_IS_LOG, &islog); 2511 2512 if (islog) { 2513 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2514 B_FALSE); 2515 print_vdev_stats(zhp, vname, oldnv ? 2516 oldchild[c] : NULL, newchild[c], 2517 cb, depth + 2); 2518 free(vname); 2519 } 2520 } 2521 2522 } 2523 2524 /* 2525 * Include level 2 ARC devices in iostat output 2526 */ 2527 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 2528 &newchild, &children) != 0) 2529 return; 2530 2531 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 2532 &oldchild, &c) != 0) 2533 return; 2534 2535 if (children > 0) { 2536 (void) printf("%-*s - - - - - " 2537 "-\n", cb->cb_namewidth, "cache"); 2538 for (c = 0; c < children; c++) { 2539 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2540 B_FALSE); 2541 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2542 newchild[c], cb, depth + 2); 2543 free(vname); 2544 } 2545 } 2546 } 2547 2548 static int 2549 refresh_iostat(zpool_handle_t *zhp, void *data) 2550 { 2551 iostat_cbdata_t *cb = data; 2552 boolean_t missing; 2553 2554 /* 2555 * If the pool has disappeared, remove it from the list and continue. 2556 */ 2557 if (zpool_refresh_stats(zhp, &missing) != 0) 2558 return (-1); 2559 2560 if (missing) 2561 pool_list_remove(cb->cb_list, zhp); 2562 2563 return (0); 2564 } 2565 2566 /* 2567 * Callback to print out the iostats for the given pool. 2568 */ 2569 int 2570 print_iostat(zpool_handle_t *zhp, void *data) 2571 { 2572 iostat_cbdata_t *cb = data; 2573 nvlist_t *oldconfig, *newconfig; 2574 nvlist_t *oldnvroot, *newnvroot; 2575 2576 newconfig = zpool_get_config(zhp, &oldconfig); 2577 2578 if (cb->cb_iteration == 1) 2579 oldconfig = NULL; 2580 2581 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2582 &newnvroot) == 0); 2583 2584 if (oldconfig == NULL) 2585 oldnvroot = NULL; 2586 else 2587 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2588 &oldnvroot) == 0); 2589 2590 /* 2591 * Print out the statistics for the pool. 2592 */ 2593 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2594 2595 if (cb->cb_verbose) 2596 print_iostat_separator(cb); 2597 2598 return (0); 2599 } 2600 2601 int 2602 get_namewidth(zpool_handle_t *zhp, void *data) 2603 { 2604 iostat_cbdata_t *cb = data; 2605 nvlist_t *config, *nvroot; 2606 2607 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2608 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2609 &nvroot) == 0); 2610 if (!cb->cb_verbose) 2611 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2612 else 2613 cb->cb_namewidth = max_width(zhp, nvroot, 0, 2614 cb->cb_namewidth); 2615 } 2616 2617 /* 2618 * The width must fall into the range [10,38]. The upper limit is the 2619 * maximum we can have and still fit in 80 columns. 2620 */ 2621 if (cb->cb_namewidth < 10) 2622 cb->cb_namewidth = 10; 2623 if (cb->cb_namewidth > 38) 2624 cb->cb_namewidth = 38; 2625 2626 return (0); 2627 } 2628 2629 /* 2630 * Parse the input string, get the 'interval' and 'count' value if there is one. 2631 */ 2632 static void 2633 get_interval_count(int *argcp, char **argv, unsigned long *iv, 2634 unsigned long *cnt) 2635 { 2636 unsigned long interval = 0, count = 0; 2637 int argc = *argcp, errno; 2638 2639 /* 2640 * Determine if the last argument is an integer or a pool name 2641 */ 2642 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2643 char *end; 2644 2645 errno = 0; 2646 interval = strtoul(argv[argc - 1], &end, 10); 2647 2648 if (*end == '\0' && errno == 0) { 2649 if (interval == 0) { 2650 (void) fprintf(stderr, gettext("interval " 2651 "cannot be zero\n")); 2652 usage(B_FALSE); 2653 } 2654 /* 2655 * Ignore the last parameter 2656 */ 2657 argc--; 2658 } else { 2659 /* 2660 * If this is not a valid number, just plow on. The 2661 * user will get a more informative error message later 2662 * on. 2663 */ 2664 interval = 0; 2665 } 2666 } 2667 2668 /* 2669 * If the last argument is also an integer, then we have both a count 2670 * and an interval. 2671 */ 2672 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2673 char *end; 2674 2675 errno = 0; 2676 count = interval; 2677 interval = strtoul(argv[argc - 1], &end, 10); 2678 2679 if (*end == '\0' && errno == 0) { 2680 if (interval == 0) { 2681 (void) fprintf(stderr, gettext("interval " 2682 "cannot be zero\n")); 2683 usage(B_FALSE); 2684 } 2685 2686 /* 2687 * Ignore the last parameter 2688 */ 2689 argc--; 2690 } else { 2691 interval = 0; 2692 } 2693 } 2694 2695 *iv = interval; 2696 *cnt = count; 2697 *argcp = argc; 2698 } 2699 2700 static void 2701 get_timestamp_arg(char c) 2702 { 2703 if (c == 'u') 2704 timestamp_fmt = UDATE; 2705 else if (c == 'd') 2706 timestamp_fmt = DDATE; 2707 else 2708 usage(B_FALSE); 2709 } 2710 2711 /* 2712 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]] 2713 * 2714 * -v Display statistics for individual vdevs 2715 * -T Display a timestamp in date(1) or Unix format 2716 * 2717 * This command can be tricky because we want to be able to deal with pool 2718 * creation/destruction as well as vdev configuration changes. The bulk of this 2719 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 2720 * on pool_list_update() to detect the addition of new pools. Configuration 2721 * changes are all handled within libzfs. 2722 */ 2723 int 2724 zpool_do_iostat(int argc, char **argv) 2725 { 2726 int c; 2727 int ret; 2728 int npools; 2729 unsigned long interval = 0, count = 0; 2730 zpool_list_t *list; 2731 boolean_t verbose = B_FALSE; 2732 iostat_cbdata_t cb; 2733 2734 /* check options */ 2735 while ((c = getopt(argc, argv, "T:v")) != -1) { 2736 switch (c) { 2737 case 'T': 2738 get_timestamp_arg(*optarg); 2739 break; 2740 case 'v': 2741 verbose = B_TRUE; 2742 break; 2743 case '?': 2744 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2745 optopt); 2746 usage(B_FALSE); 2747 } 2748 } 2749 2750 argc -= optind; 2751 argv += optind; 2752 2753 get_interval_count(&argc, argv, &interval, &count); 2754 2755 /* 2756 * Construct the list of all interesting pools. 2757 */ 2758 ret = 0; 2759 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 2760 return (1); 2761 2762 if (pool_list_count(list) == 0 && argc != 0) { 2763 pool_list_free(list); 2764 return (1); 2765 } 2766 2767 if (pool_list_count(list) == 0 && interval == 0) { 2768 pool_list_free(list); 2769 (void) fprintf(stderr, gettext("no pools available\n")); 2770 return (1); 2771 } 2772 2773 /* 2774 * Enter the main iostat loop. 2775 */ 2776 cb.cb_list = list; 2777 cb.cb_verbose = verbose; 2778 cb.cb_iteration = 0; 2779 cb.cb_namewidth = 0; 2780 2781 for (;;) { 2782 pool_list_update(list); 2783 2784 if ((npools = pool_list_count(list)) == 0) 2785 break; 2786 2787 /* 2788 * Refresh all statistics. This is done as an explicit step 2789 * before calculating the maximum name width, so that any 2790 * configuration changes are properly accounted for. 2791 */ 2792 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 2793 2794 /* 2795 * Iterate over all pools to determine the maximum width 2796 * for the pool / device name column across all pools. 2797 */ 2798 cb.cb_namewidth = 0; 2799 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 2800 2801 if (timestamp_fmt != NODATE) 2802 print_timestamp(timestamp_fmt); 2803 2804 /* 2805 * If it's the first time, or verbose mode, print the header. 2806 */ 2807 if (++cb.cb_iteration == 1 || verbose) 2808 print_iostat_header(&cb); 2809 2810 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 2811 2812 /* 2813 * If there's more than one pool, and we're not in verbose mode 2814 * (which prints a separator for us), then print a separator. 2815 */ 2816 if (npools > 1 && !verbose) 2817 print_iostat_separator(&cb); 2818 2819 if (verbose) 2820 (void) printf("\n"); 2821 2822 /* 2823 * Flush the output so that redirection to a file isn't buffered 2824 * indefinitely. 2825 */ 2826 (void) fflush(stdout); 2827 2828 if (interval == 0) 2829 break; 2830 2831 if (count != 0 && --count == 0) 2832 break; 2833 2834 (void) sleep(interval); 2835 } 2836 2837 pool_list_free(list); 2838 2839 return (ret); 2840 } 2841 2842 typedef struct list_cbdata { 2843 boolean_t cb_verbose; 2844 int cb_namewidth; 2845 boolean_t cb_scripted; 2846 zprop_list_t *cb_proplist; 2847 boolean_t cb_literal; 2848 } list_cbdata_t; 2849 2850 /* 2851 * Given a list of columns to display, output appropriate headers for each one. 2852 */ 2853 static void 2854 print_header(list_cbdata_t *cb) 2855 { 2856 zprop_list_t *pl = cb->cb_proplist; 2857 char headerbuf[ZPOOL_MAXPROPLEN]; 2858 const char *header; 2859 boolean_t first = B_TRUE; 2860 boolean_t right_justify; 2861 size_t width = 0; 2862 2863 for (; pl != NULL; pl = pl->pl_next) { 2864 width = pl->pl_width; 2865 if (first && cb->cb_verbose) { 2866 /* 2867 * Reset the width to accommodate the verbose listing 2868 * of devices. 2869 */ 2870 width = cb->cb_namewidth; 2871 } 2872 2873 if (!first) 2874 (void) printf(" "); 2875 else 2876 first = B_FALSE; 2877 2878 right_justify = B_FALSE; 2879 if (pl->pl_prop != ZPROP_INVAL) { 2880 header = zpool_prop_column_name(pl->pl_prop); 2881 right_justify = zpool_prop_align_right(pl->pl_prop); 2882 } else { 2883 int i; 2884 2885 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 2886 headerbuf[i] = toupper(pl->pl_user_prop[i]); 2887 headerbuf[i] = '\0'; 2888 header = headerbuf; 2889 } 2890 2891 if (pl->pl_next == NULL && !right_justify) 2892 (void) printf("%s", header); 2893 else if (right_justify) 2894 (void) printf("%*s", width, header); 2895 else 2896 (void) printf("%-*s", width, header); 2897 2898 } 2899 2900 (void) printf("\n"); 2901 } 2902 2903 /* 2904 * Given a pool and a list of properties, print out all the properties according 2905 * to the described layout. 2906 */ 2907 static void 2908 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 2909 { 2910 zprop_list_t *pl = cb->cb_proplist; 2911 boolean_t first = B_TRUE; 2912 char property[ZPOOL_MAXPROPLEN]; 2913 char *propstr; 2914 boolean_t right_justify; 2915 size_t width; 2916 2917 for (; pl != NULL; pl = pl->pl_next) { 2918 2919 width = pl->pl_width; 2920 if (first && cb->cb_verbose) { 2921 /* 2922 * Reset the width to accommodate the verbose listing 2923 * of devices. 2924 */ 2925 width = cb->cb_namewidth; 2926 } 2927 2928 if (!first) { 2929 if (cb->cb_scripted) 2930 (void) printf("\t"); 2931 else 2932 (void) printf(" "); 2933 } else { 2934 first = B_FALSE; 2935 } 2936 2937 right_justify = B_FALSE; 2938 if (pl->pl_prop != ZPROP_INVAL) { 2939 if (zpool_get_prop(zhp, pl->pl_prop, property, 2940 sizeof (property), NULL, cb->cb_literal) != 0) 2941 propstr = "-"; 2942 else 2943 propstr = property; 2944 2945 right_justify = zpool_prop_align_right(pl->pl_prop); 2946 } else if ((zpool_prop_feature(pl->pl_user_prop) || 2947 zpool_prop_unsupported(pl->pl_user_prop)) && 2948 zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 2949 sizeof (property)) == 0) { 2950 propstr = property; 2951 } else { 2952 propstr = "-"; 2953 } 2954 2955 2956 /* 2957 * If this is being called in scripted mode, or if this is the 2958 * last column and it is left-justified, don't include a width 2959 * format specifier. 2960 */ 2961 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 2962 (void) printf("%s", propstr); 2963 else if (right_justify) 2964 (void) printf("%*s", width, propstr); 2965 else 2966 (void) printf("%-*s", width, propstr); 2967 } 2968 2969 (void) printf("\n"); 2970 } 2971 2972 static void 2973 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 2974 boolean_t valid) 2975 { 2976 char propval[64]; 2977 boolean_t fixed; 2978 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 2979 2980 switch (prop) { 2981 case ZPOOL_PROP_EXPANDSZ: 2982 if (value == 0) 2983 (void) strlcpy(propval, "-", sizeof (propval)); 2984 else 2985 zfs_nicenum(value, propval, sizeof (propval)); 2986 break; 2987 case ZPOOL_PROP_FRAGMENTATION: 2988 if (value == ZFS_FRAG_INVALID) { 2989 (void) strlcpy(propval, "-", sizeof (propval)); 2990 } else { 2991 (void) snprintf(propval, sizeof (propval), "%llu%%", 2992 value); 2993 } 2994 break; 2995 case ZPOOL_PROP_CAPACITY: 2996 (void) snprintf(propval, sizeof (propval), "%llu%%", value); 2997 break; 2998 default: 2999 zfs_nicenum(value, propval, sizeof (propval)); 3000 } 3001 3002 if (!valid) 3003 (void) strlcpy(propval, "-", sizeof (propval)); 3004 3005 if (scripted) 3006 (void) printf("\t%s", propval); 3007 else 3008 (void) printf(" %*s", width, propval); 3009 } 3010 3011 void 3012 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 3013 list_cbdata_t *cb, int depth) 3014 { 3015 nvlist_t **child; 3016 vdev_stat_t *vs; 3017 uint_t c, children; 3018 char *vname; 3019 boolean_t scripted = cb->cb_scripted; 3020 uint64_t islog = B_FALSE; 3021 boolean_t haslog = B_FALSE; 3022 char *dashes = "%-*s - - - - - -\n"; 3023 3024 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 3025 (uint64_t **)&vs, &c) == 0); 3026 3027 if (name != NULL) { 3028 boolean_t toplevel = (vs->vs_space != 0); 3029 uint64_t cap; 3030 3031 if (scripted) 3032 (void) printf("\t%s", name); 3033 else if (strlen(name) + depth > cb->cb_namewidth) 3034 (void) printf("%*s%s", depth, "", name); 3035 else 3036 (void) printf("%*s%s%*s", depth, "", name, 3037 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 3038 3039 /* 3040 * Print the properties for the individual vdevs. Some 3041 * properties are only applicable to toplevel vdevs. The 3042 * 'toplevel' boolean value is passed to the print_one_column() 3043 * to indicate that the value is valid. 3044 */ 3045 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 3046 toplevel); 3047 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 3048 toplevel); 3049 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 3050 scripted, toplevel); 3051 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 3052 B_TRUE); 3053 print_one_column(ZPOOL_PROP_FRAGMENTATION, 3054 vs->vs_fragmentation, scripted, 3055 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 3056 cap = (vs->vs_space == 0) ? 0 : 3057 (vs->vs_alloc * 100 / vs->vs_space); 3058 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 3059 (void) printf("\n"); 3060 } 3061 3062 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 3063 &child, &children) != 0) 3064 return; 3065 3066 for (c = 0; c < children; c++) { 3067 uint64_t ishole = B_FALSE; 3068 3069 if (nvlist_lookup_uint64(child[c], 3070 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 3071 continue; 3072 3073 if (nvlist_lookup_uint64(child[c], 3074 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) { 3075 haslog = B_TRUE; 3076 continue; 3077 } 3078 3079 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3080 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3081 free(vname); 3082 } 3083 3084 if (haslog == B_TRUE) { 3085 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3086 (void) printf(dashes, cb->cb_namewidth, "log"); 3087 for (c = 0; c < children; c++) { 3088 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3089 &islog) != 0 || !islog) 3090 continue; 3091 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3092 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3093 free(vname); 3094 } 3095 } 3096 3097 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 3098 &child, &children) == 0 && children > 0) { 3099 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3100 (void) printf(dashes, cb->cb_namewidth, "cache"); 3101 for (c = 0; c < children; c++) { 3102 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3103 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3104 free(vname); 3105 } 3106 } 3107 3108 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 3109 &children) == 0 && children > 0) { 3110 /* LINTED E_SEC_PRINTF_VAR_FMT */ 3111 (void) printf(dashes, cb->cb_namewidth, "spare"); 3112 for (c = 0; c < children; c++) { 3113 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3114 print_list_stats(zhp, vname, child[c], cb, depth + 2); 3115 free(vname); 3116 } 3117 } 3118 } 3119 3120 3121 /* 3122 * Generic callback function to list a pool. 3123 */ 3124 int 3125 list_callback(zpool_handle_t *zhp, void *data) 3126 { 3127 list_cbdata_t *cbp = data; 3128 nvlist_t *config; 3129 nvlist_t *nvroot; 3130 3131 config = zpool_get_config(zhp, NULL); 3132 3133 print_pool(zhp, cbp); 3134 if (!cbp->cb_verbose) 3135 return (0); 3136 3137 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3138 &nvroot) == 0); 3139 print_list_stats(zhp, NULL, nvroot, cbp, 0); 3140 3141 return (0); 3142 } 3143 3144 /* 3145 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3146 * 3147 * -H Scripted mode. Don't display headers, and separate properties 3148 * by a single tab. 3149 * -o List of properties to display. Defaults to 3150 * "name,size,allocated,free,expandsize,fragmentation,capacity," 3151 * "dedupratio,health,altroot" 3152 * -p Diplay values in parsable (exact) format. 3153 * -T Display a timestamp in date(1) or Unix format 3154 * 3155 * List all pools in the system, whether or not they're healthy. Output space 3156 * statistics for each one, as well as health status summary. 3157 */ 3158 int 3159 zpool_do_list(int argc, char **argv) 3160 { 3161 int c; 3162 int ret; 3163 list_cbdata_t cb = { 0 }; 3164 static char default_props[] = 3165 "name,size,allocated,free,expandsize,fragmentation,capacity," 3166 "dedupratio,health,altroot"; 3167 char *props = default_props; 3168 unsigned long interval = 0, count = 0; 3169 zpool_list_t *list; 3170 boolean_t first = B_TRUE; 3171 3172 /* check options */ 3173 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) { 3174 switch (c) { 3175 case 'H': 3176 cb.cb_scripted = B_TRUE; 3177 break; 3178 case 'o': 3179 props = optarg; 3180 break; 3181 case 'p': 3182 cb.cb_literal = B_TRUE; 3183 break; 3184 case 'T': 3185 get_timestamp_arg(*optarg); 3186 break; 3187 case 'v': 3188 cb.cb_verbose = B_TRUE; 3189 break; 3190 case ':': 3191 (void) fprintf(stderr, gettext("missing argument for " 3192 "'%c' option\n"), optopt); 3193 usage(B_FALSE); 3194 break; 3195 case '?': 3196 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3197 optopt); 3198 usage(B_FALSE); 3199 } 3200 } 3201 3202 argc -= optind; 3203 argv += optind; 3204 3205 get_interval_count(&argc, argv, &interval, &count); 3206 3207 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 3208 usage(B_FALSE); 3209 3210 for (;;) { 3211 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 3212 &ret)) == NULL) 3213 return (1); 3214 3215 if (pool_list_count(list) == 0) 3216 break; 3217 3218 cb.cb_namewidth = 0; 3219 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3220 3221 if (timestamp_fmt != NODATE) 3222 print_timestamp(timestamp_fmt); 3223 3224 if (!cb.cb_scripted && (first || cb.cb_verbose)) { 3225 print_header(&cb); 3226 first = B_FALSE; 3227 } 3228 ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 3229 3230 if (interval == 0) 3231 break; 3232 3233 if (count != 0 && --count == 0) 3234 break; 3235 3236 pool_list_free(list); 3237 (void) sleep(interval); 3238 } 3239 3240 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 3241 (void) printf(gettext("no pools available\n")); 3242 ret = 0; 3243 } 3244 3245 pool_list_free(list); 3246 zprop_free_list(cb.cb_proplist); 3247 return (ret); 3248 } 3249 3250 static int 3251 zpool_do_attach_or_replace(int argc, char **argv, int replacing) 3252 { 3253 boolean_t force = B_FALSE; 3254 int c; 3255 nvlist_t *nvroot; 3256 char *poolname, *old_disk, *new_disk; 3257 zpool_handle_t *zhp; 3258 zpool_boot_label_t boot_type; 3259 uint64_t boot_size; 3260 int ret; 3261 3262 /* check options */ 3263 while ((c = getopt(argc, argv, "f")) != -1) { 3264 switch (c) { 3265 case 'f': 3266 force = B_TRUE; 3267 break; 3268 case '?': 3269 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3270 optopt); 3271 usage(B_FALSE); 3272 } 3273 } 3274 3275 argc -= optind; 3276 argv += optind; 3277 3278 /* get pool name and check number of arguments */ 3279 if (argc < 1) { 3280 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3281 usage(B_FALSE); 3282 } 3283 3284 poolname = argv[0]; 3285 3286 if (argc < 2) { 3287 (void) fprintf(stderr, 3288 gettext("missing <device> specification\n")); 3289 usage(B_FALSE); 3290 } 3291 3292 old_disk = argv[1]; 3293 3294 if (argc < 3) { 3295 if (!replacing) { 3296 (void) fprintf(stderr, 3297 gettext("missing <new_device> specification\n")); 3298 usage(B_FALSE); 3299 } 3300 new_disk = old_disk; 3301 argc -= 1; 3302 argv += 1; 3303 } else { 3304 new_disk = argv[2]; 3305 argc -= 2; 3306 argv += 2; 3307 } 3308 3309 if (argc > 1) { 3310 (void) fprintf(stderr, gettext("too many arguments\n")); 3311 usage(B_FALSE); 3312 } 3313 3314 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3315 return (1); 3316 3317 if (zpool_get_config(zhp, NULL) == NULL) { 3318 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 3319 poolname); 3320 zpool_close(zhp); 3321 return (1); 3322 } 3323 3324 if (zpool_is_bootable(zhp)) 3325 boot_type = ZPOOL_COPY_BOOT_LABEL; 3326 else 3327 boot_type = ZPOOL_NO_BOOT_LABEL; 3328 3329 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 3330 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 3331 boot_type, boot_size, argc, argv); 3332 if (nvroot == NULL) { 3333 zpool_close(zhp); 3334 return (1); 3335 } 3336 3337 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 3338 3339 nvlist_free(nvroot); 3340 zpool_close(zhp); 3341 3342 return (ret); 3343 } 3344 3345 /* 3346 * zpool replace [-f] <pool> <device> <new_device> 3347 * 3348 * -f Force attach, even if <new_device> appears to be in use. 3349 * 3350 * Replace <device> with <new_device>. 3351 */ 3352 /* ARGSUSED */ 3353 int 3354 zpool_do_replace(int argc, char **argv) 3355 { 3356 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 3357 } 3358 3359 /* 3360 * zpool attach [-f] <pool> <device> <new_device> 3361 * 3362 * -f Force attach, even if <new_device> appears to be in use. 3363 * 3364 * Attach <new_device> to the mirror containing <device>. If <device> is not 3365 * part of a mirror, then <device> will be transformed into a mirror of 3366 * <device> and <new_device>. In either case, <new_device> will begin life 3367 * with a DTL of [0, now], and will immediately begin to resilver itself. 3368 */ 3369 int 3370 zpool_do_attach(int argc, char **argv) 3371 { 3372 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 3373 } 3374 3375 /* 3376 * zpool detach [-f] <pool> <device> 3377 * 3378 * -f Force detach of <device>, even if DTLs argue against it 3379 * (not supported yet) 3380 * 3381 * Detach a device from a mirror. The operation will be refused if <device> 3382 * is the last device in the mirror, or if the DTLs indicate that this device 3383 * has the only valid copy of some data. 3384 */ 3385 /* ARGSUSED */ 3386 int 3387 zpool_do_detach(int argc, char **argv) 3388 { 3389 int c; 3390 char *poolname, *path; 3391 zpool_handle_t *zhp; 3392 int ret; 3393 3394 /* check options */ 3395 while ((c = getopt(argc, argv, "f")) != -1) { 3396 switch (c) { 3397 case 'f': 3398 case '?': 3399 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3400 optopt); 3401 usage(B_FALSE); 3402 } 3403 } 3404 3405 argc -= optind; 3406 argv += optind; 3407 3408 /* get pool name and check number of arguments */ 3409 if (argc < 1) { 3410 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3411 usage(B_FALSE); 3412 } 3413 3414 if (argc < 2) { 3415 (void) fprintf(stderr, 3416 gettext("missing <device> specification\n")); 3417 usage(B_FALSE); 3418 } 3419 3420 poolname = argv[0]; 3421 path = argv[1]; 3422 3423 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3424 return (1); 3425 3426 ret = zpool_vdev_detach(zhp, path); 3427 3428 zpool_close(zhp); 3429 3430 return (ret); 3431 } 3432 3433 /* 3434 * zpool split [-n] [-o prop=val] ... 3435 * [-o mntopt] ... 3436 * [-R altroot] <pool> <newpool> [<device> ...] 3437 * 3438 * -n Do not split the pool, but display the resulting layout if 3439 * it were to be split. 3440 * -o Set property=value, or set mount options. 3441 * -R Mount the split-off pool under an alternate root. 3442 * 3443 * Splits the named pool and gives it the new pool name. Devices to be split 3444 * off may be listed, provided that no more than one device is specified 3445 * per top-level vdev mirror. The newly split pool is left in an exported 3446 * state unless -R is specified. 3447 * 3448 * Restrictions: the top-level of the pool pool must only be made up of 3449 * mirrors; all devices in the pool must be healthy; no device may be 3450 * undergoing a resilvering operation. 3451 */ 3452 int 3453 zpool_do_split(int argc, char **argv) 3454 { 3455 char *srcpool, *newpool, *propval; 3456 char *mntopts = NULL; 3457 splitflags_t flags; 3458 int c, ret = 0; 3459 zpool_handle_t *zhp; 3460 nvlist_t *config, *props = NULL; 3461 3462 flags.dryrun = B_FALSE; 3463 flags.import = B_FALSE; 3464 3465 /* check options */ 3466 while ((c = getopt(argc, argv, ":R:no:")) != -1) { 3467 switch (c) { 3468 case 'R': 3469 flags.import = B_TRUE; 3470 if (add_prop_list( 3471 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 3472 &props, B_TRUE) != 0) { 3473 nvlist_free(props); 3474 usage(B_FALSE); 3475 } 3476 break; 3477 case 'n': 3478 flags.dryrun = B_TRUE; 3479 break; 3480 case 'o': 3481 if ((propval = strchr(optarg, '=')) != NULL) { 3482 *propval = '\0'; 3483 propval++; 3484 if (add_prop_list(optarg, propval, 3485 &props, B_TRUE) != 0) { 3486 nvlist_free(props); 3487 usage(B_FALSE); 3488 } 3489 } else { 3490 mntopts = optarg; 3491 } 3492 break; 3493 case ':': 3494 (void) fprintf(stderr, gettext("missing argument for " 3495 "'%c' option\n"), optopt); 3496 usage(B_FALSE); 3497 break; 3498 case '?': 3499 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3500 optopt); 3501 usage(B_FALSE); 3502 break; 3503 } 3504 } 3505 3506 if (!flags.import && mntopts != NULL) { 3507 (void) fprintf(stderr, gettext("setting mntopts is only " 3508 "valid when importing the pool\n")); 3509 usage(B_FALSE); 3510 } 3511 3512 argc -= optind; 3513 argv += optind; 3514 3515 if (argc < 1) { 3516 (void) fprintf(stderr, gettext("Missing pool name\n")); 3517 usage(B_FALSE); 3518 } 3519 if (argc < 2) { 3520 (void) fprintf(stderr, gettext("Missing new pool name\n")); 3521 usage(B_FALSE); 3522 } 3523 3524 srcpool = argv[0]; 3525 newpool = argv[1]; 3526 3527 argc -= 2; 3528 argv += 2; 3529 3530 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 3531 return (1); 3532 3533 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 3534 if (config == NULL) { 3535 ret = 1; 3536 } else { 3537 if (flags.dryrun) { 3538 (void) printf(gettext("would create '%s' with the " 3539 "following layout:\n\n"), newpool); 3540 print_vdev_tree(NULL, newpool, config, 0, B_FALSE); 3541 } 3542 nvlist_free(config); 3543 } 3544 3545 zpool_close(zhp); 3546 3547 if (ret != 0 || flags.dryrun || !flags.import) 3548 return (ret); 3549 3550 /* 3551 * The split was successful. Now we need to open the new 3552 * pool and import it. 3553 */ 3554 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 3555 return (1); 3556 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 3557 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 3558 ret = 1; 3559 (void) fprintf(stderr, gettext("Split was successful, but " 3560 "the datasets could not all be mounted\n")); 3561 (void) fprintf(stderr, gettext("Try doing '%s' with a " 3562 "different altroot\n"), "zpool import"); 3563 } 3564 zpool_close(zhp); 3565 3566 return (ret); 3567 } 3568 3569 3570 3571 /* 3572 * zpool online <pool> <device> ... 3573 */ 3574 int 3575 zpool_do_online(int argc, char **argv) 3576 { 3577 int c, i; 3578 char *poolname; 3579 zpool_handle_t *zhp; 3580 int ret = 0; 3581 vdev_state_t newstate; 3582 int flags = 0; 3583 3584 /* check options */ 3585 while ((c = getopt(argc, argv, "et")) != -1) { 3586 switch (c) { 3587 case 'e': 3588 flags |= ZFS_ONLINE_EXPAND; 3589 break; 3590 case 't': 3591 case '?': 3592 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3593 optopt); 3594 usage(B_FALSE); 3595 } 3596 } 3597 3598 argc -= optind; 3599 argv += optind; 3600 3601 /* get pool name and check number of arguments */ 3602 if (argc < 1) { 3603 (void) fprintf(stderr, gettext("missing pool name\n")); 3604 usage(B_FALSE); 3605 } 3606 if (argc < 2) { 3607 (void) fprintf(stderr, gettext("missing device name\n")); 3608 usage(B_FALSE); 3609 } 3610 3611 poolname = argv[0]; 3612 3613 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3614 return (1); 3615 3616 for (i = 1; i < argc; i++) { 3617 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 3618 if (newstate != VDEV_STATE_HEALTHY) { 3619 (void) printf(gettext("warning: device '%s' " 3620 "onlined, but remains in faulted state\n"), 3621 argv[i]); 3622 if (newstate == VDEV_STATE_FAULTED) 3623 (void) printf(gettext("use 'zpool " 3624 "clear' to restore a faulted " 3625 "device\n")); 3626 else 3627 (void) printf(gettext("use 'zpool " 3628 "replace' to replace devices " 3629 "that are no longer present\n")); 3630 } 3631 } else { 3632 ret = 1; 3633 } 3634 } 3635 3636 zpool_close(zhp); 3637 3638 return (ret); 3639 } 3640 3641 /* 3642 * zpool offline [-ft] <pool> <device> ... 3643 * 3644 * -f Force the device into the offline state, even if doing 3645 * so would appear to compromise pool availability. 3646 * (not supported yet) 3647 * 3648 * -t Only take the device off-line temporarily. The offline 3649 * state will not be persistent across reboots. 3650 */ 3651 /* ARGSUSED */ 3652 int 3653 zpool_do_offline(int argc, char **argv) 3654 { 3655 int c, i; 3656 char *poolname; 3657 zpool_handle_t *zhp; 3658 int ret = 0; 3659 boolean_t istmp = B_FALSE; 3660 3661 /* check options */ 3662 while ((c = getopt(argc, argv, "ft")) != -1) { 3663 switch (c) { 3664 case 't': 3665 istmp = B_TRUE; 3666 break; 3667 case 'f': 3668 case '?': 3669 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3670 optopt); 3671 usage(B_FALSE); 3672 } 3673 } 3674 3675 argc -= optind; 3676 argv += optind; 3677 3678 /* get pool name and check number of arguments */ 3679 if (argc < 1) { 3680 (void) fprintf(stderr, gettext("missing pool name\n")); 3681 usage(B_FALSE); 3682 } 3683 if (argc < 2) { 3684 (void) fprintf(stderr, gettext("missing device name\n")); 3685 usage(B_FALSE); 3686 } 3687 3688 poolname = argv[0]; 3689 3690 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3691 return (1); 3692 3693 for (i = 1; i < argc; i++) { 3694 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 3695 ret = 1; 3696 } 3697 3698 zpool_close(zhp); 3699 3700 return (ret); 3701 } 3702 3703 /* 3704 * zpool clear <pool> [device] 3705 * 3706 * Clear all errors associated with a pool or a particular device. 3707 */ 3708 int 3709 zpool_do_clear(int argc, char **argv) 3710 { 3711 int c; 3712 int ret = 0; 3713 boolean_t dryrun = B_FALSE; 3714 boolean_t do_rewind = B_FALSE; 3715 boolean_t xtreme_rewind = B_FALSE; 3716 uint32_t rewind_policy = ZPOOL_NO_REWIND; 3717 nvlist_t *policy = NULL; 3718 zpool_handle_t *zhp; 3719 char *pool, *device; 3720 3721 /* check options */ 3722 while ((c = getopt(argc, argv, "FnX")) != -1) { 3723 switch (c) { 3724 case 'F': 3725 do_rewind = B_TRUE; 3726 break; 3727 case 'n': 3728 dryrun = B_TRUE; 3729 break; 3730 case 'X': 3731 xtreme_rewind = B_TRUE; 3732 break; 3733 case '?': 3734 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3735 optopt); 3736 usage(B_FALSE); 3737 } 3738 } 3739 3740 argc -= optind; 3741 argv += optind; 3742 3743 if (argc < 1) { 3744 (void) fprintf(stderr, gettext("missing pool name\n")); 3745 usage(B_FALSE); 3746 } 3747 3748 if (argc > 2) { 3749 (void) fprintf(stderr, gettext("too many arguments\n")); 3750 usage(B_FALSE); 3751 } 3752 3753 if ((dryrun || xtreme_rewind) && !do_rewind) { 3754 (void) fprintf(stderr, 3755 gettext("-n or -X only meaningful with -F\n")); 3756 usage(B_FALSE); 3757 } 3758 if (dryrun) 3759 rewind_policy = ZPOOL_TRY_REWIND; 3760 else if (do_rewind) 3761 rewind_policy = ZPOOL_DO_REWIND; 3762 if (xtreme_rewind) 3763 rewind_policy |= ZPOOL_EXTREME_REWIND; 3764 3765 /* In future, further rewind policy choices can be passed along here */ 3766 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 3767 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 3768 return (1); 3769 3770 pool = argv[0]; 3771 device = argc == 2 ? argv[1] : NULL; 3772 3773 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 3774 nvlist_free(policy); 3775 return (1); 3776 } 3777 3778 if (zpool_clear(zhp, device, policy) != 0) 3779 ret = 1; 3780 3781 zpool_close(zhp); 3782 3783 nvlist_free(policy); 3784 3785 return (ret); 3786 } 3787 3788 /* 3789 * zpool reguid <pool> 3790 */ 3791 int 3792 zpool_do_reguid(int argc, char **argv) 3793 { 3794 int c; 3795 char *poolname; 3796 zpool_handle_t *zhp; 3797 int ret = 0; 3798 3799 /* check options */ 3800 while ((c = getopt(argc, argv, "")) != -1) { 3801 switch (c) { 3802 case '?': 3803 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3804 optopt); 3805 usage(B_FALSE); 3806 } 3807 } 3808 3809 argc -= optind; 3810 argv += optind; 3811 3812 /* get pool name and check number of arguments */ 3813 if (argc < 1) { 3814 (void) fprintf(stderr, gettext("missing pool name\n")); 3815 usage(B_FALSE); 3816 } 3817 3818 if (argc > 1) { 3819 (void) fprintf(stderr, gettext("too many arguments\n")); 3820 usage(B_FALSE); 3821 } 3822 3823 poolname = argv[0]; 3824 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3825 return (1); 3826 3827 ret = zpool_reguid(zhp); 3828 3829 zpool_close(zhp); 3830 return (ret); 3831 } 3832 3833 3834 /* 3835 * zpool reopen <pool> 3836 * 3837 * Reopen the pool so that the kernel can update the sizes of all vdevs. 3838 */ 3839 int 3840 zpool_do_reopen(int argc, char **argv) 3841 { 3842 int c; 3843 int ret = 0; 3844 zpool_handle_t *zhp; 3845 char *pool; 3846 3847 /* check options */ 3848 while ((c = getopt(argc, argv, "")) != -1) { 3849 switch (c) { 3850 case '?': 3851 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3852 optopt); 3853 usage(B_FALSE); 3854 } 3855 } 3856 3857 argc--; 3858 argv++; 3859 3860 if (argc < 1) { 3861 (void) fprintf(stderr, gettext("missing pool name\n")); 3862 usage(B_FALSE); 3863 } 3864 3865 if (argc > 1) { 3866 (void) fprintf(stderr, gettext("too many arguments\n")); 3867 usage(B_FALSE); 3868 } 3869 3870 pool = argv[0]; 3871 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 3872 return (1); 3873 3874 ret = zpool_reopen(zhp); 3875 zpool_close(zhp); 3876 return (ret); 3877 } 3878 3879 typedef struct scrub_cbdata { 3880 int cb_type; 3881 int cb_argc; 3882 char **cb_argv; 3883 pool_scrub_cmd_t cb_scrub_cmd; 3884 } scrub_cbdata_t; 3885 3886 int 3887 scrub_callback(zpool_handle_t *zhp, void *data) 3888 { 3889 scrub_cbdata_t *cb = data; 3890 int err; 3891 3892 /* 3893 * Ignore faulted pools. 3894 */ 3895 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 3896 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 3897 "currently unavailable\n"), zpool_get_name(zhp)); 3898 return (1); 3899 } 3900 3901 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 3902 3903 return (err != 0); 3904 } 3905 3906 /* 3907 * zpool scrub [-s | -p] <pool> ... 3908 * 3909 * -s Stop. Stops any in-progress scrub. 3910 * -p Pause. Pause in-progress scrub. 3911 */ 3912 int 3913 zpool_do_scrub(int argc, char **argv) 3914 { 3915 int c; 3916 scrub_cbdata_t cb; 3917 3918 cb.cb_type = POOL_SCAN_SCRUB; 3919 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 3920 3921 /* check options */ 3922 while ((c = getopt(argc, argv, "sp")) != -1) { 3923 switch (c) { 3924 case 's': 3925 cb.cb_type = POOL_SCAN_NONE; 3926 break; 3927 case 'p': 3928 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 3929 break; 3930 case '?': 3931 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3932 optopt); 3933 usage(B_FALSE); 3934 } 3935 } 3936 3937 if (cb.cb_type == POOL_SCAN_NONE && 3938 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 3939 (void) fprintf(stderr, gettext("invalid option combination: " 3940 "-s and -p are mutually exclusive\n")); 3941 usage(B_FALSE); 3942 } 3943 3944 cb.cb_argc = argc; 3945 cb.cb_argv = argv; 3946 argc -= optind; 3947 argv += optind; 3948 3949 if (argc < 1) { 3950 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3951 usage(B_FALSE); 3952 } 3953 3954 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 3955 } 3956 3957 typedef struct status_cbdata { 3958 int cb_count; 3959 boolean_t cb_allpools; 3960 boolean_t cb_verbose; 3961 boolean_t cb_explain; 3962 boolean_t cb_first; 3963 boolean_t cb_dedup_stats; 3964 } status_cbdata_t; 3965 3966 /* 3967 * Print out detailed scrub status. 3968 */ 3969 void 3970 print_scan_status(pool_scan_stat_t *ps) 3971 { 3972 time_t start, end, pause; 3973 uint64_t elapsed, mins_left, hours_left; 3974 uint64_t pass_exam, examined, total; 3975 uint_t rate; 3976 double fraction_done; 3977 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 3978 3979 (void) printf(gettext(" scan: ")); 3980 3981 /* If there's never been a scan, there's not much to say. */ 3982 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 3983 ps->pss_func >= POOL_SCAN_FUNCS) { 3984 (void) printf(gettext("none requested\n")); 3985 return; 3986 } 3987 3988 start = ps->pss_start_time; 3989 end = ps->pss_end_time; 3990 pause = ps->pss_pass_scrub_pause; 3991 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 3992 3993 assert(ps->pss_func == POOL_SCAN_SCRUB || 3994 ps->pss_func == POOL_SCAN_RESILVER); 3995 /* 3996 * Scan is finished or canceled. 3997 */ 3998 if (ps->pss_state == DSS_FINISHED) { 3999 uint64_t minutes_taken = (end - start) / 60; 4000 char *fmt = NULL; 4001 4002 if (ps->pss_func == POOL_SCAN_SCRUB) { 4003 fmt = gettext("scrub repaired %s in %lluh%um with " 4004 "%llu errors on %s"); 4005 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4006 fmt = gettext("resilvered %s in %lluh%um with " 4007 "%llu errors on %s"); 4008 } 4009 /* LINTED */ 4010 (void) printf(fmt, processed_buf, 4011 (u_longlong_t)(minutes_taken / 60), 4012 (uint_t)(minutes_taken % 60), 4013 (u_longlong_t)ps->pss_errors, 4014 ctime((time_t *)&end)); 4015 return; 4016 } else if (ps->pss_state == DSS_CANCELED) { 4017 if (ps->pss_func == POOL_SCAN_SCRUB) { 4018 (void) printf(gettext("scrub canceled on %s"), 4019 ctime(&end)); 4020 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4021 (void) printf(gettext("resilver canceled on %s"), 4022 ctime(&end)); 4023 } 4024 return; 4025 } 4026 4027 assert(ps->pss_state == DSS_SCANNING); 4028 4029 /* 4030 * Scan is in progress. 4031 */ 4032 if (ps->pss_func == POOL_SCAN_SCRUB) { 4033 if (pause == 0) { 4034 (void) printf(gettext("scrub in progress since %s"), 4035 ctime(&start)); 4036 } else { 4037 char buf[32]; 4038 struct tm *p = localtime(&pause); 4039 (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p); 4040 (void) printf(gettext("scrub paused since %s\n"), buf); 4041 (void) printf(gettext("\tscrub started on %s"), 4042 ctime(&start)); 4043 } 4044 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4045 (void) printf(gettext("resilver in progress since %s"), 4046 ctime(&start)); 4047 } 4048 4049 examined = ps->pss_examined ? ps->pss_examined : 1; 4050 total = ps->pss_to_examine; 4051 fraction_done = (double)examined / total; 4052 4053 /* elapsed time for this pass */ 4054 elapsed = time(NULL) - ps->pss_pass_start; 4055 elapsed -= ps->pss_pass_scrub_spent_paused; 4056 elapsed = elapsed ? elapsed : 1; 4057 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1; 4058 rate = pass_exam / elapsed; 4059 rate = rate ? rate : 1; 4060 mins_left = ((total - examined) / rate) / 60; 4061 hours_left = mins_left / 60; 4062 4063 zfs_nicenum(examined, examined_buf, sizeof (examined_buf)); 4064 zfs_nicenum(total, total_buf, sizeof (total_buf)); 4065 4066 /* 4067 * do not print estimated time if hours_left is more than 30 days 4068 * or we have a paused scrub 4069 */ 4070 if (pause == 0) { 4071 zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 4072 (void) printf(gettext("\t%s scanned out of %s at %s/s"), 4073 examined_buf, total_buf, rate_buf); 4074 if (hours_left < (30 * 24)) { 4075 (void) printf(gettext(", %lluh%um to go\n"), 4076 (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 4077 } else { 4078 (void) printf(gettext( 4079 ", (scan is slow, no estimated time)\n")); 4080 } 4081 } else { 4082 (void) printf(gettext("\t%s scanned out of %s\n"), 4083 examined_buf, total_buf); 4084 } 4085 4086 if (ps->pss_func == POOL_SCAN_RESILVER) { 4087 (void) printf(gettext(" %s resilvered, %.2f%% done\n"), 4088 processed_buf, 100 * fraction_done); 4089 } else if (ps->pss_func == POOL_SCAN_SCRUB) { 4090 (void) printf(gettext(" %s repaired, %.2f%% done\n"), 4091 processed_buf, 100 * fraction_done); 4092 } 4093 } 4094 4095 static void 4096 print_error_log(zpool_handle_t *zhp) 4097 { 4098 nvlist_t *nverrlist = NULL; 4099 nvpair_t *elem; 4100 char *pathname; 4101 size_t len = MAXPATHLEN * 2; 4102 4103 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 4104 (void) printf("errors: List of errors unavailable " 4105 "(insufficient privileges)\n"); 4106 return; 4107 } 4108 4109 (void) printf("errors: Permanent errors have been " 4110 "detected in the following files:\n\n"); 4111 4112 pathname = safe_malloc(len); 4113 elem = NULL; 4114 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 4115 nvlist_t *nv; 4116 uint64_t dsobj, obj; 4117 4118 verify(nvpair_value_nvlist(elem, &nv) == 0); 4119 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 4120 &dsobj) == 0); 4121 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 4122 &obj) == 0); 4123 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 4124 (void) printf("%7s %s\n", "", pathname); 4125 } 4126 free(pathname); 4127 nvlist_free(nverrlist); 4128 } 4129 4130 static void 4131 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 4132 int namewidth) 4133 { 4134 uint_t i; 4135 char *name; 4136 4137 if (nspares == 0) 4138 return; 4139 4140 (void) printf(gettext("\tspares\n")); 4141 4142 for (i = 0; i < nspares; i++) { 4143 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); 4144 print_status_config(zhp, name, spares[i], 4145 namewidth, 2, B_TRUE); 4146 free(name); 4147 } 4148 } 4149 4150 static void 4151 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 4152 int namewidth) 4153 { 4154 uint_t i; 4155 char *name; 4156 4157 if (nl2cache == 0) 4158 return; 4159 4160 (void) printf(gettext("\tcache\n")); 4161 4162 for (i = 0; i < nl2cache; i++) { 4163 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE); 4164 print_status_config(zhp, name, l2cache[i], 4165 namewidth, 2, B_FALSE); 4166 free(name); 4167 } 4168 } 4169 4170 static void 4171 print_dedup_stats(nvlist_t *config) 4172 { 4173 ddt_histogram_t *ddh; 4174 ddt_stat_t *dds; 4175 ddt_object_t *ddo; 4176 uint_t c; 4177 4178 /* 4179 * If the pool was faulted then we may not have been able to 4180 * obtain the config. Otherwise, if we have anything in the dedup 4181 * table continue processing the stats. 4182 */ 4183 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 4184 (uint64_t **)&ddo, &c) != 0) 4185 return; 4186 4187 (void) printf("\n"); 4188 (void) printf(gettext(" dedup: ")); 4189 if (ddo->ddo_count == 0) { 4190 (void) printf(gettext("no DDT entries\n")); 4191 return; 4192 } 4193 4194 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 4195 (u_longlong_t)ddo->ddo_count, 4196 (u_longlong_t)ddo->ddo_dspace, 4197 (u_longlong_t)ddo->ddo_mspace); 4198 4199 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 4200 (uint64_t **)&dds, &c) == 0); 4201 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 4202 (uint64_t **)&ddh, &c) == 0); 4203 zpool_dump_ddt(dds, ddh); 4204 } 4205 4206 /* 4207 * Display a summary of pool status. Displays a summary such as: 4208 * 4209 * pool: tank 4210 * status: DEGRADED 4211 * reason: One or more devices ... 4212 * see: http://illumos.org/msg/ZFS-xxxx-01 4213 * config: 4214 * mirror DEGRADED 4215 * c1t0d0 OK 4216 * c2t0d0 UNAVAIL 4217 * 4218 * When given the '-v' option, we print out the complete config. If the '-e' 4219 * option is specified, then we print out error rate information as well. 4220 */ 4221 int 4222 status_callback(zpool_handle_t *zhp, void *data) 4223 { 4224 status_cbdata_t *cbp = data; 4225 nvlist_t *config, *nvroot; 4226 char *msgid; 4227 int reason; 4228 const char *health; 4229 uint_t c; 4230 vdev_stat_t *vs; 4231 4232 config = zpool_get_config(zhp, NULL); 4233 reason = zpool_get_status(zhp, &msgid); 4234 4235 cbp->cb_count++; 4236 4237 /* 4238 * If we were given 'zpool status -x', only report those pools with 4239 * problems. 4240 */ 4241 if (cbp->cb_explain && 4242 (reason == ZPOOL_STATUS_OK || 4243 reason == ZPOOL_STATUS_VERSION_OLDER || 4244 reason == ZPOOL_STATUS_FEAT_DISABLED)) { 4245 if (!cbp->cb_allpools) { 4246 (void) printf(gettext("pool '%s' is healthy\n"), 4247 zpool_get_name(zhp)); 4248 if (cbp->cb_first) 4249 cbp->cb_first = B_FALSE; 4250 } 4251 return (0); 4252 } 4253 4254 if (cbp->cb_first) 4255 cbp->cb_first = B_FALSE; 4256 else 4257 (void) printf("\n"); 4258 4259 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4260 &nvroot) == 0); 4261 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 4262 (uint64_t **)&vs, &c) == 0); 4263 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 4264 4265 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 4266 (void) printf(gettext(" state: %s\n"), health); 4267 4268 switch (reason) { 4269 case ZPOOL_STATUS_MISSING_DEV_R: 4270 (void) printf(gettext("status: One or more devices could not " 4271 "be opened. Sufficient replicas exist for\n\tthe pool to " 4272 "continue functioning in a degraded state.\n")); 4273 (void) printf(gettext("action: Attach the missing device and " 4274 "online it using 'zpool online'.\n")); 4275 break; 4276 4277 case ZPOOL_STATUS_MISSING_DEV_NR: 4278 (void) printf(gettext("status: One or more devices could not " 4279 "be opened. There are insufficient\n\treplicas for the " 4280 "pool to continue functioning.\n")); 4281 (void) printf(gettext("action: Attach the missing device and " 4282 "online it using 'zpool online'.\n")); 4283 break; 4284 4285 case ZPOOL_STATUS_CORRUPT_LABEL_R: 4286 (void) printf(gettext("status: One or more devices could not " 4287 "be used because the label is missing or\n\tinvalid. " 4288 "Sufficient replicas exist for the pool to continue\n\t" 4289 "functioning in a degraded state.\n")); 4290 (void) printf(gettext("action: Replace the device using " 4291 "'zpool replace'.\n")); 4292 break; 4293 4294 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 4295 (void) printf(gettext("status: One or more devices could not " 4296 "be used because the label is missing \n\tor invalid. " 4297 "There are insufficient replicas for the pool to " 4298 "continue\n\tfunctioning.\n")); 4299 zpool_explain_recover(zpool_get_handle(zhp), 4300 zpool_get_name(zhp), reason, config); 4301 break; 4302 4303 case ZPOOL_STATUS_FAILING_DEV: 4304 (void) printf(gettext("status: One or more devices has " 4305 "experienced an unrecoverable error. An\n\tattempt was " 4306 "made to correct the error. Applications are " 4307 "unaffected.\n")); 4308 (void) printf(gettext("action: Determine if the device needs " 4309 "to be replaced, and clear the errors\n\tusing " 4310 "'zpool clear' or replace the device with 'zpool " 4311 "replace'.\n")); 4312 break; 4313 4314 case ZPOOL_STATUS_OFFLINE_DEV: 4315 (void) printf(gettext("status: One or more devices has " 4316 "been taken offline by the administrator.\n\tSufficient " 4317 "replicas exist for the pool to continue functioning in " 4318 "a\n\tdegraded state.\n")); 4319 (void) printf(gettext("action: Online the device using " 4320 "'zpool online' or replace the device with\n\t'zpool " 4321 "replace'.\n")); 4322 break; 4323 4324 case ZPOOL_STATUS_REMOVED_DEV: 4325 (void) printf(gettext("status: One or more devices has " 4326 "been removed by the administrator.\n\tSufficient " 4327 "replicas exist for the pool to continue functioning in " 4328 "a\n\tdegraded state.\n")); 4329 (void) printf(gettext("action: Online the device using " 4330 "'zpool online' or replace the device with\n\t'zpool " 4331 "replace'.\n")); 4332 break; 4333 4334 case ZPOOL_STATUS_RESILVERING: 4335 (void) printf(gettext("status: One or more devices is " 4336 "currently being resilvered. The pool will\n\tcontinue " 4337 "to function, possibly in a degraded state.\n")); 4338 (void) printf(gettext("action: Wait for the resilver to " 4339 "complete.\n")); 4340 break; 4341 4342 case ZPOOL_STATUS_CORRUPT_DATA: 4343 (void) printf(gettext("status: One or more devices has " 4344 "experienced an error resulting in data\n\tcorruption. " 4345 "Applications may be affected.\n")); 4346 (void) printf(gettext("action: Restore the file in question " 4347 "if possible. Otherwise restore the\n\tentire pool from " 4348 "backup.\n")); 4349 break; 4350 4351 case ZPOOL_STATUS_CORRUPT_POOL: 4352 (void) printf(gettext("status: The pool metadata is corrupted " 4353 "and the pool cannot be opened.\n")); 4354 zpool_explain_recover(zpool_get_handle(zhp), 4355 zpool_get_name(zhp), reason, config); 4356 break; 4357 4358 case ZPOOL_STATUS_VERSION_OLDER: 4359 (void) printf(gettext("status: The pool is formatted using a " 4360 "legacy on-disk format. The pool can\n\tstill be used, " 4361 "but some features are unavailable.\n")); 4362 (void) printf(gettext("action: Upgrade the pool using 'zpool " 4363 "upgrade'. Once this is done, the\n\tpool will no longer " 4364 "be accessible on software that does not support feature\n" 4365 "\tflags.\n")); 4366 break; 4367 4368 case ZPOOL_STATUS_VERSION_NEWER: 4369 (void) printf(gettext("status: The pool has been upgraded to a " 4370 "newer, incompatible on-disk version.\n\tThe pool cannot " 4371 "be accessed on this system.\n")); 4372 (void) printf(gettext("action: Access the pool from a system " 4373 "running more recent software, or\n\trestore the pool from " 4374 "backup.\n")); 4375 break; 4376 4377 case ZPOOL_STATUS_FEAT_DISABLED: 4378 (void) printf(gettext("status: Some supported features are not " 4379 "enabled on the pool. The pool can\n\tstill be used, but " 4380 "some features are unavailable.\n")); 4381 (void) printf(gettext("action: Enable all features using " 4382 "'zpool upgrade'. Once this is done,\n\tthe pool may no " 4383 "longer be accessible by software that does not support\n\t" 4384 "the features. See zpool-features(5) for details.\n")); 4385 break; 4386 4387 case ZPOOL_STATUS_UNSUP_FEAT_READ: 4388 (void) printf(gettext("status: The pool cannot be accessed on " 4389 "this system because it uses the\n\tfollowing feature(s) " 4390 "not supported on this system:\n")); 4391 zpool_print_unsup_feat(config); 4392 (void) printf("\n"); 4393 (void) printf(gettext("action: Access the pool from a system " 4394 "that supports the required feature(s),\n\tor restore the " 4395 "pool from backup.\n")); 4396 break; 4397 4398 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 4399 (void) printf(gettext("status: The pool can only be accessed " 4400 "in read-only mode on this system. It\n\tcannot be " 4401 "accessed in read-write mode because it uses the " 4402 "following\n\tfeature(s) not supported on this system:\n")); 4403 zpool_print_unsup_feat(config); 4404 (void) printf("\n"); 4405 (void) printf(gettext("action: The pool cannot be accessed in " 4406 "read-write mode. Import the pool with\n" 4407 "\t\"-o readonly=on\", access the pool from a system that " 4408 "supports the\n\trequired feature(s), or restore the " 4409 "pool from backup.\n")); 4410 break; 4411 4412 case ZPOOL_STATUS_FAULTED_DEV_R: 4413 (void) printf(gettext("status: One or more devices are " 4414 "faulted in response to persistent errors.\n\tSufficient " 4415 "replicas exist for the pool to continue functioning " 4416 "in a\n\tdegraded state.\n")); 4417 (void) printf(gettext("action: Replace the faulted device, " 4418 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 4419 break; 4420 4421 case ZPOOL_STATUS_FAULTED_DEV_NR: 4422 (void) printf(gettext("status: One or more devices are " 4423 "faulted in response to persistent errors. There are " 4424 "insufficient replicas for the pool to\n\tcontinue " 4425 "functioning.\n")); 4426 (void) printf(gettext("action: Destroy and re-create the pool " 4427 "from a backup source. Manually marking the device\n" 4428 "\trepaired using 'zpool clear' may allow some data " 4429 "to be recovered.\n")); 4430 break; 4431 4432 case ZPOOL_STATUS_IO_FAILURE_WAIT: 4433 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 4434 (void) printf(gettext("status: One or more devices are " 4435 "faulted in response to IO failures.\n")); 4436 (void) printf(gettext("action: Make sure the affected devices " 4437 "are connected, then run 'zpool clear'.\n")); 4438 break; 4439 4440 case ZPOOL_STATUS_BAD_LOG: 4441 (void) printf(gettext("status: An intent log record " 4442 "could not be read.\n" 4443 "\tWaiting for adminstrator intervention to fix the " 4444 "faulted pool.\n")); 4445 (void) printf(gettext("action: Either restore the affected " 4446 "device(s) and run 'zpool online',\n" 4447 "\tor ignore the intent log records by running " 4448 "'zpool clear'.\n")); 4449 break; 4450 4451 default: 4452 /* 4453 * The remaining errors can't actually be generated, yet. 4454 */ 4455 assert(reason == ZPOOL_STATUS_OK); 4456 } 4457 4458 if (msgid != NULL) 4459 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 4460 msgid); 4461 4462 if (config != NULL) { 4463 int namewidth; 4464 uint64_t nerr; 4465 nvlist_t **spares, **l2cache; 4466 uint_t nspares, nl2cache; 4467 pool_scan_stat_t *ps = NULL; 4468 4469 (void) nvlist_lookup_uint64_array(nvroot, 4470 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 4471 print_scan_status(ps); 4472 4473 namewidth = max_width(zhp, nvroot, 0, 0); 4474 if (namewidth < 10) 4475 namewidth = 10; 4476 4477 (void) printf(gettext("config:\n\n")); 4478 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 4479 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 4480 print_status_config(zhp, zpool_get_name(zhp), nvroot, 4481 namewidth, 0, B_FALSE); 4482 4483 if (num_logs(nvroot) > 0) 4484 print_logs(zhp, nvroot, namewidth, B_TRUE); 4485 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 4486 &l2cache, &nl2cache) == 0) 4487 print_l2cache(zhp, l2cache, nl2cache, namewidth); 4488 4489 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 4490 &spares, &nspares) == 0) 4491 print_spares(zhp, spares, nspares, namewidth); 4492 4493 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 4494 &nerr) == 0) { 4495 nvlist_t *nverrlist = NULL; 4496 4497 /* 4498 * If the approximate error count is small, get a 4499 * precise count by fetching the entire log and 4500 * uniquifying the results. 4501 */ 4502 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 4503 zpool_get_errlog(zhp, &nverrlist) == 0) { 4504 nvpair_t *elem; 4505 4506 elem = NULL; 4507 nerr = 0; 4508 while ((elem = nvlist_next_nvpair(nverrlist, 4509 elem)) != NULL) { 4510 nerr++; 4511 } 4512 } 4513 nvlist_free(nverrlist); 4514 4515 (void) printf("\n"); 4516 4517 if (nerr == 0) 4518 (void) printf(gettext("errors: No known data " 4519 "errors\n")); 4520 else if (!cbp->cb_verbose) 4521 (void) printf(gettext("errors: %llu data " 4522 "errors, use '-v' for a list\n"), 4523 (u_longlong_t)nerr); 4524 else 4525 print_error_log(zhp); 4526 } 4527 4528 if (cbp->cb_dedup_stats) 4529 print_dedup_stats(config); 4530 } else { 4531 (void) printf(gettext("config: The configuration cannot be " 4532 "determined.\n")); 4533 } 4534 4535 return (0); 4536 } 4537 4538 /* 4539 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]] 4540 * 4541 * -v Display complete error logs 4542 * -x Display only pools with potential problems 4543 * -D Display dedup status (undocumented) 4544 * -T Display a timestamp in date(1) or Unix format 4545 * 4546 * Describes the health status of all pools or some subset. 4547 */ 4548 int 4549 zpool_do_status(int argc, char **argv) 4550 { 4551 int c; 4552 int ret; 4553 unsigned long interval = 0, count = 0; 4554 status_cbdata_t cb = { 0 }; 4555 4556 /* check options */ 4557 while ((c = getopt(argc, argv, "vxDT:")) != -1) { 4558 switch (c) { 4559 case 'v': 4560 cb.cb_verbose = B_TRUE; 4561 break; 4562 case 'x': 4563 cb.cb_explain = B_TRUE; 4564 break; 4565 case 'D': 4566 cb.cb_dedup_stats = B_TRUE; 4567 break; 4568 case 'T': 4569 get_timestamp_arg(*optarg); 4570 break; 4571 case '?': 4572 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4573 optopt); 4574 usage(B_FALSE); 4575 } 4576 } 4577 4578 argc -= optind; 4579 argv += optind; 4580 4581 get_interval_count(&argc, argv, &interval, &count); 4582 4583 if (argc == 0) 4584 cb.cb_allpools = B_TRUE; 4585 4586 cb.cb_first = B_TRUE; 4587 4588 for (;;) { 4589 if (timestamp_fmt != NODATE) 4590 print_timestamp(timestamp_fmt); 4591 4592 ret = for_each_pool(argc, argv, B_TRUE, NULL, 4593 status_callback, &cb); 4594 4595 if (argc == 0 && cb.cb_count == 0) 4596 (void) printf(gettext("no pools available\n")); 4597 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 4598 (void) printf(gettext("all pools are healthy\n")); 4599 4600 if (ret != 0) 4601 return (ret); 4602 4603 if (interval == 0) 4604 break; 4605 4606 if (count != 0 && --count == 0) 4607 break; 4608 4609 (void) sleep(interval); 4610 } 4611 4612 return (0); 4613 } 4614 4615 typedef struct upgrade_cbdata { 4616 int cb_first; 4617 int cb_argc; 4618 uint64_t cb_version; 4619 char **cb_argv; 4620 } upgrade_cbdata_t; 4621 4622 static int 4623 upgrade_version(zpool_handle_t *zhp, uint64_t version) 4624 { 4625 int ret; 4626 nvlist_t *config; 4627 uint64_t oldversion; 4628 4629 config = zpool_get_config(zhp, NULL); 4630 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4631 &oldversion) == 0); 4632 4633 assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 4634 assert(oldversion < version); 4635 4636 ret = zpool_upgrade(zhp, version); 4637 if (ret != 0) 4638 return (ret); 4639 4640 if (version >= SPA_VERSION_FEATURES) { 4641 (void) printf(gettext("Successfully upgraded " 4642 "'%s' from version %llu to feature flags.\n"), 4643 zpool_get_name(zhp), oldversion); 4644 } else { 4645 (void) printf(gettext("Successfully upgraded " 4646 "'%s' from version %llu to version %llu.\n"), 4647 zpool_get_name(zhp), oldversion, version); 4648 } 4649 4650 return (0); 4651 } 4652 4653 static int 4654 upgrade_enable_all(zpool_handle_t *zhp, int *countp) 4655 { 4656 int i, ret, count; 4657 boolean_t firstff = B_TRUE; 4658 nvlist_t *enabled = zpool_get_features(zhp); 4659 4660 count = 0; 4661 for (i = 0; i < SPA_FEATURES; i++) { 4662 const char *fname = spa_feature_table[i].fi_uname; 4663 const char *fguid = spa_feature_table[i].fi_guid; 4664 if (!nvlist_exists(enabled, fguid)) { 4665 char *propname; 4666 verify(-1 != asprintf(&propname, "feature@%s", fname)); 4667 ret = zpool_set_prop(zhp, propname, 4668 ZFS_FEATURE_ENABLED); 4669 if (ret != 0) { 4670 free(propname); 4671 return (ret); 4672 } 4673 count++; 4674 4675 if (firstff) { 4676 (void) printf(gettext("Enabled the " 4677 "following features on '%s':\n"), 4678 zpool_get_name(zhp)); 4679 firstff = B_FALSE; 4680 } 4681 (void) printf(gettext(" %s\n"), fname); 4682 free(propname); 4683 } 4684 } 4685 4686 if (countp != NULL) 4687 *countp = count; 4688 return (0); 4689 } 4690 4691 static int 4692 upgrade_cb(zpool_handle_t *zhp, void *arg) 4693 { 4694 upgrade_cbdata_t *cbp = arg; 4695 nvlist_t *config; 4696 uint64_t version; 4697 boolean_t printnl = B_FALSE; 4698 int ret; 4699 4700 config = zpool_get_config(zhp, NULL); 4701 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4702 &version) == 0); 4703 4704 assert(SPA_VERSION_IS_SUPPORTED(version)); 4705 4706 if (version < cbp->cb_version) { 4707 cbp->cb_first = B_FALSE; 4708 ret = upgrade_version(zhp, cbp->cb_version); 4709 if (ret != 0) 4710 return (ret); 4711 printnl = B_TRUE; 4712 4713 /* 4714 * If they did "zpool upgrade -a", then we could 4715 * be doing ioctls to different pools. We need 4716 * to log this history once to each pool, and bypass 4717 * the normal history logging that happens in main(). 4718 */ 4719 (void) zpool_log_history(g_zfs, history_str); 4720 log_history = B_FALSE; 4721 } 4722 4723 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 4724 int count; 4725 ret = upgrade_enable_all(zhp, &count); 4726 if (ret != 0) 4727 return (ret); 4728 4729 if (count > 0) { 4730 cbp->cb_first = B_FALSE; 4731 printnl = B_TRUE; 4732 } 4733 } 4734 4735 if (printnl) { 4736 (void) printf(gettext("\n")); 4737 } 4738 4739 return (0); 4740 } 4741 4742 static int 4743 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 4744 { 4745 upgrade_cbdata_t *cbp = arg; 4746 nvlist_t *config; 4747 uint64_t version; 4748 4749 config = zpool_get_config(zhp, NULL); 4750 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4751 &version) == 0); 4752 4753 assert(SPA_VERSION_IS_SUPPORTED(version)); 4754 4755 if (version < SPA_VERSION_FEATURES) { 4756 if (cbp->cb_first) { 4757 (void) printf(gettext("The following pools are " 4758 "formatted with legacy version numbers and can\n" 4759 "be upgraded to use feature flags. After " 4760 "being upgraded, these pools\nwill no " 4761 "longer be accessible by software that does not " 4762 "support feature\nflags.\n\n")); 4763 (void) printf(gettext("VER POOL\n")); 4764 (void) printf(gettext("--- ------------\n")); 4765 cbp->cb_first = B_FALSE; 4766 } 4767 4768 (void) printf("%2llu %s\n", (u_longlong_t)version, 4769 zpool_get_name(zhp)); 4770 } 4771 4772 return (0); 4773 } 4774 4775 static int 4776 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 4777 { 4778 upgrade_cbdata_t *cbp = arg; 4779 nvlist_t *config; 4780 uint64_t version; 4781 4782 config = zpool_get_config(zhp, NULL); 4783 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4784 &version) == 0); 4785 4786 if (version >= SPA_VERSION_FEATURES) { 4787 int i; 4788 boolean_t poolfirst = B_TRUE; 4789 nvlist_t *enabled = zpool_get_features(zhp); 4790 4791 for (i = 0; i < SPA_FEATURES; i++) { 4792 const char *fguid = spa_feature_table[i].fi_guid; 4793 const char *fname = spa_feature_table[i].fi_uname; 4794 if (!nvlist_exists(enabled, fguid)) { 4795 if (cbp->cb_first) { 4796 (void) printf(gettext("\nSome " 4797 "supported features are not " 4798 "enabled on the following pools. " 4799 "Once a\nfeature is enabled the " 4800 "pool may become incompatible with " 4801 "software\nthat does not support " 4802 "the feature. See " 4803 "zpool-features(5) for " 4804 "details.\n\n")); 4805 (void) printf(gettext("POOL " 4806 "FEATURE\n")); 4807 (void) printf(gettext("------" 4808 "---------\n")); 4809 cbp->cb_first = B_FALSE; 4810 } 4811 4812 if (poolfirst) { 4813 (void) printf(gettext("%s\n"), 4814 zpool_get_name(zhp)); 4815 poolfirst = B_FALSE; 4816 } 4817 4818 (void) printf(gettext(" %s\n"), fname); 4819 } 4820 } 4821 } 4822 4823 return (0); 4824 } 4825 4826 /* ARGSUSED */ 4827 static int 4828 upgrade_one(zpool_handle_t *zhp, void *data) 4829 { 4830 boolean_t printnl = B_FALSE; 4831 upgrade_cbdata_t *cbp = data; 4832 uint64_t cur_version; 4833 int ret; 4834 4835 if (strcmp("log", zpool_get_name(zhp)) == 0) { 4836 (void) printf(gettext("'log' is now a reserved word\n" 4837 "Pool 'log' must be renamed using export and import" 4838 " to upgrade.\n")); 4839 return (1); 4840 } 4841 4842 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 4843 if (cur_version > cbp->cb_version) { 4844 (void) printf(gettext("Pool '%s' is already formatted " 4845 "using more current version '%llu'.\n\n"), 4846 zpool_get_name(zhp), cur_version); 4847 return (0); 4848 } 4849 4850 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 4851 (void) printf(gettext("Pool '%s' is already formatted " 4852 "using version %llu.\n\n"), zpool_get_name(zhp), 4853 cbp->cb_version); 4854 return (0); 4855 } 4856 4857 if (cur_version != cbp->cb_version) { 4858 printnl = B_TRUE; 4859 ret = upgrade_version(zhp, cbp->cb_version); 4860 if (ret != 0) 4861 return (ret); 4862 } 4863 4864 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 4865 int count = 0; 4866 ret = upgrade_enable_all(zhp, &count); 4867 if (ret != 0) 4868 return (ret); 4869 4870 if (count != 0) { 4871 printnl = B_TRUE; 4872 } else if (cur_version == SPA_VERSION) { 4873 (void) printf(gettext("Pool '%s' already has all " 4874 "supported features enabled.\n"), 4875 zpool_get_name(zhp)); 4876 } 4877 } 4878 4879 if (printnl) { 4880 (void) printf(gettext("\n")); 4881 } 4882 4883 return (0); 4884 } 4885 4886 /* 4887 * zpool upgrade 4888 * zpool upgrade -v 4889 * zpool upgrade [-V version] <-a | pool ...> 4890 * 4891 * With no arguments, display downrev'd ZFS pool available for upgrade. 4892 * Individual pools can be upgraded by specifying the pool, and '-a' will 4893 * upgrade all pools. 4894 */ 4895 int 4896 zpool_do_upgrade(int argc, char **argv) 4897 { 4898 int c; 4899 upgrade_cbdata_t cb = { 0 }; 4900 int ret = 0; 4901 boolean_t showversions = B_FALSE; 4902 boolean_t upgradeall = B_FALSE; 4903 char *end; 4904 4905 4906 /* check options */ 4907 while ((c = getopt(argc, argv, ":avV:")) != -1) { 4908 switch (c) { 4909 case 'a': 4910 upgradeall = B_TRUE; 4911 break; 4912 case 'v': 4913 showversions = B_TRUE; 4914 break; 4915 case 'V': 4916 cb.cb_version = strtoll(optarg, &end, 10); 4917 if (*end != '\0' || 4918 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 4919 (void) fprintf(stderr, 4920 gettext("invalid version '%s'\n"), optarg); 4921 usage(B_FALSE); 4922 } 4923 break; 4924 case ':': 4925 (void) fprintf(stderr, gettext("missing argument for " 4926 "'%c' option\n"), optopt); 4927 usage(B_FALSE); 4928 break; 4929 case '?': 4930 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4931 optopt); 4932 usage(B_FALSE); 4933 } 4934 } 4935 4936 cb.cb_argc = argc; 4937 cb.cb_argv = argv; 4938 argc -= optind; 4939 argv += optind; 4940 4941 if (cb.cb_version == 0) { 4942 cb.cb_version = SPA_VERSION; 4943 } else if (!upgradeall && argc == 0) { 4944 (void) fprintf(stderr, gettext("-V option is " 4945 "incompatible with other arguments\n")); 4946 usage(B_FALSE); 4947 } 4948 4949 if (showversions) { 4950 if (upgradeall || argc != 0) { 4951 (void) fprintf(stderr, gettext("-v option is " 4952 "incompatible with other arguments\n")); 4953 usage(B_FALSE); 4954 } 4955 } else if (upgradeall) { 4956 if (argc != 0) { 4957 (void) fprintf(stderr, gettext("-a option should not " 4958 "be used along with a pool name\n")); 4959 usage(B_FALSE); 4960 } 4961 } 4962 4963 (void) printf(gettext("This system supports ZFS pool feature " 4964 "flags.\n\n")); 4965 if (showversions) { 4966 int i; 4967 4968 (void) printf(gettext("The following features are " 4969 "supported:\n\n")); 4970 (void) printf(gettext("FEAT DESCRIPTION\n")); 4971 (void) printf("----------------------------------------------" 4972 "---------------\n"); 4973 for (i = 0; i < SPA_FEATURES; i++) { 4974 zfeature_info_t *fi = &spa_feature_table[i]; 4975 const char *ro = 4976 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 4977 " (read-only compatible)" : ""; 4978 4979 (void) printf("%-37s%s\n", fi->fi_uname, ro); 4980 (void) printf(" %s\n", fi->fi_desc); 4981 } 4982 (void) printf("\n"); 4983 4984 (void) printf(gettext("The following legacy versions are also " 4985 "supported:\n\n")); 4986 (void) printf(gettext("VER DESCRIPTION\n")); 4987 (void) printf("--- -----------------------------------------" 4988 "---------------\n"); 4989 (void) printf(gettext(" 1 Initial ZFS version\n")); 4990 (void) printf(gettext(" 2 Ditto blocks " 4991 "(replicated metadata)\n")); 4992 (void) printf(gettext(" 3 Hot spares and double parity " 4993 "RAID-Z\n")); 4994 (void) printf(gettext(" 4 zpool history\n")); 4995 (void) printf(gettext(" 5 Compression using the gzip " 4996 "algorithm\n")); 4997 (void) printf(gettext(" 6 bootfs pool property\n")); 4998 (void) printf(gettext(" 7 Separate intent log devices\n")); 4999 (void) printf(gettext(" 8 Delegated administration\n")); 5000 (void) printf(gettext(" 9 refquota and refreservation " 5001 "properties\n")); 5002 (void) printf(gettext(" 10 Cache devices\n")); 5003 (void) printf(gettext(" 11 Improved scrub performance\n")); 5004 (void) printf(gettext(" 12 Snapshot properties\n")); 5005 (void) printf(gettext(" 13 snapused property\n")); 5006 (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 5007 (void) printf(gettext(" 15 user/group space accounting\n")); 5008 (void) printf(gettext(" 16 stmf property support\n")); 5009 (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 5010 (void) printf(gettext(" 18 Snapshot user holds\n")); 5011 (void) printf(gettext(" 19 Log device removal\n")); 5012 (void) printf(gettext(" 20 Compression using zle " 5013 "(zero-length encoding)\n")); 5014 (void) printf(gettext(" 21 Deduplication\n")); 5015 (void) printf(gettext(" 22 Received properties\n")); 5016 (void) printf(gettext(" 23 Slim ZIL\n")); 5017 (void) printf(gettext(" 24 System attributes\n")); 5018 (void) printf(gettext(" 25 Improved scrub stats\n")); 5019 (void) printf(gettext(" 26 Improved snapshot deletion " 5020 "performance\n")); 5021 (void) printf(gettext(" 27 Improved snapshot creation " 5022 "performance\n")); 5023 (void) printf(gettext(" 28 Multiple vdev replacements\n")); 5024 (void) printf(gettext("\nFor more information on a particular " 5025 "version, including supported releases,\n")); 5026 (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 5027 } else if (argc == 0 && upgradeall) { 5028 cb.cb_first = B_TRUE; 5029 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 5030 if (ret == 0 && cb.cb_first) { 5031 if (cb.cb_version == SPA_VERSION) { 5032 (void) printf(gettext("All pools are already " 5033 "formatted using feature flags.\n\n")); 5034 (void) printf(gettext("Every feature flags " 5035 "pool already has all supported features " 5036 "enabled.\n")); 5037 } else { 5038 (void) printf(gettext("All pools are already " 5039 "formatted with version %llu or higher.\n"), 5040 cb.cb_version); 5041 } 5042 } 5043 } else if (argc == 0) { 5044 cb.cb_first = B_TRUE; 5045 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 5046 assert(ret == 0); 5047 5048 if (cb.cb_first) { 5049 (void) printf(gettext("All pools are formatted " 5050 "using feature flags.\n\n")); 5051 } else { 5052 (void) printf(gettext("\nUse 'zpool upgrade -v' " 5053 "for a list of available legacy versions.\n")); 5054 } 5055 5056 cb.cb_first = B_TRUE; 5057 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 5058 assert(ret == 0); 5059 5060 if (cb.cb_first) { 5061 (void) printf(gettext("Every feature flags pool has " 5062 "all supported features enabled.\n")); 5063 } else { 5064 (void) printf(gettext("\n")); 5065 } 5066 } else { 5067 ret = for_each_pool(argc, argv, B_FALSE, NULL, 5068 upgrade_one, &cb); 5069 } 5070 5071 return (ret); 5072 } 5073 5074 typedef struct hist_cbdata { 5075 boolean_t first; 5076 boolean_t longfmt; 5077 boolean_t internal; 5078 } hist_cbdata_t; 5079 5080 /* 5081 * Print out the command history for a specific pool. 5082 */ 5083 static int 5084 get_history_one(zpool_handle_t *zhp, void *data) 5085 { 5086 nvlist_t *nvhis; 5087 nvlist_t **records; 5088 uint_t numrecords; 5089 int ret, i; 5090 hist_cbdata_t *cb = (hist_cbdata_t *)data; 5091 5092 cb->first = B_FALSE; 5093 5094 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 5095 5096 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 5097 return (ret); 5098 5099 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 5100 &records, &numrecords) == 0); 5101 for (i = 0; i < numrecords; i++) { 5102 nvlist_t *rec = records[i]; 5103 char tbuf[30] = ""; 5104 5105 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 5106 time_t tsec; 5107 struct tm t; 5108 5109 tsec = fnvlist_lookup_uint64(records[i], 5110 ZPOOL_HIST_TIME); 5111 (void) localtime_r(&tsec, &t); 5112 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 5113 } 5114 5115 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 5116 (void) printf("%s %s", tbuf, 5117 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 5118 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 5119 int ievent = 5120 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 5121 if (!cb->internal) 5122 continue; 5123 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 5124 (void) printf("%s unrecognized record:\n", 5125 tbuf); 5126 dump_nvlist(rec, 4); 5127 continue; 5128 } 5129 (void) printf("%s [internal %s txg:%lld] %s", tbuf, 5130 zfs_history_event_names[ievent], 5131 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5132 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 5133 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 5134 if (!cb->internal) 5135 continue; 5136 (void) printf("%s [txg:%lld] %s", tbuf, 5137 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5138 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 5139 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 5140 (void) printf(" %s (%llu)", 5141 fnvlist_lookup_string(rec, 5142 ZPOOL_HIST_DSNAME), 5143 fnvlist_lookup_uint64(rec, 5144 ZPOOL_HIST_DSID)); 5145 } 5146 (void) printf(" %s", fnvlist_lookup_string(rec, 5147 ZPOOL_HIST_INT_STR)); 5148 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 5149 if (!cb->internal) 5150 continue; 5151 (void) printf("%s ioctl %s\n", tbuf, 5152 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 5153 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 5154 (void) printf(" input:\n"); 5155 dump_nvlist(fnvlist_lookup_nvlist(rec, 5156 ZPOOL_HIST_INPUT_NVL), 8); 5157 } 5158 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 5159 (void) printf(" output:\n"); 5160 dump_nvlist(fnvlist_lookup_nvlist(rec, 5161 ZPOOL_HIST_OUTPUT_NVL), 8); 5162 } 5163 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 5164 (void) printf(" errno: %lld\n", 5165 fnvlist_lookup_int64(rec, 5166 ZPOOL_HIST_ERRNO)); 5167 } 5168 } else { 5169 if (!cb->internal) 5170 continue; 5171 (void) printf("%s unrecognized record:\n", tbuf); 5172 dump_nvlist(rec, 4); 5173 } 5174 5175 if (!cb->longfmt) { 5176 (void) printf("\n"); 5177 continue; 5178 } 5179 (void) printf(" ["); 5180 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 5181 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 5182 struct passwd *pwd = getpwuid(who); 5183 (void) printf("user %d ", (int)who); 5184 if (pwd != NULL) 5185 (void) printf("(%s) ", pwd->pw_name); 5186 } 5187 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 5188 (void) printf("on %s", 5189 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 5190 } 5191 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 5192 (void) printf(":%s", 5193 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 5194 } 5195 (void) printf("]"); 5196 (void) printf("\n"); 5197 } 5198 (void) printf("\n"); 5199 nvlist_free(nvhis); 5200 5201 return (ret); 5202 } 5203 5204 /* 5205 * zpool history <pool> 5206 * 5207 * Displays the history of commands that modified pools. 5208 */ 5209 int 5210 zpool_do_history(int argc, char **argv) 5211 { 5212 hist_cbdata_t cbdata = { 0 }; 5213 int ret; 5214 int c; 5215 5216 cbdata.first = B_TRUE; 5217 /* check options */ 5218 while ((c = getopt(argc, argv, "li")) != -1) { 5219 switch (c) { 5220 case 'l': 5221 cbdata.longfmt = B_TRUE; 5222 break; 5223 case 'i': 5224 cbdata.internal = B_TRUE; 5225 break; 5226 case '?': 5227 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5228 optopt); 5229 usage(B_FALSE); 5230 } 5231 } 5232 argc -= optind; 5233 argv += optind; 5234 5235 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 5236 &cbdata); 5237 5238 if (argc == 0 && cbdata.first == B_TRUE) { 5239 (void) printf(gettext("no pools available\n")); 5240 return (0); 5241 } 5242 5243 return (ret); 5244 } 5245 5246 static int 5247 get_callback(zpool_handle_t *zhp, void *data) 5248 { 5249 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 5250 char value[MAXNAMELEN]; 5251 zprop_source_t srctype; 5252 zprop_list_t *pl; 5253 5254 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 5255 5256 /* 5257 * Skip the special fake placeholder. This will also skip 5258 * over the name property when 'all' is specified. 5259 */ 5260 if (pl->pl_prop == ZPOOL_PROP_NAME && 5261 pl == cbp->cb_proplist) 5262 continue; 5263 5264 if (pl->pl_prop == ZPROP_INVAL && 5265 (zpool_prop_feature(pl->pl_user_prop) || 5266 zpool_prop_unsupported(pl->pl_user_prop))) { 5267 srctype = ZPROP_SRC_LOCAL; 5268 5269 if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 5270 value, sizeof (value)) == 0) { 5271 zprop_print_one_property(zpool_get_name(zhp), 5272 cbp, pl->pl_user_prop, value, srctype, 5273 NULL, NULL); 5274 } 5275 } else { 5276 if (zpool_get_prop(zhp, pl->pl_prop, value, 5277 sizeof (value), &srctype, cbp->cb_literal) != 0) 5278 continue; 5279 5280 zprop_print_one_property(zpool_get_name(zhp), cbp, 5281 zpool_prop_to_name(pl->pl_prop), value, srctype, 5282 NULL, NULL); 5283 } 5284 } 5285 return (0); 5286 } 5287 5288 /* 5289 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 5290 * 5291 * -H Scripted mode. Don't display headers, and separate properties 5292 * by a single tab. 5293 * -o List of columns to display. Defaults to 5294 * "name,property,value,source". 5295 * -p Diplay values in parsable (exact) format. 5296 * 5297 * Get properties of pools in the system. Output space statistics 5298 * for each one as well as other attributes. 5299 */ 5300 int 5301 zpool_do_get(int argc, char **argv) 5302 { 5303 zprop_get_cbdata_t cb = { 0 }; 5304 zprop_list_t fake_name = { 0 }; 5305 int ret; 5306 int c, i; 5307 char *value; 5308 5309 cb.cb_first = B_TRUE; 5310 5311 /* 5312 * Set up default columns and sources. 5313 */ 5314 cb.cb_sources = ZPROP_SRC_ALL; 5315 cb.cb_columns[0] = GET_COL_NAME; 5316 cb.cb_columns[1] = GET_COL_PROPERTY; 5317 cb.cb_columns[2] = GET_COL_VALUE; 5318 cb.cb_columns[3] = GET_COL_SOURCE; 5319 cb.cb_type = ZFS_TYPE_POOL; 5320 5321 /* check options */ 5322 while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 5323 switch (c) { 5324 case 'p': 5325 cb.cb_literal = B_TRUE; 5326 break; 5327 case 'H': 5328 cb.cb_scripted = B_TRUE; 5329 break; 5330 case 'o': 5331 bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 5332 i = 0; 5333 while (*optarg != '\0') { 5334 static char *col_subopts[] = 5335 { "name", "property", "value", "source", 5336 "all", NULL }; 5337 5338 if (i == ZFS_GET_NCOLS) { 5339 (void) fprintf(stderr, gettext("too " 5340 "many fields given to -o " 5341 "option\n")); 5342 usage(B_FALSE); 5343 } 5344 5345 switch (getsubopt(&optarg, col_subopts, 5346 &value)) { 5347 case 0: 5348 cb.cb_columns[i++] = GET_COL_NAME; 5349 break; 5350 case 1: 5351 cb.cb_columns[i++] = GET_COL_PROPERTY; 5352 break; 5353 case 2: 5354 cb.cb_columns[i++] = GET_COL_VALUE; 5355 break; 5356 case 3: 5357 cb.cb_columns[i++] = GET_COL_SOURCE; 5358 break; 5359 case 4: 5360 if (i > 0) { 5361 (void) fprintf(stderr, 5362 gettext("\"all\" conflicts " 5363 "with specific fields " 5364 "given to -o option\n")); 5365 usage(B_FALSE); 5366 } 5367 cb.cb_columns[0] = GET_COL_NAME; 5368 cb.cb_columns[1] = GET_COL_PROPERTY; 5369 cb.cb_columns[2] = GET_COL_VALUE; 5370 cb.cb_columns[3] = GET_COL_SOURCE; 5371 i = ZFS_GET_NCOLS; 5372 break; 5373 default: 5374 (void) fprintf(stderr, 5375 gettext("invalid column name " 5376 "'%s'\n"), value); 5377 usage(B_FALSE); 5378 } 5379 } 5380 break; 5381 case '?': 5382 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5383 optopt); 5384 usage(B_FALSE); 5385 } 5386 } 5387 5388 argc -= optind; 5389 argv += optind; 5390 5391 if (argc < 1) { 5392 (void) fprintf(stderr, gettext("missing property " 5393 "argument\n")); 5394 usage(B_FALSE); 5395 } 5396 5397 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 5398 ZFS_TYPE_POOL) != 0) 5399 usage(B_FALSE); 5400 5401 argc--; 5402 argv++; 5403 5404 if (cb.cb_proplist != NULL) { 5405 fake_name.pl_prop = ZPOOL_PROP_NAME; 5406 fake_name.pl_width = strlen(gettext("NAME")); 5407 fake_name.pl_next = cb.cb_proplist; 5408 cb.cb_proplist = &fake_name; 5409 } 5410 5411 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 5412 get_callback, &cb); 5413 5414 if (cb.cb_proplist == &fake_name) 5415 zprop_free_list(fake_name.pl_next); 5416 else 5417 zprop_free_list(cb.cb_proplist); 5418 5419 return (ret); 5420 } 5421 5422 typedef struct set_cbdata { 5423 char *cb_propname; 5424 char *cb_value; 5425 boolean_t cb_any_successful; 5426 } set_cbdata_t; 5427 5428 int 5429 set_callback(zpool_handle_t *zhp, void *data) 5430 { 5431 int error; 5432 set_cbdata_t *cb = (set_cbdata_t *)data; 5433 5434 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 5435 5436 if (!error) 5437 cb->cb_any_successful = B_TRUE; 5438 5439 return (error); 5440 } 5441 5442 int 5443 zpool_do_set(int argc, char **argv) 5444 { 5445 set_cbdata_t cb = { 0 }; 5446 int error; 5447 5448 if (argc > 1 && argv[1][0] == '-') { 5449 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5450 argv[1][1]); 5451 usage(B_FALSE); 5452 } 5453 5454 if (argc < 2) { 5455 (void) fprintf(stderr, gettext("missing property=value " 5456 "argument\n")); 5457 usage(B_FALSE); 5458 } 5459 5460 if (argc < 3) { 5461 (void) fprintf(stderr, gettext("missing pool name\n")); 5462 usage(B_FALSE); 5463 } 5464 5465 if (argc > 3) { 5466 (void) fprintf(stderr, gettext("too many pool names\n")); 5467 usage(B_FALSE); 5468 } 5469 5470 cb.cb_propname = argv[1]; 5471 cb.cb_value = strchr(cb.cb_propname, '='); 5472 if (cb.cb_value == NULL) { 5473 (void) fprintf(stderr, gettext("missing value in " 5474 "property=value argument\n")); 5475 usage(B_FALSE); 5476 } 5477 5478 *(cb.cb_value) = '\0'; 5479 cb.cb_value++; 5480 5481 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 5482 set_callback, &cb); 5483 5484 return (error); 5485 } 5486 5487 static int 5488 find_command_idx(char *command, int *idx) 5489 { 5490 int i; 5491 5492 for (i = 0; i < NCOMMAND; i++) { 5493 if (command_table[i].name == NULL) 5494 continue; 5495 5496 if (strcmp(command, command_table[i].name) == 0) { 5497 *idx = i; 5498 return (0); 5499 } 5500 } 5501 return (1); 5502 } 5503 5504 int 5505 main(int argc, char **argv) 5506 { 5507 int ret = 0; 5508 int i; 5509 char *cmdname; 5510 5511 (void) setlocale(LC_ALL, ""); 5512 (void) textdomain(TEXT_DOMAIN); 5513 5514 if ((g_zfs = libzfs_init()) == NULL) { 5515 (void) fprintf(stderr, gettext("internal error: failed to " 5516 "initialize ZFS library\n")); 5517 return (1); 5518 } 5519 5520 libzfs_print_on_error(g_zfs, B_TRUE); 5521 5522 opterr = 0; 5523 5524 /* 5525 * Make sure the user has specified some command. 5526 */ 5527 if (argc < 2) { 5528 (void) fprintf(stderr, gettext("missing command\n")); 5529 usage(B_FALSE); 5530 } 5531 5532 cmdname = argv[1]; 5533 5534 /* 5535 * Special case '-?' 5536 */ 5537 if (strcmp(cmdname, "-?") == 0) 5538 usage(B_TRUE); 5539 5540 zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 5541 5542 /* 5543 * Run the appropriate command. 5544 */ 5545 if (find_command_idx(cmdname, &i) == 0) { 5546 current_command = &command_table[i]; 5547 ret = command_table[i].func(argc - 1, argv + 1); 5548 } else if (strchr(cmdname, '=')) { 5549 verify(find_command_idx("set", &i) == 0); 5550 current_command = &command_table[i]; 5551 ret = command_table[i].func(argc, argv); 5552 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 5553 /* 5554 * 'freeze' is a vile debugging abomination, so we treat 5555 * it as such. 5556 */ 5557 char buf[16384]; 5558 int fd = open(ZFS_DEV, O_RDWR); 5559 (void) strcpy((void *)buf, argv[2]); 5560 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 5561 } else { 5562 (void) fprintf(stderr, gettext("unrecognized " 5563 "command '%s'\n"), cmdname); 5564 usage(B_FALSE); 5565 } 5566 5567 if (ret == 0 && log_history) 5568 (void) zpool_log_history(g_zfs, history_str); 5569 5570 libzfs_fini(g_zfs); 5571 5572 /* 5573 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 5574 * for the purposes of running ::findleaks. 5575 */ 5576 if (getenv("ZFS_ABORT") != NULL) { 5577 (void) printf("dumping core by request\n"); 5578 abort(); 5579 } 5580 5581 return (ret); 5582 } 5583