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