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