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 2011 Nexenta Systems, Inc. All rights reserved. 25 * Copyright (c) 2011, 2020 by Delphix. All rights reserved. 26 * Copyright (c) 2012 by Frederik Wessels. All rights reserved. 27 * Copyright (c) 2012 by Cyril Plisko. All rights reserved. 28 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved. 29 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>. 30 * Copyright (c) 2017 Datto Inc. 31 * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. 32 * Copyright (c) 2017, Intel Corporation. 33 * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com> 34 * Copyright (c) 2021, Colm Buckley <colm@tuatha.org> 35 * Copyright [2021] Hewlett Packard Enterprise Development LP 36 */ 37 38#include <assert.h> 39#include <ctype.h> 40#include <dirent.h> 41#include <errno.h> 42#include <fcntl.h> 43#include <getopt.h> 44#include <libgen.h> 45#include <libintl.h> 46#include <libuutil.h> 47#include <locale.h> 48#include <pthread.h> 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#include <strings.h> 53#include <time.h> 54#include <unistd.h> 55#include <pwd.h> 56#include <zone.h> 57#include <sys/wait.h> 58#include <zfs_prop.h> 59#include <sys/fs/zfs.h> 60#include <sys/stat.h> 61#include <sys/systeminfo.h> 62#include <sys/fm/fs/zfs.h> 63#include <sys/fm/util.h> 64#include <sys/fm/protocol.h> 65#include <sys/zfs_ioctl.h> 66#include <sys/mount.h> 67#include <sys/sysmacros.h> 68 69#include <math.h> 70 71#include <libzfs.h> 72#include <libzutil.h> 73 74#include "zpool_util.h" 75#include "zfs_comutil.h" 76#include "zfeature_common.h" 77 78#include "statcommon.h" 79 80libzfs_handle_t *g_zfs; 81 82static int zpool_do_create(int, char **); 83static int zpool_do_destroy(int, char **); 84 85static int zpool_do_add(int, char **); 86static int zpool_do_remove(int, char **); 87static int zpool_do_labelclear(int, char **); 88 89static int zpool_do_checkpoint(int, char **); 90 91static int zpool_do_list(int, char **); 92static int zpool_do_iostat(int, char **); 93static int zpool_do_status(int, char **); 94 95static int zpool_do_online(int, char **); 96static int zpool_do_offline(int, char **); 97static int zpool_do_clear(int, char **); 98static int zpool_do_reopen(int, char **); 99 100static int zpool_do_reguid(int, char **); 101 102static int zpool_do_attach(int, char **); 103static int zpool_do_detach(int, char **); 104static int zpool_do_replace(int, char **); 105static int zpool_do_split(int, char **); 106 107static int zpool_do_initialize(int, char **); 108static int zpool_do_scrub(int, char **); 109static int zpool_do_resilver(int, char **); 110static int zpool_do_trim(int, char **); 111 112static int zpool_do_import(int, char **); 113static int zpool_do_export(int, char **); 114 115static int zpool_do_upgrade(int, char **); 116 117static int zpool_do_history(int, char **); 118static int zpool_do_events(int, char **); 119 120static int zpool_do_get(int, char **); 121static int zpool_do_set(int, char **); 122 123static int zpool_do_sync(int, char **); 124 125static int zpool_do_version(int, char **); 126 127static int zpool_do_wait(int, char **); 128 129static zpool_compat_status_t zpool_do_load_compat( 130 const char *, boolean_t *); 131 132/* 133 * These libumem hooks provide a reasonable set of defaults for the allocator's 134 * debugging facilities. 135 */ 136 137#ifdef DEBUG 138const char * 139_umem_debug_init(void) 140{ 141 return ("default,verbose"); /* $UMEM_DEBUG setting */ 142} 143 144const char * 145_umem_logging_init(void) 146{ 147 return ("fail,contents"); /* $UMEM_LOGGING setting */ 148} 149#endif 150 151typedef enum { 152 HELP_ADD, 153 HELP_ATTACH, 154 HELP_CLEAR, 155 HELP_CREATE, 156 HELP_CHECKPOINT, 157 HELP_DESTROY, 158 HELP_DETACH, 159 HELP_EXPORT, 160 HELP_HISTORY, 161 HELP_IMPORT, 162 HELP_IOSTAT, 163 HELP_LABELCLEAR, 164 HELP_LIST, 165 HELP_OFFLINE, 166 HELP_ONLINE, 167 HELP_REPLACE, 168 HELP_REMOVE, 169 HELP_INITIALIZE, 170 HELP_SCRUB, 171 HELP_RESILVER, 172 HELP_TRIM, 173 HELP_STATUS, 174 HELP_UPGRADE, 175 HELP_EVENTS, 176 HELP_GET, 177 HELP_SET, 178 HELP_SPLIT, 179 HELP_SYNC, 180 HELP_REGUID, 181 HELP_REOPEN, 182 HELP_VERSION, 183 HELP_WAIT 184} zpool_help_t; 185 186 187/* 188 * Flags for stats to display with "zpool iostats" 189 */ 190enum iostat_type { 191 IOS_DEFAULT = 0, 192 IOS_LATENCY = 1, 193 IOS_QUEUES = 2, 194 IOS_L_HISTO = 3, 195 IOS_RQ_HISTO = 4, 196 IOS_COUNT, /* always last element */ 197}; 198 199/* iostat_type entries as bitmasks */ 200#define IOS_DEFAULT_M (1ULL << IOS_DEFAULT) 201#define IOS_LATENCY_M (1ULL << IOS_LATENCY) 202#define IOS_QUEUES_M (1ULL << IOS_QUEUES) 203#define IOS_L_HISTO_M (1ULL << IOS_L_HISTO) 204#define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO) 205 206/* Mask of all the histo bits */ 207#define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M) 208 209/* 210 * Lookup table for iostat flags to nvlist names. Basically a list 211 * of all the nvlists a flag requires. Also specifies the order in 212 * which data gets printed in zpool iostat. 213 */ 214static const char *vsx_type_to_nvlist[IOS_COUNT][13] = { 215 [IOS_L_HISTO] = { 216 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO, 217 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO, 218 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO, 219 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO, 220 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO, 221 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO, 222 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO, 223 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO, 224 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO, 225 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO, 226 NULL}, 227 [IOS_LATENCY] = { 228 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO, 229 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO, 230 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO, 231 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO, 232 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO, 233 NULL}, 234 [IOS_QUEUES] = { 235 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE, 236 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE, 237 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE, 238 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE, 239 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE, 240 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE, 241 NULL}, 242 [IOS_RQ_HISTO] = { 243 ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO, 244 ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO, 245 ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO, 246 ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO, 247 ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO, 248 ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO, 249 ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO, 250 ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO, 251 ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO, 252 ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO, 253 ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO, 254 ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO, 255 NULL}, 256}; 257 258 259/* 260 * Given a cb->cb_flags with a histogram bit set, return the iostat_type. 261 * Right now, only one histo bit is ever set at one time, so we can 262 * just do a highbit64(a) 263 */ 264#define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1) 265 266typedef struct zpool_command { 267 const char *name; 268 int (*func)(int, char **); 269 zpool_help_t usage; 270} zpool_command_t; 271 272/* 273 * Master command table. Each ZFS command has a name, associated function, and 274 * usage message. The usage messages need to be internationalized, so we have 275 * to have a function to return the usage message based on a command index. 276 * 277 * These commands are organized according to how they are displayed in the usage 278 * message. An empty command (one with a NULL name) indicates an empty line in 279 * the generic usage message. 280 */ 281static zpool_command_t command_table[] = { 282 { "version", zpool_do_version, HELP_VERSION }, 283 { NULL }, 284 { "create", zpool_do_create, HELP_CREATE }, 285 { "destroy", zpool_do_destroy, HELP_DESTROY }, 286 { NULL }, 287 { "add", zpool_do_add, HELP_ADD }, 288 { "remove", zpool_do_remove, HELP_REMOVE }, 289 { NULL }, 290 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 291 { NULL }, 292 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 293 { NULL }, 294 { "list", zpool_do_list, HELP_LIST }, 295 { "iostat", zpool_do_iostat, HELP_IOSTAT }, 296 { "status", zpool_do_status, HELP_STATUS }, 297 { NULL }, 298 { "online", zpool_do_online, HELP_ONLINE }, 299 { "offline", zpool_do_offline, HELP_OFFLINE }, 300 { "clear", zpool_do_clear, HELP_CLEAR }, 301 { "reopen", zpool_do_reopen, HELP_REOPEN }, 302 { NULL }, 303 { "attach", zpool_do_attach, HELP_ATTACH }, 304 { "detach", zpool_do_detach, HELP_DETACH }, 305 { "replace", zpool_do_replace, HELP_REPLACE }, 306 { "split", zpool_do_split, HELP_SPLIT }, 307 { NULL }, 308 { "initialize", zpool_do_initialize, HELP_INITIALIZE }, 309 { "resilver", zpool_do_resilver, HELP_RESILVER }, 310 { "scrub", zpool_do_scrub, HELP_SCRUB }, 311 { "trim", zpool_do_trim, HELP_TRIM }, 312 { NULL }, 313 { "import", zpool_do_import, HELP_IMPORT }, 314 { "export", zpool_do_export, HELP_EXPORT }, 315 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 316 { "reguid", zpool_do_reguid, HELP_REGUID }, 317 { NULL }, 318 { "history", zpool_do_history, HELP_HISTORY }, 319 { "events", zpool_do_events, HELP_EVENTS }, 320 { NULL }, 321 { "get", zpool_do_get, HELP_GET }, 322 { "set", zpool_do_set, HELP_SET }, 323 { "sync", zpool_do_sync, HELP_SYNC }, 324 { NULL }, 325 { "wait", zpool_do_wait, HELP_WAIT }, 326}; 327 328#define NCOMMAND (ARRAY_SIZE(command_table)) 329 330#define VDEV_ALLOC_CLASS_LOGS "logs" 331 332static zpool_command_t *current_command; 333static char history_str[HIS_MAX_RECORD_LEN]; 334static boolean_t log_history = B_TRUE; 335static uint_t timestamp_fmt = NODATE; 336 337static const char * 338get_usage(zpool_help_t idx) 339{ 340 switch (idx) { 341 case HELP_ADD: 342 return (gettext("\tadd [-fgLnP] [-o property=value] " 343 "<pool> <vdev> ...\n")); 344 case HELP_ATTACH: 345 return (gettext("\tattach [-fsw] [-o property=value] " 346 "<pool> <device> <new-device>\n")); 347 case HELP_CLEAR: 348 return (gettext("\tclear [-nF] <pool> [device]\n")); 349 case HELP_CREATE: 350 return (gettext("\tcreate [-fnd] [-o property=value] ... \n" 351 "\t [-O file-system-property=value] ... \n" 352 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 353 case HELP_CHECKPOINT: 354 return (gettext("\tcheckpoint [-d [-w]] <pool> ...\n")); 355 case HELP_DESTROY: 356 return (gettext("\tdestroy [-f] <pool>\n")); 357 case HELP_DETACH: 358 return (gettext("\tdetach <pool> <device>\n")); 359 case HELP_EXPORT: 360 return (gettext("\texport [-af] <pool> ...\n")); 361 case HELP_HISTORY: 362 return (gettext("\thistory [-il] [<pool>] ...\n")); 363 case HELP_IMPORT: 364 return (gettext("\timport [-d dir] [-D]\n" 365 "\timport [-o mntopts] [-o property=value] ... \n" 366 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 367 "[-R root] [-F [-n]] -a\n" 368 "\timport [-o mntopts] [-o property=value] ... \n" 369 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 370 "[-R root] [-F [-n]]\n" 371 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 372 case HELP_IOSTAT: 373 return (gettext("\tiostat [[[-c [script1,script2,...]" 374 "[-lq]]|[-rw]] [-T d | u] [-ghHLpPvy]\n" 375 "\t [[pool ...]|[pool vdev ...]|[vdev ...]]" 376 " [[-n] interval [count]]\n")); 377 case HELP_LABELCLEAR: 378 return (gettext("\tlabelclear [-f] <vdev>\n")); 379 case HELP_LIST: 380 return (gettext("\tlist [-gHLpPv] [-o property[,...]] " 381 "[-T d|u] [pool] ... \n" 382 "\t [interval [count]]\n")); 383 case HELP_OFFLINE: 384 return (gettext("\toffline [-f] [-t] <pool> <device> ...\n")); 385 case HELP_ONLINE: 386 return (gettext("\tonline [-e] <pool> <device> ...\n")); 387 case HELP_REPLACE: 388 return (gettext("\treplace [-fsw] [-o property=value] " 389 "<pool> <device> [new-device]\n")); 390 case HELP_REMOVE: 391 return (gettext("\tremove [-npsw] <pool> <device> ...\n")); 392 case HELP_REOPEN: 393 return (gettext("\treopen [-n] <pool>\n")); 394 case HELP_INITIALIZE: 395 return (gettext("\tinitialize [-c | -s] [-w] <pool> " 396 "[<device> ...]\n")); 397 case HELP_SCRUB: 398 return (gettext("\tscrub [-s | -p] [-w] <pool> ...\n")); 399 case HELP_RESILVER: 400 return (gettext("\tresilver <pool> ...\n")); 401 case HELP_TRIM: 402 return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> " 403 "[<device> ...]\n")); 404 case HELP_STATUS: 405 return (gettext("\tstatus [-c [script1,script2,...]] " 406 "[-igLpPstvxD] [-T d|u] [pool] ... \n" 407 "\t [interval [count]]\n")); 408 case HELP_UPGRADE: 409 return (gettext("\tupgrade\n" 410 "\tupgrade -v\n" 411 "\tupgrade [-V version] <-a | pool ...>\n")); 412 case HELP_EVENTS: 413 return (gettext("\tevents [-vHf [pool] | -c]\n")); 414 case HELP_GET: 415 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 416 "<\"all\" | property[,...]> <pool> ...\n")); 417 case HELP_SET: 418 return (gettext("\tset <property=value> <pool> \n")); 419 case HELP_SPLIT: 420 return (gettext("\tsplit [-gLnPl] [-R altroot] [-o mntopts]\n" 421 "\t [-o property=value] <pool> <newpool> " 422 "[<device> ...]\n")); 423 case HELP_REGUID: 424 return (gettext("\treguid <pool>\n")); 425 case HELP_SYNC: 426 return (gettext("\tsync [pool] ...\n")); 427 case HELP_VERSION: 428 return (gettext("\tversion\n")); 429 case HELP_WAIT: 430 return (gettext("\twait [-Hp] [-T d|u] [-t <activity>[,...]] " 431 "<pool> [interval]\n")); 432 } 433 434 abort(); 435 /* NOTREACHED */ 436} 437 438static void 439zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) 440{ 441 uint_t children = 0; 442 nvlist_t **child; 443 uint_t i; 444 445 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 446 &child, &children); 447 448 if (children == 0) { 449 char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 450 VDEV_NAME_PATH); 451 452 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 && 453 strcmp(path, VDEV_TYPE_HOLE) != 0) 454 fnvlist_add_boolean(res, path); 455 456 free(path); 457 return; 458 } 459 460 for (i = 0; i < children; i++) { 461 zpool_collect_leaves(zhp, child[i], res); 462 } 463} 464 465/* 466 * Callback routine that will print out a pool property value. 467 */ 468static int 469print_prop_cb(int prop, void *cb) 470{ 471 FILE *fp = cb; 472 473 (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop)); 474 475 if (zpool_prop_readonly(prop)) 476 (void) fprintf(fp, " NO "); 477 else 478 (void) fprintf(fp, " YES "); 479 480 if (zpool_prop_values(prop) == NULL) 481 (void) fprintf(fp, "-\n"); 482 else 483 (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 484 485 return (ZPROP_CONT); 486} 487 488/* 489 * Display usage message. If we're inside a command, display only the usage for 490 * that command. Otherwise, iterate over the entire command table and display 491 * a complete usage message. 492 */ 493static void 494usage(boolean_t requested) 495{ 496 FILE *fp = requested ? stdout : stderr; 497 498 if (current_command == NULL) { 499 int i; 500 501 (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 502 (void) fprintf(fp, 503 gettext("where 'command' is one of the following:\n\n")); 504 505 for (i = 0; i < NCOMMAND; i++) { 506 if (command_table[i].name == NULL) 507 (void) fprintf(fp, "\n"); 508 else 509 (void) fprintf(fp, "%s", 510 get_usage(command_table[i].usage)); 511 } 512 } else { 513 (void) fprintf(fp, gettext("usage:\n")); 514 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 515 } 516 517 if (current_command != NULL && 518 ((strcmp(current_command->name, "set") == 0) || 519 (strcmp(current_command->name, "get") == 0) || 520 (strcmp(current_command->name, "list") == 0))) { 521 522 (void) fprintf(fp, 523 gettext("\nthe following properties are supported:\n")); 524 525 (void) fprintf(fp, "\n\t%-19s %s %s\n\n", 526 "PROPERTY", "EDIT", "VALUES"); 527 528 /* Iterate over all properties */ 529 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 530 ZFS_TYPE_POOL); 531 532 (void) fprintf(fp, "\t%-19s ", "feature@..."); 533 (void) fprintf(fp, "YES disabled | enabled | active\n"); 534 535 (void) fprintf(fp, gettext("\nThe feature@ properties must be " 536 "appended with a feature name.\nSee zpool-features(7).\n")); 537 } 538 539 /* 540 * See comments at end of main(). 541 */ 542 if (getenv("ZFS_ABORT") != NULL) { 543 (void) printf("dumping core by request\n"); 544 abort(); 545 } 546 547 exit(requested ? 0 : 2); 548} 549 550/* 551 * zpool initialize [-c | -s] [-w] <pool> [<vdev> ...] 552 * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool 553 * if none specified. 554 * 555 * -c Cancel. Ends active initializing. 556 * -s Suspend. Initializing can then be restarted with no flags. 557 * -w Wait. Blocks until initializing has completed. 558 */ 559int 560zpool_do_initialize(int argc, char **argv) 561{ 562 int c; 563 char *poolname; 564 zpool_handle_t *zhp; 565 nvlist_t *vdevs; 566 int err = 0; 567 boolean_t wait = B_FALSE; 568 569 struct option long_options[] = { 570 {"cancel", no_argument, NULL, 'c'}, 571 {"suspend", no_argument, NULL, 's'}, 572 {"wait", no_argument, NULL, 'w'}, 573 {0, 0, 0, 0} 574 }; 575 576 pool_initialize_func_t cmd_type = POOL_INITIALIZE_START; 577 while ((c = getopt_long(argc, argv, "csw", long_options, NULL)) != -1) { 578 switch (c) { 579 case 'c': 580 if (cmd_type != POOL_INITIALIZE_START && 581 cmd_type != POOL_INITIALIZE_CANCEL) { 582 (void) fprintf(stderr, gettext("-c cannot be " 583 "combined with other options\n")); 584 usage(B_FALSE); 585 } 586 cmd_type = POOL_INITIALIZE_CANCEL; 587 break; 588 case 's': 589 if (cmd_type != POOL_INITIALIZE_START && 590 cmd_type != POOL_INITIALIZE_SUSPEND) { 591 (void) fprintf(stderr, gettext("-s cannot be " 592 "combined with other options\n")); 593 usage(B_FALSE); 594 } 595 cmd_type = POOL_INITIALIZE_SUSPEND; 596 break; 597 case 'w': 598 wait = B_TRUE; 599 break; 600 case '?': 601 if (optopt != 0) { 602 (void) fprintf(stderr, 603 gettext("invalid option '%c'\n"), optopt); 604 } else { 605 (void) fprintf(stderr, 606 gettext("invalid option '%s'\n"), 607 argv[optind - 1]); 608 } 609 usage(B_FALSE); 610 } 611 } 612 613 argc -= optind; 614 argv += optind; 615 616 if (argc < 1) { 617 (void) fprintf(stderr, gettext("missing pool name argument\n")); 618 usage(B_FALSE); 619 return (-1); 620 } 621 622 if (wait && (cmd_type != POOL_INITIALIZE_START)) { 623 (void) fprintf(stderr, gettext("-w cannot be used with -c or " 624 "-s\n")); 625 usage(B_FALSE); 626 } 627 628 poolname = argv[0]; 629 zhp = zpool_open(g_zfs, poolname); 630 if (zhp == NULL) 631 return (-1); 632 633 vdevs = fnvlist_alloc(); 634 if (argc == 1) { 635 /* no individual leaf vdevs specified, so add them all */ 636 nvlist_t *config = zpool_get_config(zhp, NULL); 637 nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 638 ZPOOL_CONFIG_VDEV_TREE); 639 zpool_collect_leaves(zhp, nvroot, vdevs); 640 } else { 641 for (int i = 1; i < argc; i++) { 642 fnvlist_add_boolean(vdevs, argv[i]); 643 } 644 } 645 646 if (wait) 647 err = zpool_initialize_wait(zhp, cmd_type, vdevs); 648 else 649 err = zpool_initialize(zhp, cmd_type, vdevs); 650 651 fnvlist_free(vdevs); 652 zpool_close(zhp); 653 654 return (err); 655} 656 657/* 658 * print a pool vdev config for dry runs 659 */ 660static void 661print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 662 const char *match, int name_flags) 663{ 664 nvlist_t **child; 665 uint_t c, children; 666 char *vname; 667 boolean_t printed = B_FALSE; 668 669 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 670 &child, &children) != 0) { 671 if (name != NULL) 672 (void) printf("\t%*s%s\n", indent, "", name); 673 return; 674 } 675 676 for (c = 0; c < children; c++) { 677 uint64_t is_log = B_FALSE, is_hole = B_FALSE; 678 char *class = ""; 679 680 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 681 &is_hole); 682 683 if (is_hole == B_TRUE) { 684 continue; 685 } 686 687 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 688 &is_log); 689 if (is_log) 690 class = VDEV_ALLOC_BIAS_LOG; 691 (void) nvlist_lookup_string(child[c], 692 ZPOOL_CONFIG_ALLOCATION_BIAS, &class); 693 if (strcmp(match, class) != 0) 694 continue; 695 696 if (!printed && name != NULL) { 697 (void) printf("\t%*s%s\n", indent, "", name); 698 printed = B_TRUE; 699 } 700 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags); 701 print_vdev_tree(zhp, vname, child[c], indent + 2, "", 702 name_flags); 703 free(vname); 704 } 705} 706 707/* 708 * Print the list of l2cache devices for dry runs. 709 */ 710static void 711print_cache_list(nvlist_t *nv, int indent) 712{ 713 nvlist_t **child; 714 uint_t c, children; 715 716 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 717 &child, &children) == 0 && children > 0) { 718 (void) printf("\t%*s%s\n", indent, "", "cache"); 719 } else { 720 return; 721 } 722 for (c = 0; c < children; c++) { 723 char *vname; 724 725 vname = zpool_vdev_name(g_zfs, NULL, child[c], 0); 726 (void) printf("\t%*s%s\n", indent + 2, "", vname); 727 free(vname); 728 } 729} 730 731/* 732 * Print the list of spares for dry runs. 733 */ 734static void 735print_spare_list(nvlist_t *nv, int indent) 736{ 737 nvlist_t **child; 738 uint_t c, children; 739 740 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 741 &child, &children) == 0 && children > 0) { 742 (void) printf("\t%*s%s\n", indent, "", "spares"); 743 } else { 744 return; 745 } 746 for (c = 0; c < children; c++) { 747 char *vname; 748 749 vname = zpool_vdev_name(g_zfs, NULL, child[c], 0); 750 (void) printf("\t%*s%s\n", indent + 2, "", vname); 751 free(vname); 752 } 753} 754 755static boolean_t 756prop_list_contains_feature(nvlist_t *proplist) 757{ 758 nvpair_t *nvp; 759 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 760 nvp = nvlist_next_nvpair(proplist, nvp)) { 761 if (zpool_prop_feature(nvpair_name(nvp))) 762 return (B_TRUE); 763 } 764 return (B_FALSE); 765} 766 767/* 768 * Add a property pair (name, string-value) into a property nvlist. 769 */ 770static int 771add_prop_list(const char *propname, char *propval, nvlist_t **props, 772 boolean_t poolprop) 773{ 774 zpool_prop_t prop = ZPOOL_PROP_INVAL; 775 nvlist_t *proplist; 776 const char *normnm; 777 char *strval; 778 779 if (*props == NULL && 780 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 781 (void) fprintf(stderr, 782 gettext("internal error: out of memory\n")); 783 return (1); 784 } 785 786 proplist = *props; 787 788 if (poolprop) { 789 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 790 const char *cname = 791 zpool_prop_to_name(ZPOOL_PROP_COMPATIBILITY); 792 793 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL && 794 !zpool_prop_feature(propname)) { 795 (void) fprintf(stderr, gettext("property '%s' is " 796 "not a valid pool property\n"), propname); 797 return (2); 798 } 799 800 /* 801 * feature@ properties and version should not be specified 802 * at the same time. 803 */ 804 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 805 nvlist_exists(proplist, vname)) || 806 (prop == ZPOOL_PROP_VERSION && 807 prop_list_contains_feature(proplist))) { 808 (void) fprintf(stderr, gettext("'feature@' and " 809 "'version' properties cannot be specified " 810 "together\n")); 811 return (2); 812 } 813 814 /* 815 * if version is specified, only "legacy" compatibility 816 * may be requested 817 */ 818 if ((prop == ZPOOL_PROP_COMPATIBILITY && 819 strcmp(propval, ZPOOL_COMPAT_LEGACY) != 0 && 820 nvlist_exists(proplist, vname)) || 821 (prop == ZPOOL_PROP_VERSION && 822 nvlist_exists(proplist, cname) && 823 strcmp(fnvlist_lookup_string(proplist, cname), 824 ZPOOL_COMPAT_LEGACY) != 0)) { 825 (void) fprintf(stderr, gettext("when 'version' is " 826 "specified, the 'compatibility' feature may only " 827 "be set to '" ZPOOL_COMPAT_LEGACY "'\n")); 828 return (2); 829 } 830 831 if (zpool_prop_feature(propname)) 832 normnm = propname; 833 else 834 normnm = zpool_prop_to_name(prop); 835 } else { 836 zfs_prop_t fsprop = zfs_name_to_prop(propname); 837 838 if (zfs_prop_valid_for_type(fsprop, ZFS_TYPE_FILESYSTEM, 839 B_FALSE)) { 840 normnm = zfs_prop_to_name(fsprop); 841 } else if (zfs_prop_user(propname) || 842 zfs_prop_userquota(propname)) { 843 normnm = propname; 844 } else { 845 (void) fprintf(stderr, gettext("property '%s' is " 846 "not a valid filesystem property\n"), propname); 847 return (2); 848 } 849 } 850 851 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 852 prop != ZPOOL_PROP_CACHEFILE) { 853 (void) fprintf(stderr, gettext("property '%s' " 854 "specified multiple times\n"), propname); 855 return (2); 856 } 857 858 if (nvlist_add_string(proplist, normnm, propval) != 0) { 859 (void) fprintf(stderr, gettext("internal " 860 "error: out of memory\n")); 861 return (1); 862 } 863 864 return (0); 865} 866 867/* 868 * Set a default property pair (name, string-value) in a property nvlist 869 */ 870static int 871add_prop_list_default(const char *propname, char *propval, nvlist_t **props, 872 boolean_t poolprop) 873{ 874 char *pval; 875 876 if (nvlist_lookup_string(*props, propname, &pval) == 0) 877 return (0); 878 879 return (add_prop_list(propname, propval, props, B_TRUE)); 880} 881 882/* 883 * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ... 884 * 885 * -f Force addition of devices, even if they appear in use 886 * -g Display guid for individual vdev name. 887 * -L Follow links when resolving vdev path name. 888 * -n Do not add the devices, but display the resulting layout if 889 * they were to be added. 890 * -o Set property=value. 891 * -P Display full path for vdev name. 892 * 893 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 894 * handled by make_root_vdev(), which constructs the nvlist needed to pass to 895 * libzfs. 896 */ 897int 898zpool_do_add(int argc, char **argv) 899{ 900 boolean_t force = B_FALSE; 901 boolean_t dryrun = B_FALSE; 902 int name_flags = 0; 903 int c; 904 nvlist_t *nvroot; 905 char *poolname; 906 int ret; 907 zpool_handle_t *zhp; 908 nvlist_t *config; 909 nvlist_t *props = NULL; 910 char *propval; 911 912 /* check options */ 913 while ((c = getopt(argc, argv, "fgLno:P")) != -1) { 914 switch (c) { 915 case 'f': 916 force = B_TRUE; 917 break; 918 case 'g': 919 name_flags |= VDEV_NAME_GUID; 920 break; 921 case 'L': 922 name_flags |= VDEV_NAME_FOLLOW_LINKS; 923 break; 924 case 'n': 925 dryrun = B_TRUE; 926 break; 927 case 'o': 928 if ((propval = strchr(optarg, '=')) == NULL) { 929 (void) fprintf(stderr, gettext("missing " 930 "'=' for -o option\n")); 931 usage(B_FALSE); 932 } 933 *propval = '\0'; 934 propval++; 935 936 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 937 (add_prop_list(optarg, propval, &props, B_TRUE))) 938 usage(B_FALSE); 939 break; 940 case 'P': 941 name_flags |= VDEV_NAME_PATH; 942 break; 943 case '?': 944 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 945 optopt); 946 usage(B_FALSE); 947 } 948 } 949 950 argc -= optind; 951 argv += optind; 952 953 /* get pool name and check number of arguments */ 954 if (argc < 1) { 955 (void) fprintf(stderr, gettext("missing pool name argument\n")); 956 usage(B_FALSE); 957 } 958 if (argc < 2) { 959 (void) fprintf(stderr, gettext("missing vdev specification\n")); 960 usage(B_FALSE); 961 } 962 963 poolname = argv[0]; 964 965 argc--; 966 argv++; 967 968 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 969 return (1); 970 971 if ((config = zpool_get_config(zhp, NULL)) == NULL) { 972 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 973 poolname); 974 zpool_close(zhp); 975 return (1); 976 } 977 978 /* unless manually specified use "ashift" pool property (if set) */ 979 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 980 int intval; 981 zprop_source_t src; 982 char strval[ZPOOL_MAXPROPLEN]; 983 984 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 985 if (src != ZPROP_SRC_DEFAULT) { 986 (void) sprintf(strval, "%" PRId32, intval); 987 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 988 &props, B_TRUE) == 0); 989 } 990 } 991 992 /* pass off to make_root_vdev for processing */ 993 nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun, 994 argc, argv); 995 if (nvroot == NULL) { 996 zpool_close(zhp); 997 return (1); 998 } 999 1000 if (dryrun) { 1001 nvlist_t *poolnvroot; 1002 nvlist_t **l2child, **sparechild; 1003 uint_t l2children, sparechildren, c; 1004 char *vname; 1005 boolean_t hadcache = B_FALSE, hadspare = B_FALSE; 1006 1007 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1008 &poolnvroot) == 0); 1009 1010 (void) printf(gettext("would update '%s' to the following " 1011 "configuration:\n\n"), zpool_get_name(zhp)); 1012 1013 /* print original main pool and new tree */ 1014 print_vdev_tree(zhp, poolname, poolnvroot, 0, "", 1015 name_flags | VDEV_NAME_TYPE_ID); 1016 print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags); 1017 1018 /* print other classes: 'dedup', 'special', and 'log' */ 1019 if (zfs_special_devs(poolnvroot, VDEV_ALLOC_BIAS_DEDUP)) { 1020 print_vdev_tree(zhp, "dedup", poolnvroot, 0, 1021 VDEV_ALLOC_BIAS_DEDUP, name_flags); 1022 print_vdev_tree(zhp, NULL, nvroot, 0, 1023 VDEV_ALLOC_BIAS_DEDUP, name_flags); 1024 } else if (zfs_special_devs(nvroot, VDEV_ALLOC_BIAS_DEDUP)) { 1025 print_vdev_tree(zhp, "dedup", nvroot, 0, 1026 VDEV_ALLOC_BIAS_DEDUP, name_flags); 1027 } 1028 1029 if (zfs_special_devs(poolnvroot, VDEV_ALLOC_BIAS_SPECIAL)) { 1030 print_vdev_tree(zhp, "special", poolnvroot, 0, 1031 VDEV_ALLOC_BIAS_SPECIAL, name_flags); 1032 print_vdev_tree(zhp, NULL, nvroot, 0, 1033 VDEV_ALLOC_BIAS_SPECIAL, name_flags); 1034 } else if (zfs_special_devs(nvroot, VDEV_ALLOC_BIAS_SPECIAL)) { 1035 print_vdev_tree(zhp, "special", nvroot, 0, 1036 VDEV_ALLOC_BIAS_SPECIAL, name_flags); 1037 } 1038 1039 if (num_logs(poolnvroot) > 0) { 1040 print_vdev_tree(zhp, "logs", poolnvroot, 0, 1041 VDEV_ALLOC_BIAS_LOG, name_flags); 1042 print_vdev_tree(zhp, NULL, nvroot, 0, 1043 VDEV_ALLOC_BIAS_LOG, name_flags); 1044 } else if (num_logs(nvroot) > 0) { 1045 print_vdev_tree(zhp, "logs", nvroot, 0, 1046 VDEV_ALLOC_BIAS_LOG, name_flags); 1047 } 1048 1049 /* Do the same for the caches */ 1050 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_L2CACHE, 1051 &l2child, &l2children) == 0 && l2children) { 1052 hadcache = B_TRUE; 1053 (void) printf(gettext("\tcache\n")); 1054 for (c = 0; c < l2children; c++) { 1055 vname = zpool_vdev_name(g_zfs, NULL, 1056 l2child[c], name_flags); 1057 (void) printf("\t %s\n", vname); 1058 free(vname); 1059 } 1060 } 1061 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 1062 &l2child, &l2children) == 0 && l2children) { 1063 if (!hadcache) 1064 (void) printf(gettext("\tcache\n")); 1065 for (c = 0; c < l2children; c++) { 1066 vname = zpool_vdev_name(g_zfs, NULL, 1067 l2child[c], name_flags); 1068 (void) printf("\t %s\n", vname); 1069 free(vname); 1070 } 1071 } 1072 /* And finally the spares */ 1073 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_SPARES, 1074 &sparechild, &sparechildren) == 0 && sparechildren > 0) { 1075 hadspare = B_TRUE; 1076 (void) printf(gettext("\tspares\n")); 1077 for (c = 0; c < sparechildren; c++) { 1078 vname = zpool_vdev_name(g_zfs, NULL, 1079 sparechild[c], name_flags); 1080 (void) printf("\t %s\n", vname); 1081 free(vname); 1082 } 1083 } 1084 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 1085 &sparechild, &sparechildren) == 0 && sparechildren > 0) { 1086 if (!hadspare) 1087 (void) printf(gettext("\tspares\n")); 1088 for (c = 0; c < sparechildren; c++) { 1089 vname = zpool_vdev_name(g_zfs, NULL, 1090 sparechild[c], name_flags); 1091 (void) printf("\t %s\n", vname); 1092 free(vname); 1093 } 1094 } 1095 1096 ret = 0; 1097 } else { 1098 ret = (zpool_add(zhp, nvroot) != 0); 1099 } 1100 1101 nvlist_free(props); 1102 nvlist_free(nvroot); 1103 zpool_close(zhp); 1104 1105 return (ret); 1106} 1107 1108/* 1109 * zpool remove [-npsw] <pool> <vdev> ... 1110 * 1111 * Removes the given vdev from the pool. 1112 */ 1113int 1114zpool_do_remove(int argc, char **argv) 1115{ 1116 char *poolname; 1117 int i, ret = 0; 1118 zpool_handle_t *zhp = NULL; 1119 boolean_t stop = B_FALSE; 1120 int c; 1121 boolean_t noop = B_FALSE; 1122 boolean_t parsable = B_FALSE; 1123 boolean_t wait = B_FALSE; 1124 1125 /* check options */ 1126 while ((c = getopt(argc, argv, "npsw")) != -1) { 1127 switch (c) { 1128 case 'n': 1129 noop = B_TRUE; 1130 break; 1131 case 'p': 1132 parsable = B_TRUE; 1133 break; 1134 case 's': 1135 stop = B_TRUE; 1136 break; 1137 case 'w': 1138 wait = B_TRUE; 1139 break; 1140 case '?': 1141 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1142 optopt); 1143 usage(B_FALSE); 1144 } 1145 } 1146 1147 argc -= optind; 1148 argv += optind; 1149 1150 /* get pool name and check number of arguments */ 1151 if (argc < 1) { 1152 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1153 usage(B_FALSE); 1154 } 1155 1156 poolname = argv[0]; 1157 1158 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 1159 return (1); 1160 1161 if (stop && noop) { 1162 (void) fprintf(stderr, gettext("stop request ignored\n")); 1163 return (0); 1164 } 1165 1166 if (stop) { 1167 if (argc > 1) { 1168 (void) fprintf(stderr, gettext("too many arguments\n")); 1169 usage(B_FALSE); 1170 } 1171 if (zpool_vdev_remove_cancel(zhp) != 0) 1172 ret = 1; 1173 if (wait) { 1174 (void) fprintf(stderr, gettext("invalid option " 1175 "combination: -w cannot be used with -s\n")); 1176 usage(B_FALSE); 1177 } 1178 } else { 1179 if (argc < 2) { 1180 (void) fprintf(stderr, gettext("missing device\n")); 1181 usage(B_FALSE); 1182 } 1183 1184 for (i = 1; i < argc; i++) { 1185 if (noop) { 1186 uint64_t size; 1187 1188 if (zpool_vdev_indirect_size(zhp, argv[i], 1189 &size) != 0) { 1190 ret = 1; 1191 break; 1192 } 1193 if (parsable) { 1194 (void) printf("%s %llu\n", 1195 argv[i], (unsigned long long)size); 1196 } else { 1197 char valstr[32]; 1198 zfs_nicenum(size, valstr, 1199 sizeof (valstr)); 1200 (void) printf("Memory that will be " 1201 "used after removing %s: %s\n", 1202 argv[i], valstr); 1203 } 1204 } else { 1205 if (zpool_vdev_remove(zhp, argv[i]) != 0) 1206 ret = 1; 1207 } 1208 } 1209 1210 if (ret == 0 && wait) 1211 ret = zpool_wait(zhp, ZPOOL_WAIT_REMOVE); 1212 } 1213 zpool_close(zhp); 1214 1215 return (ret); 1216} 1217 1218/* 1219 * zpool labelclear [-f] <vdev> 1220 * 1221 * -f Force clearing the label for the vdevs which are members of 1222 * the exported or foreign pools. 1223 * 1224 * Verifies that the vdev is not active and zeros out the label information 1225 * on the device. 1226 */ 1227int 1228zpool_do_labelclear(int argc, char **argv) 1229{ 1230 char vdev[MAXPATHLEN]; 1231 char *name = NULL; 1232 struct stat st; 1233 int c, fd = -1, ret = 0; 1234 nvlist_t *config; 1235 pool_state_t state; 1236 boolean_t inuse = B_FALSE; 1237 boolean_t force = B_FALSE; 1238 1239 /* check options */ 1240 while ((c = getopt(argc, argv, "f")) != -1) { 1241 switch (c) { 1242 case 'f': 1243 force = B_TRUE; 1244 break; 1245 default: 1246 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1247 optopt); 1248 usage(B_FALSE); 1249 } 1250 } 1251 1252 argc -= optind; 1253 argv += optind; 1254 1255 /* get vdev name */ 1256 if (argc < 1) { 1257 (void) fprintf(stderr, gettext("missing vdev name\n")); 1258 usage(B_FALSE); 1259 } 1260 if (argc > 1) { 1261 (void) fprintf(stderr, gettext("too many arguments\n")); 1262 usage(B_FALSE); 1263 } 1264 1265 /* 1266 * Check if we were given absolute path and use it as is. 1267 * Otherwise if the provided vdev name doesn't point to a file, 1268 * try prepending expected disk paths and partition numbers. 1269 */ 1270 (void) strlcpy(vdev, argv[0], sizeof (vdev)); 1271 if (vdev[0] != '/' && stat(vdev, &st) != 0) { 1272 int error; 1273 1274 error = zfs_resolve_shortname(argv[0], vdev, MAXPATHLEN); 1275 if (error == 0 && zfs_dev_is_whole_disk(vdev)) { 1276 if (zfs_append_partition(vdev, MAXPATHLEN) == -1) 1277 error = ENOENT; 1278 } 1279 1280 if (error || (stat(vdev, &st) != 0)) { 1281 (void) fprintf(stderr, gettext( 1282 "failed to find device %s, try specifying absolute " 1283 "path instead\n"), argv[0]); 1284 return (1); 1285 } 1286 } 1287 1288 if ((fd = open(vdev, O_RDWR)) < 0) { 1289 (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 1290 vdev, strerror(errno)); 1291 return (1); 1292 } 1293 1294 /* 1295 * Flush all dirty pages for the block device. This should not be 1296 * fatal when the device does not support BLKFLSBUF as would be the 1297 * case for a file vdev. 1298 */ 1299 if ((zfs_dev_flush(fd) != 0) && (errno != ENOTTY)) 1300 (void) fprintf(stderr, gettext("failed to invalidate " 1301 "cache for %s: %s\n"), vdev, strerror(errno)); 1302 1303 if (zpool_read_label(fd, &config, NULL) != 0) { 1304 (void) fprintf(stderr, 1305 gettext("failed to read label from %s\n"), vdev); 1306 ret = 1; 1307 goto errout; 1308 } 1309 nvlist_free(config); 1310 1311 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 1312 if (ret != 0) { 1313 (void) fprintf(stderr, 1314 gettext("failed to check state for %s\n"), vdev); 1315 ret = 1; 1316 goto errout; 1317 } 1318 1319 if (!inuse) 1320 goto wipe_label; 1321 1322 switch (state) { 1323 default: 1324 case POOL_STATE_ACTIVE: 1325 case POOL_STATE_SPARE: 1326 case POOL_STATE_L2CACHE: 1327 (void) fprintf(stderr, gettext( 1328 "%s is a member (%s) of pool \"%s\"\n"), 1329 vdev, zpool_pool_state_to_name(state), name); 1330 ret = 1; 1331 goto errout; 1332 1333 case POOL_STATE_EXPORTED: 1334 if (force) 1335 break; 1336 (void) fprintf(stderr, gettext( 1337 "use '-f' to override the following error:\n" 1338 "%s is a member of exported pool \"%s\"\n"), 1339 vdev, name); 1340 ret = 1; 1341 goto errout; 1342 1343 case POOL_STATE_POTENTIALLY_ACTIVE: 1344 if (force) 1345 break; 1346 (void) fprintf(stderr, gettext( 1347 "use '-f' to override the following error:\n" 1348 "%s is a member of potentially active pool \"%s\"\n"), 1349 vdev, name); 1350 ret = 1; 1351 goto errout; 1352 1353 case POOL_STATE_DESTROYED: 1354 /* inuse should never be set for a destroyed pool */ 1355 assert(0); 1356 break; 1357 } 1358 1359wipe_label: 1360 ret = zpool_clear_label(fd); 1361 if (ret != 0) { 1362 (void) fprintf(stderr, 1363 gettext("failed to clear label for %s\n"), vdev); 1364 } 1365 1366errout: 1367 free(name); 1368 (void) close(fd); 1369 1370 return (ret); 1371} 1372 1373/* 1374 * zpool create [-fnd] [-o property=value] ... 1375 * [-O file-system-property=value] ... 1376 * [-R root] [-m mountpoint] <pool> <dev> ... 1377 * 1378 * -f Force creation, even if devices appear in use 1379 * -n Do not create the pool, but display the resulting layout if it 1380 * were to be created. 1381 * -R Create a pool under an alternate root 1382 * -m Set default mountpoint for the root dataset. By default it's 1383 * '/<pool>' 1384 * -o Set property=value. 1385 * -o Set feature@feature=enabled|disabled. 1386 * -d Don't automatically enable all supported pool features 1387 * (individual features can be enabled with -o). 1388 * -O Set fsproperty=value in the pool's root file system 1389 * 1390 * Creates the named pool according to the given vdev specification. The 1391 * bulk of the vdev processing is done in make_root_vdev() in zpool_vdev.c. 1392 * Once we get the nvlist back from make_root_vdev(), we either print out the 1393 * contents (if '-n' was specified), or pass it to libzfs to do the creation. 1394 */ 1395int 1396zpool_do_create(int argc, char **argv) 1397{ 1398 boolean_t force = B_FALSE; 1399 boolean_t dryrun = B_FALSE; 1400 boolean_t enable_pool_features = B_TRUE; 1401 1402 int c; 1403 nvlist_t *nvroot = NULL; 1404 char *poolname; 1405 char *tname = NULL; 1406 int ret = 1; 1407 char *altroot = NULL; 1408 char *compat = NULL; 1409 char *mountpoint = NULL; 1410 nvlist_t *fsprops = NULL; 1411 nvlist_t *props = NULL; 1412 char *propval; 1413 1414 /* check options */ 1415 while ((c = getopt(argc, argv, ":fndR:m:o:O:t:")) != -1) { 1416 switch (c) { 1417 case 'f': 1418 force = B_TRUE; 1419 break; 1420 case 'n': 1421 dryrun = B_TRUE; 1422 break; 1423 case 'd': 1424 enable_pool_features = B_FALSE; 1425 break; 1426 case 'R': 1427 altroot = optarg; 1428 if (add_prop_list(zpool_prop_to_name( 1429 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1430 goto errout; 1431 if (add_prop_list_default(zpool_prop_to_name( 1432 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1433 goto errout; 1434 break; 1435 case 'm': 1436 /* Equivalent to -O mountpoint=optarg */ 1437 mountpoint = optarg; 1438 break; 1439 case 'o': 1440 if ((propval = strchr(optarg, '=')) == NULL) { 1441 (void) fprintf(stderr, gettext("missing " 1442 "'=' for -o option\n")); 1443 goto errout; 1444 } 1445 *propval = '\0'; 1446 propval++; 1447 1448 if (add_prop_list(optarg, propval, &props, B_TRUE)) 1449 goto errout; 1450 1451 /* 1452 * If the user is creating a pool that doesn't support 1453 * feature flags, don't enable any features. 1454 */ 1455 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 1456 char *end; 1457 u_longlong_t ver; 1458 1459 ver = strtoull(propval, &end, 10); 1460 if (*end == '\0' && 1461 ver < SPA_VERSION_FEATURES) { 1462 enable_pool_features = B_FALSE; 1463 } 1464 } 1465 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 1466 altroot = propval; 1467 if (zpool_name_to_prop(optarg) == 1468 ZPOOL_PROP_COMPATIBILITY) 1469 compat = propval; 1470 break; 1471 case 'O': 1472 if ((propval = strchr(optarg, '=')) == NULL) { 1473 (void) fprintf(stderr, gettext("missing " 1474 "'=' for -O option\n")); 1475 goto errout; 1476 } 1477 *propval = '\0'; 1478 propval++; 1479 1480 /* 1481 * Mountpoints are checked and then added later. 1482 * Uniquely among properties, they can be specified 1483 * more than once, to avoid conflict with -m. 1484 */ 1485 if (0 == strcmp(optarg, 1486 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 1487 mountpoint = propval; 1488 } else if (add_prop_list(optarg, propval, &fsprops, 1489 B_FALSE)) { 1490 goto errout; 1491 } 1492 break; 1493 case 't': 1494 /* 1495 * Sanity check temporary pool name. 1496 */ 1497 if (strchr(optarg, '/') != NULL) { 1498 (void) fprintf(stderr, gettext("cannot create " 1499 "'%s': invalid character '/' in temporary " 1500 "name\n"), optarg); 1501 (void) fprintf(stderr, gettext("use 'zfs " 1502 "create' to create a dataset\n")); 1503 goto errout; 1504 } 1505 1506 if (add_prop_list(zpool_prop_to_name( 1507 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE)) 1508 goto errout; 1509 if (add_prop_list_default(zpool_prop_to_name( 1510 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1511 goto errout; 1512 tname = optarg; 1513 break; 1514 case ':': 1515 (void) fprintf(stderr, gettext("missing argument for " 1516 "'%c' option\n"), optopt); 1517 goto badusage; 1518 case '?': 1519 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1520 optopt); 1521 goto badusage; 1522 } 1523 } 1524 1525 argc -= optind; 1526 argv += optind; 1527 1528 /* get pool name and check number of arguments */ 1529 if (argc < 1) { 1530 (void) fprintf(stderr, gettext("missing pool name argument\n")); 1531 goto badusage; 1532 } 1533 if (argc < 2) { 1534 (void) fprintf(stderr, gettext("missing vdev specification\n")); 1535 goto badusage; 1536 } 1537 1538 poolname = argv[0]; 1539 1540 /* 1541 * As a special case, check for use of '/' in the name, and direct the 1542 * user to use 'zfs create' instead. 1543 */ 1544 if (strchr(poolname, '/') != NULL) { 1545 (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1546 "character '/' in pool name\n"), poolname); 1547 (void) fprintf(stderr, gettext("use 'zfs create' to " 1548 "create a dataset\n")); 1549 goto errout; 1550 } 1551 1552 /* pass off to make_root_vdev for bulk processing */ 1553 nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun, 1554 argc - 1, argv + 1); 1555 if (nvroot == NULL) 1556 goto errout; 1557 1558 /* make_root_vdev() allows 0 toplevel children if there are spares */ 1559 if (!zfs_allocatable_devs(nvroot)) { 1560 (void) fprintf(stderr, gettext("invalid vdev " 1561 "specification: at least one toplevel vdev must be " 1562 "specified\n")); 1563 goto errout; 1564 } 1565 1566 if (altroot != NULL && altroot[0] != '/') { 1567 (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1568 "must be an absolute path\n"), altroot); 1569 goto errout; 1570 } 1571 1572 /* 1573 * Check the validity of the mountpoint and direct the user to use the 1574 * '-m' mountpoint option if it looks like its in use. 1575 */ 1576 if (mountpoint == NULL || 1577 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1578 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 1579 char buf[MAXPATHLEN]; 1580 DIR *dirp; 1581 1582 if (mountpoint && mountpoint[0] != '/') { 1583 (void) fprintf(stderr, gettext("invalid mountpoint " 1584 "'%s': must be an absolute path, 'legacy', or " 1585 "'none'\n"), mountpoint); 1586 goto errout; 1587 } 1588 1589 if (mountpoint == NULL) { 1590 if (altroot != NULL) 1591 (void) snprintf(buf, sizeof (buf), "%s/%s", 1592 altroot, poolname); 1593 else 1594 (void) snprintf(buf, sizeof (buf), "/%s", 1595 poolname); 1596 } else { 1597 if (altroot != NULL) 1598 (void) snprintf(buf, sizeof (buf), "%s%s", 1599 altroot, mountpoint); 1600 else 1601 (void) snprintf(buf, sizeof (buf), "%s", 1602 mountpoint); 1603 } 1604 1605 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 1606 (void) fprintf(stderr, gettext("mountpoint '%s' : " 1607 "%s\n"), buf, strerror(errno)); 1608 (void) fprintf(stderr, gettext("use '-m' " 1609 "option to provide a different default\n")); 1610 goto errout; 1611 } else if (dirp) { 1612 int count = 0; 1613 1614 while (count < 3 && readdir(dirp) != NULL) 1615 count++; 1616 (void) closedir(dirp); 1617 1618 if (count > 2) { 1619 (void) fprintf(stderr, gettext("mountpoint " 1620 "'%s' exists and is not empty\n"), buf); 1621 (void) fprintf(stderr, gettext("use '-m' " 1622 "option to provide a " 1623 "different default\n")); 1624 goto errout; 1625 } 1626 } 1627 } 1628 1629 /* 1630 * Now that the mountpoint's validity has been checked, ensure that 1631 * the property is set appropriately prior to creating the pool. 1632 */ 1633 if (mountpoint != NULL) { 1634 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 1635 mountpoint, &fsprops, B_FALSE); 1636 if (ret != 0) 1637 goto errout; 1638 } 1639 1640 ret = 1; 1641 if (dryrun) { 1642 /* 1643 * For a dry run invocation, print out a basic message and run 1644 * through all the vdevs in the list and print out in an 1645 * appropriate hierarchy. 1646 */ 1647 (void) printf(gettext("would create '%s' with the " 1648 "following layout:\n\n"), poolname); 1649 1650 print_vdev_tree(NULL, poolname, nvroot, 0, "", 0); 1651 print_vdev_tree(NULL, "dedup", nvroot, 0, 1652 VDEV_ALLOC_BIAS_DEDUP, 0); 1653 print_vdev_tree(NULL, "special", nvroot, 0, 1654 VDEV_ALLOC_BIAS_SPECIAL, 0); 1655 print_vdev_tree(NULL, "logs", nvroot, 0, 1656 VDEV_ALLOC_BIAS_LOG, 0); 1657 print_cache_list(nvroot, 0); 1658 print_spare_list(nvroot, 0); 1659 1660 ret = 0; 1661 } else { 1662 /* 1663 * Load in feature set. 1664 * Note: if compatibility property not given, we'll have 1665 * NULL, which means 'all features'. 1666 */ 1667 boolean_t requested_features[SPA_FEATURES]; 1668 if (zpool_do_load_compat(compat, requested_features) != 1669 ZPOOL_COMPATIBILITY_OK) 1670 goto errout; 1671 1672 /* 1673 * props contains list of features to enable. 1674 * For each feature: 1675 * - remove it if feature@name=disabled 1676 * - leave it there if feature@name=enabled 1677 * - add it if: 1678 * - enable_pool_features (ie: no '-d' or '-o version') 1679 * - it's supported by the kernel module 1680 * - it's in the requested feature set 1681 * - warn if it's enabled but not in compat 1682 */ 1683 for (spa_feature_t i = 0; i < SPA_FEATURES; i++) { 1684 char propname[MAXPATHLEN]; 1685 char *propval; 1686 zfeature_info_t *feat = &spa_feature_table[i]; 1687 1688 (void) snprintf(propname, sizeof (propname), 1689 "feature@%s", feat->fi_uname); 1690 1691 if (!nvlist_lookup_string(props, propname, &propval)) { 1692 if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0) 1693 (void) nvlist_remove_all(props, 1694 propname); 1695 if (strcmp(propval, 1696 ZFS_FEATURE_ENABLED) == 0 && 1697 !requested_features[i]) 1698 (void) fprintf(stderr, gettext( 1699 "Warning: feature \"%s\" enabled " 1700 "but is not in specified " 1701 "'compatibility' feature set.\n"), 1702 feat->fi_uname); 1703 } else if ( 1704 enable_pool_features && 1705 feat->fi_zfs_mod_supported && 1706 requested_features[i]) { 1707 ret = add_prop_list(propname, 1708 ZFS_FEATURE_ENABLED, &props, B_TRUE); 1709 if (ret != 0) 1710 goto errout; 1711 } 1712 } 1713 1714 ret = 1; 1715 if (zpool_create(g_zfs, poolname, 1716 nvroot, props, fsprops) == 0) { 1717 zfs_handle_t *pool = zfs_open(g_zfs, 1718 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM); 1719 if (pool != NULL) { 1720 if (zfs_mount(pool, NULL, 0) == 0) { 1721 ret = zfs_shareall(pool); 1722 zfs_commit_all_shares(); 1723 } 1724 zfs_close(pool); 1725 } 1726 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 1727 (void) fprintf(stderr, gettext("pool name may have " 1728 "been omitted\n")); 1729 } 1730 } 1731 1732errout: 1733 nvlist_free(nvroot); 1734 nvlist_free(fsprops); 1735 nvlist_free(props); 1736 return (ret); 1737badusage: 1738 nvlist_free(fsprops); 1739 nvlist_free(props); 1740 usage(B_FALSE); 1741 return (2); 1742} 1743 1744/* 1745 * zpool destroy <pool> 1746 * 1747 * -f Forcefully unmount any datasets 1748 * 1749 * Destroy the given pool. Automatically unmounts any datasets in the pool. 1750 */ 1751int 1752zpool_do_destroy(int argc, char **argv) 1753{ 1754 boolean_t force = B_FALSE; 1755 int c; 1756 char *pool; 1757 zpool_handle_t *zhp; 1758 int ret; 1759 1760 /* check options */ 1761 while ((c = getopt(argc, argv, "f")) != -1) { 1762 switch (c) { 1763 case 'f': 1764 force = B_TRUE; 1765 break; 1766 case '?': 1767 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1768 optopt); 1769 usage(B_FALSE); 1770 } 1771 } 1772 1773 argc -= optind; 1774 argv += optind; 1775 1776 /* check arguments */ 1777 if (argc < 1) { 1778 (void) fprintf(stderr, gettext("missing pool argument\n")); 1779 usage(B_FALSE); 1780 } 1781 if (argc > 1) { 1782 (void) fprintf(stderr, gettext("too many arguments\n")); 1783 usage(B_FALSE); 1784 } 1785 1786 pool = argv[0]; 1787 1788 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1789 /* 1790 * As a special case, check for use of '/' in the name, and 1791 * direct the user to use 'zfs destroy' instead. 1792 */ 1793 if (strchr(pool, '/') != NULL) 1794 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1795 "destroy a dataset\n")); 1796 return (1); 1797 } 1798 1799 if (zpool_disable_datasets(zhp, force) != 0) { 1800 (void) fprintf(stderr, gettext("could not destroy '%s': " 1801 "could not unmount datasets\n"), zpool_get_name(zhp)); 1802 zpool_close(zhp); 1803 return (1); 1804 } 1805 1806 /* The history must be logged as part of the export */ 1807 log_history = B_FALSE; 1808 1809 ret = (zpool_destroy(zhp, history_str) != 0); 1810 1811 zpool_close(zhp); 1812 1813 return (ret); 1814} 1815 1816typedef struct export_cbdata { 1817 boolean_t force; 1818 boolean_t hardforce; 1819} export_cbdata_t; 1820 1821/* 1822 * Export one pool 1823 */ 1824static int 1825zpool_export_one(zpool_handle_t *zhp, void *data) 1826{ 1827 export_cbdata_t *cb = data; 1828 1829 if (zpool_disable_datasets(zhp, cb->force) != 0) 1830 return (1); 1831 1832 /* The history must be logged as part of the export */ 1833 log_history = B_FALSE; 1834 1835 if (cb->hardforce) { 1836 if (zpool_export_force(zhp, history_str) != 0) 1837 return (1); 1838 } else if (zpool_export(zhp, cb->force, history_str) != 0) { 1839 return (1); 1840 } 1841 1842 return (0); 1843} 1844 1845/* 1846 * zpool export [-f] <pool> ... 1847 * 1848 * -a Export all pools 1849 * -f Forcefully unmount datasets 1850 * 1851 * Export the given pools. By default, the command will attempt to cleanly 1852 * unmount any active datasets within the pool. If the '-f' flag is specified, 1853 * then the datasets will be forcefully unmounted. 1854 */ 1855int 1856zpool_do_export(int argc, char **argv) 1857{ 1858 export_cbdata_t cb; 1859 boolean_t do_all = B_FALSE; 1860 boolean_t force = B_FALSE; 1861 boolean_t hardforce = B_FALSE; 1862 int c, ret; 1863 1864 /* check options */ 1865 while ((c = getopt(argc, argv, "afF")) != -1) { 1866 switch (c) { 1867 case 'a': 1868 do_all = B_TRUE; 1869 break; 1870 case 'f': 1871 force = B_TRUE; 1872 break; 1873 case 'F': 1874 hardforce = B_TRUE; 1875 break; 1876 case '?': 1877 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1878 optopt); 1879 usage(B_FALSE); 1880 } 1881 } 1882 1883 cb.force = force; 1884 cb.hardforce = hardforce; 1885 argc -= optind; 1886 argv += optind; 1887 1888 if (do_all) { 1889 if (argc != 0) { 1890 (void) fprintf(stderr, gettext("too many arguments\n")); 1891 usage(B_FALSE); 1892 } 1893 1894 return (for_each_pool(argc, argv, B_TRUE, NULL, 1895 B_FALSE, zpool_export_one, &cb)); 1896 } 1897 1898 /* check arguments */ 1899 if (argc < 1) { 1900 (void) fprintf(stderr, gettext("missing pool argument\n")); 1901 usage(B_FALSE); 1902 } 1903 1904 ret = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, zpool_export_one, 1905 &cb); 1906 1907 return (ret); 1908} 1909 1910/* 1911 * Given a vdev configuration, determine the maximum width needed for the device 1912 * name column. 1913 */ 1914static int 1915max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max, 1916 int name_flags) 1917{ 1918 char *name; 1919 nvlist_t **child; 1920 uint_t c, children; 1921 int ret; 1922 1923 name = zpool_vdev_name(g_zfs, zhp, nv, name_flags); 1924 if (strlen(name) + depth > max) 1925 max = strlen(name) + depth; 1926 1927 free(name); 1928 1929 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1930 &child, &children) == 0) { 1931 for (c = 0; c < children; c++) 1932 if ((ret = max_width(zhp, child[c], depth + 2, 1933 max, name_flags)) > max) 1934 max = ret; 1935 } 1936 1937 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1938 &child, &children) == 0) { 1939 for (c = 0; c < children; c++) 1940 if ((ret = max_width(zhp, child[c], depth + 2, 1941 max, name_flags)) > max) 1942 max = ret; 1943 } 1944 1945 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1946 &child, &children) == 0) { 1947 for (c = 0; c < children; c++) 1948 if ((ret = max_width(zhp, child[c], depth + 2, 1949 max, name_flags)) > max) 1950 max = ret; 1951 } 1952 1953 return (max); 1954} 1955 1956typedef struct spare_cbdata { 1957 uint64_t cb_guid; 1958 zpool_handle_t *cb_zhp; 1959} spare_cbdata_t; 1960 1961static boolean_t 1962find_vdev(nvlist_t *nv, uint64_t search) 1963{ 1964 uint64_t guid; 1965 nvlist_t **child; 1966 uint_t c, children; 1967 1968 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1969 search == guid) 1970 return (B_TRUE); 1971 1972 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1973 &child, &children) == 0) { 1974 for (c = 0; c < children; c++) 1975 if (find_vdev(child[c], search)) 1976 return (B_TRUE); 1977 } 1978 1979 return (B_FALSE); 1980} 1981 1982static int 1983find_spare(zpool_handle_t *zhp, void *data) 1984{ 1985 spare_cbdata_t *cbp = data; 1986 nvlist_t *config, *nvroot; 1987 1988 config = zpool_get_config(zhp, NULL); 1989 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1990 &nvroot) == 0); 1991 1992 if (find_vdev(nvroot, cbp->cb_guid)) { 1993 cbp->cb_zhp = zhp; 1994 return (1); 1995 } 1996 1997 zpool_close(zhp); 1998 return (0); 1999} 2000 2001typedef struct status_cbdata { 2002 int cb_count; 2003 int cb_name_flags; 2004 int cb_namewidth; 2005 boolean_t cb_allpools; 2006 boolean_t cb_verbose; 2007 boolean_t cb_literal; 2008 boolean_t cb_explain; 2009 boolean_t cb_first; 2010 boolean_t cb_dedup_stats; 2011 boolean_t cb_print_status; 2012 boolean_t cb_print_slow_ios; 2013 boolean_t cb_print_vdev_init; 2014 boolean_t cb_print_vdev_trim; 2015 vdev_cmd_data_list_t *vcdl; 2016} status_cbdata_t; 2017 2018/* Return 1 if string is NULL, empty, or whitespace; return 0 otherwise. */ 2019static int 2020is_blank_str(char *str) 2021{ 2022 while (str != NULL && *str != '\0') { 2023 if (!isblank(*str)) 2024 return (0); 2025 str++; 2026 } 2027 return (1); 2028} 2029 2030/* Print command output lines for specific vdev in a specific pool */ 2031static void 2032zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, char *path) 2033{ 2034 vdev_cmd_data_t *data; 2035 int i, j; 2036 char *val; 2037 2038 for (i = 0; i < vcdl->count; i++) { 2039 if ((strcmp(vcdl->data[i].path, path) != 0) || 2040 (strcmp(vcdl->data[i].pool, pool) != 0)) { 2041 /* Not the vdev we're looking for */ 2042 continue; 2043 } 2044 2045 data = &vcdl->data[i]; 2046 /* Print out all the output values for this vdev */ 2047 for (j = 0; j < vcdl->uniq_cols_cnt; j++) { 2048 val = NULL; 2049 /* Does this vdev have values for this column? */ 2050 for (int k = 0; k < data->cols_cnt; k++) { 2051 if (strcmp(data->cols[k], 2052 vcdl->uniq_cols[j]) == 0) { 2053 /* yes it does, record the value */ 2054 val = data->lines[k]; 2055 break; 2056 } 2057 } 2058 /* 2059 * Mark empty values with dashes to make output 2060 * awk-able. 2061 */ 2062 if (val == NULL || is_blank_str(val)) 2063 val = "-"; 2064 2065 printf("%*s", vcdl->uniq_cols_width[j], val); 2066 if (j < vcdl->uniq_cols_cnt - 1) 2067 printf(" "); 2068 } 2069 2070 /* Print out any values that aren't in a column at the end */ 2071 for (j = data->cols_cnt; j < data->lines_cnt; j++) { 2072 /* Did we have any columns? If so print a spacer. */ 2073 if (vcdl->uniq_cols_cnt > 0) 2074 printf(" "); 2075 2076 val = data->lines[j]; 2077 printf("%s", val ? val : ""); 2078 } 2079 break; 2080 } 2081} 2082 2083/* 2084 * Print vdev initialization status for leaves 2085 */ 2086static void 2087print_status_initialize(vdev_stat_t *vs, boolean_t verbose) 2088{ 2089 if (verbose) { 2090 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || 2091 vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || 2092 vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && 2093 !vs->vs_scan_removing) { 2094 char zbuf[1024]; 2095 char tbuf[256]; 2096 struct tm zaction_ts; 2097 2098 time_t t = vs->vs_initialize_action_time; 2099 int initialize_pct = 100; 2100 if (vs->vs_initialize_state != 2101 VDEV_INITIALIZE_COMPLETE) { 2102 initialize_pct = (vs->vs_initialize_bytes_done * 2103 100 / (vs->vs_initialize_bytes_est + 1)); 2104 } 2105 2106 (void) localtime_r(&t, &zaction_ts); 2107 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 2108 2109 switch (vs->vs_initialize_state) { 2110 case VDEV_INITIALIZE_SUSPENDED: 2111 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 2112 gettext("suspended, started at"), tbuf); 2113 break; 2114 case VDEV_INITIALIZE_ACTIVE: 2115 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 2116 gettext("started at"), tbuf); 2117 break; 2118 case VDEV_INITIALIZE_COMPLETE: 2119 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 2120 gettext("completed at"), tbuf); 2121 break; 2122 } 2123 2124 (void) printf(gettext(" (%d%% initialized%s)"), 2125 initialize_pct, zbuf); 2126 } else { 2127 (void) printf(gettext(" (uninitialized)")); 2128 } 2129 } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) { 2130 (void) printf(gettext(" (initializing)")); 2131 } 2132} 2133 2134/* 2135 * Print vdev TRIM status for leaves 2136 */ 2137static void 2138print_status_trim(vdev_stat_t *vs, boolean_t verbose) 2139{ 2140 if (verbose) { 2141 if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE || 2142 vs->vs_trim_state == VDEV_TRIM_SUSPENDED || 2143 vs->vs_trim_state == VDEV_TRIM_COMPLETE) && 2144 !vs->vs_scan_removing) { 2145 char zbuf[1024]; 2146 char tbuf[256]; 2147 struct tm zaction_ts; 2148 2149 time_t t = vs->vs_trim_action_time; 2150 int trim_pct = 100; 2151 if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) { 2152 trim_pct = (vs->vs_trim_bytes_done * 2153 100 / (vs->vs_trim_bytes_est + 1)); 2154 } 2155 2156 (void) localtime_r(&t, &zaction_ts); 2157 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 2158 2159 switch (vs->vs_trim_state) { 2160 case VDEV_TRIM_SUSPENDED: 2161 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 2162 gettext("suspended, started at"), tbuf); 2163 break; 2164 case VDEV_TRIM_ACTIVE: 2165 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 2166 gettext("started at"), tbuf); 2167 break; 2168 case VDEV_TRIM_COMPLETE: 2169 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 2170 gettext("completed at"), tbuf); 2171 break; 2172 } 2173 2174 (void) printf(gettext(" (%d%% trimmed%s)"), 2175 trim_pct, zbuf); 2176 } else if (vs->vs_trim_notsup) { 2177 (void) printf(gettext(" (trim unsupported)")); 2178 } else { 2179 (void) printf(gettext(" (untrimmed)")); 2180 } 2181 } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) { 2182 (void) printf(gettext(" (trimming)")); 2183 } 2184} 2185 2186/* 2187 * Return the color associated with a health string. This includes returning 2188 * NULL for no color change. 2189 */ 2190static char * 2191health_str_to_color(const char *health) 2192{ 2193 if (strcmp(health, gettext("FAULTED")) == 0 || 2194 strcmp(health, gettext("SUSPENDED")) == 0 || 2195 strcmp(health, gettext("UNAVAIL")) == 0) { 2196 return (ANSI_RED); 2197 } 2198 2199 if (strcmp(health, gettext("OFFLINE")) == 0 || 2200 strcmp(health, gettext("DEGRADED")) == 0 || 2201 strcmp(health, gettext("REMOVED")) == 0) { 2202 return (ANSI_YELLOW); 2203 } 2204 2205 return (NULL); 2206} 2207 2208/* 2209 * Print out configuration state as requested by status_callback. 2210 */ 2211static void 2212print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name, 2213 nvlist_t *nv, int depth, boolean_t isspare, vdev_rebuild_stat_t *vrs) 2214{ 2215 nvlist_t **child, *root; 2216 uint_t c, i, vsc, children; 2217 pool_scan_stat_t *ps = NULL; 2218 vdev_stat_t *vs; 2219 char rbuf[6], wbuf[6], cbuf[6]; 2220 char *vname; 2221 uint64_t notpresent; 2222 spare_cbdata_t spare_cb; 2223 const char *state; 2224 char *type; 2225 char *path = NULL; 2226 char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL; 2227 2228 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2229 &child, &children) != 0) 2230 children = 0; 2231 2232 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 2233 (uint64_t **)&vs, &vsc) == 0); 2234 2235 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 2236 2237 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 2238 return; 2239 2240 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2241 2242 if (isspare) { 2243 /* 2244 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 2245 * online drives. 2246 */ 2247 if (vs->vs_aux == VDEV_AUX_SPARED) 2248 state = gettext("INUSE"); 2249 else if (vs->vs_state == VDEV_STATE_HEALTHY) 2250 state = gettext("AVAIL"); 2251 } 2252 2253 printf_color(health_str_to_color(state), 2254 "\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth, 2255 name, state); 2256 2257 if (!isspare) { 2258 if (vs->vs_read_errors) 2259 rcolor = ANSI_RED; 2260 2261 if (vs->vs_write_errors) 2262 wcolor = ANSI_RED; 2263 2264 if (vs->vs_checksum_errors) 2265 ccolor = ANSI_RED; 2266 2267 if (cb->cb_literal) { 2268 printf(" "); 2269 printf_color(rcolor, "%5llu", 2270 (u_longlong_t)vs->vs_read_errors); 2271 printf(" "); 2272 printf_color(wcolor, "%5llu", 2273 (u_longlong_t)vs->vs_write_errors); 2274 printf(" "); 2275 printf_color(ccolor, "%5llu", 2276 (u_longlong_t)vs->vs_checksum_errors); 2277 } else { 2278 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 2279 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 2280 zfs_nicenum(vs->vs_checksum_errors, cbuf, 2281 sizeof (cbuf)); 2282 printf(" "); 2283 printf_color(rcolor, "%5s", rbuf); 2284 printf(" "); 2285 printf_color(wcolor, "%5s", wbuf); 2286 printf(" "); 2287 printf_color(ccolor, "%5s", cbuf); 2288 } 2289 if (cb->cb_print_slow_ios) { 2290 if (children == 0) { 2291 /* Only leafs vdevs have slow IOs */ 2292 zfs_nicenum(vs->vs_slow_ios, rbuf, 2293 sizeof (rbuf)); 2294 } else { 2295 snprintf(rbuf, sizeof (rbuf), "-"); 2296 } 2297 2298 if (cb->cb_literal) 2299 printf(" %5llu", (u_longlong_t)vs->vs_slow_ios); 2300 else 2301 printf(" %5s", rbuf); 2302 } 2303 } 2304 2305 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 2306 ¬present) == 0) { 2307 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2308 (void) printf(" %s %s", gettext("was"), path); 2309 } else if (vs->vs_aux != 0) { 2310 (void) printf(" "); 2311 color_start(ANSI_RED); 2312 switch (vs->vs_aux) { 2313 case VDEV_AUX_OPEN_FAILED: 2314 (void) printf(gettext("cannot open")); 2315 break; 2316 2317 case VDEV_AUX_BAD_GUID_SUM: 2318 (void) printf(gettext("missing device")); 2319 break; 2320 2321 case VDEV_AUX_NO_REPLICAS: 2322 (void) printf(gettext("insufficient replicas")); 2323 break; 2324 2325 case VDEV_AUX_VERSION_NEWER: 2326 (void) printf(gettext("newer version")); 2327 break; 2328 2329 case VDEV_AUX_UNSUP_FEAT: 2330 (void) printf(gettext("unsupported feature(s)")); 2331 break; 2332 2333 case VDEV_AUX_ASHIFT_TOO_BIG: 2334 (void) printf(gettext("unsupported minimum blocksize")); 2335 break; 2336 2337 case VDEV_AUX_SPARED: 2338 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 2339 &spare_cb.cb_guid) == 0); 2340 if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) { 2341 if (strcmp(zpool_get_name(spare_cb.cb_zhp), 2342 zpool_get_name(zhp)) == 0) 2343 (void) printf(gettext("currently in " 2344 "use")); 2345 else 2346 (void) printf(gettext("in use by " 2347 "pool '%s'"), 2348 zpool_get_name(spare_cb.cb_zhp)); 2349 zpool_close(spare_cb.cb_zhp); 2350 } else { 2351 (void) printf(gettext("currently in use")); 2352 } 2353 break; 2354 2355 case VDEV_AUX_ERR_EXCEEDED: 2356 (void) printf(gettext("too many errors")); 2357 break; 2358 2359 case VDEV_AUX_IO_FAILURE: 2360 (void) printf(gettext("experienced I/O failures")); 2361 break; 2362 2363 case VDEV_AUX_BAD_LOG: 2364 (void) printf(gettext("bad intent log")); 2365 break; 2366 2367 case VDEV_AUX_EXTERNAL: 2368 (void) printf(gettext("external device fault")); 2369 break; 2370 2371 case VDEV_AUX_SPLIT_POOL: 2372 (void) printf(gettext("split into new pool")); 2373 break; 2374 2375 case VDEV_AUX_ACTIVE: 2376 (void) printf(gettext("currently in use")); 2377 break; 2378 2379 case VDEV_AUX_CHILDREN_OFFLINE: 2380 (void) printf(gettext("all children offline")); 2381 break; 2382 2383 case VDEV_AUX_BAD_LABEL: 2384 (void) printf(gettext("invalid label")); 2385 break; 2386 2387 default: 2388 (void) printf(gettext("corrupted data")); 2389 break; 2390 } 2391 color_end(); 2392 } else if (children == 0 && !isspare && 2393 getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") == NULL && 2394 VDEV_STAT_VALID(vs_physical_ashift, vsc) && 2395 vs->vs_configured_ashift < vs->vs_physical_ashift) { 2396 (void) printf( 2397 gettext(" block size: %dB configured, %dB native"), 2398 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift); 2399 } 2400 2401 /* The root vdev has the scrub/resilver stats */ 2402 root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 2403 ZPOOL_CONFIG_VDEV_TREE); 2404 (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS, 2405 (uint64_t **)&ps, &c); 2406 2407 if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) { 2408 if (vs->vs_scan_processed != 0) { 2409 (void) printf(gettext(" (%s)"), 2410 (ps->pss_func == POOL_SCAN_RESILVER) ? 2411 "resilvering" : "repairing"); 2412 } else if (vs->vs_resilver_deferred) { 2413 (void) printf(gettext(" (awaiting resilver)")); 2414 } 2415 } 2416 2417 /* The top-level vdevs have the rebuild stats */ 2418 if (vrs != NULL && vrs->vrs_state == VDEV_REBUILD_ACTIVE && 2419 children == 0) { 2420 if (vs->vs_rebuild_processed != 0) { 2421 (void) printf(gettext(" (resilvering)")); 2422 } 2423 } 2424 2425 if (cb->vcdl != NULL) { 2426 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) { 2427 printf(" "); 2428 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path); 2429 } 2430 } 2431 2432 /* Display vdev initialization and trim status for leaves. */ 2433 if (children == 0) { 2434 print_status_initialize(vs, cb->cb_print_vdev_init); 2435 print_status_trim(vs, cb->cb_print_vdev_trim); 2436 } 2437 2438 (void) printf("\n"); 2439 2440 for (c = 0; c < children; c++) { 2441 uint64_t islog = B_FALSE, ishole = B_FALSE; 2442 2443 /* Don't print logs or holes here */ 2444 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2445 &islog); 2446 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 2447 &ishole); 2448 if (islog || ishole) 2449 continue; 2450 /* Only print normal classes here */ 2451 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 2452 continue; 2453 2454 /* Provide vdev_rebuild_stats to children if available */ 2455 if (vrs == NULL) { 2456 (void) nvlist_lookup_uint64_array(nv, 2457 ZPOOL_CONFIG_REBUILD_STATS, 2458 (uint64_t **)&vrs, &i); 2459 } 2460 2461 vname = zpool_vdev_name(g_zfs, zhp, child[c], 2462 cb->cb_name_flags | VDEV_NAME_TYPE_ID); 2463 print_status_config(zhp, cb, vname, child[c], depth + 2, 2464 isspare, vrs); 2465 free(vname); 2466 } 2467} 2468 2469/* 2470 * Print the configuration of an exported pool. Iterate over all vdevs in the 2471 * pool, printing out the name and status for each one. 2472 */ 2473static void 2474print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv, 2475 int depth) 2476{ 2477 nvlist_t **child; 2478 uint_t c, children; 2479 vdev_stat_t *vs; 2480 char *type, *vname; 2481 2482 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 2483 if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 2484 strcmp(type, VDEV_TYPE_HOLE) == 0) 2485 return; 2486 2487 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 2488 (uint64_t **)&vs, &c) == 0); 2489 2490 (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name); 2491 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 2492 2493 if (vs->vs_aux != 0) { 2494 (void) printf(" "); 2495 2496 switch (vs->vs_aux) { 2497 case VDEV_AUX_OPEN_FAILED: 2498 (void) printf(gettext("cannot open")); 2499 break; 2500 2501 case VDEV_AUX_BAD_GUID_SUM: 2502 (void) printf(gettext("missing device")); 2503 break; 2504 2505 case VDEV_AUX_NO_REPLICAS: 2506 (void) printf(gettext("insufficient replicas")); 2507 break; 2508 2509 case VDEV_AUX_VERSION_NEWER: 2510 (void) printf(gettext("newer version")); 2511 break; 2512 2513 case VDEV_AUX_UNSUP_FEAT: 2514 (void) printf(gettext("unsupported feature(s)")); 2515 break; 2516 2517 case VDEV_AUX_ERR_EXCEEDED: 2518 (void) printf(gettext("too many errors")); 2519 break; 2520 2521 case VDEV_AUX_ACTIVE: 2522 (void) printf(gettext("currently in use")); 2523 break; 2524 2525 case VDEV_AUX_CHILDREN_OFFLINE: 2526 (void) printf(gettext("all children offline")); 2527 break; 2528 2529 case VDEV_AUX_BAD_LABEL: 2530 (void) printf(gettext("invalid label")); 2531 break; 2532 2533 default: 2534 (void) printf(gettext("corrupted data")); 2535 break; 2536 } 2537 } 2538 (void) printf("\n"); 2539 2540 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2541 &child, &children) != 0) 2542 return; 2543 2544 for (c = 0; c < children; c++) { 2545 uint64_t is_log = B_FALSE; 2546 2547 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2548 &is_log); 2549 if (is_log) 2550 continue; 2551 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 2552 continue; 2553 2554 vname = zpool_vdev_name(g_zfs, NULL, child[c], 2555 cb->cb_name_flags | VDEV_NAME_TYPE_ID); 2556 print_import_config(cb, vname, child[c], depth + 2); 2557 free(vname); 2558 } 2559 2560 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 2561 &child, &children) == 0) { 2562 (void) printf(gettext("\tcache\n")); 2563 for (c = 0; c < children; c++) { 2564 vname = zpool_vdev_name(g_zfs, NULL, child[c], 2565 cb->cb_name_flags); 2566 (void) printf("\t %s\n", vname); 2567 free(vname); 2568 } 2569 } 2570 2571 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 2572 &child, &children) == 0) { 2573 (void) printf(gettext("\tspares\n")); 2574 for (c = 0; c < children; c++) { 2575 vname = zpool_vdev_name(g_zfs, NULL, child[c], 2576 cb->cb_name_flags); 2577 (void) printf("\t %s\n", vname); 2578 free(vname); 2579 } 2580 } 2581} 2582 2583/* 2584 * Print specialized class vdevs. 2585 * 2586 * These are recorded as top level vdevs in the main pool child array 2587 * but with "is_log" set to 1 or an "alloc_bias" string. We use either 2588 * print_status_config() or print_import_config() to print the top level 2589 * class vdevs then any of their children (eg mirrored slogs) are printed 2590 * recursively - which works because only the top level vdev is marked. 2591 */ 2592static void 2593print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv, 2594 const char *class) 2595{ 2596 uint_t c, children; 2597 nvlist_t **child; 2598 boolean_t printed = B_FALSE; 2599 2600 assert(zhp != NULL || !cb->cb_verbose); 2601 2602 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 2603 &children) != 0) 2604 return; 2605 2606 for (c = 0; c < children; c++) { 2607 uint64_t is_log = B_FALSE; 2608 char *bias = NULL; 2609 char *type = NULL; 2610 2611 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2612 &is_log); 2613 2614 if (is_log) { 2615 bias = VDEV_ALLOC_CLASS_LOGS; 2616 } else { 2617 (void) nvlist_lookup_string(child[c], 2618 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 2619 (void) nvlist_lookup_string(child[c], 2620 ZPOOL_CONFIG_TYPE, &type); 2621 } 2622 2623 if (bias == NULL || strcmp(bias, class) != 0) 2624 continue; 2625 if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 2626 continue; 2627 2628 if (!printed) { 2629 (void) printf("\t%s\t\n", gettext(class)); 2630 printed = B_TRUE; 2631 } 2632 2633 char *name = zpool_vdev_name(g_zfs, zhp, child[c], 2634 cb->cb_name_flags | VDEV_NAME_TYPE_ID); 2635 if (cb->cb_print_status) 2636 print_status_config(zhp, cb, name, child[c], 2, 2637 B_FALSE, NULL); 2638 else 2639 print_import_config(cb, name, child[c], 2); 2640 free(name); 2641 } 2642} 2643 2644/* 2645 * Display the status for the given pool. 2646 */ 2647static int 2648show_import(nvlist_t *config, boolean_t report_error) 2649{ 2650 uint64_t pool_state; 2651 vdev_stat_t *vs; 2652 char *name; 2653 uint64_t guid; 2654 uint64_t hostid = 0; 2655 char *msgid; 2656 char *hostname = "unknown"; 2657 nvlist_t *nvroot, *nvinfo; 2658 zpool_status_t reason; 2659 zpool_errata_t errata; 2660 const char *health; 2661 uint_t vsc; 2662 char *comment; 2663 status_cbdata_t cb = { 0 }; 2664 2665 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2666 &name) == 0); 2667 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 2668 &guid) == 0); 2669 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2670 &pool_state) == 0); 2671 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2672 &nvroot) == 0); 2673 2674 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 2675 (uint64_t **)&vs, &vsc) == 0); 2676 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2677 2678 reason = zpool_import_status(config, &msgid, &errata); 2679 2680 /* 2681 * If we're importing using a cachefile, then we won't report any 2682 * errors unless we are in the scan phase of the import. 2683 */ 2684 if (reason != ZPOOL_STATUS_OK && !report_error) 2685 return (reason); 2686 2687 (void) printf(gettext(" pool: %s\n"), name); 2688 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 2689 (void) printf(gettext(" state: %s"), health); 2690 if (pool_state == POOL_STATE_DESTROYED) 2691 (void) printf(gettext(" (DESTROYED)")); 2692 (void) printf("\n"); 2693 2694 switch (reason) { 2695 case ZPOOL_STATUS_MISSING_DEV_R: 2696 case ZPOOL_STATUS_MISSING_DEV_NR: 2697 case ZPOOL_STATUS_BAD_GUID_SUM: 2698 printf_color(ANSI_BOLD, gettext("status: ")); 2699 printf_color(ANSI_YELLOW, gettext("One or more devices are " 2700 "missing from the system.\n")); 2701 break; 2702 2703 case ZPOOL_STATUS_CORRUPT_LABEL_R: 2704 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 2705 printf_color(ANSI_BOLD, gettext("status: ")); 2706 printf_color(ANSI_YELLOW, gettext("One or more devices contains" 2707 " corrupted data.\n")); 2708 break; 2709 2710 case ZPOOL_STATUS_CORRUPT_DATA: 2711 (void) printf( 2712 gettext(" status: The pool data is corrupted.\n")); 2713 break; 2714 2715 case ZPOOL_STATUS_OFFLINE_DEV: 2716 printf_color(ANSI_BOLD, gettext("status: ")); 2717 printf_color(ANSI_YELLOW, gettext("One or more devices " 2718 "are offlined.\n")); 2719 break; 2720 2721 case ZPOOL_STATUS_CORRUPT_POOL: 2722 printf_color(ANSI_BOLD, gettext("status: ")); 2723 printf_color(ANSI_YELLOW, gettext("The pool metadata is " 2724 "corrupted.\n")); 2725 break; 2726 2727 case ZPOOL_STATUS_VERSION_OLDER: 2728 printf_color(ANSI_BOLD, gettext("status: ")); 2729 printf_color(ANSI_YELLOW, gettext("The pool is formatted using " 2730 "a legacy on-disk version.\n")); 2731 break; 2732 2733 case ZPOOL_STATUS_VERSION_NEWER: 2734 printf_color(ANSI_BOLD, gettext("status: ")); 2735 printf_color(ANSI_YELLOW, gettext("The pool is formatted using " 2736 "an incompatible version.\n")); 2737 break; 2738 2739 case ZPOOL_STATUS_FEAT_DISABLED: 2740 printf_color(ANSI_BOLD, gettext("status: ")); 2741 printf_color(ANSI_YELLOW, gettext("Some supported " 2742 "features are not enabled on the pool.\n\t" 2743 "(Note that they may be intentionally disabled " 2744 "if the\n\t'compatibility' property is set.)\n")); 2745 break; 2746 2747 case ZPOOL_STATUS_COMPATIBILITY_ERR: 2748 printf_color(ANSI_BOLD, gettext("status: ")); 2749 printf_color(ANSI_YELLOW, gettext("Error reading or parsing " 2750 "the file(s) indicated by the 'compatibility'\n" 2751 "property.\n")); 2752 break; 2753 2754 case ZPOOL_STATUS_INCOMPATIBLE_FEAT: 2755 printf_color(ANSI_BOLD, gettext("status: ")); 2756 printf_color(ANSI_YELLOW, gettext("One or more features " 2757 "are enabled on the pool despite not being\n" 2758 "requested by the 'compatibility' property.\n")); 2759 break; 2760 2761 case ZPOOL_STATUS_UNSUP_FEAT_READ: 2762 printf_color(ANSI_BOLD, gettext("status: ")); 2763 printf_color(ANSI_YELLOW, gettext("The pool uses the following " 2764 "feature(s) not supported on this system:\n")); 2765 color_start(ANSI_YELLOW); 2766 zpool_print_unsup_feat(config); 2767 color_end(); 2768 break; 2769 2770 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2771 printf_color(ANSI_BOLD, gettext("status: ")); 2772 printf_color(ANSI_YELLOW, gettext("The pool can only be " 2773 "accessed in read-only mode on this system. It\n\tcannot be" 2774 " accessed in read-write mode because it uses the " 2775 "following\n\tfeature(s) not supported on this system:\n")); 2776 color_start(ANSI_YELLOW); 2777 zpool_print_unsup_feat(config); 2778 color_end(); 2779 break; 2780 2781 case ZPOOL_STATUS_HOSTID_ACTIVE: 2782 printf_color(ANSI_BOLD, gettext("status: ")); 2783 printf_color(ANSI_YELLOW, gettext("The pool is currently " 2784 "imported by another system.\n")); 2785 break; 2786 2787 case ZPOOL_STATUS_HOSTID_REQUIRED: 2788 printf_color(ANSI_BOLD, gettext("status: ")); 2789 printf_color(ANSI_YELLOW, gettext("The pool has the " 2790 "multihost property on. It cannot\n\tbe safely imported " 2791 "when the system hostid is not set.\n")); 2792 break; 2793 2794 case ZPOOL_STATUS_HOSTID_MISMATCH: 2795 printf_color(ANSI_BOLD, gettext("status: ")); 2796 printf_color(ANSI_YELLOW, gettext("The pool was last accessed " 2797 "by another system.\n")); 2798 break; 2799 2800 case ZPOOL_STATUS_FAULTED_DEV_R: 2801 case ZPOOL_STATUS_FAULTED_DEV_NR: 2802 printf_color(ANSI_BOLD, gettext("status: ")); 2803 printf_color(ANSI_YELLOW, gettext("One or more devices are " 2804 "faulted.\n")); 2805 break; 2806 2807 case ZPOOL_STATUS_BAD_LOG: 2808 printf_color(ANSI_BOLD, gettext("status: ")); 2809 printf_color(ANSI_YELLOW, gettext("An intent log record cannot " 2810 "be read.\n")); 2811 break; 2812 2813 case ZPOOL_STATUS_RESILVERING: 2814 case ZPOOL_STATUS_REBUILDING: 2815 printf_color(ANSI_BOLD, gettext("status: ")); 2816 printf_color(ANSI_YELLOW, gettext("One or more devices were " 2817 "being resilvered.\n")); 2818 break; 2819 2820 case ZPOOL_STATUS_ERRATA: 2821 printf_color(ANSI_BOLD, gettext("status: ")); 2822 printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"), 2823 errata); 2824 break; 2825 2826 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 2827 printf_color(ANSI_BOLD, gettext("status: ")); 2828 printf_color(ANSI_YELLOW, gettext("One or more devices are " 2829 "configured to use a non-native block size.\n" 2830 "\tExpect reduced performance.\n")); 2831 break; 2832 2833 default: 2834 /* 2835 * No other status can be seen when importing pools. 2836 */ 2837 assert(reason == ZPOOL_STATUS_OK); 2838 } 2839 2840 /* 2841 * Print out an action according to the overall state of the pool. 2842 */ 2843 if (vs->vs_state == VDEV_STATE_HEALTHY) { 2844 if (reason == ZPOOL_STATUS_VERSION_OLDER || 2845 reason == ZPOOL_STATUS_FEAT_DISABLED) { 2846 (void) printf(gettext(" action: The pool can be " 2847 "imported using its name or numeric identifier, " 2848 "though\n\tsome features will not be available " 2849 "without an explicit 'zpool upgrade'.\n")); 2850 } else if (reason == ZPOOL_STATUS_COMPATIBILITY_ERR) { 2851 (void) printf(gettext(" action: The pool can be " 2852 "imported using its name or numeric\n\tidentifier, " 2853 "though the file(s) indicated by its " 2854 "'compatibility'\n\tproperty cannot be parsed at " 2855 "this time.\n")); 2856 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 2857 (void) printf(gettext(" action: The pool can be " 2858 "imported using its name or numeric " 2859 "identifier and\n\tthe '-f' flag.\n")); 2860 } else if (reason == ZPOOL_STATUS_ERRATA) { 2861 switch (errata) { 2862 case ZPOOL_ERRATA_NONE: 2863 break; 2864 2865 case ZPOOL_ERRATA_ZOL_2094_SCRUB: 2866 (void) printf(gettext(" action: The pool can " 2867 "be imported using its name or numeric " 2868 "identifier,\n\thowever there is a compat" 2869 "ibility issue which should be corrected" 2870 "\n\tby running 'zpool scrub'\n")); 2871 break; 2872 2873 case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY: 2874 (void) printf(gettext(" action: The pool can" 2875 "not be imported with this version of ZFS " 2876 "due to\n\tan active asynchronous destroy. " 2877 "Revert to an earlier version\n\tand " 2878 "allow the destroy to complete before " 2879 "updating.\n")); 2880 break; 2881 2882 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 2883 (void) printf(gettext(" action: Existing " 2884 "encrypted datasets contain an on-disk " 2885 "incompatibility, which\n\tneeds to be " 2886 "corrected. Backup these datasets to new " 2887 "encrypted datasets\n\tand destroy the " 2888 "old ones.\n")); 2889 break; 2890 2891 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 2892 (void) printf(gettext(" action: Existing " 2893 "encrypted snapshots and bookmarks contain " 2894 "an on-disk\n\tincompatibility. This may " 2895 "cause on-disk corruption if they are used" 2896 "\n\twith 'zfs recv'. To correct the " 2897 "issue, enable the bookmark_v2 feature.\n\t" 2898 "No additional action is needed if there " 2899 "are no encrypted snapshots or\n\t" 2900 "bookmarks. If preserving the encrypted " 2901 "snapshots and bookmarks is\n\trequired, " 2902 "use a non-raw send to backup and restore " 2903 "them. Alternately,\n\tthey may be removed" 2904 " to resolve the incompatibility.\n")); 2905 break; 2906 default: 2907 /* 2908 * All errata must contain an action message. 2909 */ 2910 assert(0); 2911 } 2912 } else { 2913 (void) printf(gettext(" action: The pool can be " 2914 "imported using its name or numeric " 2915 "identifier.\n")); 2916 } 2917 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 2918 (void) printf(gettext(" action: The pool can be imported " 2919 "despite missing or damaged devices. The\n\tfault " 2920 "tolerance of the pool may be compromised if imported.\n")); 2921 } else { 2922 switch (reason) { 2923 case ZPOOL_STATUS_VERSION_NEWER: 2924 (void) printf(gettext(" action: The pool cannot be " 2925 "imported. Access the pool on a system running " 2926 "newer\n\tsoftware, or recreate the pool from " 2927 "backup.\n")); 2928 break; 2929 case ZPOOL_STATUS_UNSUP_FEAT_READ: 2930 printf_color(ANSI_BOLD, gettext("action: ")); 2931 printf_color(ANSI_YELLOW, gettext("The pool cannot be " 2932 "imported. Access the pool on a system that " 2933 "supports\n\tthe required feature(s), or recreate " 2934 "the pool from backup.\n")); 2935 break; 2936 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2937 printf_color(ANSI_BOLD, gettext("action: ")); 2938 printf_color(ANSI_YELLOW, gettext("The pool cannot be " 2939 "imported in read-write mode. Import the pool " 2940 "with\n" 2941 "\t\"-o readonly=on\", access the pool on a system " 2942 "that supports the\n\trequired feature(s), or " 2943 "recreate the pool from backup.\n")); 2944 break; 2945 case ZPOOL_STATUS_MISSING_DEV_R: 2946 case ZPOOL_STATUS_MISSING_DEV_NR: 2947 case ZPOOL_STATUS_BAD_GUID_SUM: 2948 (void) printf(gettext(" action: The pool cannot be " 2949 "imported. Attach the missing\n\tdevices and try " 2950 "again.\n")); 2951 break; 2952 case ZPOOL_STATUS_HOSTID_ACTIVE: 2953 VERIFY0(nvlist_lookup_nvlist(config, 2954 ZPOOL_CONFIG_LOAD_INFO, &nvinfo)); 2955 2956 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2957 hostname = fnvlist_lookup_string(nvinfo, 2958 ZPOOL_CONFIG_MMP_HOSTNAME); 2959 2960 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2961 hostid = fnvlist_lookup_uint64(nvinfo, 2962 ZPOOL_CONFIG_MMP_HOSTID); 2963 2964 (void) printf(gettext(" action: The pool must be " 2965 "exported from %s (hostid=%lx)\n\tbefore it " 2966 "can be safely imported.\n"), hostname, 2967 (unsigned long) hostid); 2968 break; 2969 case ZPOOL_STATUS_HOSTID_REQUIRED: 2970 (void) printf(gettext(" action: Set a unique system " 2971 "hostid with the zgenhostid(8) command.\n")); 2972 break; 2973 default: 2974 (void) printf(gettext(" action: The pool cannot be " 2975 "imported due to damaged devices or data.\n")); 2976 } 2977 } 2978 2979 /* Print the comment attached to the pool. */ 2980 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 2981 (void) printf(gettext("comment: %s\n"), comment); 2982 2983 /* 2984 * If the state is "closed" or "can't open", and the aux state 2985 * is "corrupt data": 2986 */ 2987 if (((vs->vs_state == VDEV_STATE_CLOSED) || 2988 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 2989 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 2990 if (pool_state == POOL_STATE_DESTROYED) 2991 (void) printf(gettext("\tThe pool was destroyed, " 2992 "but can be imported using the '-Df' flags.\n")); 2993 else if (pool_state != POOL_STATE_EXPORTED) 2994 (void) printf(gettext("\tThe pool may be active on " 2995 "another system, but can be imported using\n\t" 2996 "the '-f' flag.\n")); 2997 } 2998 2999 if (msgid != NULL) { 3000 (void) printf(gettext( 3001 " see: https://openzfs.github.io/openzfs-docs/msg/%s\n"), 3002 msgid); 3003 } 3004 3005 (void) printf(gettext(" config:\n\n")); 3006 3007 cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name), 3008 VDEV_NAME_TYPE_ID); 3009 if (cb.cb_namewidth < 10) 3010 cb.cb_namewidth = 10; 3011 3012 print_import_config(&cb, name, nvroot, 0); 3013 3014 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP); 3015 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 3016 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS); 3017 3018 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 3019 (void) printf(gettext("\n\tAdditional devices are known to " 3020 "be part of this pool, though their\n\texact " 3021 "configuration cannot be determined.\n")); 3022 } 3023 return (0); 3024} 3025 3026static boolean_t 3027zfs_force_import_required(nvlist_t *config) 3028{ 3029 uint64_t state; 3030 uint64_t hostid = 0; 3031 nvlist_t *nvinfo; 3032 3033 state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE); 3034 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); 3035 3036 if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid()) 3037 return (B_TRUE); 3038 3039 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 3040 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) { 3041 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo, 3042 ZPOOL_CONFIG_MMP_STATE); 3043 3044 if (mmp_state != MMP_STATE_INACTIVE) 3045 return (B_TRUE); 3046 } 3047 3048 return (B_FALSE); 3049} 3050 3051/* 3052 * Perform the import for the given configuration. This passes the heavy 3053 * lifting off to zpool_import_props(), and then mounts the datasets contained 3054 * within the pool. 3055 */ 3056static int 3057do_import(nvlist_t *config, const char *newname, const char *mntopts, 3058 nvlist_t *props, int flags) 3059{ 3060 int ret = 0; 3061 zpool_handle_t *zhp; 3062 char *name; 3063 uint64_t version; 3064 3065 name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME); 3066 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); 3067 3068 if (!SPA_VERSION_IS_SUPPORTED(version)) { 3069 (void) fprintf(stderr, gettext("cannot import '%s': pool " 3070 "is formatted using an unsupported ZFS version\n"), name); 3071 return (1); 3072 } else if (zfs_force_import_required(config) && 3073 !(flags & ZFS_IMPORT_ANY_HOST)) { 3074 mmp_state_t mmp_state = MMP_STATE_INACTIVE; 3075 nvlist_t *nvinfo; 3076 3077 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 3078 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) 3079 mmp_state = fnvlist_lookup_uint64(nvinfo, 3080 ZPOOL_CONFIG_MMP_STATE); 3081 3082 if (mmp_state == MMP_STATE_ACTIVE) { 3083 char *hostname = "<unknown>"; 3084 uint64_t hostid = 0; 3085 3086 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 3087 hostname = fnvlist_lookup_string(nvinfo, 3088 ZPOOL_CONFIG_MMP_HOSTNAME); 3089 3090 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 3091 hostid = fnvlist_lookup_uint64(nvinfo, 3092 ZPOOL_CONFIG_MMP_HOSTID); 3093 3094 (void) fprintf(stderr, gettext("cannot import '%s': " 3095 "pool is imported on %s (hostid: " 3096 "0x%lx)\nExport the pool on the other system, " 3097 "then run 'zpool import'.\n"), 3098 name, hostname, (unsigned long) hostid); 3099 } else if (mmp_state == MMP_STATE_NO_HOSTID) { 3100 (void) fprintf(stderr, gettext("Cannot import '%s': " 3101 "pool has the multihost property on and the\n" 3102 "system's hostid is not set. Set a unique hostid " 3103 "with the zgenhostid(8) command.\n"), name); 3104 } else { 3105 char *hostname = "<unknown>"; 3106 uint64_t timestamp = 0; 3107 uint64_t hostid = 0; 3108 3109 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME)) 3110 hostname = fnvlist_lookup_string(config, 3111 ZPOOL_CONFIG_HOSTNAME); 3112 3113 if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP)) 3114 timestamp = fnvlist_lookup_uint64(config, 3115 ZPOOL_CONFIG_TIMESTAMP); 3116 3117 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID)) 3118 hostid = fnvlist_lookup_uint64(config, 3119 ZPOOL_CONFIG_HOSTID); 3120 3121 (void) fprintf(stderr, gettext("cannot import '%s': " 3122 "pool was previously in use from another system.\n" 3123 "Last accessed by %s (hostid=%lx) at %s" 3124 "The pool can be imported, use 'zpool import -f' " 3125 "to import the pool.\n"), name, hostname, 3126 (unsigned long)hostid, ctime((time_t *)×tamp)); 3127 } 3128 3129 return (1); 3130 } 3131 3132 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 3133 return (1); 3134 3135 if (newname != NULL) 3136 name = (char *)newname; 3137 3138 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 3139 return (1); 3140 3141 /* 3142 * Loading keys is best effort. We don't want to return immediately 3143 * if it fails but we do want to give the error to the caller. 3144 */ 3145 if (flags & ZFS_IMPORT_LOAD_KEYS) { 3146 ret = zfs_crypto_attempt_load_keys(g_zfs, name); 3147 if (ret != 0) 3148 ret = 1; 3149 } 3150 3151 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 3152 !(flags & ZFS_IMPORT_ONLY) && 3153 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 3154 zpool_close(zhp); 3155 return (1); 3156 } 3157 3158 zpool_close(zhp); 3159 return (ret); 3160} 3161 3162static int 3163import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags, 3164 char *orig_name, char *new_name, 3165 boolean_t do_destroyed, boolean_t pool_specified, boolean_t do_all, 3166 importargs_t *import) 3167{ 3168 nvlist_t *config = NULL; 3169 nvlist_t *found_config = NULL; 3170 uint64_t pool_state; 3171 3172 /* 3173 * At this point we have a list of import candidate configs. Even if 3174 * we were searching by pool name or guid, we still need to 3175 * post-process the list to deal with pool state and possible 3176 * duplicate names. 3177 */ 3178 int err = 0; 3179 nvpair_t *elem = NULL; 3180 boolean_t first = B_TRUE; 3181 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 3182 3183 verify(nvpair_value_nvlist(elem, &config) == 0); 3184 3185 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 3186 &pool_state) == 0); 3187 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 3188 continue; 3189 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 3190 continue; 3191 3192 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 3193 import->policy) == 0); 3194 3195 if (!pool_specified) { 3196 if (first) 3197 first = B_FALSE; 3198 else if (!do_all) 3199 (void) printf("\n"); 3200 3201 if (do_all) { 3202 err |= do_import(config, NULL, mntopts, 3203 props, flags); 3204 } else { 3205 /* 3206 * If we're importing from cachefile, then 3207 * we don't want to report errors until we 3208 * are in the scan phase of the import. If 3209 * we get an error, then we return that error 3210 * to invoke the scan phase. 3211 */ 3212 if (import->cachefile && !import->scan) 3213 err = show_import(config, B_FALSE); 3214 else 3215 (void) show_import(config, B_TRUE); 3216 } 3217 } else if (import->poolname != NULL) { 3218 char *name; 3219 3220 /* 3221 * We are searching for a pool based on name. 3222 */ 3223 verify(nvlist_lookup_string(config, 3224 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 3225 3226 if (strcmp(name, import->poolname) == 0) { 3227 if (found_config != NULL) { 3228 (void) fprintf(stderr, gettext( 3229 "cannot import '%s': more than " 3230 "one matching pool\n"), 3231 import->poolname); 3232 (void) fprintf(stderr, gettext( 3233 "import by numeric ID instead\n")); 3234 err = B_TRUE; 3235 } 3236 found_config = config; 3237 } 3238 } else { 3239 uint64_t guid; 3240 3241 /* 3242 * Search for a pool by guid. 3243 */ 3244 verify(nvlist_lookup_uint64(config, 3245 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 3246 3247 if (guid == import->guid) 3248 found_config = config; 3249 } 3250 } 3251 3252 /* 3253 * If we were searching for a specific pool, verify that we found a 3254 * pool, and then do the import. 3255 */ 3256 if (pool_specified && err == 0) { 3257 if (found_config == NULL) { 3258 (void) fprintf(stderr, gettext("cannot import '%s': " 3259 "no such pool available\n"), orig_name); 3260 err = B_TRUE; 3261 } else { 3262 err |= do_import(found_config, new_name, 3263 mntopts, props, flags); 3264 } 3265 } 3266 3267 /* 3268 * If we were just looking for pools, report an error if none were 3269 * found. 3270 */ 3271 if (!pool_specified && first) 3272 (void) fprintf(stderr, 3273 gettext("no pools available to import\n")); 3274 return (err); 3275} 3276 3277typedef struct target_exists_args { 3278 const char *poolname; 3279 uint64_t poolguid; 3280} target_exists_args_t; 3281 3282static int 3283name_or_guid_exists(zpool_handle_t *zhp, void *data) 3284{ 3285 target_exists_args_t *args = data; 3286 nvlist_t *config = zpool_get_config(zhp, NULL); 3287 int found = 0; 3288 3289 if (config == NULL) 3290 return (0); 3291 3292 if (args->poolname != NULL) { 3293 char *pool_name; 3294 3295 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 3296 &pool_name) == 0); 3297 if (strcmp(pool_name, args->poolname) == 0) 3298 found = 1; 3299 } else { 3300 uint64_t pool_guid; 3301 3302 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 3303 &pool_guid) == 0); 3304 if (pool_guid == args->poolguid) 3305 found = 1; 3306 } 3307 zpool_close(zhp); 3308 3309 return (found); 3310} 3311/* 3312 * zpool checkpoint <pool> 3313 * checkpoint --discard <pool> 3314 * 3315 * -d Discard the checkpoint from a checkpointed 3316 * --discard pool. 3317 * 3318 * -w Wait for discarding a checkpoint to complete. 3319 * --wait 3320 * 3321 * Checkpoints the specified pool, by taking a "snapshot" of its 3322 * current state. A pool can only have one checkpoint at a time. 3323 */ 3324int 3325zpool_do_checkpoint(int argc, char **argv) 3326{ 3327 boolean_t discard, wait; 3328 char *pool; 3329 zpool_handle_t *zhp; 3330 int c, err; 3331 3332 struct option long_options[] = { 3333 {"discard", no_argument, NULL, 'd'}, 3334 {"wait", no_argument, NULL, 'w'}, 3335 {0, 0, 0, 0} 3336 }; 3337 3338 discard = B_FALSE; 3339 wait = B_FALSE; 3340 while ((c = getopt_long(argc, argv, ":dw", long_options, NULL)) != -1) { 3341 switch (c) { 3342 case 'd': 3343 discard = B_TRUE; 3344 break; 3345 case 'w': 3346 wait = B_TRUE; 3347 break; 3348 case '?': 3349 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3350 optopt); 3351 usage(B_FALSE); 3352 } 3353 } 3354 3355 if (wait && !discard) { 3356 (void) fprintf(stderr, gettext("--wait only valid when " 3357 "--discard also specified\n")); 3358 usage(B_FALSE); 3359 } 3360 3361 argc -= optind; 3362 argv += optind; 3363 3364 if (argc < 1) { 3365 (void) fprintf(stderr, gettext("missing pool argument\n")); 3366 usage(B_FALSE); 3367 } 3368 3369 if (argc > 1) { 3370 (void) fprintf(stderr, gettext("too many arguments\n")); 3371 usage(B_FALSE); 3372 } 3373 3374 pool = argv[0]; 3375 3376 if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 3377 /* As a special case, check for use of '/' in the name */ 3378 if (strchr(pool, '/') != NULL) 3379 (void) fprintf(stderr, gettext("'zpool checkpoint' " 3380 "doesn't work on datasets. To save the state " 3381 "of a dataset from a specific point in time " 3382 "please use 'zfs snapshot'\n")); 3383 return (1); 3384 } 3385 3386 if (discard) { 3387 err = (zpool_discard_checkpoint(zhp) != 0); 3388 if (err == 0 && wait) 3389 err = zpool_wait(zhp, ZPOOL_WAIT_CKPT_DISCARD); 3390 } else { 3391 err = (zpool_checkpoint(zhp) != 0); 3392 } 3393 3394 zpool_close(zhp); 3395 3396 return (err); 3397} 3398 3399#define CHECKPOINT_OPT 1024 3400 3401/* 3402 * zpool import [-d dir] [-D] 3403 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 3404 * [-d dir | -c cachefile | -s] [-f] -a 3405 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 3406 * [-d dir | -c cachefile | -s] [-f] [-n] [-F] <pool | id> 3407 * [newpool] 3408 * 3409 * -c Read pool information from a cachefile instead of searching 3410 * devices. If importing from a cachefile config fails, then 3411 * fallback to searching for devices only in the directories that 3412 * exist in the cachefile. 3413 * 3414 * -d Scan in a specific directory, other than /dev/. More than 3415 * one directory can be specified using multiple '-d' options. 3416 * 3417 * -D Scan for previously destroyed pools or import all or only 3418 * specified destroyed pools. 3419 * 3420 * -R Temporarily import the pool, with all mountpoints relative to 3421 * the given root. The pool will remain exported when the machine 3422 * is rebooted. 3423 * 3424 * -V Import even in the presence of faulted vdevs. This is an 3425 * intentionally undocumented option for testing purposes, and 3426 * treats the pool configuration as complete, leaving any bad 3427 * vdevs in the FAULTED state. In other words, it does verbatim 3428 * import. 3429 * 3430 * -f Force import, even if it appears that the pool is active. 3431 * 3432 * -F Attempt rewind if necessary. 3433 * 3434 * -n See if rewind would work, but don't actually rewind. 3435 * 3436 * -N Import the pool but don't mount datasets. 3437 * 3438 * -T Specify a starting txg to use for import. This option is 3439 * intentionally undocumented option for testing purposes. 3440 * 3441 * -a Import all pools found. 3442 * 3443 * -l Load encryption keys while importing. 3444 * 3445 * -o Set property=value and/or temporary mount options (without '='). 3446 * 3447 * -s Scan using the default search path, the libblkid cache will 3448 * not be consulted. 3449 * 3450 * --rewind-to-checkpoint 3451 * Import the pool and revert back to the checkpoint. 3452 * 3453 * The import command scans for pools to import, and import pools based on pool 3454 * name and GUID. The pool can also be renamed as part of the import process. 3455 */ 3456int 3457zpool_do_import(int argc, char **argv) 3458{ 3459 char **searchdirs = NULL; 3460 char *env, *envdup = NULL; 3461 int nsearch = 0; 3462 int c; 3463 int err = 0; 3464 nvlist_t *pools = NULL; 3465 boolean_t do_all = B_FALSE; 3466 boolean_t do_destroyed = B_FALSE; 3467 char *mntopts = NULL; 3468 uint64_t searchguid = 0; 3469 char *searchname = NULL; 3470 char *propval; 3471 nvlist_t *policy = NULL; 3472 nvlist_t *props = NULL; 3473 int flags = ZFS_IMPORT_NORMAL; 3474 uint32_t rewind_policy = ZPOOL_NO_REWIND; 3475 boolean_t dryrun = B_FALSE; 3476 boolean_t do_rewind = B_FALSE; 3477 boolean_t xtreme_rewind = B_FALSE; 3478 boolean_t do_scan = B_FALSE; 3479 boolean_t pool_exists = B_FALSE; 3480 boolean_t pool_specified = B_FALSE; 3481 uint64_t txg = -1ULL; 3482 char *cachefile = NULL; 3483 importargs_t idata = { 0 }; 3484 char *endptr; 3485 3486 struct option long_options[] = { 3487 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 3488 {0, 0, 0, 0} 3489 }; 3490 3491 /* check options */ 3492 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:R:stT:VX", 3493 long_options, NULL)) != -1) { 3494 switch (c) { 3495 case 'a': 3496 do_all = B_TRUE; 3497 break; 3498 case 'c': 3499 cachefile = optarg; 3500 break; 3501 case 'd': 3502 if (searchdirs == NULL) { 3503 searchdirs = safe_malloc(sizeof (char *)); 3504 } else { 3505 char **tmp = safe_malloc((nsearch + 1) * 3506 sizeof (char *)); 3507 bcopy(searchdirs, tmp, nsearch * 3508 sizeof (char *)); 3509 free(searchdirs); 3510 searchdirs = tmp; 3511 } 3512 searchdirs[nsearch++] = optarg; 3513 break; 3514 case 'D': 3515 do_destroyed = B_TRUE; 3516 break; 3517 case 'f': 3518 flags |= ZFS_IMPORT_ANY_HOST; 3519 break; 3520 case 'F': 3521 do_rewind = B_TRUE; 3522 break; 3523 case 'l': 3524 flags |= ZFS_IMPORT_LOAD_KEYS; 3525 break; 3526 case 'm': 3527 flags |= ZFS_IMPORT_MISSING_LOG; 3528 break; 3529 case 'n': 3530 dryrun = B_TRUE; 3531 break; 3532 case 'N': 3533 flags |= ZFS_IMPORT_ONLY; 3534 break; 3535 case 'o': 3536 if ((propval = strchr(optarg, '=')) != NULL) { 3537 *propval = '\0'; 3538 propval++; 3539 if (add_prop_list(optarg, propval, 3540 &props, B_TRUE)) 3541 goto error; 3542 } else { 3543 mntopts = optarg; 3544 } 3545 break; 3546 case 'R': 3547 if (add_prop_list(zpool_prop_to_name( 3548 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 3549 goto error; 3550 if (add_prop_list_default(zpool_prop_to_name( 3551 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 3552 goto error; 3553 break; 3554 case 's': 3555 do_scan = B_TRUE; 3556 break; 3557 case 't': 3558 flags |= ZFS_IMPORT_TEMP_NAME; 3559 if (add_prop_list_default(zpool_prop_to_name( 3560 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 3561 goto error; 3562 break; 3563 3564 case 'T': 3565 errno = 0; 3566 txg = strtoull(optarg, &endptr, 0); 3567 if (errno != 0 || *endptr != '\0') { 3568 (void) fprintf(stderr, 3569 gettext("invalid txg value\n")); 3570 usage(B_FALSE); 3571 } 3572 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 3573 break; 3574 case 'V': 3575 flags |= ZFS_IMPORT_VERBATIM; 3576 break; 3577 case 'X': 3578 xtreme_rewind = B_TRUE; 3579 break; 3580 case CHECKPOINT_OPT: 3581 flags |= ZFS_IMPORT_CHECKPOINT; 3582 break; 3583 case ':': 3584 (void) fprintf(stderr, gettext("missing argument for " 3585 "'%c' option\n"), optopt); 3586 usage(B_FALSE); 3587 break; 3588 case '?': 3589 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3590 optopt); 3591 usage(B_FALSE); 3592 } 3593 } 3594 3595 argc -= optind; 3596 argv += optind; 3597 3598 if (cachefile && nsearch != 0) { 3599 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 3600 usage(B_FALSE); 3601 } 3602 3603 if (cachefile && do_scan) { 3604 (void) fprintf(stderr, gettext("-c is incompatible with -s\n")); 3605 usage(B_FALSE); 3606 } 3607 3608 if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) { 3609 (void) fprintf(stderr, gettext("-l is incompatible with -N\n")); 3610 usage(B_FALSE); 3611 } 3612 3613 if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) { 3614 (void) fprintf(stderr, gettext("-l is only meaningful during " 3615 "an import\n")); 3616 usage(B_FALSE); 3617 } 3618 3619 if ((dryrun || xtreme_rewind) && !do_rewind) { 3620 (void) fprintf(stderr, 3621 gettext("-n or -X only meaningful with -F\n")); 3622 usage(B_FALSE); 3623 } 3624 if (dryrun) 3625 rewind_policy = ZPOOL_TRY_REWIND; 3626 else if (do_rewind) 3627 rewind_policy = ZPOOL_DO_REWIND; 3628 if (xtreme_rewind) 3629 rewind_policy |= ZPOOL_EXTREME_REWIND; 3630 3631 /* In the future, we can capture further policy and include it here */ 3632 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 3633 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 || 3634 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 3635 rewind_policy) != 0) 3636 goto error; 3637 3638 /* check argument count */ 3639 if (do_all) { 3640 if (argc != 0) { 3641 (void) fprintf(stderr, gettext("too many arguments\n")); 3642 usage(B_FALSE); 3643 } 3644 } else { 3645 if (argc > 2) { 3646 (void) fprintf(stderr, gettext("too many arguments\n")); 3647 usage(B_FALSE); 3648 } 3649 } 3650 3651 /* 3652 * Check for the effective uid. We do this explicitly here because 3653 * otherwise any attempt to discover pools will silently fail. 3654 */ 3655 if (argc == 0 && geteuid() != 0) { 3656 (void) fprintf(stderr, gettext("cannot " 3657 "discover pools: permission denied\n")); 3658 if (searchdirs != NULL) 3659 free(searchdirs); 3660 3661 nvlist_free(props); 3662 nvlist_free(policy); 3663 return (1); 3664 } 3665 3666 /* 3667 * Depending on the arguments given, we do one of the following: 3668 * 3669 * <none> Iterate through all pools and display information about 3670 * each one. 3671 * 3672 * -a Iterate through all pools and try to import each one. 3673 * 3674 * <id> Find the pool that corresponds to the given GUID/pool 3675 * name and import that one. 3676 * 3677 * -D Above options applies only to destroyed pools. 3678 */ 3679 if (argc != 0) { 3680 char *endptr; 3681 3682 errno = 0; 3683 searchguid = strtoull(argv[0], &endptr, 10); 3684 if (errno != 0 || *endptr != '\0') { 3685 searchname = argv[0]; 3686 searchguid = 0; 3687 } 3688 pool_specified = B_TRUE; 3689 3690 /* 3691 * User specified a name or guid. Ensure it's unique. 3692 */ 3693 target_exists_args_t search = {searchname, searchguid}; 3694 pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search); 3695 } 3696 3697 /* 3698 * Check the environment for the preferred search path. 3699 */ 3700 if ((searchdirs == NULL) && (env = getenv("ZPOOL_IMPORT_PATH"))) { 3701 char *dir; 3702 3703 envdup = strdup(env); 3704 3705 dir = strtok(envdup, ":"); 3706 while (dir != NULL) { 3707 if (searchdirs == NULL) { 3708 searchdirs = safe_malloc(sizeof (char *)); 3709 } else { 3710 char **tmp = safe_malloc((nsearch + 1) * 3711 sizeof (char *)); 3712 bcopy(searchdirs, tmp, nsearch * 3713 sizeof (char *)); 3714 free(searchdirs); 3715 searchdirs = tmp; 3716 } 3717 searchdirs[nsearch++] = dir; 3718 dir = strtok(NULL, ":"); 3719 } 3720 } 3721 3722 idata.path = searchdirs; 3723 idata.paths = nsearch; 3724 idata.poolname = searchname; 3725 idata.guid = searchguid; 3726 idata.cachefile = cachefile; 3727 idata.scan = do_scan; 3728 idata.policy = policy; 3729 3730 pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops); 3731 3732 if (pools != NULL && pool_exists && 3733 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 3734 (void) fprintf(stderr, gettext("cannot import '%s': " 3735 "a pool with that name already exists\n"), 3736 argv[0]); 3737 (void) fprintf(stderr, gettext("use the form '%s " 3738 "<pool | id> <newpool>' to give it a new name\n"), 3739 "zpool import"); 3740 err = 1; 3741 } else if (pools == NULL && pool_exists) { 3742 (void) fprintf(stderr, gettext("cannot import '%s': " 3743 "a pool with that name is already created/imported,\n"), 3744 argv[0]); 3745 (void) fprintf(stderr, gettext("and no additional pools " 3746 "with that name were found\n")); 3747 err = 1; 3748 } else if (pools == NULL) { 3749 if (argc != 0) { 3750 (void) fprintf(stderr, gettext("cannot import '%s': " 3751 "no such pool available\n"), argv[0]); 3752 } 3753 err = 1; 3754 } 3755 3756 if (err == 1) { 3757 if (searchdirs != NULL) 3758 free(searchdirs); 3759 if (envdup != NULL) 3760 free(envdup); 3761 nvlist_free(policy); 3762 nvlist_free(pools); 3763 nvlist_free(props); 3764 return (1); 3765 } 3766 3767 err = import_pools(pools, props, mntopts, flags, argv[0], 3768 argc == 1 ? NULL : argv[1], do_destroyed, pool_specified, 3769 do_all, &idata); 3770 3771 /* 3772 * If we're using the cachefile and we failed to import, then 3773 * fallback to scanning the directory for pools that match 3774 * those in the cachefile. 3775 */ 3776 if (err != 0 && cachefile != NULL) { 3777 (void) printf(gettext("cachefile import failed, retrying\n")); 3778 3779 /* 3780 * We use the scan flag to gather the directories that exist 3781 * in the cachefile. If we need to fallback to searching for 3782 * the pool config, we will only search devices in these 3783 * directories. 3784 */ 3785 idata.scan = B_TRUE; 3786 nvlist_free(pools); 3787 pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops); 3788 3789 err = import_pools(pools, props, mntopts, flags, argv[0], 3790 argc == 1 ? NULL : argv[1], do_destroyed, pool_specified, 3791 do_all, &idata); 3792 } 3793 3794error: 3795 nvlist_free(props); 3796 nvlist_free(pools); 3797 nvlist_free(policy); 3798 if (searchdirs != NULL) 3799 free(searchdirs); 3800 if (envdup != NULL) 3801 free(envdup); 3802 3803 return (err ? 1 : 0); 3804} 3805 3806/* 3807 * zpool sync [-f] [pool] ... 3808 * 3809 * -f (undocumented) force uberblock (and config including zpool cache file) 3810 * update. 3811 * 3812 * Sync the specified pool(s). 3813 * Without arguments "zpool sync" will sync all pools. 3814 * This command initiates TXG sync(s) and will return after the TXG(s) commit. 3815 * 3816 */ 3817static int 3818zpool_do_sync(int argc, char **argv) 3819{ 3820 int ret; 3821 boolean_t force = B_FALSE; 3822 3823 /* check options */ 3824 while ((ret = getopt(argc, argv, "f")) != -1) { 3825 switch (ret) { 3826 case 'f': 3827 force = B_TRUE; 3828 break; 3829 case '?': 3830 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3831 optopt); 3832 usage(B_FALSE); 3833 } 3834 } 3835 3836 argc -= optind; 3837 argv += optind; 3838 3839 /* if argc == 0 we will execute zpool_sync_one on all pools */ 3840 ret = for_each_pool(argc, argv, B_FALSE, NULL, B_FALSE, zpool_sync_one, 3841 &force); 3842 3843 return (ret); 3844} 3845 3846typedef struct iostat_cbdata { 3847 uint64_t cb_flags; 3848 int cb_name_flags; 3849 int cb_namewidth; 3850 int cb_iteration; 3851 char **cb_vdev_names; /* Only show these vdevs */ 3852 unsigned int cb_vdev_names_count; 3853 boolean_t cb_verbose; 3854 boolean_t cb_literal; 3855 boolean_t cb_scripted; 3856 zpool_list_t *cb_list; 3857 vdev_cmd_data_list_t *vcdl; 3858} iostat_cbdata_t; 3859 3860/* iostat labels */ 3861typedef struct name_and_columns { 3862 const char *name; /* Column name */ 3863 unsigned int columns; /* Center name to this number of columns */ 3864} name_and_columns_t; 3865 3866#define IOSTAT_MAX_LABELS 13 /* Max number of labels on one line */ 3867 3868static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] = 3869{ 3870 [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2}, 3871 {NULL}}, 3872 [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2}, 3873 {"asyncq_wait", 2}, {"scrub", 1}, {"trim", 1}, {NULL}}, 3874 [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2}, 3875 {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2}, 3876 {"trimq_write", 2}, {NULL}}, 3877 [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2}, 3878 {"asyncq_wait", 2}, {NULL}}, 3879 [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2}, 3880 {"async_read", 2}, {"async_write", 2}, {"scrub", 2}, 3881 {"trim", 2}, {NULL}}, 3882}; 3883 3884/* Shorthand - if "columns" field not set, default to 1 column */ 3885static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] = 3886{ 3887 [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"}, 3888 {"write"}, {NULL}}, 3889 [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"}, 3890 {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {NULL}}, 3891 [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"}, 3892 {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"}, 3893 {"pend"}, {"activ"}, {NULL}}, 3894 [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"}, 3895 {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {NULL}}, 3896 [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, 3897 {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, {NULL}}, 3898}; 3899 3900static const char *histo_to_title[] = { 3901 [IOS_L_HISTO] = "latency", 3902 [IOS_RQ_HISTO] = "req_size", 3903}; 3904 3905/* 3906 * Return the number of labels in a null-terminated name_and_columns_t 3907 * array. 3908 * 3909 */ 3910static unsigned int 3911label_array_len(const name_and_columns_t *labels) 3912{ 3913 int i = 0; 3914 3915 while (labels[i].name) 3916 i++; 3917 3918 return (i); 3919} 3920 3921/* 3922 * Return the number of strings in a null-terminated string array. 3923 * For example: 3924 * 3925 * const char foo[] = {"bar", "baz", NULL} 3926 * 3927 * returns 2 3928 */ 3929static uint64_t 3930str_array_len(const char *array[]) 3931{ 3932 uint64_t i = 0; 3933 while (array[i]) 3934 i++; 3935 3936 return (i); 3937} 3938 3939 3940/* 3941 * Return a default column width for default/latency/queue columns. This does 3942 * not include histograms, which have their columns autosized. 3943 */ 3944static unsigned int 3945default_column_width(iostat_cbdata_t *cb, enum iostat_type type) 3946{ 3947 unsigned long column_width = 5; /* Normal niceprint */ 3948 static unsigned long widths[] = { 3949 /* 3950 * Choose some sane default column sizes for printing the 3951 * raw numbers. 3952 */ 3953 [IOS_DEFAULT] = 15, /* 1PB capacity */ 3954 [IOS_LATENCY] = 10, /* 1B ns = 10sec */ 3955 [IOS_QUEUES] = 6, /* 1M queue entries */ 3956 [IOS_L_HISTO] = 10, /* 1B ns = 10sec */ 3957 [IOS_RQ_HISTO] = 6, /* 1M queue entries */ 3958 }; 3959 3960 if (cb->cb_literal) 3961 column_width = widths[type]; 3962 3963 return (column_width); 3964} 3965 3966/* 3967 * Print the column labels, i.e: 3968 * 3969 * capacity operations bandwidth 3970 * alloc free read write read write ... 3971 * 3972 * If force_column_width is set, use it for the column width. If not set, use 3973 * the default column width. 3974 */ 3975static void 3976print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width, 3977 const name_and_columns_t labels[][IOSTAT_MAX_LABELS]) 3978{ 3979 int i, idx, s; 3980 int text_start, rw_column_width, spaces_to_end; 3981 uint64_t flags = cb->cb_flags; 3982 uint64_t f; 3983 unsigned int column_width = force_column_width; 3984 3985 /* For each bit set in flags */ 3986 for (f = flags; f; f &= ~(1ULL << idx)) { 3987 idx = lowbit64(f) - 1; 3988 if (!force_column_width) 3989 column_width = default_column_width(cb, idx); 3990 /* Print our top labels centered over "read write" label. */ 3991 for (i = 0; i < label_array_len(labels[idx]); i++) { 3992 const char *name = labels[idx][i].name; 3993 /* 3994 * We treat labels[][].columns == 0 as shorthand 3995 * for one column. It makes writing out the label 3996 * tables more concise. 3997 */ 3998 unsigned int columns = MAX(1, labels[idx][i].columns); 3999 unsigned int slen = strlen(name); 4000 4001 rw_column_width = (column_width * columns) + 4002 (2 * (columns - 1)); 4003 4004 text_start = (int)((rw_column_width) / columns - 4005 slen / columns); 4006 if (text_start < 0) 4007 text_start = 0; 4008 4009 printf(" "); /* Two spaces between columns */ 4010 4011 /* Space from beginning of column to label */ 4012 for (s = 0; s < text_start; s++) 4013 printf(" "); 4014 4015 printf("%s", name); 4016 4017 /* Print space after label to end of column */ 4018 spaces_to_end = rw_column_width - text_start - slen; 4019 if (spaces_to_end < 0) 4020 spaces_to_end = 0; 4021 4022 for (s = 0; s < spaces_to_end; s++) 4023 printf(" "); 4024 } 4025 } 4026} 4027 4028 4029/* 4030 * print_cmd_columns - Print custom column titles from -c 4031 * 4032 * If the user specified the "zpool status|iostat -c" then print their custom 4033 * column titles in the header. For example, print_cmd_columns() would print 4034 * the " col1 col2" part of this: 4035 * 4036 * $ zpool iostat -vc 'echo col1=val1; echo col2=val2' 4037 * ... 4038 * capacity operations bandwidth 4039 * pool alloc free read write read write col1 col2 4040 * ---------- ----- ----- ----- ----- ----- ----- ---- ---- 4041 * mypool 269K 1008M 0 0 107 946 4042 * mirror 269K 1008M 0 0 107 946 4043 * sdb - - 0 0 102 473 val1 val2 4044 * sdc - - 0 0 5 473 val1 val2 4045 * ---------- ----- ----- ----- ----- ----- ----- ---- ---- 4046 */ 4047static void 4048print_cmd_columns(vdev_cmd_data_list_t *vcdl, int use_dashes) 4049{ 4050 int i, j; 4051 vdev_cmd_data_t *data = &vcdl->data[0]; 4052 4053 if (vcdl->count == 0 || data == NULL) 4054 return; 4055 4056 /* 4057 * Each vdev cmd should have the same column names unless the user did 4058 * something weird with their cmd. Just take the column names from the 4059 * first vdev and assume it works for all of them. 4060 */ 4061 for (i = 0; i < vcdl->uniq_cols_cnt; i++) { 4062 printf(" "); 4063 if (use_dashes) { 4064 for (j = 0; j < vcdl->uniq_cols_width[i]; j++) 4065 printf("-"); 4066 } else { 4067 printf_color(ANSI_BOLD, "%*s", vcdl->uniq_cols_width[i], 4068 vcdl->uniq_cols[i]); 4069 } 4070 } 4071} 4072 4073 4074/* 4075 * Utility function to print out a line of dashes like: 4076 * 4077 * -------------------------------- ----- ----- ----- ----- ----- 4078 * 4079 * ...or a dashed named-row line like: 4080 * 4081 * logs - - - - - 4082 * 4083 * @cb: iostat data 4084 * 4085 * @force_column_width If non-zero, use the value as the column width. 4086 * Otherwise use the default column widths. 4087 * 4088 * @name: Print a dashed named-row line starting 4089 * with @name. Otherwise, print a regular 4090 * dashed line. 4091 */ 4092static void 4093print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width, 4094 const char *name) 4095{ 4096 int i; 4097 unsigned int namewidth; 4098 uint64_t flags = cb->cb_flags; 4099 uint64_t f; 4100 int idx; 4101 const name_and_columns_t *labels; 4102 const char *title; 4103 4104 4105 if (cb->cb_flags & IOS_ANYHISTO_M) { 4106 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]; 4107 } else if (cb->cb_vdev_names_count) { 4108 title = "vdev"; 4109 } else { 4110 title = "pool"; 4111 } 4112 4113 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth), 4114 name ? strlen(name) : 0); 4115 4116 4117 if (name) { 4118 printf("%-*s", namewidth, name); 4119 } else { 4120 for (i = 0; i < namewidth; i++) 4121 (void) printf("-"); 4122 } 4123 4124 /* For each bit in flags */ 4125 for (f = flags; f; f &= ~(1ULL << idx)) { 4126 unsigned int column_width; 4127 idx = lowbit64(f) - 1; 4128 if (force_column_width) 4129 column_width = force_column_width; 4130 else 4131 column_width = default_column_width(cb, idx); 4132 4133 labels = iostat_bottom_labels[idx]; 4134 for (i = 0; i < label_array_len(labels); i++) { 4135 if (name) 4136 printf(" %*s-", column_width - 1, " "); 4137 else 4138 printf(" %.*s", column_width, 4139 "--------------------"); 4140 } 4141 } 4142} 4143 4144 4145static void 4146print_iostat_separator_impl(iostat_cbdata_t *cb, 4147 unsigned int force_column_width) 4148{ 4149 print_iostat_dashes(cb, force_column_width, NULL); 4150} 4151 4152static void 4153print_iostat_separator(iostat_cbdata_t *cb) 4154{ 4155 print_iostat_separator_impl(cb, 0); 4156} 4157 4158static void 4159print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width, 4160 const char *histo_vdev_name) 4161{ 4162 unsigned int namewidth; 4163 const char *title; 4164 4165 if (cb->cb_flags & IOS_ANYHISTO_M) { 4166 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]; 4167 } else if (cb->cb_vdev_names_count) { 4168 title = "vdev"; 4169 } else { 4170 title = "pool"; 4171 } 4172 4173 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth), 4174 histo_vdev_name ? strlen(histo_vdev_name) : 0); 4175 4176 if (histo_vdev_name) 4177 printf("%-*s", namewidth, histo_vdev_name); 4178 else 4179 printf("%*s", namewidth, ""); 4180 4181 4182 print_iostat_labels(cb, force_column_width, iostat_top_labels); 4183 printf("\n"); 4184 4185 printf("%-*s", namewidth, title); 4186 4187 print_iostat_labels(cb, force_column_width, iostat_bottom_labels); 4188 if (cb->vcdl != NULL) 4189 print_cmd_columns(cb->vcdl, 0); 4190 4191 printf("\n"); 4192 4193 print_iostat_separator_impl(cb, force_column_width); 4194 4195 if (cb->vcdl != NULL) 4196 print_cmd_columns(cb->vcdl, 1); 4197 4198 printf("\n"); 4199} 4200 4201static void 4202print_iostat_header(iostat_cbdata_t *cb) 4203{ 4204 print_iostat_header_impl(cb, 0, NULL); 4205} 4206 4207 4208/* 4209 * Display a single statistic. 4210 */ 4211static void 4212print_one_stat(uint64_t value, enum zfs_nicenum_format format, 4213 unsigned int column_size, boolean_t scripted) 4214{ 4215 char buf[64]; 4216 4217 zfs_nicenum_format(value, buf, sizeof (buf), format); 4218 4219 if (scripted) 4220 printf("\t%s", buf); 4221 else 4222 printf(" %*s", column_size, buf); 4223} 4224 4225/* 4226 * Calculate the default vdev stats 4227 * 4228 * Subtract oldvs from newvs, apply a scaling factor, and save the resulting 4229 * stats into calcvs. 4230 */ 4231static void 4232calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs, 4233 vdev_stat_t *calcvs) 4234{ 4235 int i; 4236 4237 memcpy(calcvs, newvs, sizeof (*calcvs)); 4238 for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++) 4239 calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]); 4240 4241 for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++) 4242 calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]); 4243} 4244 4245/* 4246 * Internal representation of the extended iostats data. 4247 * 4248 * The extended iostat stats are exported in nvlists as either uint64_t arrays 4249 * or single uint64_t's. We make both look like arrays to make them easier 4250 * to process. In order to make single uint64_t's look like arrays, we set 4251 * __data to the stat data, and then set *data = &__data with count = 1. Then, 4252 * we can just use *data and count. 4253 */ 4254struct stat_array { 4255 uint64_t *data; 4256 uint_t count; /* Number of entries in data[] */ 4257 uint64_t __data; /* Only used when data is a single uint64_t */ 4258}; 4259 4260static uint64_t 4261stat_histo_max(struct stat_array *nva, unsigned int len) 4262{ 4263 uint64_t max = 0; 4264 int i; 4265 for (i = 0; i < len; i++) 4266 max = MAX(max, array64_max(nva[i].data, nva[i].count)); 4267 4268 return (max); 4269} 4270 4271/* 4272 * Helper function to lookup a uint64_t array or uint64_t value and store its 4273 * data as a stat_array. If the nvpair is a single uint64_t value, then we make 4274 * it look like a one element array to make it easier to process. 4275 */ 4276static int 4277nvpair64_to_stat_array(nvlist_t *nvl, const char *name, 4278 struct stat_array *nva) 4279{ 4280 nvpair_t *tmp; 4281 int ret; 4282 4283 verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0); 4284 switch (nvpair_type(tmp)) { 4285 case DATA_TYPE_UINT64_ARRAY: 4286 ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count); 4287 break; 4288 case DATA_TYPE_UINT64: 4289 ret = nvpair_value_uint64(tmp, &nva->__data); 4290 nva->data = &nva->__data; 4291 nva->count = 1; 4292 break; 4293 default: 4294 /* Not a uint64_t */ 4295 ret = EINVAL; 4296 break; 4297 } 4298 4299 return (ret); 4300} 4301 4302/* 4303 * Given a list of nvlist names, look up the extended stats in newnv and oldnv, 4304 * subtract them, and return the results in a newly allocated stat_array. 4305 * You must free the returned array after you are done with it with 4306 * free_calc_stats(). 4307 * 4308 * Additionally, you can set "oldnv" to NULL if you simply want the newnv 4309 * values. 4310 */ 4311static struct stat_array * 4312calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv, 4313 nvlist_t *newnv) 4314{ 4315 nvlist_t *oldnvx = NULL, *newnvx; 4316 struct stat_array *oldnva, *newnva, *calcnva; 4317 int i, j; 4318 unsigned int alloc_size = (sizeof (struct stat_array)) * len; 4319 4320 /* Extract our extended stats nvlist from the main list */ 4321 verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX, 4322 &newnvx) == 0); 4323 if (oldnv) { 4324 verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX, 4325 &oldnvx) == 0); 4326 } 4327 4328 newnva = safe_malloc(alloc_size); 4329 oldnva = safe_malloc(alloc_size); 4330 calcnva = safe_malloc(alloc_size); 4331 4332 for (j = 0; j < len; j++) { 4333 verify(nvpair64_to_stat_array(newnvx, names[j], 4334 &newnva[j]) == 0); 4335 calcnva[j].count = newnva[j].count; 4336 alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]); 4337 calcnva[j].data = safe_malloc(alloc_size); 4338 memcpy(calcnva[j].data, newnva[j].data, alloc_size); 4339 4340 if (oldnvx) { 4341 verify(nvpair64_to_stat_array(oldnvx, names[j], 4342 &oldnva[j]) == 0); 4343 for (i = 0; i < oldnva[j].count; i++) 4344 calcnva[j].data[i] -= oldnva[j].data[i]; 4345 } 4346 } 4347 free(newnva); 4348 free(oldnva); 4349 return (calcnva); 4350} 4351 4352static void 4353free_calc_stats(struct stat_array *nva, unsigned int len) 4354{ 4355 int i; 4356 for (i = 0; i < len; i++) 4357 free(nva[i].data); 4358 4359 free(nva); 4360} 4361 4362static void 4363print_iostat_histo(struct stat_array *nva, unsigned int len, 4364 iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth, 4365 double scale) 4366{ 4367 int i, j; 4368 char buf[6]; 4369 uint64_t val; 4370 enum zfs_nicenum_format format; 4371 unsigned int buckets; 4372 unsigned int start_bucket; 4373 4374 if (cb->cb_literal) 4375 format = ZFS_NICENUM_RAW; 4376 else 4377 format = ZFS_NICENUM_1024; 4378 4379 /* All these histos are the same size, so just use nva[0].count */ 4380 buckets = nva[0].count; 4381 4382 if (cb->cb_flags & IOS_RQ_HISTO_M) { 4383 /* Start at 512 - req size should never be lower than this */ 4384 start_bucket = 9; 4385 } else { 4386 start_bucket = 0; 4387 } 4388 4389 for (j = start_bucket; j < buckets; j++) { 4390 /* Print histogram bucket label */ 4391 if (cb->cb_flags & IOS_L_HISTO_M) { 4392 /* Ending range of this bucket */ 4393 val = (1UL << (j + 1)) - 1; 4394 zfs_nicetime(val, buf, sizeof (buf)); 4395 } else { 4396 /* Request size (starting range of bucket) */ 4397 val = (1UL << j); 4398 zfs_nicenum(val, buf, sizeof (buf)); 4399 } 4400 4401 if (cb->cb_scripted) 4402 printf("%llu", (u_longlong_t)val); 4403 else 4404 printf("%-*s", namewidth, buf); 4405 4406 /* Print the values on the line */ 4407 for (i = 0; i < len; i++) { 4408 print_one_stat(nva[i].data[j] * scale, format, 4409 column_width, cb->cb_scripted); 4410 } 4411 printf("\n"); 4412 } 4413} 4414 4415static void 4416print_solid_separator(unsigned int length) 4417{ 4418 while (length--) 4419 printf("-"); 4420 printf("\n"); 4421} 4422 4423static void 4424print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv, 4425 nvlist_t *newnv, double scale, const char *name) 4426{ 4427 unsigned int column_width; 4428 unsigned int namewidth; 4429 unsigned int entire_width; 4430 enum iostat_type type; 4431 struct stat_array *nva; 4432 const char **names; 4433 unsigned int names_len; 4434 4435 /* What type of histo are we? */ 4436 type = IOS_HISTO_IDX(cb->cb_flags); 4437 4438 /* Get NULL-terminated array of nvlist names for our histo */ 4439 names = vsx_type_to_nvlist[type]; 4440 names_len = str_array_len(names); /* num of names */ 4441 4442 nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv); 4443 4444 if (cb->cb_literal) { 4445 column_width = MAX(5, 4446 (unsigned int) log10(stat_histo_max(nva, names_len)) + 1); 4447 } else { 4448 column_width = 5; 4449 } 4450 4451 namewidth = MAX(cb->cb_namewidth, 4452 strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)])); 4453 4454 /* 4455 * Calculate the entire line width of what we're printing. The 4456 * +2 is for the two spaces between columns: 4457 */ 4458 /* read write */ 4459 /* ----- ----- */ 4460 /* |___| <---------- column_width */ 4461 /* */ 4462 /* |__________| <--- entire_width */ 4463 /* */ 4464 entire_width = namewidth + (column_width + 2) * 4465 label_array_len(iostat_bottom_labels[type]); 4466 4467 if (cb->cb_scripted) 4468 printf("%s\n", name); 4469 else 4470 print_iostat_header_impl(cb, column_width, name); 4471 4472 print_iostat_histo(nva, names_len, cb, column_width, 4473 namewidth, scale); 4474 4475 free_calc_stats(nva, names_len); 4476 if (!cb->cb_scripted) 4477 print_solid_separator(entire_width); 4478} 4479 4480/* 4481 * Calculate the average latency of a power-of-two latency histogram 4482 */ 4483static uint64_t 4484single_histo_average(uint64_t *histo, unsigned int buckets) 4485{ 4486 int i; 4487 uint64_t count = 0, total = 0; 4488 4489 for (i = 0; i < buckets; i++) { 4490 /* 4491 * Our buckets are power-of-two latency ranges. Use the 4492 * midpoint latency of each bucket to calculate the average. 4493 * For example: 4494 * 4495 * Bucket Midpoint 4496 * 8ns-15ns: 12ns 4497 * 16ns-31ns: 24ns 4498 * ... 4499 */ 4500 if (histo[i] != 0) { 4501 total += histo[i] * (((1UL << i) + ((1UL << i)/2))); 4502 count += histo[i]; 4503 } 4504 } 4505 4506 /* Prevent divide by zero */ 4507 return (count == 0 ? 0 : total / count); 4508} 4509 4510static void 4511print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *oldnv, 4512 nvlist_t *newnv) 4513{ 4514 int i; 4515 uint64_t val; 4516 const char *names[] = { 4517 ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE, 4518 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE, 4519 ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE, 4520 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE, 4521 ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE, 4522 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE, 4523 ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE, 4524 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE, 4525 ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE, 4526 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE, 4527 ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE, 4528 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE, 4529 }; 4530 4531 struct stat_array *nva; 4532 4533 unsigned int column_width = default_column_width(cb, IOS_QUEUES); 4534 enum zfs_nicenum_format format; 4535 4536 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv); 4537 4538 if (cb->cb_literal) 4539 format = ZFS_NICENUM_RAW; 4540 else 4541 format = ZFS_NICENUM_1024; 4542 4543 for (i = 0; i < ARRAY_SIZE(names); i++) { 4544 val = nva[i].data[0]; 4545 print_one_stat(val, format, column_width, cb->cb_scripted); 4546 } 4547 4548 free_calc_stats(nva, ARRAY_SIZE(names)); 4549} 4550 4551static void 4552print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv, 4553 nvlist_t *newnv) 4554{ 4555 int i; 4556 uint64_t val; 4557 const char *names[] = { 4558 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO, 4559 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO, 4560 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO, 4561 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO, 4562 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO, 4563 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO, 4564 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO, 4565 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO, 4566 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO, 4567 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO, 4568 }; 4569 struct stat_array *nva; 4570 4571 unsigned int column_width = default_column_width(cb, IOS_LATENCY); 4572 enum zfs_nicenum_format format; 4573 4574 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv); 4575 4576 if (cb->cb_literal) 4577 format = ZFS_NICENUM_RAWTIME; 4578 else 4579 format = ZFS_NICENUM_TIME; 4580 4581 /* Print our avg latencies on the line */ 4582 for (i = 0; i < ARRAY_SIZE(names); i++) { 4583 /* Compute average latency for a latency histo */ 4584 val = single_histo_average(nva[i].data, nva[i].count); 4585 print_one_stat(val, format, column_width, cb->cb_scripted); 4586 } 4587 free_calc_stats(nva, ARRAY_SIZE(names)); 4588} 4589 4590/* 4591 * Print default statistics (capacity/operations/bandwidth) 4592 */ 4593static void 4594print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale) 4595{ 4596 unsigned int column_width = default_column_width(cb, IOS_DEFAULT); 4597 enum zfs_nicenum_format format; 4598 char na; /* char to print for "not applicable" values */ 4599 4600 if (cb->cb_literal) { 4601 format = ZFS_NICENUM_RAW; 4602 na = '0'; 4603 } else { 4604 format = ZFS_NICENUM_1024; 4605 na = '-'; 4606 } 4607 4608 /* only toplevel vdevs have capacity stats */ 4609 if (vs->vs_space == 0) { 4610 if (cb->cb_scripted) 4611 printf("\t%c\t%c", na, na); 4612 else 4613 printf(" %*c %*c", column_width, na, column_width, 4614 na); 4615 } else { 4616 print_one_stat(vs->vs_alloc, format, column_width, 4617 cb->cb_scripted); 4618 print_one_stat(vs->vs_space - vs->vs_alloc, format, 4619 column_width, cb->cb_scripted); 4620 } 4621 4622 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale), 4623 format, column_width, cb->cb_scripted); 4624 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale), 4625 format, column_width, cb->cb_scripted); 4626 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale), 4627 format, column_width, cb->cb_scripted); 4628 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale), 4629 format, column_width, cb->cb_scripted); 4630} 4631 4632static const char *class_name[] = { 4633 VDEV_ALLOC_BIAS_DEDUP, 4634 VDEV_ALLOC_BIAS_SPECIAL, 4635 VDEV_ALLOC_CLASS_LOGS 4636}; 4637 4638/* 4639 * Print out all the statistics for the given vdev. This can either be the 4640 * toplevel configuration, or called recursively. If 'name' is NULL, then this 4641 * is a verbose output, and we don't want to display the toplevel pool stats. 4642 * 4643 * Returns the number of stat lines printed. 4644 */ 4645static unsigned int 4646print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 4647 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 4648{ 4649 nvlist_t **oldchild, **newchild; 4650 uint_t c, children, oldchildren; 4651 vdev_stat_t *oldvs, *newvs, *calcvs; 4652 vdev_stat_t zerovs = { 0 }; 4653 char *vname; 4654 int i; 4655 int ret = 0; 4656 uint64_t tdelta; 4657 double scale; 4658 4659 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 4660 return (ret); 4661 4662 calcvs = safe_malloc(sizeof (*calcvs)); 4663 4664 if (oldnv != NULL) { 4665 verify(nvlist_lookup_uint64_array(oldnv, 4666 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 4667 } else { 4668 oldvs = &zerovs; 4669 } 4670 4671 /* Do we only want to see a specific vdev? */ 4672 for (i = 0; i < cb->cb_vdev_names_count; i++) { 4673 /* Yes we do. Is this the vdev? */ 4674 if (strcmp(name, cb->cb_vdev_names[i]) == 0) { 4675 /* 4676 * This is our vdev. Since it is the only vdev we 4677 * will be displaying, make depth = 0 so that it 4678 * doesn't get indented. 4679 */ 4680 depth = 0; 4681 break; 4682 } 4683 } 4684 4685 if (cb->cb_vdev_names_count && (i == cb->cb_vdev_names_count)) { 4686 /* Couldn't match the name */ 4687 goto children; 4688 } 4689 4690 4691 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 4692 (uint64_t **)&newvs, &c) == 0); 4693 4694 /* 4695 * Print the vdev name unless it's is a histogram. Histograms 4696 * display the vdev name in the header itself. 4697 */ 4698 if (!(cb->cb_flags & IOS_ANYHISTO_M)) { 4699 if (cb->cb_scripted) { 4700 printf("%s", name); 4701 } else { 4702 if (strlen(name) + depth > cb->cb_namewidth) 4703 (void) printf("%*s%s", depth, "", name); 4704 else 4705 (void) printf("%*s%s%*s", depth, "", name, 4706 (int)(cb->cb_namewidth - strlen(name) - 4707 depth), ""); 4708 } 4709 } 4710 4711 /* Calculate our scaling factor */ 4712 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 4713 if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) { 4714 /* 4715 * If we specify printing histograms with no time interval, then 4716 * print the histogram numbers over the entire lifetime of the 4717 * vdev. 4718 */ 4719 scale = 1; 4720 } else { 4721 if (tdelta == 0) 4722 scale = 1.0; 4723 else 4724 scale = (double)NANOSEC / tdelta; 4725 } 4726 4727 if (cb->cb_flags & IOS_DEFAULT_M) { 4728 calc_default_iostats(oldvs, newvs, calcvs); 4729 print_iostat_default(calcvs, cb, scale); 4730 } 4731 if (cb->cb_flags & IOS_LATENCY_M) 4732 print_iostat_latency(cb, oldnv, newnv); 4733 if (cb->cb_flags & IOS_QUEUES_M) 4734 print_iostat_queues(cb, oldnv, newnv); 4735 if (cb->cb_flags & IOS_ANYHISTO_M) { 4736 printf("\n"); 4737 print_iostat_histos(cb, oldnv, newnv, scale, name); 4738 } 4739 4740 if (cb->vcdl != NULL) { 4741 char *path; 4742 if (nvlist_lookup_string(newnv, ZPOOL_CONFIG_PATH, 4743 &path) == 0) { 4744 printf(" "); 4745 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path); 4746 } 4747 } 4748 4749 if (!(cb->cb_flags & IOS_ANYHISTO_M)) 4750 printf("\n"); 4751 4752 ret++; 4753 4754children: 4755 4756 free(calcvs); 4757 4758 if (!cb->cb_verbose) 4759 return (ret); 4760 4761 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 4762 &newchild, &children) != 0) 4763 return (ret); 4764 4765 if (oldnv) { 4766 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 4767 &oldchild, &oldchildren) != 0) 4768 return (ret); 4769 4770 children = MIN(oldchildren, children); 4771 } 4772 4773 /* 4774 * print normal top-level devices 4775 */ 4776 for (c = 0; c < children; c++) { 4777 uint64_t ishole = B_FALSE, islog = B_FALSE; 4778 4779 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 4780 &ishole); 4781 4782 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 4783 &islog); 4784 4785 if (ishole || islog) 4786 continue; 4787 4788 if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 4789 continue; 4790 4791 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 4792 cb->cb_name_flags); 4793 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 4794 newchild[c], cb, depth + 2); 4795 free(vname); 4796 } 4797 4798 /* 4799 * print all other top-level devices 4800 */ 4801 for (uint_t n = 0; n < 3; n++) { 4802 boolean_t printed = B_FALSE; 4803 4804 for (c = 0; c < children; c++) { 4805 uint64_t islog = B_FALSE; 4806 char *bias = NULL; 4807 char *type = NULL; 4808 4809 (void) nvlist_lookup_uint64(newchild[c], 4810 ZPOOL_CONFIG_IS_LOG, &islog); 4811 if (islog) { 4812 bias = VDEV_ALLOC_CLASS_LOGS; 4813 } else { 4814 (void) nvlist_lookup_string(newchild[c], 4815 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 4816 (void) nvlist_lookup_string(newchild[c], 4817 ZPOOL_CONFIG_TYPE, &type); 4818 } 4819 if (bias == NULL || strcmp(bias, class_name[n]) != 0) 4820 continue; 4821 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 4822 continue; 4823 4824 if (!printed) { 4825 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && 4826 !cb->cb_scripted && !cb->cb_vdev_names) { 4827 print_iostat_dashes(cb, 0, 4828 class_name[n]); 4829 } 4830 printf("\n"); 4831 printed = B_TRUE; 4832 } 4833 4834 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 4835 cb->cb_name_flags); 4836 ret += print_vdev_stats(zhp, vname, oldnv ? 4837 oldchild[c] : NULL, newchild[c], cb, depth + 2); 4838 free(vname); 4839 } 4840 } 4841 4842 /* 4843 * Include level 2 ARC devices in iostat output 4844 */ 4845 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 4846 &newchild, &children) != 0) 4847 return (ret); 4848 4849 if (oldnv) { 4850 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 4851 &oldchild, &oldchildren) != 0) 4852 return (ret); 4853 4854 children = MIN(oldchildren, children); 4855 } 4856 4857 if (children > 0) { 4858 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted && 4859 !cb->cb_vdev_names) { 4860 print_iostat_dashes(cb, 0, "cache"); 4861 } 4862 printf("\n"); 4863 4864 for (c = 0; c < children; c++) { 4865 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 4866 cb->cb_name_flags); 4867 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] 4868 : NULL, newchild[c], cb, depth + 2); 4869 free(vname); 4870 } 4871 } 4872 4873 return (ret); 4874} 4875 4876static int 4877refresh_iostat(zpool_handle_t *zhp, void *data) 4878{ 4879 iostat_cbdata_t *cb = data; 4880 boolean_t missing; 4881 4882 /* 4883 * If the pool has disappeared, remove it from the list and continue. 4884 */ 4885 if (zpool_refresh_stats(zhp, &missing) != 0) 4886 return (-1); 4887 4888 if (missing) 4889 pool_list_remove(cb->cb_list, zhp); 4890 4891 return (0); 4892} 4893 4894/* 4895 * Callback to print out the iostats for the given pool. 4896 */ 4897static int 4898print_iostat(zpool_handle_t *zhp, void *data) 4899{ 4900 iostat_cbdata_t *cb = data; 4901 nvlist_t *oldconfig, *newconfig; 4902 nvlist_t *oldnvroot, *newnvroot; 4903 int ret; 4904 4905 newconfig = zpool_get_config(zhp, &oldconfig); 4906 4907 if (cb->cb_iteration == 1) 4908 oldconfig = NULL; 4909 4910 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 4911 &newnvroot) == 0); 4912 4913 if (oldconfig == NULL) 4914 oldnvroot = NULL; 4915 else 4916 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 4917 &oldnvroot) == 0); 4918 4919 ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, 4920 cb, 0); 4921 if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) && 4922 !cb->cb_scripted && cb->cb_verbose && !cb->cb_vdev_names_count) { 4923 print_iostat_separator(cb); 4924 if (cb->vcdl != NULL) { 4925 print_cmd_columns(cb->vcdl, 1); 4926 } 4927 printf("\n"); 4928 } 4929 4930 return (ret); 4931} 4932 4933static int 4934get_columns(void) 4935{ 4936 struct winsize ws; 4937 int columns = 80; 4938 int error; 4939 4940 if (isatty(STDOUT_FILENO)) { 4941 error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); 4942 if (error == 0) 4943 columns = ws.ws_col; 4944 } else { 4945 columns = 999; 4946 } 4947 4948 return (columns); 4949} 4950 4951/* 4952 * Return the required length of the pool/vdev name column. The minimum 4953 * allowed width and output formatting flags must be provided. 4954 */ 4955static int 4956get_namewidth(zpool_handle_t *zhp, int min_width, int flags, boolean_t verbose) 4957{ 4958 nvlist_t *config, *nvroot; 4959 int width = min_width; 4960 4961 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 4962 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4963 &nvroot) == 0); 4964 unsigned int poolname_len = strlen(zpool_get_name(zhp)); 4965 if (verbose == B_FALSE) { 4966 width = MAX(poolname_len, min_width); 4967 } else { 4968 width = MAX(poolname_len, 4969 max_width(zhp, nvroot, 0, min_width, flags)); 4970 } 4971 } 4972 4973 return (width); 4974} 4975 4976/* 4977 * Parse the input string, get the 'interval' and 'count' value if there is one. 4978 */ 4979static void 4980get_interval_count(int *argcp, char **argv, float *iv, 4981 unsigned long *cnt) 4982{ 4983 float interval = 0; 4984 unsigned long count = 0; 4985 int argc = *argcp; 4986 4987 /* 4988 * Determine if the last argument is an integer or a pool name 4989 */ 4990 if (argc > 0 && zfs_isnumber(argv[argc - 1])) { 4991 char *end; 4992 4993 errno = 0; 4994 interval = strtof(argv[argc - 1], &end); 4995 4996 if (*end == '\0' && errno == 0) { 4997 if (interval == 0) { 4998 (void) fprintf(stderr, gettext( 4999 "interval cannot be zero\n")); 5000 usage(B_FALSE); 5001 } 5002 /* 5003 * Ignore the last parameter 5004 */ 5005 argc--; 5006 } else { 5007 /* 5008 * If this is not a valid number, just plow on. The 5009 * user will get a more informative error message later 5010 * on. 5011 */ 5012 interval = 0; 5013 } 5014 } 5015 5016 /* 5017 * If the last argument is also an integer, then we have both a count 5018 * and an interval. 5019 */ 5020 if (argc > 0 && zfs_isnumber(argv[argc - 1])) { 5021 char *end; 5022 5023 errno = 0; 5024 count = interval; 5025 interval = strtof(argv[argc - 1], &end); 5026 5027 if (*end == '\0' && errno == 0) { 5028 if (interval == 0) { 5029 (void) fprintf(stderr, gettext( 5030 "interval cannot be zero\n")); 5031 usage(B_FALSE); 5032 } 5033 5034 /* 5035 * Ignore the last parameter 5036 */ 5037 argc--; 5038 } else { 5039 interval = 0; 5040 } 5041 } 5042 5043 *iv = interval; 5044 *cnt = count; 5045 *argcp = argc; 5046} 5047 5048static void 5049get_timestamp_arg(char c) 5050{ 5051 if (c == 'u') 5052 timestamp_fmt = UDATE; 5053 else if (c == 'd') 5054 timestamp_fmt = DDATE; 5055 else 5056 usage(B_FALSE); 5057} 5058 5059/* 5060 * Return stat flags that are supported by all pools by both the module and 5061 * zpool iostat. "*data" should be initialized to all 0xFFs before running. 5062 * It will get ANDed down until only the flags that are supported on all pools 5063 * remain. 5064 */ 5065static int 5066get_stat_flags_cb(zpool_handle_t *zhp, void *data) 5067{ 5068 uint64_t *mask = data; 5069 nvlist_t *config, *nvroot, *nvx; 5070 uint64_t flags = 0; 5071 int i, j; 5072 5073 config = zpool_get_config(zhp, NULL); 5074 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 5075 &nvroot) == 0); 5076 5077 /* Default stats are always supported, but for completeness.. */ 5078 if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS)) 5079 flags |= IOS_DEFAULT_M; 5080 5081 /* Get our extended stats nvlist from the main list */ 5082 if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX, 5083 &nvx) != 0) { 5084 /* 5085 * No extended stats; they're probably running an older 5086 * module. No big deal, we support that too. 5087 */ 5088 goto end; 5089 } 5090 5091 /* For each extended stat, make sure all its nvpairs are supported */ 5092 for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) { 5093 if (!vsx_type_to_nvlist[j][0]) 5094 continue; 5095 5096 /* Start off by assuming the flag is supported, then check */ 5097 flags |= (1ULL << j); 5098 for (i = 0; vsx_type_to_nvlist[j][i]; i++) { 5099 if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) { 5100 /* flag isn't supported */ 5101 flags = flags & ~(1ULL << j); 5102 break; 5103 } 5104 } 5105 } 5106end: 5107 *mask = *mask & flags; 5108 return (0); 5109} 5110 5111/* 5112 * Return a bitmask of stats that are supported on all pools by both the module 5113 * and zpool iostat. 5114 */ 5115static uint64_t 5116get_stat_flags(zpool_list_t *list) 5117{ 5118 uint64_t mask = -1; 5119 5120 /* 5121 * get_stat_flags_cb() will lop off bits from "mask" until only the 5122 * flags that are supported on all pools remain. 5123 */ 5124 pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask); 5125 return (mask); 5126} 5127 5128/* 5129 * Return 1 if cb_data->cb_vdev_names[0] is this vdev's name, 0 otherwise. 5130 */ 5131static int 5132is_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_data) 5133{ 5134 iostat_cbdata_t *cb = cb_data; 5135 char *name = NULL; 5136 int ret = 0; 5137 5138 name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags); 5139 5140 if (strcmp(name, cb->cb_vdev_names[0]) == 0) 5141 ret = 1; /* match */ 5142 free(name); 5143 5144 return (ret); 5145} 5146 5147/* 5148 * Returns 1 if cb_data->cb_vdev_names[0] is a vdev name, 0 otherwise. 5149 */ 5150static int 5151is_vdev(zpool_handle_t *zhp, void *cb_data) 5152{ 5153 return (for_each_vdev(zhp, is_vdev_cb, cb_data)); 5154} 5155 5156/* 5157 * Check if vdevs are in a pool 5158 * 5159 * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise 5160 * return 0. If pool_name is NULL, then search all pools. 5161 */ 5162static int 5163are_vdevs_in_pool(int argc, char **argv, char *pool_name, 5164 iostat_cbdata_t *cb) 5165{ 5166 char **tmp_name; 5167 int ret = 0; 5168 int i; 5169 int pool_count = 0; 5170 5171 if ((argc == 0) || !*argv) 5172 return (0); 5173 5174 if (pool_name) 5175 pool_count = 1; 5176 5177 /* Temporarily hijack cb_vdev_names for a second... */ 5178 tmp_name = cb->cb_vdev_names; 5179 5180 /* Go though our list of prospective vdev names */ 5181 for (i = 0; i < argc; i++) { 5182 cb->cb_vdev_names = argv + i; 5183 5184 /* Is this name a vdev in our pools? */ 5185 ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL, 5186 B_FALSE, is_vdev, cb); 5187 if (!ret) { 5188 /* No match */ 5189 break; 5190 } 5191 } 5192 5193 cb->cb_vdev_names = tmp_name; 5194 5195 return (ret); 5196} 5197 5198static int 5199is_pool_cb(zpool_handle_t *zhp, void *data) 5200{ 5201 char *name = data; 5202 if (strcmp(name, zpool_get_name(zhp)) == 0) 5203 return (1); 5204 5205 return (0); 5206} 5207 5208/* 5209 * Do we have a pool named *name? If so, return 1, otherwise 0. 5210 */ 5211static int 5212is_pool(char *name) 5213{ 5214 return (for_each_pool(0, NULL, B_TRUE, NULL, B_FALSE, is_pool_cb, 5215 name)); 5216} 5217 5218/* Are all our argv[] strings pool names? If so return 1, 0 otherwise. */ 5219static int 5220are_all_pools(int argc, char **argv) 5221{ 5222 if ((argc == 0) || !*argv) 5223 return (0); 5224 5225 while (--argc >= 0) 5226 if (!is_pool(argv[argc])) 5227 return (0); 5228 5229 return (1); 5230} 5231 5232/* 5233 * Helper function to print out vdev/pool names we can't resolve. Used for an 5234 * error message. 5235 */ 5236static void 5237error_list_unresolved_vdevs(int argc, char **argv, char *pool_name, 5238 iostat_cbdata_t *cb) 5239{ 5240 int i; 5241 char *name; 5242 char *str; 5243 for (i = 0; i < argc; i++) { 5244 name = argv[i]; 5245 5246 if (is_pool(name)) 5247 str = gettext("pool"); 5248 else if (are_vdevs_in_pool(1, &name, pool_name, cb)) 5249 str = gettext("vdev in this pool"); 5250 else if (are_vdevs_in_pool(1, &name, NULL, cb)) 5251 str = gettext("vdev in another pool"); 5252 else 5253 str = gettext("unknown"); 5254 5255 fprintf(stderr, "\t%s (%s)\n", name, str); 5256 } 5257} 5258 5259/* 5260 * Same as get_interval_count(), but with additional checks to not misinterpret 5261 * guids as interval/count values. Assumes VDEV_NAME_GUID is set in 5262 * cb.cb_name_flags. 5263 */ 5264static void 5265get_interval_count_filter_guids(int *argc, char **argv, float *interval, 5266 unsigned long *count, iostat_cbdata_t *cb) 5267{ 5268 char **tmpargv = argv; 5269 int argc_for_interval = 0; 5270 5271 /* Is the last arg an interval value? Or a guid? */ 5272 if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL, cb)) { 5273 /* 5274 * The last arg is not a guid, so it's probably an 5275 * interval value. 5276 */ 5277 argc_for_interval++; 5278 5279 if (*argc >= 2 && 5280 !are_vdevs_in_pool(1, &argv[*argc - 2], NULL, cb)) { 5281 /* 5282 * The 2nd to last arg is not a guid, so it's probably 5283 * an interval value. 5284 */ 5285 argc_for_interval++; 5286 } 5287 } 5288 5289 /* Point to our list of possible intervals */ 5290 tmpargv = &argv[*argc - argc_for_interval]; 5291 5292 *argc = *argc - argc_for_interval; 5293 get_interval_count(&argc_for_interval, tmpargv, 5294 interval, count); 5295} 5296 5297/* 5298 * Floating point sleep(). Allows you to pass in a floating point value for 5299 * seconds. 5300 */ 5301static void 5302fsleep(float sec) 5303{ 5304 struct timespec req; 5305 req.tv_sec = floor(sec); 5306 req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC; 5307 nanosleep(&req, NULL); 5308} 5309 5310/* 5311 * Terminal height, in rows. Returns -1 if stdout is not connected to a TTY or 5312 * if we were unable to determine its size. 5313 */ 5314static int 5315terminal_height(void) 5316{ 5317 struct winsize win; 5318 5319 if (isatty(STDOUT_FILENO) == 0) 5320 return (-1); 5321 5322 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1 && win.ws_row > 0) 5323 return (win.ws_row); 5324 5325 return (-1); 5326} 5327 5328/* 5329 * Run one of the zpool status/iostat -c scripts with the help (-h) option and 5330 * print the result. 5331 * 5332 * name: Short name of the script ('iostat'). 5333 * path: Full path to the script ('/usr/local/etc/zfs/zpool.d/iostat'); 5334 */ 5335static void 5336print_zpool_script_help(char *name, char *path) 5337{ 5338 char *argv[] = {path, "-h", NULL}; 5339 char **lines = NULL; 5340 int lines_cnt = 0; 5341 int rc; 5342 5343 rc = libzfs_run_process_get_stdout_nopath(path, argv, NULL, &lines, 5344 &lines_cnt); 5345 if (rc != 0 || lines == NULL || lines_cnt <= 0) { 5346 if (lines != NULL) 5347 libzfs_free_str_array(lines, lines_cnt); 5348 return; 5349 } 5350 5351 for (int i = 0; i < lines_cnt; i++) 5352 if (!is_blank_str(lines[i])) 5353 printf(" %-14s %s\n", name, lines[i]); 5354 5355 libzfs_free_str_array(lines, lines_cnt); 5356} 5357 5358/* 5359 * Go though the zpool status/iostat -c scripts in the user's path, run their 5360 * help option (-h), and print out the results. 5361 */ 5362static void 5363print_zpool_dir_scripts(char *dirpath) 5364{ 5365 DIR *dir; 5366 struct dirent *ent; 5367 char fullpath[MAXPATHLEN]; 5368 struct stat dir_stat; 5369 5370 if ((dir = opendir(dirpath)) != NULL) { 5371 /* print all the files and directories within directory */ 5372 while ((ent = readdir(dir)) != NULL) { 5373 sprintf(fullpath, "%s/%s", dirpath, ent->d_name); 5374 5375 /* Print the scripts */ 5376 if (stat(fullpath, &dir_stat) == 0) 5377 if (dir_stat.st_mode & S_IXUSR && 5378 S_ISREG(dir_stat.st_mode)) 5379 print_zpool_script_help(ent->d_name, 5380 fullpath); 5381 } 5382 closedir(dir); 5383 } 5384} 5385 5386/* 5387 * Print out help text for all zpool status/iostat -c scripts. 5388 */ 5389static void 5390print_zpool_script_list(char *subcommand) 5391{ 5392 char *dir, *sp; 5393 5394 printf(gettext("Available 'zpool %s -c' commands:\n"), subcommand); 5395 5396 sp = zpool_get_cmd_search_path(); 5397 if (sp == NULL) 5398 return; 5399 5400 dir = strtok(sp, ":"); 5401 while (dir != NULL) { 5402 print_zpool_dir_scripts(dir); 5403 dir = strtok(NULL, ":"); 5404 } 5405 5406 free(sp); 5407} 5408 5409/* 5410 * Set the minimum pool/vdev name column width. The width must be at least 10, 5411 * but may be as large as the column width - 42 so it still fits on one line. 5412 * NOTE: 42 is the width of the default capacity/operations/bandwidth output 5413 */ 5414static int 5415get_namewidth_iostat(zpool_handle_t *zhp, void *data) 5416{ 5417 iostat_cbdata_t *cb = data; 5418 int width, available_width; 5419 5420 /* 5421 * get_namewidth() returns the maximum width of any name in that column 5422 * for any pool/vdev/device line that will be output. 5423 */ 5424 width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags, 5425 cb->cb_verbose); 5426 5427 /* 5428 * The width we are calculating is the width of the header and also the 5429 * padding width for names that are less than maximum width. The stats 5430 * take up 42 characters, so the width available for names is: 5431 */ 5432 available_width = get_columns() - 42; 5433 5434 /* 5435 * If the maximum width fits on a screen, then great! Make everything 5436 * line up by justifying all lines to the same width. If that max 5437 * width is larger than what's available, the name plus stats won't fit 5438 * on one line, and justifying to that width would cause every line to 5439 * wrap on the screen. We only want lines with long names to wrap. 5440 * Limit the padding to what won't wrap. 5441 */ 5442 if (width > available_width) 5443 width = available_width; 5444 5445 /* 5446 * And regardless of whatever the screen width is (get_columns can 5447 * return 0 if the width is not known or less than 42 for a narrow 5448 * terminal) have the width be a minimum of 10. 5449 */ 5450 if (width < 10) 5451 width = 10; 5452 5453 /* Save the calculated width */ 5454 cb->cb_namewidth = width; 5455 5456 return (0); 5457} 5458 5459/* 5460 * zpool iostat [[-c [script1,script2,...]] [-lq]|[-rw]] [-ghHLpPvy] [-n name] 5461 * [-T d|u] [[ pool ...]|[pool vdev ...]|[vdev ...]] 5462 * [interval [count]] 5463 * 5464 * -c CMD For each vdev, run command CMD 5465 * -g Display guid for individual vdev name. 5466 * -L Follow links when resolving vdev path name. 5467 * -P Display full path for vdev name. 5468 * -v Display statistics for individual vdevs 5469 * -h Display help 5470 * -p Display values in parsable (exact) format. 5471 * -H Scripted mode. Don't display headers, and separate properties 5472 * by a single tab. 5473 * -l Display average latency 5474 * -q Display queue depths 5475 * -w Display latency histograms 5476 * -r Display request size histogram 5477 * -T Display a timestamp in date(1) or Unix format 5478 * -n Only print headers once 5479 * 5480 * This command can be tricky because we want to be able to deal with pool 5481 * creation/destruction as well as vdev configuration changes. The bulk of this 5482 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 5483 * on pool_list_update() to detect the addition of new pools. Configuration 5484 * changes are all handled within libzfs. 5485 */ 5486int 5487zpool_do_iostat(int argc, char **argv) 5488{ 5489 int c; 5490 int ret; 5491 int npools; 5492 float interval = 0; 5493 unsigned long count = 0; 5494 int winheight = 24; 5495 zpool_list_t *list; 5496 boolean_t verbose = B_FALSE; 5497 boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE; 5498 boolean_t queues = B_FALSE, parsable = B_FALSE, scripted = B_FALSE; 5499 boolean_t omit_since_boot = B_FALSE; 5500 boolean_t guid = B_FALSE; 5501 boolean_t follow_links = B_FALSE; 5502 boolean_t full_name = B_FALSE; 5503 boolean_t headers_once = B_FALSE; 5504 iostat_cbdata_t cb = { 0 }; 5505 char *cmd = NULL; 5506 5507 /* Used for printing error message */ 5508 const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q', 5509 [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'}; 5510 5511 uint64_t unsupported_flags; 5512 5513 /* check options */ 5514 while ((c = getopt(argc, argv, "c:gLPT:vyhplqrwnH")) != -1) { 5515 switch (c) { 5516 case 'c': 5517 if (cmd != NULL) { 5518 fprintf(stderr, 5519 gettext("Can't set -c flag twice\n")); 5520 exit(1); 5521 } 5522 5523 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL && 5524 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) { 5525 fprintf(stderr, gettext( 5526 "Can't run -c, disabled by " 5527 "ZPOOL_SCRIPTS_ENABLED.\n")); 5528 exit(1); 5529 } 5530 5531 if ((getuid() <= 0 || geteuid() <= 0) && 5532 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) { 5533 fprintf(stderr, gettext( 5534 "Can't run -c with root privileges " 5535 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n")); 5536 exit(1); 5537 } 5538 cmd = optarg; 5539 verbose = B_TRUE; 5540 break; 5541 case 'g': 5542 guid = B_TRUE; 5543 break; 5544 case 'L': 5545 follow_links = B_TRUE; 5546 break; 5547 case 'P': 5548 full_name = B_TRUE; 5549 break; 5550 case 'T': 5551 get_timestamp_arg(*optarg); 5552 break; 5553 case 'v': 5554 verbose = B_TRUE; 5555 break; 5556 case 'p': 5557 parsable = B_TRUE; 5558 break; 5559 case 'l': 5560 latency = B_TRUE; 5561 break; 5562 case 'q': 5563 queues = B_TRUE; 5564 break; 5565 case 'H': 5566 scripted = B_TRUE; 5567 break; 5568 case 'w': 5569 l_histo = B_TRUE; 5570 break; 5571 case 'r': 5572 rq_histo = B_TRUE; 5573 break; 5574 case 'y': 5575 omit_since_boot = B_TRUE; 5576 break; 5577 case 'n': 5578 headers_once = B_TRUE; 5579 break; 5580 case 'h': 5581 usage(B_FALSE); 5582 break; 5583 case '?': 5584 if (optopt == 'c') { 5585 print_zpool_script_list("iostat"); 5586 exit(0); 5587 } else { 5588 fprintf(stderr, 5589 gettext("invalid option '%c'\n"), optopt); 5590 } 5591 usage(B_FALSE); 5592 } 5593 } 5594 5595 argc -= optind; 5596 argv += optind; 5597 5598 cb.cb_literal = parsable; 5599 cb.cb_scripted = scripted; 5600 5601 if (guid) 5602 cb.cb_name_flags |= VDEV_NAME_GUID; 5603 if (follow_links) 5604 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 5605 if (full_name) 5606 cb.cb_name_flags |= VDEV_NAME_PATH; 5607 cb.cb_iteration = 0; 5608 cb.cb_namewidth = 0; 5609 cb.cb_verbose = verbose; 5610 5611 /* Get our interval and count values (if any) */ 5612 if (guid) { 5613 get_interval_count_filter_guids(&argc, argv, &interval, 5614 &count, &cb); 5615 } else { 5616 get_interval_count(&argc, argv, &interval, &count); 5617 } 5618 5619 if (argc == 0) { 5620 /* No args, so just print the defaults. */ 5621 } else if (are_all_pools(argc, argv)) { 5622 /* All the args are pool names */ 5623 } else if (are_vdevs_in_pool(argc, argv, NULL, &cb)) { 5624 /* All the args are vdevs */ 5625 cb.cb_vdev_names = argv; 5626 cb.cb_vdev_names_count = argc; 5627 argc = 0; /* No pools to process */ 5628 } else if (are_all_pools(1, argv)) { 5629 /* The first arg is a pool name */ 5630 if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb)) { 5631 /* ...and the rest are vdev names */ 5632 cb.cb_vdev_names = argv + 1; 5633 cb.cb_vdev_names_count = argc - 1; 5634 argc = 1; /* One pool to process */ 5635 } else { 5636 fprintf(stderr, gettext("Expected either a list of ")); 5637 fprintf(stderr, gettext("pools, or list of vdevs in")); 5638 fprintf(stderr, " \"%s\", ", argv[0]); 5639 fprintf(stderr, gettext("but got:\n")); 5640 error_list_unresolved_vdevs(argc - 1, argv + 1, 5641 argv[0], &cb); 5642 fprintf(stderr, "\n"); 5643 usage(B_FALSE); 5644 return (1); 5645 } 5646 } else { 5647 /* 5648 * The args don't make sense. The first arg isn't a pool name, 5649 * nor are all the args vdevs. 5650 */ 5651 fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n")); 5652 fprintf(stderr, "\n"); 5653 return (1); 5654 } 5655 5656 if (cb.cb_vdev_names_count != 0) { 5657 /* 5658 * If user specified vdevs, it implies verbose. 5659 */ 5660 cb.cb_verbose = B_TRUE; 5661 } 5662 5663 /* 5664 * Construct the list of all interesting pools. 5665 */ 5666 ret = 0; 5667 if ((list = pool_list_get(argc, argv, NULL, parsable, &ret)) == NULL) 5668 return (1); 5669 5670 if (pool_list_count(list) == 0 && argc != 0) { 5671 pool_list_free(list); 5672 return (1); 5673 } 5674 5675 if (pool_list_count(list) == 0 && interval == 0) { 5676 pool_list_free(list); 5677 (void) fprintf(stderr, gettext("no pools available\n")); 5678 return (1); 5679 } 5680 5681 if ((l_histo || rq_histo) && (cmd != NULL || latency || queues)) { 5682 pool_list_free(list); 5683 (void) fprintf(stderr, 5684 gettext("[-r|-w] isn't allowed with [-c|-l|-q]\n")); 5685 usage(B_FALSE); 5686 return (1); 5687 } 5688 5689 if (l_histo && rq_histo) { 5690 pool_list_free(list); 5691 (void) fprintf(stderr, 5692 gettext("Only one of [-r|-w] can be passed at a time\n")); 5693 usage(B_FALSE); 5694 return (1); 5695 } 5696 5697 /* 5698 * Enter the main iostat loop. 5699 */ 5700 cb.cb_list = list; 5701 5702 if (l_histo) { 5703 /* 5704 * Histograms tables look out of place when you try to display 5705 * them with the other stats, so make a rule that you can only 5706 * print histograms by themselves. 5707 */ 5708 cb.cb_flags = IOS_L_HISTO_M; 5709 } else if (rq_histo) { 5710 cb.cb_flags = IOS_RQ_HISTO_M; 5711 } else { 5712 cb.cb_flags = IOS_DEFAULT_M; 5713 if (latency) 5714 cb.cb_flags |= IOS_LATENCY_M; 5715 if (queues) 5716 cb.cb_flags |= IOS_QUEUES_M; 5717 } 5718 5719 /* 5720 * See if the module supports all the stats we want to display. 5721 */ 5722 unsupported_flags = cb.cb_flags & ~get_stat_flags(list); 5723 if (unsupported_flags) { 5724 uint64_t f; 5725 int idx; 5726 fprintf(stderr, 5727 gettext("The loaded zfs module doesn't support:")); 5728 5729 /* for each bit set in unsupported_flags */ 5730 for (f = unsupported_flags; f; f &= ~(1ULL << idx)) { 5731 idx = lowbit64(f) - 1; 5732 fprintf(stderr, " -%c", flag_to_arg[idx]); 5733 } 5734 5735 fprintf(stderr, ". Try running a newer module.\n"); 5736 pool_list_free(list); 5737 5738 return (1); 5739 } 5740 5741 for (;;) { 5742 if ((npools = pool_list_count(list)) == 0) 5743 (void) fprintf(stderr, gettext("no pools available\n")); 5744 else { 5745 /* 5746 * If this is the first iteration and -y was supplied 5747 * we skip any printing. 5748 */ 5749 boolean_t skip = (omit_since_boot && 5750 cb.cb_iteration == 0); 5751 5752 /* 5753 * Refresh all statistics. This is done as an 5754 * explicit step before calculating the maximum name 5755 * width, so that any * configuration changes are 5756 * properly accounted for. 5757 */ 5758 (void) pool_list_iter(list, B_FALSE, refresh_iostat, 5759 &cb); 5760 5761 /* 5762 * Iterate over all pools to determine the maximum width 5763 * for the pool / device name column across all pools. 5764 */ 5765 cb.cb_namewidth = 0; 5766 (void) pool_list_iter(list, B_FALSE, 5767 get_namewidth_iostat, &cb); 5768 5769 if (timestamp_fmt != NODATE) 5770 print_timestamp(timestamp_fmt); 5771 5772 if (cmd != NULL && cb.cb_verbose && 5773 !(cb.cb_flags & IOS_ANYHISTO_M)) { 5774 cb.vcdl = all_pools_for_each_vdev_run(argc, 5775 argv, cmd, g_zfs, cb.cb_vdev_names, 5776 cb.cb_vdev_names_count, cb.cb_name_flags); 5777 } else { 5778 cb.vcdl = NULL; 5779 } 5780 5781 5782 /* 5783 * Check terminal size so we can print headers 5784 * even when terminal window has its height 5785 * changed. 5786 */ 5787 winheight = terminal_height(); 5788 /* 5789 * Are we connected to TTY? If not, headers_once 5790 * should be true, to avoid breaking scripts. 5791 */ 5792 if (winheight < 0) 5793 headers_once = B_TRUE; 5794 5795 /* 5796 * If it's the first time and we're not skipping it, 5797 * or either skip or verbose mode, print the header. 5798 * 5799 * The histogram code explicitly prints its header on 5800 * every vdev, so skip this for histograms. 5801 */ 5802 if (((++cb.cb_iteration == 1 && !skip) || 5803 (skip != verbose) || 5804 (!headers_once && 5805 (cb.cb_iteration % winheight) == 0)) && 5806 (!(cb.cb_flags & IOS_ANYHISTO_M)) && 5807 !cb.cb_scripted) 5808 print_iostat_header(&cb); 5809 5810 if (skip) { 5811 (void) fsleep(interval); 5812 continue; 5813 } 5814 5815 pool_list_iter(list, B_FALSE, print_iostat, &cb); 5816 5817 /* 5818 * If there's more than one pool, and we're not in 5819 * verbose mode (which prints a separator for us), 5820 * then print a separator. 5821 * 5822 * In addition, if we're printing specific vdevs then 5823 * we also want an ending separator. 5824 */ 5825 if (((npools > 1 && !verbose && 5826 !(cb.cb_flags & IOS_ANYHISTO_M)) || 5827 (!(cb.cb_flags & IOS_ANYHISTO_M) && 5828 cb.cb_vdev_names_count)) && 5829 !cb.cb_scripted) { 5830 print_iostat_separator(&cb); 5831 if (cb.vcdl != NULL) 5832 print_cmd_columns(cb.vcdl, 1); 5833 printf("\n"); 5834 } 5835 5836 if (cb.vcdl != NULL) 5837 free_vdev_cmd_data_list(cb.vcdl); 5838 5839 } 5840 5841 /* 5842 * Flush the output so that redirection to a file isn't buffered 5843 * indefinitely. 5844 */ 5845 (void) fflush(stdout); 5846 5847 if (interval == 0) 5848 break; 5849 5850 if (count != 0 && --count == 0) 5851 break; 5852 5853 (void) fsleep(interval); 5854 } 5855 5856 pool_list_free(list); 5857 5858 return (ret); 5859} 5860 5861typedef struct list_cbdata { 5862 boolean_t cb_verbose; 5863 int cb_name_flags; 5864 int cb_namewidth; 5865 boolean_t cb_scripted; 5866 zprop_list_t *cb_proplist; 5867 boolean_t cb_literal; 5868} list_cbdata_t; 5869 5870 5871/* 5872 * Given a list of columns to display, output appropriate headers for each one. 5873 */ 5874static void 5875print_header(list_cbdata_t *cb) 5876{ 5877 zprop_list_t *pl = cb->cb_proplist; 5878 char headerbuf[ZPOOL_MAXPROPLEN]; 5879 const char *header; 5880 boolean_t first = B_TRUE; 5881 boolean_t right_justify; 5882 size_t width = 0; 5883 5884 for (; pl != NULL; pl = pl->pl_next) { 5885 width = pl->pl_width; 5886 if (first && cb->cb_verbose) { 5887 /* 5888 * Reset the width to accommodate the verbose listing 5889 * of devices. 5890 */ 5891 width = cb->cb_namewidth; 5892 } 5893 5894 if (!first) 5895 (void) printf(" "); 5896 else 5897 first = B_FALSE; 5898 5899 right_justify = B_FALSE; 5900 if (pl->pl_prop != ZPROP_INVAL) { 5901 header = zpool_prop_column_name(pl->pl_prop); 5902 right_justify = zpool_prop_align_right(pl->pl_prop); 5903 } else { 5904 int i; 5905 5906 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 5907 headerbuf[i] = toupper(pl->pl_user_prop[i]); 5908 headerbuf[i] = '\0'; 5909 header = headerbuf; 5910 } 5911 5912 if (pl->pl_next == NULL && !right_justify) 5913 (void) printf("%s", header); 5914 else if (right_justify) 5915 (void) printf("%*s", (int)width, header); 5916 else 5917 (void) printf("%-*s", (int)width, header); 5918 } 5919 5920 (void) printf("\n"); 5921} 5922 5923/* 5924 * Given a pool and a list of properties, print out all the properties according 5925 * to the described layout. Used by zpool_do_list(). 5926 */ 5927static void 5928print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 5929{ 5930 zprop_list_t *pl = cb->cb_proplist; 5931 boolean_t first = B_TRUE; 5932 char property[ZPOOL_MAXPROPLEN]; 5933 char *propstr; 5934 boolean_t right_justify; 5935 size_t width; 5936 5937 for (; pl != NULL; pl = pl->pl_next) { 5938 5939 width = pl->pl_width; 5940 if (first && cb->cb_verbose) { 5941 /* 5942 * Reset the width to accommodate the verbose listing 5943 * of devices. 5944 */ 5945 width = cb->cb_namewidth; 5946 } 5947 5948 if (!first) { 5949 if (cb->cb_scripted) 5950 (void) printf("\t"); 5951 else 5952 (void) printf(" "); 5953 } else { 5954 first = B_FALSE; 5955 } 5956 5957 right_justify = B_FALSE; 5958 if (pl->pl_prop != ZPROP_INVAL) { 5959 if (zpool_get_prop(zhp, pl->pl_prop, property, 5960 sizeof (property), NULL, cb->cb_literal) != 0) 5961 propstr = "-"; 5962 else 5963 propstr = property; 5964 5965 right_justify = zpool_prop_align_right(pl->pl_prop); 5966 } else if ((zpool_prop_feature(pl->pl_user_prop) || 5967 zpool_prop_unsupported(pl->pl_user_prop)) && 5968 zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 5969 sizeof (property)) == 0) { 5970 propstr = property; 5971 } else { 5972 propstr = "-"; 5973 } 5974 5975 5976 /* 5977 * If this is being called in scripted mode, or if this is the 5978 * last column and it is left-justified, don't include a width 5979 * format specifier. 5980 */ 5981 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 5982 (void) printf("%s", propstr); 5983 else if (right_justify) 5984 (void) printf("%*s", (int)width, propstr); 5985 else 5986 (void) printf("%-*s", (int)width, propstr); 5987 } 5988 5989 (void) printf("\n"); 5990} 5991 5992static void 5993print_one_column(zpool_prop_t prop, uint64_t value, const char *str, 5994 boolean_t scripted, boolean_t valid, enum zfs_nicenum_format format) 5995{ 5996 char propval[64]; 5997 boolean_t fixed; 5998 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 5999 6000 switch (prop) { 6001 case ZPOOL_PROP_EXPANDSZ: 6002 case ZPOOL_PROP_CHECKPOINT: 6003 case ZPOOL_PROP_DEDUPRATIO: 6004 if (value == 0) 6005 (void) strlcpy(propval, "-", sizeof (propval)); 6006 else 6007 zfs_nicenum_format(value, propval, sizeof (propval), 6008 format); 6009 break; 6010 case ZPOOL_PROP_FRAGMENTATION: 6011 if (value == ZFS_FRAG_INVALID) { 6012 (void) strlcpy(propval, "-", sizeof (propval)); 6013 } else if (format == ZFS_NICENUM_RAW) { 6014 (void) snprintf(propval, sizeof (propval), "%llu", 6015 (unsigned long long)value); 6016 } else { 6017 (void) snprintf(propval, sizeof (propval), "%llu%%", 6018 (unsigned long long)value); 6019 } 6020 break; 6021 case ZPOOL_PROP_CAPACITY: 6022 /* capacity value is in parts-per-10,000 (aka permyriad) */ 6023 if (format == ZFS_NICENUM_RAW) 6024 (void) snprintf(propval, sizeof (propval), "%llu", 6025 (unsigned long long)value / 100); 6026 else 6027 (void) snprintf(propval, sizeof (propval), 6028 value < 1000 ? "%1.2f%%" : value < 10000 ? 6029 "%2.1f%%" : "%3.0f%%", value / 100.0); 6030 break; 6031 case ZPOOL_PROP_HEALTH: 6032 width = 8; 6033 (void) strlcpy(propval, str, sizeof (propval)); 6034 break; 6035 default: 6036 zfs_nicenum_format(value, propval, sizeof (propval), format); 6037 } 6038 6039 if (!valid) 6040 (void) strlcpy(propval, "-", sizeof (propval)); 6041 6042 if (scripted) 6043 (void) printf("\t%s", propval); 6044 else 6045 (void) printf(" %*s", (int)width, propval); 6046} 6047 6048/* 6049 * print static default line per vdev 6050 * not compatible with '-o' <proplist> option 6051 */ 6052static void 6053print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 6054 list_cbdata_t *cb, int depth, boolean_t isspare) 6055{ 6056 nvlist_t **child; 6057 vdev_stat_t *vs; 6058 uint_t c, children; 6059 char *vname; 6060 boolean_t scripted = cb->cb_scripted; 6061 uint64_t islog = B_FALSE; 6062 char *dashes = "%-*s - - - - " 6063 "- - - - -\n"; 6064 6065 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 6066 (uint64_t **)&vs, &c) == 0); 6067 6068 if (name != NULL) { 6069 boolean_t toplevel = (vs->vs_space != 0); 6070 uint64_t cap; 6071 enum zfs_nicenum_format format; 6072 const char *state; 6073 6074 if (cb->cb_literal) 6075 format = ZFS_NICENUM_RAW; 6076 else 6077 format = ZFS_NICENUM_1024; 6078 6079 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 6080 return; 6081 6082 if (scripted) 6083 (void) printf("\t%s", name); 6084 else if (strlen(name) + depth > cb->cb_namewidth) 6085 (void) printf("%*s%s", depth, "", name); 6086 else 6087 (void) printf("%*s%s%*s", depth, "", name, 6088 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 6089 6090 /* 6091 * Print the properties for the individual vdevs. Some 6092 * properties are only applicable to toplevel vdevs. The 6093 * 'toplevel' boolean value is passed to the print_one_column() 6094 * to indicate that the value is valid. 6095 */ 6096 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, NULL, scripted, 6097 toplevel, format); 6098 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, NULL, 6099 scripted, toplevel, format); 6100 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 6101 NULL, scripted, toplevel, format); 6102 print_one_column(ZPOOL_PROP_CHECKPOINT, 6103 vs->vs_checkpoint_space, NULL, scripted, toplevel, format); 6104 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, NULL, 6105 scripted, B_TRUE, format); 6106 print_one_column(ZPOOL_PROP_FRAGMENTATION, 6107 vs->vs_fragmentation, NULL, scripted, 6108 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel), 6109 format); 6110 cap = (vs->vs_space == 0) ? 0 : 6111 (vs->vs_alloc * 10000 / vs->vs_space); 6112 print_one_column(ZPOOL_PROP_CAPACITY, cap, NULL, 6113 scripted, toplevel, format); 6114 print_one_column(ZPOOL_PROP_DEDUPRATIO, 0, NULL, 6115 scripted, toplevel, format); 6116 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 6117 if (isspare) { 6118 if (vs->vs_aux == VDEV_AUX_SPARED) 6119 state = "INUSE"; 6120 else if (vs->vs_state == VDEV_STATE_HEALTHY) 6121 state = "AVAIL"; 6122 } 6123 print_one_column(ZPOOL_PROP_HEALTH, 0, state, scripted, 6124 B_TRUE, format); 6125 (void) printf("\n"); 6126 } 6127 6128 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 6129 &child, &children) != 0) 6130 return; 6131 6132 /* list the normal vdevs first */ 6133 for (c = 0; c < children; c++) { 6134 uint64_t ishole = B_FALSE; 6135 6136 if (nvlist_lookup_uint64(child[c], 6137 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 6138 continue; 6139 6140 if (nvlist_lookup_uint64(child[c], 6141 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) 6142 continue; 6143 6144 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 6145 continue; 6146 6147 vname = zpool_vdev_name(g_zfs, zhp, child[c], 6148 cb->cb_name_flags); 6149 print_list_stats(zhp, vname, child[c], cb, depth + 2, B_FALSE); 6150 free(vname); 6151 } 6152 6153 /* list the classes: 'logs', 'dedup', and 'special' */ 6154 for (uint_t n = 0; n < 3; n++) { 6155 boolean_t printed = B_FALSE; 6156 6157 for (c = 0; c < children; c++) { 6158 char *bias = NULL; 6159 char *type = NULL; 6160 6161 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 6162 &islog) == 0 && islog) { 6163 bias = VDEV_ALLOC_CLASS_LOGS; 6164 } else { 6165 (void) nvlist_lookup_string(child[c], 6166 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 6167 (void) nvlist_lookup_string(child[c], 6168 ZPOOL_CONFIG_TYPE, &type); 6169 } 6170 if (bias == NULL || strcmp(bias, class_name[n]) != 0) 6171 continue; 6172 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 6173 continue; 6174 6175 if (!printed) { 6176 /* LINTED E_SEC_PRINTF_VAR_FMT */ 6177 (void) printf(dashes, cb->cb_namewidth, 6178 class_name[n]); 6179 printed = B_TRUE; 6180 } 6181 vname = zpool_vdev_name(g_zfs, zhp, child[c], 6182 cb->cb_name_flags); 6183 print_list_stats(zhp, vname, child[c], cb, depth + 2, 6184 B_FALSE); 6185 free(vname); 6186 } 6187 } 6188 6189 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 6190 &child, &children) == 0 && children > 0) { 6191 /* LINTED E_SEC_PRINTF_VAR_FMT */ 6192 (void) printf(dashes, cb->cb_namewidth, "cache"); 6193 for (c = 0; c < children; c++) { 6194 vname = zpool_vdev_name(g_zfs, zhp, child[c], 6195 cb->cb_name_flags); 6196 print_list_stats(zhp, vname, child[c], cb, depth + 2, 6197 B_FALSE); 6198 free(vname); 6199 } 6200 } 6201 6202 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 6203 &children) == 0 && children > 0) { 6204 /* LINTED E_SEC_PRINTF_VAR_FMT */ 6205 (void) printf(dashes, cb->cb_namewidth, "spare"); 6206 for (c = 0; c < children; c++) { 6207 vname = zpool_vdev_name(g_zfs, zhp, child[c], 6208 cb->cb_name_flags); 6209 print_list_stats(zhp, vname, child[c], cb, depth + 2, 6210 B_TRUE); 6211 free(vname); 6212 } 6213 } 6214} 6215 6216/* 6217 * Generic callback function to list a pool. 6218 */ 6219static int 6220list_callback(zpool_handle_t *zhp, void *data) 6221{ 6222 list_cbdata_t *cbp = data; 6223 6224 print_pool(zhp, cbp); 6225 6226 if (cbp->cb_verbose) { 6227 nvlist_t *config, *nvroot; 6228 6229 config = zpool_get_config(zhp, NULL); 6230 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 6231 &nvroot) == 0); 6232 print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE); 6233 } 6234 6235 return (0); 6236} 6237 6238/* 6239 * Set the minimum pool/vdev name column width. The width must be at least 9, 6240 * but may be as large as needed. 6241 */ 6242static int 6243get_namewidth_list(zpool_handle_t *zhp, void *data) 6244{ 6245 list_cbdata_t *cb = data; 6246 int width; 6247 6248 width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags, 6249 cb->cb_verbose); 6250 6251 if (width < 9) 6252 width = 9; 6253 6254 cb->cb_namewidth = width; 6255 6256 return (0); 6257} 6258 6259/* 6260 * zpool list [-gHLpP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 6261 * 6262 * -g Display guid for individual vdev name. 6263 * -H Scripted mode. Don't display headers, and separate properties 6264 * by a single tab. 6265 * -L Follow links when resolving vdev path name. 6266 * -o List of properties to display. Defaults to 6267 * "name,size,allocated,free,expandsize,fragmentation,capacity," 6268 * "dedupratio,health,altroot" 6269 * -p Display values in parsable (exact) format. 6270 * -P Display full path for vdev name. 6271 * -T Display a timestamp in date(1) or Unix format 6272 * 6273 * List all pools in the system, whether or not they're healthy. Output space 6274 * statistics for each one, as well as health status summary. 6275 */ 6276int 6277zpool_do_list(int argc, char **argv) 6278{ 6279 int c; 6280 int ret = 0; 6281 list_cbdata_t cb = { 0 }; 6282 static char default_props[] = 6283 "name,size,allocated,free,checkpoint,expandsize,fragmentation," 6284 "capacity,dedupratio,health,altroot"; 6285 char *props = default_props; 6286 float interval = 0; 6287 unsigned long count = 0; 6288 zpool_list_t *list; 6289 boolean_t first = B_TRUE; 6290 6291 /* check options */ 6292 while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) { 6293 switch (c) { 6294 case 'g': 6295 cb.cb_name_flags |= VDEV_NAME_GUID; 6296 break; 6297 case 'H': 6298 cb.cb_scripted = B_TRUE; 6299 break; 6300 case 'L': 6301 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 6302 break; 6303 case 'o': 6304 props = optarg; 6305 break; 6306 case 'P': 6307 cb.cb_name_flags |= VDEV_NAME_PATH; 6308 break; 6309 case 'p': 6310 cb.cb_literal = B_TRUE; 6311 break; 6312 case 'T': 6313 get_timestamp_arg(*optarg); 6314 break; 6315 case 'v': 6316 cb.cb_verbose = B_TRUE; 6317 cb.cb_namewidth = 8; /* 8 until precalc is avail */ 6318 break; 6319 case ':': 6320 (void) fprintf(stderr, gettext("missing argument for " 6321 "'%c' option\n"), optopt); 6322 usage(B_FALSE); 6323 break; 6324 case '?': 6325 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6326 optopt); 6327 usage(B_FALSE); 6328 } 6329 } 6330 6331 argc -= optind; 6332 argv += optind; 6333 6334 get_interval_count(&argc, argv, &interval, &count); 6335 6336 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 6337 usage(B_FALSE); 6338 6339 for (;;) { 6340 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 6341 cb.cb_literal, &ret)) == NULL) 6342 return (1); 6343 6344 if (pool_list_count(list) == 0) 6345 break; 6346 6347 cb.cb_namewidth = 0; 6348 (void) pool_list_iter(list, B_FALSE, get_namewidth_list, &cb); 6349 6350 if (timestamp_fmt != NODATE) 6351 print_timestamp(timestamp_fmt); 6352 6353 if (!cb.cb_scripted && (first || cb.cb_verbose)) { 6354 print_header(&cb); 6355 first = B_FALSE; 6356 } 6357 ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 6358 6359 if (interval == 0) 6360 break; 6361 6362 if (count != 0 && --count == 0) 6363 break; 6364 6365 pool_list_free(list); 6366 (void) fsleep(interval); 6367 } 6368 6369 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 6370 (void) printf(gettext("no pools available\n")); 6371 ret = 0; 6372 } 6373 6374 pool_list_free(list); 6375 zprop_free_list(cb.cb_proplist); 6376 return (ret); 6377} 6378 6379static int 6380zpool_do_attach_or_replace(int argc, char **argv, int replacing) 6381{ 6382 boolean_t force = B_FALSE; 6383 boolean_t rebuild = B_FALSE; 6384 boolean_t wait = B_FALSE; 6385 int c; 6386 nvlist_t *nvroot; 6387 char *poolname, *old_disk, *new_disk; 6388 zpool_handle_t *zhp; 6389 nvlist_t *props = NULL; 6390 char *propval; 6391 int ret; 6392 6393 /* check options */ 6394 while ((c = getopt(argc, argv, "fo:sw")) != -1) { 6395 switch (c) { 6396 case 'f': 6397 force = B_TRUE; 6398 break; 6399 case 'o': 6400 if ((propval = strchr(optarg, '=')) == NULL) { 6401 (void) fprintf(stderr, gettext("missing " 6402 "'=' for -o option\n")); 6403 usage(B_FALSE); 6404 } 6405 *propval = '\0'; 6406 propval++; 6407 6408 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 6409 (add_prop_list(optarg, propval, &props, B_TRUE))) 6410 usage(B_FALSE); 6411 break; 6412 case 's': 6413 rebuild = B_TRUE; 6414 break; 6415 case 'w': 6416 wait = B_TRUE; 6417 break; 6418 case '?': 6419 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6420 optopt); 6421 usage(B_FALSE); 6422 } 6423 } 6424 6425 argc -= optind; 6426 argv += optind; 6427 6428 /* get pool name and check number of arguments */ 6429 if (argc < 1) { 6430 (void) fprintf(stderr, gettext("missing pool name argument\n")); 6431 usage(B_FALSE); 6432 } 6433 6434 poolname = argv[0]; 6435 6436 if (argc < 2) { 6437 (void) fprintf(stderr, 6438 gettext("missing <device> specification\n")); 6439 usage(B_FALSE); 6440 } 6441 6442 old_disk = argv[1]; 6443 6444 if (argc < 3) { 6445 if (!replacing) { 6446 (void) fprintf(stderr, 6447 gettext("missing <new_device> specification\n")); 6448 usage(B_FALSE); 6449 } 6450 new_disk = old_disk; 6451 argc -= 1; 6452 argv += 1; 6453 } else { 6454 new_disk = argv[2]; 6455 argc -= 2; 6456 argv += 2; 6457 } 6458 6459 if (argc > 1) { 6460 (void) fprintf(stderr, gettext("too many arguments\n")); 6461 usage(B_FALSE); 6462 } 6463 6464 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) { 6465 nvlist_free(props); 6466 return (1); 6467 } 6468 6469 if (zpool_get_config(zhp, NULL) == NULL) { 6470 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 6471 poolname); 6472 zpool_close(zhp); 6473 nvlist_free(props); 6474 return (1); 6475 } 6476 6477 /* unless manually specified use "ashift" pool property (if set) */ 6478 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 6479 int intval; 6480 zprop_source_t src; 6481 char strval[ZPOOL_MAXPROPLEN]; 6482 6483 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 6484 if (src != ZPROP_SRC_DEFAULT) { 6485 (void) sprintf(strval, "%" PRId32, intval); 6486 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 6487 &props, B_TRUE) == 0); 6488 } 6489 } 6490 6491 nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE, 6492 argc, argv); 6493 if (nvroot == NULL) { 6494 zpool_close(zhp); 6495 nvlist_free(props); 6496 return (1); 6497 } 6498 6499 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing, 6500 rebuild); 6501 6502 if (ret == 0 && wait) 6503 ret = zpool_wait(zhp, 6504 replacing ? ZPOOL_WAIT_REPLACE : ZPOOL_WAIT_RESILVER); 6505 6506 nvlist_free(props); 6507 nvlist_free(nvroot); 6508 zpool_close(zhp); 6509 6510 return (ret); 6511} 6512 6513/* 6514 * zpool replace [-fsw] [-o property=value] <pool> <device> <new_device> 6515 * 6516 * -f Force attach, even if <new_device> appears to be in use. 6517 * -s Use sequential instead of healing reconstruction for resilver. 6518 * -o Set property=value. 6519 * -w Wait for replacing to complete before returning 6520 * 6521 * Replace <device> with <new_device>. 6522 */ 6523/* ARGSUSED */ 6524int 6525zpool_do_replace(int argc, char **argv) 6526{ 6527 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 6528} 6529 6530/* 6531 * zpool attach [-fsw] [-o property=value] <pool> <device> <new_device> 6532 * 6533 * -f Force attach, even if <new_device> appears to be in use. 6534 * -s Use sequential instead of healing reconstruction for resilver. 6535 * -o Set property=value. 6536 * -w Wait for resilvering to complete before returning 6537 * 6538 * Attach <new_device> to the mirror containing <device>. If <device> is not 6539 * part of a mirror, then <device> will be transformed into a mirror of 6540 * <device> and <new_device>. In either case, <new_device> will begin life 6541 * with a DTL of [0, now], and will immediately begin to resilver itself. 6542 */ 6543int 6544zpool_do_attach(int argc, char **argv) 6545{ 6546 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 6547} 6548 6549/* 6550 * zpool detach [-f] <pool> <device> 6551 * 6552 * -f Force detach of <device>, even if DTLs argue against it 6553 * (not supported yet) 6554 * 6555 * Detach a device from a mirror. The operation will be refused if <device> 6556 * is the last device in the mirror, or if the DTLs indicate that this device 6557 * has the only valid copy of some data. 6558 */ 6559/* ARGSUSED */ 6560int 6561zpool_do_detach(int argc, char **argv) 6562{ 6563 int c; 6564 char *poolname, *path; 6565 zpool_handle_t *zhp; 6566 int ret; 6567 6568 /* check options */ 6569 while ((c = getopt(argc, argv, "")) != -1) { 6570 switch (c) { 6571 case '?': 6572 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6573 optopt); 6574 usage(B_FALSE); 6575 } 6576 } 6577 6578 argc -= optind; 6579 argv += optind; 6580 6581 /* get pool name and check number of arguments */ 6582 if (argc < 1) { 6583 (void) fprintf(stderr, gettext("missing pool name argument\n")); 6584 usage(B_FALSE); 6585 } 6586 6587 if (argc < 2) { 6588 (void) fprintf(stderr, 6589 gettext("missing <device> specification\n")); 6590 usage(B_FALSE); 6591 } 6592 6593 poolname = argv[0]; 6594 path = argv[1]; 6595 6596 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 6597 return (1); 6598 6599 ret = zpool_vdev_detach(zhp, path); 6600 6601 zpool_close(zhp); 6602 6603 return (ret); 6604} 6605 6606/* 6607 * zpool split [-gLnP] [-o prop=val] ... 6608 * [-o mntopt] ... 6609 * [-R altroot] <pool> <newpool> [<device> ...] 6610 * 6611 * -g Display guid for individual vdev name. 6612 * -L Follow links when resolving vdev path name. 6613 * -n Do not split the pool, but display the resulting layout if 6614 * it were to be split. 6615 * -o Set property=value, or set mount options. 6616 * -P Display full path for vdev name. 6617 * -R Mount the split-off pool under an alternate root. 6618 * -l Load encryption keys while importing. 6619 * 6620 * Splits the named pool and gives it the new pool name. Devices to be split 6621 * off may be listed, provided that no more than one device is specified 6622 * per top-level vdev mirror. The newly split pool is left in an exported 6623 * state unless -R is specified. 6624 * 6625 * Restrictions: the top-level of the pool pool must only be made up of 6626 * mirrors; all devices in the pool must be healthy; no device may be 6627 * undergoing a resilvering operation. 6628 */ 6629int 6630zpool_do_split(int argc, char **argv) 6631{ 6632 char *srcpool, *newpool, *propval; 6633 char *mntopts = NULL; 6634 splitflags_t flags; 6635 int c, ret = 0; 6636 boolean_t loadkeys = B_FALSE; 6637 zpool_handle_t *zhp; 6638 nvlist_t *config, *props = NULL; 6639 6640 flags.dryrun = B_FALSE; 6641 flags.import = B_FALSE; 6642 flags.name_flags = 0; 6643 6644 /* check options */ 6645 while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) { 6646 switch (c) { 6647 case 'g': 6648 flags.name_flags |= VDEV_NAME_GUID; 6649 break; 6650 case 'L': 6651 flags.name_flags |= VDEV_NAME_FOLLOW_LINKS; 6652 break; 6653 case 'R': 6654 flags.import = B_TRUE; 6655 if (add_prop_list( 6656 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 6657 &props, B_TRUE) != 0) { 6658 nvlist_free(props); 6659 usage(B_FALSE); 6660 } 6661 break; 6662 case 'l': 6663 loadkeys = B_TRUE; 6664 break; 6665 case 'n': 6666 flags.dryrun = B_TRUE; 6667 break; 6668 case 'o': 6669 if ((propval = strchr(optarg, '=')) != NULL) { 6670 *propval = '\0'; 6671 propval++; 6672 if (add_prop_list(optarg, propval, 6673 &props, B_TRUE) != 0) { 6674 nvlist_free(props); 6675 usage(B_FALSE); 6676 } 6677 } else { 6678 mntopts = optarg; 6679 } 6680 break; 6681 case 'P': 6682 flags.name_flags |= VDEV_NAME_PATH; 6683 break; 6684 case ':': 6685 (void) fprintf(stderr, gettext("missing argument for " 6686 "'%c' option\n"), optopt); 6687 usage(B_FALSE); 6688 break; 6689 case '?': 6690 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6691 optopt); 6692 usage(B_FALSE); 6693 break; 6694 } 6695 } 6696 6697 if (!flags.import && mntopts != NULL) { 6698 (void) fprintf(stderr, gettext("setting mntopts is only " 6699 "valid when importing the pool\n")); 6700 usage(B_FALSE); 6701 } 6702 6703 if (!flags.import && loadkeys) { 6704 (void) fprintf(stderr, gettext("loading keys is only " 6705 "valid when importing the pool\n")); 6706 usage(B_FALSE); 6707 } 6708 6709 argc -= optind; 6710 argv += optind; 6711 6712 if (argc < 1) { 6713 (void) fprintf(stderr, gettext("Missing pool name\n")); 6714 usage(B_FALSE); 6715 } 6716 if (argc < 2) { 6717 (void) fprintf(stderr, gettext("Missing new pool name\n")); 6718 usage(B_FALSE); 6719 } 6720 6721 srcpool = argv[0]; 6722 newpool = argv[1]; 6723 6724 argc -= 2; 6725 argv += 2; 6726 6727 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) { 6728 nvlist_free(props); 6729 return (1); 6730 } 6731 6732 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 6733 if (config == NULL) { 6734 ret = 1; 6735 } else { 6736 if (flags.dryrun) { 6737 (void) printf(gettext("would create '%s' with the " 6738 "following layout:\n\n"), newpool); 6739 print_vdev_tree(NULL, newpool, config, 0, "", 6740 flags.name_flags); 6741 print_vdev_tree(NULL, "dedup", config, 0, 6742 VDEV_ALLOC_BIAS_DEDUP, 0); 6743 print_vdev_tree(NULL, "special", config, 0, 6744 VDEV_ALLOC_BIAS_SPECIAL, 0); 6745 } 6746 } 6747 6748 zpool_close(zhp); 6749 6750 if (ret != 0 || flags.dryrun || !flags.import) { 6751 nvlist_free(config); 6752 nvlist_free(props); 6753 return (ret); 6754 } 6755 6756 /* 6757 * The split was successful. Now we need to open the new 6758 * pool and import it. 6759 */ 6760 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) { 6761 nvlist_free(config); 6762 nvlist_free(props); 6763 return (1); 6764 } 6765 6766 if (loadkeys) { 6767 ret = zfs_crypto_attempt_load_keys(g_zfs, newpool); 6768 if (ret != 0) 6769 ret = 1; 6770 } 6771 6772 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 6773 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 6774 ret = 1; 6775 (void) fprintf(stderr, gettext("Split was successful, but " 6776 "the datasets could not all be mounted\n")); 6777 (void) fprintf(stderr, gettext("Try doing '%s' with a " 6778 "different altroot\n"), "zpool import"); 6779 } 6780 zpool_close(zhp); 6781 nvlist_free(config); 6782 nvlist_free(props); 6783 6784 return (ret); 6785} 6786 6787 6788 6789/* 6790 * zpool online <pool> <device> ... 6791 */ 6792int 6793zpool_do_online(int argc, char **argv) 6794{ 6795 int c, i; 6796 char *poolname; 6797 zpool_handle_t *zhp; 6798 int ret = 0; 6799 vdev_state_t newstate; 6800 int flags = 0; 6801 6802 /* check options */ 6803 while ((c = getopt(argc, argv, "e")) != -1) { 6804 switch (c) { 6805 case 'e': 6806 flags |= ZFS_ONLINE_EXPAND; 6807 break; 6808 case '?': 6809 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6810 optopt); 6811 usage(B_FALSE); 6812 } 6813 } 6814 6815 argc -= optind; 6816 argv += optind; 6817 6818 /* get pool name and check number of arguments */ 6819 if (argc < 1) { 6820 (void) fprintf(stderr, gettext("missing pool name\n")); 6821 usage(B_FALSE); 6822 } 6823 if (argc < 2) { 6824 (void) fprintf(stderr, gettext("missing device name\n")); 6825 usage(B_FALSE); 6826 } 6827 6828 poolname = argv[0]; 6829 6830 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 6831 return (1); 6832 6833 for (i = 1; i < argc; i++) { 6834 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 6835 if (newstate != VDEV_STATE_HEALTHY) { 6836 (void) printf(gettext("warning: device '%s' " 6837 "onlined, but remains in faulted state\n"), 6838 argv[i]); 6839 if (newstate == VDEV_STATE_FAULTED) 6840 (void) printf(gettext("use 'zpool " 6841 "clear' to restore a faulted " 6842 "device\n")); 6843 else 6844 (void) printf(gettext("use 'zpool " 6845 "replace' to replace devices " 6846 "that are no longer present\n")); 6847 } 6848 } else { 6849 ret = 1; 6850 } 6851 } 6852 6853 zpool_close(zhp); 6854 6855 return (ret); 6856} 6857 6858/* 6859 * zpool offline [-ft] <pool> <device> ... 6860 * 6861 * -f Force the device into a faulted state. 6862 * 6863 * -t Only take the device off-line temporarily. The offline/faulted 6864 * state will not be persistent across reboots. 6865 */ 6866/* ARGSUSED */ 6867int 6868zpool_do_offline(int argc, char **argv) 6869{ 6870 int c, i; 6871 char *poolname; 6872 zpool_handle_t *zhp; 6873 int ret = 0; 6874 boolean_t istmp = B_FALSE; 6875 boolean_t fault = B_FALSE; 6876 6877 /* check options */ 6878 while ((c = getopt(argc, argv, "ft")) != -1) { 6879 switch (c) { 6880 case 'f': 6881 fault = B_TRUE; 6882 break; 6883 case 't': 6884 istmp = B_TRUE; 6885 break; 6886 case '?': 6887 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6888 optopt); 6889 usage(B_FALSE); 6890 } 6891 } 6892 6893 argc -= optind; 6894 argv += optind; 6895 6896 /* get pool name and check number of arguments */ 6897 if (argc < 1) { 6898 (void) fprintf(stderr, gettext("missing pool name\n")); 6899 usage(B_FALSE); 6900 } 6901 if (argc < 2) { 6902 (void) fprintf(stderr, gettext("missing device name\n")); 6903 usage(B_FALSE); 6904 } 6905 6906 poolname = argv[0]; 6907 6908 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 6909 return (1); 6910 6911 for (i = 1; i < argc; i++) { 6912 if (fault) { 6913 uint64_t guid = zpool_vdev_path_to_guid(zhp, argv[i]); 6914 vdev_aux_t aux; 6915 if (istmp == B_FALSE) { 6916 /* Force the fault to persist across imports */ 6917 aux = VDEV_AUX_EXTERNAL_PERSIST; 6918 } else { 6919 aux = VDEV_AUX_EXTERNAL; 6920 } 6921 6922 if (guid == 0 || zpool_vdev_fault(zhp, guid, aux) != 0) 6923 ret = 1; 6924 } else { 6925 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 6926 ret = 1; 6927 } 6928 } 6929 6930 zpool_close(zhp); 6931 6932 return (ret); 6933} 6934 6935/* 6936 * zpool clear <pool> [device] 6937 * 6938 * Clear all errors associated with a pool or a particular device. 6939 */ 6940int 6941zpool_do_clear(int argc, char **argv) 6942{ 6943 int c; 6944 int ret = 0; 6945 boolean_t dryrun = B_FALSE; 6946 boolean_t do_rewind = B_FALSE; 6947 boolean_t xtreme_rewind = B_FALSE; 6948 uint32_t rewind_policy = ZPOOL_NO_REWIND; 6949 nvlist_t *policy = NULL; 6950 zpool_handle_t *zhp; 6951 char *pool, *device; 6952 6953 /* check options */ 6954 while ((c = getopt(argc, argv, "FnX")) != -1) { 6955 switch (c) { 6956 case 'F': 6957 do_rewind = B_TRUE; 6958 break; 6959 case 'n': 6960 dryrun = B_TRUE; 6961 break; 6962 case 'X': 6963 xtreme_rewind = B_TRUE; 6964 break; 6965 case '?': 6966 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6967 optopt); 6968 usage(B_FALSE); 6969 } 6970 } 6971 6972 argc -= optind; 6973 argv += optind; 6974 6975 if (argc < 1) { 6976 (void) fprintf(stderr, gettext("missing pool name\n")); 6977 usage(B_FALSE); 6978 } 6979 6980 if (argc > 2) { 6981 (void) fprintf(stderr, gettext("too many arguments\n")); 6982 usage(B_FALSE); 6983 } 6984 6985 if ((dryrun || xtreme_rewind) && !do_rewind) { 6986 (void) fprintf(stderr, 6987 gettext("-n or -X only meaningful with -F\n")); 6988 usage(B_FALSE); 6989 } 6990 if (dryrun) 6991 rewind_policy = ZPOOL_TRY_REWIND; 6992 else if (do_rewind) 6993 rewind_policy = ZPOOL_DO_REWIND; 6994 if (xtreme_rewind) 6995 rewind_policy |= ZPOOL_EXTREME_REWIND; 6996 6997 /* In future, further rewind policy choices can be passed along here */ 6998 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 6999 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 7000 rewind_policy) != 0) { 7001 return (1); 7002 } 7003 7004 pool = argv[0]; 7005 device = argc == 2 ? argv[1] : NULL; 7006 7007 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 7008 nvlist_free(policy); 7009 return (1); 7010 } 7011 7012 if (zpool_clear(zhp, device, policy) != 0) 7013 ret = 1; 7014 7015 zpool_close(zhp); 7016 7017 nvlist_free(policy); 7018 7019 return (ret); 7020} 7021 7022/* 7023 * zpool reguid <pool> 7024 */ 7025int 7026zpool_do_reguid(int argc, char **argv) 7027{ 7028 int c; 7029 char *poolname; 7030 zpool_handle_t *zhp; 7031 int ret = 0; 7032 7033 /* check options */ 7034 while ((c = getopt(argc, argv, "")) != -1) { 7035 switch (c) { 7036 case '?': 7037 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7038 optopt); 7039 usage(B_FALSE); 7040 } 7041 } 7042 7043 argc -= optind; 7044 argv += optind; 7045 7046 /* get pool name and check number of arguments */ 7047 if (argc < 1) { 7048 (void) fprintf(stderr, gettext("missing pool name\n")); 7049 usage(B_FALSE); 7050 } 7051 7052 if (argc > 1) { 7053 (void) fprintf(stderr, gettext("too many arguments\n")); 7054 usage(B_FALSE); 7055 } 7056 7057 poolname = argv[0]; 7058 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 7059 return (1); 7060 7061 ret = zpool_reguid(zhp); 7062 7063 zpool_close(zhp); 7064 return (ret); 7065} 7066 7067 7068/* 7069 * zpool reopen <pool> 7070 * 7071 * Reopen the pool so that the kernel can update the sizes of all vdevs. 7072 */ 7073int 7074zpool_do_reopen(int argc, char **argv) 7075{ 7076 int c; 7077 int ret = 0; 7078 boolean_t scrub_restart = B_TRUE; 7079 7080 /* check options */ 7081 while ((c = getopt(argc, argv, "n")) != -1) { 7082 switch (c) { 7083 case 'n': 7084 scrub_restart = B_FALSE; 7085 break; 7086 case '?': 7087 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7088 optopt); 7089 usage(B_FALSE); 7090 } 7091 } 7092 7093 argc -= optind; 7094 argv += optind; 7095 7096 /* if argc == 0 we will execute zpool_reopen_one on all pools */ 7097 ret = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, zpool_reopen_one, 7098 &scrub_restart); 7099 7100 return (ret); 7101} 7102 7103typedef struct scrub_cbdata { 7104 int cb_type; 7105 pool_scrub_cmd_t cb_scrub_cmd; 7106} scrub_cbdata_t; 7107 7108static boolean_t 7109zpool_has_checkpoint(zpool_handle_t *zhp) 7110{ 7111 nvlist_t *config, *nvroot; 7112 7113 config = zpool_get_config(zhp, NULL); 7114 7115 if (config != NULL) { 7116 pool_checkpoint_stat_t *pcs = NULL; 7117 uint_t c; 7118 7119 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 7120 (void) nvlist_lookup_uint64_array(nvroot, 7121 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 7122 7123 if (pcs == NULL || pcs->pcs_state == CS_NONE) 7124 return (B_FALSE); 7125 7126 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 7127 pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 7128 return (B_TRUE); 7129 } 7130 7131 return (B_FALSE); 7132} 7133 7134static int 7135scrub_callback(zpool_handle_t *zhp, void *data) 7136{ 7137 scrub_cbdata_t *cb = data; 7138 int err; 7139 7140 /* 7141 * Ignore faulted pools. 7142 */ 7143 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 7144 (void) fprintf(stderr, gettext("cannot scan '%s': pool is " 7145 "currently unavailable\n"), zpool_get_name(zhp)); 7146 return (1); 7147 } 7148 7149 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 7150 7151 if (err == 0 && zpool_has_checkpoint(zhp) && 7152 cb->cb_type == POOL_SCAN_SCRUB) { 7153 (void) printf(gettext("warning: will not scrub state that " 7154 "belongs to the checkpoint of pool '%s'\n"), 7155 zpool_get_name(zhp)); 7156 } 7157 7158 return (err != 0); 7159} 7160 7161static int 7162wait_callback(zpool_handle_t *zhp, void *data) 7163{ 7164 zpool_wait_activity_t *act = data; 7165 return (zpool_wait(zhp, *act)); 7166} 7167 7168/* 7169 * zpool scrub [-s | -p] [-w] <pool> ... 7170 * 7171 * -s Stop. Stops any in-progress scrub. 7172 * -p Pause. Pause in-progress scrub. 7173 * -w Wait. Blocks until scrub has completed. 7174 */ 7175int 7176zpool_do_scrub(int argc, char **argv) 7177{ 7178 int c; 7179 scrub_cbdata_t cb; 7180 boolean_t wait = B_FALSE; 7181 int error; 7182 7183 cb.cb_type = POOL_SCAN_SCRUB; 7184 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 7185 7186 /* check options */ 7187 while ((c = getopt(argc, argv, "spw")) != -1) { 7188 switch (c) { 7189 case 's': 7190 cb.cb_type = POOL_SCAN_NONE; 7191 break; 7192 case 'p': 7193 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 7194 break; 7195 case 'w': 7196 wait = B_TRUE; 7197 break; 7198 case '?': 7199 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7200 optopt); 7201 usage(B_FALSE); 7202 } 7203 } 7204 7205 if (cb.cb_type == POOL_SCAN_NONE && 7206 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 7207 (void) fprintf(stderr, gettext("invalid option combination: " 7208 "-s and -p are mutually exclusive\n")); 7209 usage(B_FALSE); 7210 } 7211 7212 if (wait && (cb.cb_type == POOL_SCAN_NONE || 7213 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE)) { 7214 (void) fprintf(stderr, gettext("invalid option combination: " 7215 "-w cannot be used with -p or -s\n")); 7216 usage(B_FALSE); 7217 } 7218 7219 argc -= optind; 7220 argv += optind; 7221 7222 if (argc < 1) { 7223 (void) fprintf(stderr, gettext("missing pool name argument\n")); 7224 usage(B_FALSE); 7225 } 7226 7227 error = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, 7228 scrub_callback, &cb); 7229 7230 if (wait && !error) { 7231 zpool_wait_activity_t act = ZPOOL_WAIT_SCRUB; 7232 error = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, 7233 wait_callback, &act); 7234 } 7235 7236 return (error); 7237} 7238 7239/* 7240 * zpool resilver <pool> ... 7241 * 7242 * Restarts any in-progress resilver 7243 */ 7244int 7245zpool_do_resilver(int argc, char **argv) 7246{ 7247 int c; 7248 scrub_cbdata_t cb; 7249 7250 cb.cb_type = POOL_SCAN_RESILVER; 7251 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 7252 7253 /* check options */ 7254 while ((c = getopt(argc, argv, "")) != -1) { 7255 switch (c) { 7256 case '?': 7257 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7258 optopt); 7259 usage(B_FALSE); 7260 } 7261 } 7262 7263 argc -= optind; 7264 argv += optind; 7265 7266 if (argc < 1) { 7267 (void) fprintf(stderr, gettext("missing pool name argument\n")); 7268 usage(B_FALSE); 7269 } 7270 7271 return (for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, 7272 scrub_callback, &cb)); 7273} 7274 7275/* 7276 * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...] 7277 * 7278 * -c Cancel. Ends any in-progress trim. 7279 * -d Secure trim. Requires kernel and device support. 7280 * -r <rate> Sets the TRIM rate in bytes (per second). Supports 7281 * adding a multiplier suffix such as 'k' or 'm'. 7282 * -s Suspend. TRIM can then be restarted with no flags. 7283 * -w Wait. Blocks until trimming has completed. 7284 */ 7285int 7286zpool_do_trim(int argc, char **argv) 7287{ 7288 struct option long_options[] = { 7289 {"cancel", no_argument, NULL, 'c'}, 7290 {"secure", no_argument, NULL, 'd'}, 7291 {"rate", required_argument, NULL, 'r'}, 7292 {"suspend", no_argument, NULL, 's'}, 7293 {"wait", no_argument, NULL, 'w'}, 7294 {0, 0, 0, 0} 7295 }; 7296 7297 pool_trim_func_t cmd_type = POOL_TRIM_START; 7298 uint64_t rate = 0; 7299 boolean_t secure = B_FALSE; 7300 boolean_t wait = B_FALSE; 7301 7302 int c; 7303 while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL)) 7304 != -1) { 7305 switch (c) { 7306 case 'c': 7307 if (cmd_type != POOL_TRIM_START && 7308 cmd_type != POOL_TRIM_CANCEL) { 7309 (void) fprintf(stderr, gettext("-c cannot be " 7310 "combined with other options\n")); 7311 usage(B_FALSE); 7312 } 7313 cmd_type = POOL_TRIM_CANCEL; 7314 break; 7315 case 'd': 7316 if (cmd_type != POOL_TRIM_START) { 7317 (void) fprintf(stderr, gettext("-d cannot be " 7318 "combined with the -c or -s options\n")); 7319 usage(B_FALSE); 7320 } 7321 secure = B_TRUE; 7322 break; 7323 case 'r': 7324 if (cmd_type != POOL_TRIM_START) { 7325 (void) fprintf(stderr, gettext("-r cannot be " 7326 "combined with the -c or -s options\n")); 7327 usage(B_FALSE); 7328 } 7329 if (zfs_nicestrtonum(NULL, optarg, &rate) == -1) { 7330 (void) fprintf(stderr, 7331 gettext("invalid value for rate\n")); 7332 usage(B_FALSE); 7333 } 7334 break; 7335 case 's': 7336 if (cmd_type != POOL_TRIM_START && 7337 cmd_type != POOL_TRIM_SUSPEND) { 7338 (void) fprintf(stderr, gettext("-s cannot be " 7339 "combined with other options\n")); 7340 usage(B_FALSE); 7341 } 7342 cmd_type = POOL_TRIM_SUSPEND; 7343 break; 7344 case 'w': 7345 wait = B_TRUE; 7346 break; 7347 case '?': 7348 if (optopt != 0) { 7349 (void) fprintf(stderr, 7350 gettext("invalid option '%c'\n"), optopt); 7351 } else { 7352 (void) fprintf(stderr, 7353 gettext("invalid option '%s'\n"), 7354 argv[optind - 1]); 7355 } 7356 usage(B_FALSE); 7357 } 7358 } 7359 7360 argc -= optind; 7361 argv += optind; 7362 7363 if (argc < 1) { 7364 (void) fprintf(stderr, gettext("missing pool name argument\n")); 7365 usage(B_FALSE); 7366 return (-1); 7367 } 7368 7369 if (wait && (cmd_type != POOL_TRIM_START)) { 7370 (void) fprintf(stderr, gettext("-w cannot be used with -c or " 7371 "-s\n")); 7372 usage(B_FALSE); 7373 } 7374 7375 char *poolname = argv[0]; 7376 zpool_handle_t *zhp = zpool_open(g_zfs, poolname); 7377 if (zhp == NULL) 7378 return (-1); 7379 7380 trimflags_t trim_flags = { 7381 .secure = secure, 7382 .rate = rate, 7383 .wait = wait, 7384 }; 7385 7386 nvlist_t *vdevs = fnvlist_alloc(); 7387 if (argc == 1) { 7388 /* no individual leaf vdevs specified, so add them all */ 7389 nvlist_t *config = zpool_get_config(zhp, NULL); 7390 nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 7391 ZPOOL_CONFIG_VDEV_TREE); 7392 zpool_collect_leaves(zhp, nvroot, vdevs); 7393 trim_flags.fullpool = B_TRUE; 7394 } else { 7395 trim_flags.fullpool = B_FALSE; 7396 for (int i = 1; i < argc; i++) { 7397 fnvlist_add_boolean(vdevs, argv[i]); 7398 } 7399 } 7400 7401 int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags); 7402 7403 fnvlist_free(vdevs); 7404 zpool_close(zhp); 7405 7406 return (error); 7407} 7408 7409/* 7410 * Converts a total number of seconds to a human readable string broken 7411 * down in to days/hours/minutes/seconds. 7412 */ 7413static void 7414secs_to_dhms(uint64_t total, char *buf) 7415{ 7416 uint64_t days = total / 60 / 60 / 24; 7417 uint64_t hours = (total / 60 / 60) % 24; 7418 uint64_t mins = (total / 60) % 60; 7419 uint64_t secs = (total % 60); 7420 7421 if (days > 0) { 7422 (void) sprintf(buf, "%llu days %02llu:%02llu:%02llu", 7423 (u_longlong_t)days, (u_longlong_t)hours, 7424 (u_longlong_t)mins, (u_longlong_t)secs); 7425 } else { 7426 (void) sprintf(buf, "%02llu:%02llu:%02llu", 7427 (u_longlong_t)hours, (u_longlong_t)mins, 7428 (u_longlong_t)secs); 7429 } 7430} 7431 7432/* 7433 * Print out detailed scrub status. 7434 */ 7435static void 7436print_scan_scrub_resilver_status(pool_scan_stat_t *ps) 7437{ 7438 time_t start, end, pause; 7439 uint64_t pass_scanned, scanned, pass_issued, issued, total; 7440 uint64_t elapsed, scan_rate, issue_rate; 7441 double fraction_done; 7442 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; 7443 char srate_buf[7], irate_buf[7], time_buf[32]; 7444 7445 printf(" "); 7446 printf_color(ANSI_BOLD, gettext("scan:")); 7447 printf(" "); 7448 7449 /* If there's never been a scan, there's not much to say. */ 7450 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 7451 ps->pss_func >= POOL_SCAN_FUNCS) { 7452 (void) printf(gettext("none requested\n")); 7453 return; 7454 } 7455 7456 start = ps->pss_start_time; 7457 end = ps->pss_end_time; 7458 pause = ps->pss_pass_scrub_pause; 7459 7460 zfs_nicebytes(ps->pss_processed, processed_buf, sizeof (processed_buf)); 7461 7462 assert(ps->pss_func == POOL_SCAN_SCRUB || 7463 ps->pss_func == POOL_SCAN_RESILVER); 7464 7465 /* Scan is finished or canceled. */ 7466 if (ps->pss_state == DSS_FINISHED) { 7467 secs_to_dhms(end - start, time_buf); 7468 7469 if (ps->pss_func == POOL_SCAN_SCRUB) { 7470 (void) printf(gettext("scrub repaired %s " 7471 "in %s with %llu errors on %s"), processed_buf, 7472 time_buf, (u_longlong_t)ps->pss_errors, 7473 ctime(&end)); 7474 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 7475 (void) printf(gettext("resilvered %s " 7476 "in %s with %llu errors on %s"), processed_buf, 7477 time_buf, (u_longlong_t)ps->pss_errors, 7478 ctime(&end)); 7479 } 7480 return; 7481 } else if (ps->pss_state == DSS_CANCELED) { 7482 if (ps->pss_func == POOL_SCAN_SCRUB) { 7483 (void) printf(gettext("scrub canceled on %s"), 7484 ctime(&end)); 7485 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 7486 (void) printf(gettext("resilver canceled on %s"), 7487 ctime(&end)); 7488 } 7489 return; 7490 } 7491 7492 assert(ps->pss_state == DSS_SCANNING); 7493 7494 /* Scan is in progress. Resilvers can't be paused. */ 7495 if (ps->pss_func == POOL_SCAN_SCRUB) { 7496 if (pause == 0) { 7497 (void) printf(gettext("scrub in progress since %s"), 7498 ctime(&start)); 7499 } else { 7500 (void) printf(gettext("scrub paused since %s"), 7501 ctime(&pause)); 7502 (void) printf(gettext("\tscrub started on %s"), 7503 ctime(&start)); 7504 } 7505 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 7506 (void) printf(gettext("resilver in progress since %s"), 7507 ctime(&start)); 7508 } 7509 7510 scanned = ps->pss_examined; 7511 pass_scanned = ps->pss_pass_exam; 7512 issued = ps->pss_issued; 7513 pass_issued = ps->pss_pass_issued; 7514 total = ps->pss_to_examine; 7515 7516 /* we are only done with a block once we have issued the IO for it */ 7517 fraction_done = (double)issued / total; 7518 7519 /* elapsed time for this pass, rounding up to 1 if it's 0 */ 7520 elapsed = time(NULL) - ps->pss_pass_start; 7521 elapsed -= ps->pss_pass_scrub_spent_paused; 7522 elapsed = (elapsed != 0) ? elapsed : 1; 7523 7524 scan_rate = pass_scanned / elapsed; 7525 issue_rate = pass_issued / elapsed; 7526 uint64_t total_secs_left = (issue_rate != 0 && total >= issued) ? 7527 ((total - issued) / issue_rate) : UINT64_MAX; 7528 secs_to_dhms(total_secs_left, time_buf); 7529 7530 /* format all of the numbers we will be reporting */ 7531 zfs_nicebytes(scanned, scanned_buf, sizeof (scanned_buf)); 7532 zfs_nicebytes(issued, issued_buf, sizeof (issued_buf)); 7533 zfs_nicebytes(total, total_buf, sizeof (total_buf)); 7534 zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf)); 7535 zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf)); 7536 7537 /* do not print estimated time if we have a paused scrub */ 7538 if (pause == 0) { 7539 (void) printf(gettext("\t%s scanned at %s/s, " 7540 "%s issued at %s/s, %s total\n"), 7541 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); 7542 } else { 7543 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), 7544 scanned_buf, issued_buf, total_buf); 7545 } 7546 7547 if (ps->pss_func == POOL_SCAN_RESILVER) { 7548 (void) printf(gettext("\t%s resilvered, %.2f%% done"), 7549 processed_buf, 100 * fraction_done); 7550 } else if (ps->pss_func == POOL_SCAN_SCRUB) { 7551 (void) printf(gettext("\t%s repaired, %.2f%% done"), 7552 processed_buf, 100 * fraction_done); 7553 } 7554 7555 if (pause == 0) { 7556 if (total_secs_left != UINT64_MAX && 7557 issue_rate >= 10 * 1024 * 1024) { 7558 (void) printf(gettext(", %s to go\n"), time_buf); 7559 } else { 7560 (void) printf(gettext(", no estimated " 7561 "completion time\n")); 7562 } 7563 } else { 7564 (void) printf(gettext("\n")); 7565 } 7566} 7567 7568static void 7569print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name) 7570{ 7571 if (vrs == NULL || vrs->vrs_state == VDEV_REBUILD_NONE) 7572 return; 7573 7574 printf(" "); 7575 printf_color(ANSI_BOLD, gettext("scan:")); 7576 printf(" "); 7577 7578 uint64_t bytes_scanned = vrs->vrs_bytes_scanned; 7579 uint64_t bytes_issued = vrs->vrs_bytes_issued; 7580 uint64_t bytes_rebuilt = vrs->vrs_bytes_rebuilt; 7581 uint64_t bytes_est = vrs->vrs_bytes_est; 7582 uint64_t scan_rate = (vrs->vrs_pass_bytes_scanned / 7583 (vrs->vrs_pass_time_ms + 1)) * 1000; 7584 uint64_t issue_rate = (vrs->vrs_pass_bytes_issued / 7585 (vrs->vrs_pass_time_ms + 1)) * 1000; 7586 double scan_pct = MIN((double)bytes_scanned * 100 / 7587 (bytes_est + 1), 100); 7588 7589 /* Format all of the numbers we will be reporting */ 7590 char bytes_scanned_buf[7], bytes_issued_buf[7]; 7591 char bytes_rebuilt_buf[7], bytes_est_buf[7]; 7592 char scan_rate_buf[7], issue_rate_buf[7], time_buf[32]; 7593 zfs_nicebytes(bytes_scanned, bytes_scanned_buf, 7594 sizeof (bytes_scanned_buf)); 7595 zfs_nicebytes(bytes_issued, bytes_issued_buf, 7596 sizeof (bytes_issued_buf)); 7597 zfs_nicebytes(bytes_rebuilt, bytes_rebuilt_buf, 7598 sizeof (bytes_rebuilt_buf)); 7599 zfs_nicebytes(bytes_est, bytes_est_buf, sizeof (bytes_est_buf)); 7600 zfs_nicebytes(scan_rate, scan_rate_buf, sizeof (scan_rate_buf)); 7601 zfs_nicebytes(issue_rate, issue_rate_buf, sizeof (issue_rate_buf)); 7602 7603 time_t start = vrs->vrs_start_time; 7604 time_t end = vrs->vrs_end_time; 7605 7606 /* Rebuild is finished or canceled. */ 7607 if (vrs->vrs_state == VDEV_REBUILD_COMPLETE) { 7608 secs_to_dhms(vrs->vrs_scan_time_ms / 1000, time_buf); 7609 (void) printf(gettext("resilvered (%s) %s in %s " 7610 "with %llu errors on %s"), vdev_name, bytes_rebuilt_buf, 7611 time_buf, (u_longlong_t)vrs->vrs_errors, ctime(&end)); 7612 return; 7613 } else if (vrs->vrs_state == VDEV_REBUILD_CANCELED) { 7614 (void) printf(gettext("resilver (%s) canceled on %s"), 7615 vdev_name, ctime(&end)); 7616 return; 7617 } else if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) { 7618 (void) printf(gettext("resilver (%s) in progress since %s"), 7619 vdev_name, ctime(&start)); 7620 } 7621 7622 assert(vrs->vrs_state == VDEV_REBUILD_ACTIVE); 7623 7624 secs_to_dhms(MAX((int64_t)bytes_est - (int64_t)bytes_scanned, 0) / 7625 MAX(scan_rate, 1), time_buf); 7626 7627 (void) printf(gettext("\t%s scanned at %s/s, %s issued %s/s, " 7628 "%s total\n"), bytes_scanned_buf, scan_rate_buf, 7629 bytes_issued_buf, issue_rate_buf, bytes_est_buf); 7630 (void) printf(gettext("\t%s resilvered, %.2f%% done"), 7631 bytes_rebuilt_buf, scan_pct); 7632 7633 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) { 7634 if (scan_rate >= 10 * 1024 * 1024) { 7635 (void) printf(gettext(", %s to go\n"), time_buf); 7636 } else { 7637 (void) printf(gettext(", no estimated " 7638 "completion time\n")); 7639 } 7640 } else { 7641 (void) printf(gettext("\n")); 7642 } 7643} 7644 7645/* 7646 * Print rebuild status for top-level vdevs. 7647 */ 7648static void 7649print_rebuild_status(zpool_handle_t *zhp, nvlist_t *nvroot) 7650{ 7651 nvlist_t **child; 7652 uint_t children; 7653 7654 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 7655 &child, &children) != 0) 7656 children = 0; 7657 7658 for (uint_t c = 0; c < children; c++) { 7659 vdev_rebuild_stat_t *vrs; 7660 uint_t i; 7661 7662 if (nvlist_lookup_uint64_array(child[c], 7663 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) { 7664 char *name = zpool_vdev_name(g_zfs, zhp, 7665 child[c], VDEV_NAME_TYPE_ID); 7666 print_rebuild_status_impl(vrs, name); 7667 free(name); 7668 } 7669 } 7670} 7671 7672/* 7673 * As we don't scrub checkpointed blocks, we want to warn the user that we 7674 * skipped scanning some blocks if a checkpoint exists or existed at any 7675 * time during the scan. If a sequential instead of healing reconstruction 7676 * was performed then the blocks were reconstructed. However, their checksums 7677 * have not been verified so we still print the warning. 7678 */ 7679static void 7680print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 7681{ 7682 if (ps == NULL || pcs == NULL) 7683 return; 7684 7685 if (pcs->pcs_state == CS_NONE || 7686 pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 7687 return; 7688 7689 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 7690 7691 if (ps->pss_state == DSS_NONE) 7692 return; 7693 7694 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 7695 ps->pss_end_time < pcs->pcs_start_time) 7696 return; 7697 7698 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 7699 (void) printf(gettext(" scan warning: skipped blocks " 7700 "that are only referenced by the checkpoint.\n")); 7701 } else { 7702 assert(ps->pss_state == DSS_SCANNING); 7703 (void) printf(gettext(" scan warning: skipping blocks " 7704 "that are only referenced by the checkpoint.\n")); 7705 } 7706} 7707 7708/* 7709 * Returns B_TRUE if there is an active rebuild in progress. Otherwise, 7710 * B_FALSE is returned and 'rebuild_end_time' is set to the end time for 7711 * the last completed (or cancelled) rebuild. 7712 */ 7713static boolean_t 7714check_rebuilding(nvlist_t *nvroot, uint64_t *rebuild_end_time) 7715{ 7716 nvlist_t **child; 7717 uint_t children; 7718 boolean_t rebuilding = B_FALSE; 7719 uint64_t end_time = 0; 7720 7721 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 7722 &child, &children) != 0) 7723 children = 0; 7724 7725 for (uint_t c = 0; c < children; c++) { 7726 vdev_rebuild_stat_t *vrs; 7727 uint_t i; 7728 7729 if (nvlist_lookup_uint64_array(child[c], 7730 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) { 7731 7732 if (vrs->vrs_end_time > end_time) 7733 end_time = vrs->vrs_end_time; 7734 7735 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) { 7736 rebuilding = B_TRUE; 7737 end_time = 0; 7738 break; 7739 } 7740 } 7741 } 7742 7743 if (rebuild_end_time != NULL) 7744 *rebuild_end_time = end_time; 7745 7746 return (rebuilding); 7747} 7748 7749/* 7750 * Print the scan status. 7751 */ 7752static void 7753print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot) 7754{ 7755 uint64_t rebuild_end_time = 0, resilver_end_time = 0; 7756 boolean_t have_resilver = B_FALSE, have_scrub = B_FALSE; 7757 boolean_t active_resilver = B_FALSE; 7758 pool_checkpoint_stat_t *pcs = NULL; 7759 pool_scan_stat_t *ps = NULL; 7760 uint_t c; 7761 7762 if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS, 7763 (uint64_t **)&ps, &c) == 0) { 7764 if (ps->pss_func == POOL_SCAN_RESILVER) { 7765 resilver_end_time = ps->pss_end_time; 7766 active_resilver = (ps->pss_state == DSS_SCANNING); 7767 } 7768 7769 have_resilver = (ps->pss_func == POOL_SCAN_RESILVER); 7770 have_scrub = (ps->pss_func == POOL_SCAN_SCRUB); 7771 } 7772 7773 boolean_t active_rebuild = check_rebuilding(nvroot, &rebuild_end_time); 7774 boolean_t have_rebuild = (active_rebuild || (rebuild_end_time > 0)); 7775 7776 /* Always print the scrub status when available. */ 7777 if (have_scrub) 7778 print_scan_scrub_resilver_status(ps); 7779 7780 /* 7781 * When there is an active resilver or rebuild print its status. 7782 * Otherwise print the status of the last resilver or rebuild. 7783 */ 7784 if (active_resilver || (!active_rebuild && have_resilver && 7785 resilver_end_time && resilver_end_time > rebuild_end_time)) { 7786 print_scan_scrub_resilver_status(ps); 7787 } else if (active_rebuild || (!active_resilver && have_rebuild && 7788 rebuild_end_time && rebuild_end_time > resilver_end_time)) { 7789 print_rebuild_status(zhp, nvroot); 7790 } 7791 7792 (void) nvlist_lookup_uint64_array(nvroot, 7793 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 7794 print_checkpoint_scan_warning(ps, pcs); 7795} 7796 7797/* 7798 * Print out detailed removal status. 7799 */ 7800static void 7801print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 7802{ 7803 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 7804 time_t start, end; 7805 nvlist_t *config, *nvroot; 7806 nvlist_t **child; 7807 uint_t children; 7808 char *vdev_name; 7809 7810 if (prs == NULL || prs->prs_state == DSS_NONE) 7811 return; 7812 7813 /* 7814 * Determine name of vdev. 7815 */ 7816 config = zpool_get_config(zhp, NULL); 7817 nvroot = fnvlist_lookup_nvlist(config, 7818 ZPOOL_CONFIG_VDEV_TREE); 7819 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 7820 &child, &children) == 0); 7821 assert(prs->prs_removing_vdev < children); 7822 vdev_name = zpool_vdev_name(g_zfs, zhp, 7823 child[prs->prs_removing_vdev], B_TRUE); 7824 7825 printf_color(ANSI_BOLD, gettext("remove: ")); 7826 7827 start = prs->prs_start_time; 7828 end = prs->prs_end_time; 7829 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 7830 7831 /* 7832 * Removal is finished or canceled. 7833 */ 7834 if (prs->prs_state == DSS_FINISHED) { 7835 uint64_t minutes_taken = (end - start) / 60; 7836 7837 (void) printf(gettext("Removal of vdev %llu copied %s " 7838 "in %lluh%um, completed on %s"), 7839 (longlong_t)prs->prs_removing_vdev, 7840 copied_buf, 7841 (u_longlong_t)(minutes_taken / 60), 7842 (uint_t)(minutes_taken % 60), 7843 ctime((time_t *)&end)); 7844 } else if (prs->prs_state == DSS_CANCELED) { 7845 (void) printf(gettext("Removal of %s canceled on %s"), 7846 vdev_name, ctime(&end)); 7847 } else { 7848 uint64_t copied, total, elapsed, mins_left, hours_left; 7849 double fraction_done; 7850 uint_t rate; 7851 7852 assert(prs->prs_state == DSS_SCANNING); 7853 7854 /* 7855 * Removal is in progress. 7856 */ 7857 (void) printf(gettext( 7858 "Evacuation of %s in progress since %s"), 7859 vdev_name, ctime(&start)); 7860 7861 copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 7862 total = prs->prs_to_copy; 7863 fraction_done = (double)copied / total; 7864 7865 /* elapsed time for this pass */ 7866 elapsed = time(NULL) - prs->prs_start_time; 7867 elapsed = elapsed > 0 ? elapsed : 1; 7868 rate = copied / elapsed; 7869 rate = rate > 0 ? rate : 1; 7870 mins_left = ((total - copied) / rate) / 60; 7871 hours_left = mins_left / 60; 7872 7873 zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 7874 zfs_nicenum(total, total_buf, sizeof (total_buf)); 7875 zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 7876 7877 /* 7878 * do not print estimated time if hours_left is more than 7879 * 30 days 7880 */ 7881 (void) printf(gettext( 7882 "\t%s copied out of %s at %s/s, %.2f%% done"), 7883 examined_buf, total_buf, rate_buf, 100 * fraction_done); 7884 if (hours_left < (30 * 24)) { 7885 (void) printf(gettext(", %lluh%um to go\n"), 7886 (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 7887 } else { 7888 (void) printf(gettext( 7889 ", (copy is slow, no estimated time)\n")); 7890 } 7891 } 7892 free(vdev_name); 7893 7894 if (prs->prs_mapping_memory > 0) { 7895 char mem_buf[7]; 7896 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 7897 (void) printf(gettext( 7898 "\t%s memory used for removed device mappings\n"), 7899 mem_buf); 7900 } 7901} 7902 7903static void 7904print_checkpoint_status(pool_checkpoint_stat_t *pcs) 7905{ 7906 time_t start; 7907 char space_buf[7]; 7908 7909 if (pcs == NULL || pcs->pcs_state == CS_NONE) 7910 return; 7911 7912 (void) printf(gettext("checkpoint: ")); 7913 7914 start = pcs->pcs_start_time; 7915 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 7916 7917 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 7918 char *date = ctime(&start); 7919 7920 /* 7921 * ctime() adds a newline at the end of the generated 7922 * string, thus the weird format specifier and the 7923 * strlen() call used to chop it off from the output. 7924 */ 7925 (void) printf(gettext("created %.*s, consumes %s\n"), 7926 (int)(strlen(date) - 1), date, space_buf); 7927 return; 7928 } 7929 7930 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 7931 7932 (void) printf(gettext("discarding, %s remaining.\n"), 7933 space_buf); 7934} 7935 7936static void 7937print_error_log(zpool_handle_t *zhp) 7938{ 7939 nvlist_t *nverrlist = NULL; 7940 nvpair_t *elem; 7941 char *pathname; 7942 size_t len = MAXPATHLEN * 2; 7943 7944 if (zpool_get_errlog(zhp, &nverrlist) != 0) 7945 return; 7946 7947 (void) printf("errors: Permanent errors have been " 7948 "detected in the following files:\n\n"); 7949 7950 pathname = safe_malloc(len); 7951 elem = NULL; 7952 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 7953 nvlist_t *nv; 7954 uint64_t dsobj, obj; 7955 7956 verify(nvpair_value_nvlist(elem, &nv) == 0); 7957 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 7958 &dsobj) == 0); 7959 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 7960 &obj) == 0); 7961 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 7962 (void) printf("%7s %s\n", "", pathname); 7963 } 7964 free(pathname); 7965 nvlist_free(nverrlist); 7966} 7967 7968static void 7969print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares, 7970 uint_t nspares) 7971{ 7972 uint_t i; 7973 char *name; 7974 7975 if (nspares == 0) 7976 return; 7977 7978 (void) printf(gettext("\tspares\n")); 7979 7980 for (i = 0; i < nspares; i++) { 7981 name = zpool_vdev_name(g_zfs, zhp, spares[i], 7982 cb->cb_name_flags); 7983 print_status_config(zhp, cb, name, spares[i], 2, B_TRUE, NULL); 7984 free(name); 7985 } 7986} 7987 7988static void 7989print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache, 7990 uint_t nl2cache) 7991{ 7992 uint_t i; 7993 char *name; 7994 7995 if (nl2cache == 0) 7996 return; 7997 7998 (void) printf(gettext("\tcache\n")); 7999 8000 for (i = 0; i < nl2cache; i++) { 8001 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], 8002 cb->cb_name_flags); 8003 print_status_config(zhp, cb, name, l2cache[i], 2, 8004 B_FALSE, NULL); 8005 free(name); 8006 } 8007} 8008 8009static void 8010print_dedup_stats(nvlist_t *config) 8011{ 8012 ddt_histogram_t *ddh; 8013 ddt_stat_t *dds; 8014 ddt_object_t *ddo; 8015 uint_t c; 8016 char dspace[6], mspace[6]; 8017 8018 /* 8019 * If the pool was faulted then we may not have been able to 8020 * obtain the config. Otherwise, if we have anything in the dedup 8021 * table continue processing the stats. 8022 */ 8023 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 8024 (uint64_t **)&ddo, &c) != 0) 8025 return; 8026 8027 (void) printf("\n"); 8028 (void) printf(gettext(" dedup: ")); 8029 if (ddo->ddo_count == 0) { 8030 (void) printf(gettext("no DDT entries\n")); 8031 return; 8032 } 8033 8034 zfs_nicebytes(ddo->ddo_dspace, dspace, sizeof (dspace)); 8035 zfs_nicebytes(ddo->ddo_mspace, mspace, sizeof (mspace)); 8036 (void) printf("DDT entries %llu, size %s on disk, %s in core\n", 8037 (u_longlong_t)ddo->ddo_count, 8038 dspace, 8039 mspace); 8040 8041 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 8042 (uint64_t **)&dds, &c) == 0); 8043 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 8044 (uint64_t **)&ddh, &c) == 0); 8045 zpool_dump_ddt(dds, ddh); 8046} 8047 8048/* 8049 * Display a summary of pool status. Displays a summary such as: 8050 * 8051 * pool: tank 8052 * status: DEGRADED 8053 * reason: One or more devices ... 8054 * see: https://openzfs.github.io/openzfs-docs/msg/ZFS-xxxx-01 8055 * config: 8056 * mirror DEGRADED 8057 * c1t0d0 OK 8058 * c2t0d0 UNAVAIL 8059 * 8060 * When given the '-v' option, we print out the complete config. If the '-e' 8061 * option is specified, then we print out error rate information as well. 8062 */ 8063static int 8064status_callback(zpool_handle_t *zhp, void *data) 8065{ 8066 status_cbdata_t *cbp = data; 8067 nvlist_t *config, *nvroot; 8068 char *msgid; 8069 zpool_status_t reason; 8070 zpool_errata_t errata; 8071 const char *health; 8072 uint_t c; 8073 vdev_stat_t *vs; 8074 8075 config = zpool_get_config(zhp, NULL); 8076 reason = zpool_get_status(zhp, &msgid, &errata); 8077 8078 cbp->cb_count++; 8079 8080 /* 8081 * If we were given 'zpool status -x', only report those pools with 8082 * problems. 8083 */ 8084 if (cbp->cb_explain && 8085 (reason == ZPOOL_STATUS_OK || 8086 reason == ZPOOL_STATUS_VERSION_OLDER || 8087 reason == ZPOOL_STATUS_FEAT_DISABLED || 8088 reason == ZPOOL_STATUS_COMPATIBILITY_ERR || 8089 reason == ZPOOL_STATUS_INCOMPATIBLE_FEAT)) { 8090 if (!cbp->cb_allpools) { 8091 (void) printf(gettext("pool '%s' is healthy\n"), 8092 zpool_get_name(zhp)); 8093 if (cbp->cb_first) 8094 cbp->cb_first = B_FALSE; 8095 } 8096 return (0); 8097 } 8098 8099 if (cbp->cb_first) 8100 cbp->cb_first = B_FALSE; 8101 else 8102 (void) printf("\n"); 8103 8104 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 8105 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 8106 (uint64_t **)&vs, &c) == 0); 8107 8108 health = zpool_get_state_str(zhp); 8109 8110 printf(" "); 8111 printf_color(ANSI_BOLD, gettext("pool:")); 8112 printf(" %s\n", zpool_get_name(zhp)); 8113 printf(" "); 8114 printf_color(ANSI_BOLD, gettext("state: ")); 8115 8116 printf_color(health_str_to_color(health), "%s", health); 8117 8118 printf("\n"); 8119 8120 switch (reason) { 8121 case ZPOOL_STATUS_MISSING_DEV_R: 8122 printf_color(ANSI_BOLD, gettext("status: ")); 8123 printf_color(ANSI_YELLOW, gettext("One or more devices could " 8124 "not be opened. Sufficient replicas exist for\n\tthe pool " 8125 "to continue functioning in a degraded state.\n")); 8126 printf_color(ANSI_BOLD, gettext("action: ")); 8127 printf_color(ANSI_YELLOW, gettext("Attach the missing device " 8128 "and online it using 'zpool online'.\n")); 8129 break; 8130 8131 case ZPOOL_STATUS_MISSING_DEV_NR: 8132 printf_color(ANSI_BOLD, gettext("status: ")); 8133 printf_color(ANSI_YELLOW, gettext("One or more devices could " 8134 "not be opened. There are insufficient\n\treplicas for the" 8135 " pool to continue functioning.\n")); 8136 printf_color(ANSI_BOLD, gettext("action: ")); 8137 printf_color(ANSI_YELLOW, gettext("Attach the missing device " 8138 "and online it using 'zpool online'.\n")); 8139 break; 8140 8141 case ZPOOL_STATUS_CORRUPT_LABEL_R: 8142 printf_color(ANSI_BOLD, gettext("status: ")); 8143 printf_color(ANSI_YELLOW, gettext("One or more devices could " 8144 "not be used because the label is missing or\n\tinvalid. " 8145 "Sufficient replicas exist for the pool to continue\n\t" 8146 "functioning in a degraded state.\n")); 8147 printf_color(ANSI_BOLD, gettext("action: ")); 8148 printf_color(ANSI_YELLOW, gettext("Replace the device using " 8149 "'zpool replace'.\n")); 8150 break; 8151 8152 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 8153 printf_color(ANSI_BOLD, gettext("status: ")); 8154 printf_color(ANSI_YELLOW, gettext("One or more devices could " 8155 "not be used because the label is missing \n\tor invalid. " 8156 "There are insufficient replicas for the pool to " 8157 "continue\n\tfunctioning.\n")); 8158 zpool_explain_recover(zpool_get_handle(zhp), 8159 zpool_get_name(zhp), reason, config); 8160 break; 8161 8162 case ZPOOL_STATUS_FAILING_DEV: 8163 printf_color(ANSI_BOLD, gettext("status: ")); 8164 printf_color(ANSI_YELLOW, gettext("One or more devices has " 8165 "experienced an unrecoverable error. An\n\tattempt was " 8166 "made to correct the error. Applications are " 8167 "unaffected.\n")); 8168 printf_color(ANSI_BOLD, gettext("action: ")); 8169 printf_color(ANSI_YELLOW, gettext("Determine if the " 8170 "device needs to be replaced, and clear the errors\n\tusing" 8171 " 'zpool clear' or replace the device with 'zpool " 8172 "replace'.\n")); 8173 break; 8174 8175 case ZPOOL_STATUS_OFFLINE_DEV: 8176 printf_color(ANSI_BOLD, gettext("status: ")); 8177 printf_color(ANSI_YELLOW, gettext("One or more devices has " 8178 "been taken offline by the administrator.\n\tSufficient " 8179 "replicas exist for the pool to continue functioning in " 8180 "a\n\tdegraded state.\n")); 8181 printf_color(ANSI_BOLD, gettext("action: ")); 8182 printf_color(ANSI_YELLOW, gettext("Online the device " 8183 "using 'zpool online' or replace the device with\n\t'zpool " 8184 "replace'.\n")); 8185 break; 8186 8187 case ZPOOL_STATUS_REMOVED_DEV: 8188 printf_color(ANSI_BOLD, gettext("status: ")); 8189 printf_color(ANSI_YELLOW, gettext("One or more devices has " 8190 "been removed by the administrator.\n\tSufficient " 8191 "replicas exist for the pool to continue functioning in " 8192 "a\n\tdegraded state.\n")); 8193 printf_color(ANSI_BOLD, gettext("action: ")); 8194 printf_color(ANSI_YELLOW, gettext("Online the device " 8195 "using zpool online' or replace the device with\n\t'zpool " 8196 "replace'.\n")); 8197 break; 8198 8199 case ZPOOL_STATUS_RESILVERING: 8200 case ZPOOL_STATUS_REBUILDING: 8201 printf_color(ANSI_BOLD, gettext("status: ")); 8202 printf_color(ANSI_YELLOW, gettext("One or more devices is " 8203 "currently being resilvered. The pool will\n\tcontinue " 8204 "to function, possibly in a degraded state.\n")); 8205 printf_color(ANSI_BOLD, gettext("action: ")); 8206 printf_color(ANSI_YELLOW, gettext("Wait for the resilver to " 8207 "complete.\n")); 8208 break; 8209 8210 case ZPOOL_STATUS_REBUILD_SCRUB: 8211 printf_color(ANSI_BOLD, gettext("status: ")); 8212 printf_color(ANSI_YELLOW, gettext("One or more devices have " 8213 "been sequentially resilvered, scrubbing\n\tthe pool " 8214 "is recommended.\n")); 8215 printf_color(ANSI_BOLD, gettext("action: ")); 8216 printf_color(ANSI_YELLOW, gettext("Use 'zpool scrub' to " 8217 "verify all data checksums.\n")); 8218 break; 8219 8220 case ZPOOL_STATUS_CORRUPT_DATA: 8221 printf_color(ANSI_BOLD, gettext("status: ")); 8222 printf_color(ANSI_YELLOW, gettext("One or more devices has " 8223 "experienced an error resulting in data\n\tcorruption. " 8224 "Applications may be affected.\n")); 8225 printf_color(ANSI_BOLD, gettext("action: ")); 8226 printf_color(ANSI_YELLOW, gettext("Restore the file in question" 8227 " if possible. Otherwise restore the\n\tentire pool from " 8228 "backup.\n")); 8229 break; 8230 8231 case ZPOOL_STATUS_CORRUPT_POOL: 8232 printf_color(ANSI_BOLD, gettext("status: ")); 8233 printf_color(ANSI_YELLOW, gettext("The pool metadata is " 8234 "corrupted and the pool cannot be opened.\n")); 8235 zpool_explain_recover(zpool_get_handle(zhp), 8236 zpool_get_name(zhp), reason, config); 8237 break; 8238 8239 case ZPOOL_STATUS_VERSION_OLDER: 8240 printf_color(ANSI_BOLD, gettext("status: ")); 8241 printf_color(ANSI_YELLOW, gettext("The pool is formatted using " 8242 "a legacy on-disk format. The pool can\n\tstill be used, " 8243 "but some features are unavailable.\n")); 8244 printf_color(ANSI_BOLD, gettext("action: ")); 8245 printf_color(ANSI_YELLOW, gettext("Upgrade the pool using " 8246 "'zpool upgrade'. Once this is done, the\n\tpool will no " 8247 "longer be accessible on software that does not support\n\t" 8248 "feature flags.\n")); 8249 break; 8250 8251 case ZPOOL_STATUS_VERSION_NEWER: 8252 printf_color(ANSI_BOLD, gettext("status: ")); 8253 printf_color(ANSI_YELLOW, gettext("The pool has been upgraded " 8254 "to a newer, incompatible on-disk version.\n\tThe pool " 8255 "cannot be accessed on this system.\n")); 8256 printf_color(ANSI_BOLD, gettext("action: ")); 8257 printf_color(ANSI_YELLOW, gettext("Access the pool from a " 8258 "system running more recent software, or\n\trestore the " 8259 "pool from backup.\n")); 8260 break; 8261 8262 case ZPOOL_STATUS_FEAT_DISABLED: 8263 printf_color(ANSI_BOLD, gettext("status: ")); 8264 printf_color(ANSI_YELLOW, gettext("Some supported and " 8265 "requested features are not enabled on the pool.\n\t" 8266 "The pool can still be used, but some features are " 8267 "unavailable.\n")); 8268 printf_color(ANSI_BOLD, gettext("action: ")); 8269 printf_color(ANSI_YELLOW, gettext("Enable all features using " 8270 "'zpool upgrade'. Once this is done,\n\tthe pool may no " 8271 "longer be accessible by software that does not support\n\t" 8272 "the features. See zpool-features(7) for details.\n")); 8273 break; 8274 8275 case ZPOOL_STATUS_COMPATIBILITY_ERR: 8276 printf_color(ANSI_BOLD, gettext("status: ")); 8277 printf_color(ANSI_YELLOW, gettext("This pool has a " 8278 "compatibility list specified, but it could not be\n\t" 8279 "read/parsed at this time. The pool can still be used, " 8280 "but this\n\tshould be investigated.\n")); 8281 printf_color(ANSI_BOLD, gettext("action: ")); 8282 printf_color(ANSI_YELLOW, gettext("Check the value of the " 8283 "'compatibility' property against the\n\t" 8284 "appropriate file in " ZPOOL_SYSCONF_COMPAT_D " or " 8285 ZPOOL_DATA_COMPAT_D ".\n")); 8286 break; 8287 8288 case ZPOOL_STATUS_INCOMPATIBLE_FEAT: 8289 printf_color(ANSI_BOLD, gettext("status: ")); 8290 printf_color(ANSI_YELLOW, gettext("One or more features " 8291 "are enabled on the pool despite not being\n\t" 8292 "requested by the 'compatibility' property.\n")); 8293 printf_color(ANSI_BOLD, gettext("action: ")); 8294 printf_color(ANSI_YELLOW, gettext("Consider setting " 8295 "'compatibility' to an appropriate value, or\n\t" 8296 "adding needed features to the relevant file in\n\t" 8297 ZPOOL_SYSCONF_COMPAT_D " or " ZPOOL_DATA_COMPAT_D ".\n")); 8298 break; 8299 8300 case ZPOOL_STATUS_UNSUP_FEAT_READ: 8301 printf_color(ANSI_BOLD, gettext("status: ")); 8302 printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed " 8303 "on this system because it uses the\n\tfollowing feature(s)" 8304 " not supported on this system:\n")); 8305 zpool_print_unsup_feat(config); 8306 (void) printf("\n"); 8307 printf_color(ANSI_BOLD, gettext("action: ")); 8308 printf_color(ANSI_YELLOW, gettext("Access the pool from a " 8309 "system that supports the required feature(s),\n\tor " 8310 "restore the pool from backup.\n")); 8311 break; 8312 8313 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 8314 printf_color(ANSI_BOLD, gettext("status: ")); 8315 printf_color(ANSI_YELLOW, gettext("The pool can only be " 8316 "accessed in read-only mode on this system. It\n\tcannot be" 8317 " accessed in read-write mode because it uses the " 8318 "following\n\tfeature(s) not supported on this system:\n")); 8319 zpool_print_unsup_feat(config); 8320 (void) printf("\n"); 8321 printf_color(ANSI_BOLD, gettext("action: ")); 8322 printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed " 8323 "in read-write mode. Import the pool with\n" 8324 "\t\"-o readonly=on\", access the pool from a system that " 8325 "supports the\n\trequired feature(s), or restore the " 8326 "pool from backup.\n")); 8327 break; 8328 8329 case ZPOOL_STATUS_FAULTED_DEV_R: 8330 printf_color(ANSI_BOLD, gettext("status: ")); 8331 printf_color(ANSI_YELLOW, gettext("One or more devices are " 8332 "faulted in response to persistent errors.\n\tSufficient " 8333 "replicas exist for the pool to continue functioning " 8334 "in a\n\tdegraded state.\n")); 8335 printf_color(ANSI_BOLD, gettext("action: ")); 8336 printf_color(ANSI_YELLOW, gettext("Replace the faulted device, " 8337 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 8338 break; 8339 8340 case ZPOOL_STATUS_FAULTED_DEV_NR: 8341 printf_color(ANSI_BOLD, gettext("status: ")); 8342 printf_color(ANSI_YELLOW, gettext("One or more devices are " 8343 "faulted in response to persistent errors. There are " 8344 "insufficient replicas for the pool to\n\tcontinue " 8345 "functioning.\n")); 8346 printf_color(ANSI_BOLD, gettext("action: ")); 8347 printf_color(ANSI_YELLOW, gettext("Destroy and re-create the " 8348 "pool from a backup source. Manually marking the device\n" 8349 "\trepaired using 'zpool clear' may allow some data " 8350 "to be recovered.\n")); 8351 break; 8352 8353 case ZPOOL_STATUS_IO_FAILURE_MMP: 8354 printf_color(ANSI_BOLD, gettext("status: ")); 8355 printf_color(ANSI_YELLOW, gettext("The pool is suspended " 8356 "because multihost writes failed or were delayed;\n\t" 8357 "another system could import the pool undetected.\n")); 8358 printf_color(ANSI_BOLD, gettext("action: ")); 8359 printf_color(ANSI_YELLOW, gettext("Make sure the pool's devices" 8360 " are connected, then reboot your system and\n\timport the " 8361 "pool.\n")); 8362 break; 8363 8364 case ZPOOL_STATUS_IO_FAILURE_WAIT: 8365 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 8366 printf_color(ANSI_BOLD, gettext("status: ")); 8367 printf_color(ANSI_YELLOW, gettext("One or more devices are " 8368 "faulted in response to IO failures.\n")); 8369 printf_color(ANSI_BOLD, gettext("action: ")); 8370 printf_color(ANSI_YELLOW, gettext("Make sure the affected " 8371 "devices are connected, then run 'zpool clear'.\n")); 8372 break; 8373 8374 case ZPOOL_STATUS_BAD_LOG: 8375 printf_color(ANSI_BOLD, gettext("status: ")); 8376 printf_color(ANSI_YELLOW, gettext("An intent log record " 8377 "could not be read.\n" 8378 "\tWaiting for administrator intervention to fix the " 8379 "faulted pool.\n")); 8380 printf_color(ANSI_BOLD, gettext("action: ")); 8381 printf_color(ANSI_YELLOW, gettext("Either restore the affected " 8382 "device(s) and run 'zpool online',\n" 8383 "\tor ignore the intent log records by running " 8384 "'zpool clear'.\n")); 8385 break; 8386 8387 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 8388 (void) printf(gettext("status: One or more devices are " 8389 "configured to use a non-native block size.\n" 8390 "\tExpect reduced performance.\n")); 8391 (void) printf(gettext("action: Replace affected devices with " 8392 "devices that support the\n\tconfigured block size, or " 8393 "migrate data to a properly configured\n\tpool.\n")); 8394 break; 8395 8396 case ZPOOL_STATUS_HOSTID_MISMATCH: 8397 printf_color(ANSI_BOLD, gettext("status: ")); 8398 printf_color(ANSI_YELLOW, gettext("Mismatch between pool hostid" 8399 " and system hostid on imported pool.\n\tThis pool was " 8400 "previously imported into a system with a different " 8401 "hostid,\n\tand then was verbatim imported into this " 8402 "system.\n")); 8403 printf_color(ANSI_BOLD, gettext("action: ")); 8404 printf_color(ANSI_YELLOW, gettext("Export this pool on all " 8405 "systems on which it is imported.\n" 8406 "\tThen import it to correct the mismatch.\n")); 8407 break; 8408 8409 case ZPOOL_STATUS_ERRATA: 8410 printf_color(ANSI_BOLD, gettext("status: ")); 8411 printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"), 8412 errata); 8413 8414 switch (errata) { 8415 case ZPOOL_ERRATA_NONE: 8416 break; 8417 8418 case ZPOOL_ERRATA_ZOL_2094_SCRUB: 8419 printf_color(ANSI_BOLD, gettext("action: ")); 8420 printf_color(ANSI_YELLOW, gettext("To correct the issue" 8421 " run 'zpool scrub'.\n")); 8422 break; 8423 8424 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 8425 (void) printf(gettext("\tExisting encrypted datasets " 8426 "contain an on-disk incompatibility\n\twhich " 8427 "needs to be corrected.\n")); 8428 printf_color(ANSI_BOLD, gettext("action: ")); 8429 printf_color(ANSI_YELLOW, gettext("To correct the issue" 8430 " backup existing encrypted datasets to new\n\t" 8431 "encrypted datasets and destroy the old ones. " 8432 "'zfs mount -o ro' can\n\tbe used to temporarily " 8433 "mount existing encrypted datasets readonly.\n")); 8434 break; 8435 8436 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 8437 (void) printf(gettext("\tExisting encrypted snapshots " 8438 "and bookmarks contain an on-disk\n\tincompat" 8439 "ibility. This may cause on-disk corruption if " 8440 "they are used\n\twith 'zfs recv'.\n")); 8441 printf_color(ANSI_BOLD, gettext("action: ")); 8442 printf_color(ANSI_YELLOW, gettext("To correct the" 8443 "issue, enable the bookmark_v2 feature. No " 8444 "additional\n\taction is needed if there are no " 8445 "encrypted snapshots or bookmarks.\n\tIf preserving" 8446 "the encrypted snapshots and bookmarks is required," 8447 " use\n\ta non-raw send to backup and restore them." 8448 " Alternately, they may be\n\tremoved to resolve " 8449 "the incompatibility.\n")); 8450 break; 8451 8452 default: 8453 /* 8454 * All errata which allow the pool to be imported 8455 * must contain an action message. 8456 */ 8457 assert(0); 8458 } 8459 break; 8460 8461 default: 8462 /* 8463 * The remaining errors can't actually be generated, yet. 8464 */ 8465 assert(reason == ZPOOL_STATUS_OK); 8466 } 8467 8468 if (msgid != NULL) { 8469 printf(" "); 8470 printf_color(ANSI_BOLD, gettext("see:")); 8471 printf(gettext( 8472 " https://openzfs.github.io/openzfs-docs/msg/%s\n"), 8473 msgid); 8474 } 8475 8476 if (config != NULL) { 8477 uint64_t nerr; 8478 nvlist_t **spares, **l2cache; 8479 uint_t nspares, nl2cache; 8480 pool_checkpoint_stat_t *pcs = NULL; 8481 pool_removal_stat_t *prs = NULL; 8482 8483 print_scan_status(zhp, nvroot); 8484 8485 (void) nvlist_lookup_uint64_array(nvroot, 8486 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 8487 print_removal_status(zhp, prs); 8488 8489 (void) nvlist_lookup_uint64_array(nvroot, 8490 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 8491 print_checkpoint_status(pcs); 8492 8493 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 8494 cbp->cb_name_flags | VDEV_NAME_TYPE_ID); 8495 if (cbp->cb_namewidth < 10) 8496 cbp->cb_namewidth = 10; 8497 8498 color_start(ANSI_BOLD); 8499 (void) printf(gettext("config:\n\n")); 8500 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s"), 8501 cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE", 8502 "CKSUM"); 8503 color_end(); 8504 8505 if (cbp->cb_print_slow_ios) { 8506 printf_color(ANSI_BOLD, " %5s", gettext("SLOW")); 8507 } 8508 8509 if (cbp->vcdl != NULL) 8510 print_cmd_columns(cbp->vcdl, 0); 8511 8512 printf("\n"); 8513 8514 print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0, 8515 B_FALSE, NULL); 8516 8517 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP); 8518 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 8519 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS); 8520 8521 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 8522 &l2cache, &nl2cache) == 0) 8523 print_l2cache(zhp, cbp, l2cache, nl2cache); 8524 8525 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 8526 &spares, &nspares) == 0) 8527 print_spares(zhp, cbp, spares, nspares); 8528 8529 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 8530 &nerr) == 0) { 8531 nvlist_t *nverrlist = NULL; 8532 8533 /* 8534 * If the approximate error count is small, get a 8535 * precise count by fetching the entire log and 8536 * uniquifying the results. 8537 */ 8538 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 8539 zpool_get_errlog(zhp, &nverrlist) == 0) { 8540 nvpair_t *elem; 8541 8542 elem = NULL; 8543 nerr = 0; 8544 while ((elem = nvlist_next_nvpair(nverrlist, 8545 elem)) != NULL) { 8546 nerr++; 8547 } 8548 } 8549 nvlist_free(nverrlist); 8550 8551 (void) printf("\n"); 8552 8553 if (nerr == 0) 8554 (void) printf(gettext("errors: No known data " 8555 "errors\n")); 8556 else if (!cbp->cb_verbose) 8557 (void) printf(gettext("errors: %llu data " 8558 "errors, use '-v' for a list\n"), 8559 (u_longlong_t)nerr); 8560 else 8561 print_error_log(zhp); 8562 } 8563 8564 if (cbp->cb_dedup_stats) 8565 print_dedup_stats(config); 8566 } else { 8567 (void) printf(gettext("config: The configuration cannot be " 8568 "determined.\n")); 8569 } 8570 8571 return (0); 8572} 8573 8574/* 8575 * zpool status [-c [script1,script2,...]] [-igLpPstvx] [-T d|u] [pool] ... 8576 * [interval [count]] 8577 * 8578 * -c CMD For each vdev, run command CMD 8579 * -i Display vdev initialization status. 8580 * -g Display guid for individual vdev name. 8581 * -L Follow links when resolving vdev path name. 8582 * -p Display values in parsable (exact) format. 8583 * -P Display full path for vdev name. 8584 * -s Display slow IOs column. 8585 * -v Display complete error logs 8586 * -x Display only pools with potential problems 8587 * -D Display dedup status (undocumented) 8588 * -t Display vdev TRIM status. 8589 * -T Display a timestamp in date(1) or Unix format 8590 * 8591 * Describes the health status of all pools or some subset. 8592 */ 8593int 8594zpool_do_status(int argc, char **argv) 8595{ 8596 int c; 8597 int ret; 8598 float interval = 0; 8599 unsigned long count = 0; 8600 status_cbdata_t cb = { 0 }; 8601 char *cmd = NULL; 8602 8603 /* check options */ 8604 while ((c = getopt(argc, argv, "c:igLpPsvxDtT:")) != -1) { 8605 switch (c) { 8606 case 'c': 8607 if (cmd != NULL) { 8608 fprintf(stderr, 8609 gettext("Can't set -c flag twice\n")); 8610 exit(1); 8611 } 8612 8613 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL && 8614 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) { 8615 fprintf(stderr, gettext( 8616 "Can't run -c, disabled by " 8617 "ZPOOL_SCRIPTS_ENABLED.\n")); 8618 exit(1); 8619 } 8620 8621 if ((getuid() <= 0 || geteuid() <= 0) && 8622 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) { 8623 fprintf(stderr, gettext( 8624 "Can't run -c with root privileges " 8625 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n")); 8626 exit(1); 8627 } 8628 cmd = optarg; 8629 break; 8630 case 'i': 8631 cb.cb_print_vdev_init = B_TRUE; 8632 break; 8633 case 'g': 8634 cb.cb_name_flags |= VDEV_NAME_GUID; 8635 break; 8636 case 'L': 8637 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 8638 break; 8639 case 'p': 8640 cb.cb_literal = B_TRUE; 8641 break; 8642 case 'P': 8643 cb.cb_name_flags |= VDEV_NAME_PATH; 8644 break; 8645 case 's': 8646 cb.cb_print_slow_ios = B_TRUE; 8647 break; 8648 case 'v': 8649 cb.cb_verbose = B_TRUE; 8650 break; 8651 case 'x': 8652 cb.cb_explain = B_TRUE; 8653 break; 8654 case 'D': 8655 cb.cb_dedup_stats = B_TRUE; 8656 break; 8657 case 't': 8658 cb.cb_print_vdev_trim = B_TRUE; 8659 break; 8660 case 'T': 8661 get_timestamp_arg(*optarg); 8662 break; 8663 case '?': 8664 if (optopt == 'c') { 8665 print_zpool_script_list("status"); 8666 exit(0); 8667 } else { 8668 fprintf(stderr, 8669 gettext("invalid option '%c'\n"), optopt); 8670 } 8671 usage(B_FALSE); 8672 } 8673 } 8674 8675 argc -= optind; 8676 argv += optind; 8677 8678 get_interval_count(&argc, argv, &interval, &count); 8679 8680 if (argc == 0) 8681 cb.cb_allpools = B_TRUE; 8682 8683 cb.cb_first = B_TRUE; 8684 cb.cb_print_status = B_TRUE; 8685 8686 for (;;) { 8687 if (timestamp_fmt != NODATE) 8688 print_timestamp(timestamp_fmt); 8689 8690 if (cmd != NULL) 8691 cb.vcdl = all_pools_for_each_vdev_run(argc, argv, cmd, 8692 NULL, NULL, 0, 0); 8693 8694 ret = for_each_pool(argc, argv, B_TRUE, NULL, cb.cb_literal, 8695 status_callback, &cb); 8696 8697 if (cb.vcdl != NULL) 8698 free_vdev_cmd_data_list(cb.vcdl); 8699 8700 if (argc == 0 && cb.cb_count == 0) 8701 (void) fprintf(stderr, gettext("no pools available\n")); 8702 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 8703 (void) printf(gettext("all pools are healthy\n")); 8704 8705 if (ret != 0) 8706 return (ret); 8707 8708 if (interval == 0) 8709 break; 8710 8711 if (count != 0 && --count == 0) 8712 break; 8713 8714 (void) fsleep(interval); 8715 } 8716 8717 return (0); 8718} 8719 8720typedef struct upgrade_cbdata { 8721 int cb_first; 8722 int cb_argc; 8723 uint64_t cb_version; 8724 char **cb_argv; 8725} upgrade_cbdata_t; 8726 8727static int 8728check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs) 8729{ 8730 int zfs_version = (int)zfs_prop_get_int(zhp, ZFS_PROP_VERSION); 8731 int *count = (int *)unsupp_fs; 8732 8733 if (zfs_version > ZPL_VERSION) { 8734 (void) printf(gettext("%s (v%d) is not supported by this " 8735 "implementation of ZFS.\n"), 8736 zfs_get_name(zhp), zfs_version); 8737 (*count)++; 8738 } 8739 8740 zfs_iter_filesystems(zhp, check_unsupp_fs, unsupp_fs); 8741 8742 zfs_close(zhp); 8743 8744 return (0); 8745} 8746 8747static int 8748upgrade_version(zpool_handle_t *zhp, uint64_t version) 8749{ 8750 int ret; 8751 nvlist_t *config; 8752 uint64_t oldversion; 8753 int unsupp_fs = 0; 8754 8755 config = zpool_get_config(zhp, NULL); 8756 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 8757 &oldversion) == 0); 8758 8759 char compat[ZFS_MAXPROPLEN]; 8760 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat, 8761 ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) 8762 compat[0] = '\0'; 8763 8764 assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 8765 assert(oldversion < version); 8766 8767 ret = zfs_iter_root(zpool_get_handle(zhp), check_unsupp_fs, &unsupp_fs); 8768 if (ret != 0) 8769 return (ret); 8770 8771 if (unsupp_fs) { 8772 (void) fprintf(stderr, gettext("Upgrade not performed due " 8773 "to %d unsupported filesystems (max v%d).\n"), 8774 unsupp_fs, (int)ZPL_VERSION); 8775 return (1); 8776 } 8777 8778 if (strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) { 8779 (void) fprintf(stderr, gettext("Upgrade not performed because " 8780 "'compatibility' property set to '" 8781 ZPOOL_COMPAT_LEGACY "'.\n")); 8782 return (1); 8783 } 8784 8785 ret = zpool_upgrade(zhp, version); 8786 if (ret != 0) 8787 return (ret); 8788 8789 if (version >= SPA_VERSION_FEATURES) { 8790 (void) printf(gettext("Successfully upgraded " 8791 "'%s' from version %llu to feature flags.\n"), 8792 zpool_get_name(zhp), (u_longlong_t)oldversion); 8793 } else { 8794 (void) printf(gettext("Successfully upgraded " 8795 "'%s' from version %llu to version %llu.\n"), 8796 zpool_get_name(zhp), (u_longlong_t)oldversion, 8797 (u_longlong_t)version); 8798 } 8799 8800 return (0); 8801} 8802 8803static int 8804upgrade_enable_all(zpool_handle_t *zhp, int *countp) 8805{ 8806 int i, ret, count; 8807 boolean_t firstff = B_TRUE; 8808 nvlist_t *enabled = zpool_get_features(zhp); 8809 8810 char compat[ZFS_MAXPROPLEN]; 8811 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat, 8812 ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) 8813 compat[0] = '\0'; 8814 8815 boolean_t requested_features[SPA_FEATURES]; 8816 if (zpool_do_load_compat(compat, requested_features) != 8817 ZPOOL_COMPATIBILITY_OK) 8818 return (-1); 8819 8820 count = 0; 8821 for (i = 0; i < SPA_FEATURES; i++) { 8822 const char *fname = spa_feature_table[i].fi_uname; 8823 const char *fguid = spa_feature_table[i].fi_guid; 8824 8825 if (!spa_feature_table[i].fi_zfs_mod_supported) 8826 continue; 8827 8828 if (!nvlist_exists(enabled, fguid) && requested_features[i]) { 8829 char *propname; 8830 verify(-1 != asprintf(&propname, "feature@%s", fname)); 8831 ret = zpool_set_prop(zhp, propname, 8832 ZFS_FEATURE_ENABLED); 8833 if (ret != 0) { 8834 free(propname); 8835 return (ret); 8836 } 8837 count++; 8838 8839 if (firstff) { 8840 (void) printf(gettext("Enabled the " 8841 "following features on '%s':\n"), 8842 zpool_get_name(zhp)); 8843 firstff = B_FALSE; 8844 } 8845 (void) printf(gettext(" %s\n"), fname); 8846 free(propname); 8847 } 8848 } 8849 8850 if (countp != NULL) 8851 *countp = count; 8852 return (0); 8853} 8854 8855static int 8856upgrade_cb(zpool_handle_t *zhp, void *arg) 8857{ 8858 upgrade_cbdata_t *cbp = arg; 8859 nvlist_t *config; 8860 uint64_t version; 8861 boolean_t modified_pool = B_FALSE; 8862 int ret; 8863 8864 config = zpool_get_config(zhp, NULL); 8865 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 8866 &version) == 0); 8867 8868 assert(SPA_VERSION_IS_SUPPORTED(version)); 8869 8870 if (version < cbp->cb_version) { 8871 cbp->cb_first = B_FALSE; 8872 ret = upgrade_version(zhp, cbp->cb_version); 8873 if (ret != 0) 8874 return (ret); 8875 modified_pool = B_TRUE; 8876 8877 /* 8878 * If they did "zpool upgrade -a", then we could 8879 * be doing ioctls to different pools. We need 8880 * to log this history once to each pool, and bypass 8881 * the normal history logging that happens in main(). 8882 */ 8883 (void) zpool_log_history(g_zfs, history_str); 8884 log_history = B_FALSE; 8885 } 8886 8887 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 8888 int count; 8889 ret = upgrade_enable_all(zhp, &count); 8890 if (ret != 0) 8891 return (ret); 8892 8893 if (count > 0) { 8894 cbp->cb_first = B_FALSE; 8895 modified_pool = B_TRUE; 8896 } 8897 } 8898 8899 if (modified_pool) { 8900 (void) printf("\n"); 8901 (void) after_zpool_upgrade(zhp); 8902 } 8903 8904 return (0); 8905} 8906 8907static int 8908upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 8909{ 8910 upgrade_cbdata_t *cbp = arg; 8911 nvlist_t *config; 8912 uint64_t version; 8913 8914 config = zpool_get_config(zhp, NULL); 8915 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 8916 &version) == 0); 8917 8918 assert(SPA_VERSION_IS_SUPPORTED(version)); 8919 8920 if (version < SPA_VERSION_FEATURES) { 8921 if (cbp->cb_first) { 8922 (void) printf(gettext("The following pools are " 8923 "formatted with legacy version numbers and can\n" 8924 "be upgraded to use feature flags. After " 8925 "being upgraded, these pools\nwill no " 8926 "longer be accessible by software that does not " 8927 "support feature\nflags.\n\n" 8928 "Note that setting a pool's 'compatibility' " 8929 "feature to '" ZPOOL_COMPAT_LEGACY "' will\n" 8930 "inhibit upgrades.\n\n")); 8931 (void) printf(gettext("VER POOL\n")); 8932 (void) printf(gettext("--- ------------\n")); 8933 cbp->cb_first = B_FALSE; 8934 } 8935 8936 (void) printf("%2llu %s\n", (u_longlong_t)version, 8937 zpool_get_name(zhp)); 8938 } 8939 8940 return (0); 8941} 8942 8943static int 8944upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 8945{ 8946 upgrade_cbdata_t *cbp = arg; 8947 nvlist_t *config; 8948 uint64_t version; 8949 8950 config = zpool_get_config(zhp, NULL); 8951 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 8952 &version) == 0); 8953 8954 if (version >= SPA_VERSION_FEATURES) { 8955 int i; 8956 boolean_t poolfirst = B_TRUE; 8957 nvlist_t *enabled = zpool_get_features(zhp); 8958 8959 for (i = 0; i < SPA_FEATURES; i++) { 8960 const char *fguid = spa_feature_table[i].fi_guid; 8961 const char *fname = spa_feature_table[i].fi_uname; 8962 8963 if (!spa_feature_table[i].fi_zfs_mod_supported) 8964 continue; 8965 8966 if (!nvlist_exists(enabled, fguid)) { 8967 if (cbp->cb_first) { 8968 (void) printf(gettext("\nSome " 8969 "supported features are not " 8970 "enabled on the following pools. " 8971 "Once a\nfeature is enabled the " 8972 "pool may become incompatible with " 8973 "software\nthat does not support " 8974 "the feature. See " 8975 "zpool-features(7) for " 8976 "details.\n\n" 8977 "Note that the pool " 8978 "'compatibility' feature can be " 8979 "used to inhibit\nfeature " 8980 "upgrades.\n\n")); 8981 (void) printf(gettext("POOL " 8982 "FEATURE\n")); 8983 (void) printf(gettext("------" 8984 "---------\n")); 8985 cbp->cb_first = B_FALSE; 8986 } 8987 8988 if (poolfirst) { 8989 (void) printf(gettext("%s\n"), 8990 zpool_get_name(zhp)); 8991 poolfirst = B_FALSE; 8992 } 8993 8994 (void) printf(gettext(" %s\n"), fname); 8995 } 8996 /* 8997 * If they did "zpool upgrade -a", then we could 8998 * be doing ioctls to different pools. We need 8999 * to log this history once to each pool, and bypass 9000 * the normal history logging that happens in main(). 9001 */ 9002 (void) zpool_log_history(g_zfs, history_str); 9003 log_history = B_FALSE; 9004 } 9005 } 9006 9007 return (0); 9008} 9009 9010/* ARGSUSED */ 9011static int 9012upgrade_one(zpool_handle_t *zhp, void *data) 9013{ 9014 boolean_t modified_pool = B_FALSE; 9015 upgrade_cbdata_t *cbp = data; 9016 uint64_t cur_version; 9017 int ret; 9018 9019 if (strcmp("log", zpool_get_name(zhp)) == 0) { 9020 (void) fprintf(stderr, gettext("'log' is now a reserved word\n" 9021 "Pool 'log' must be renamed using export and import" 9022 " to upgrade.\n")); 9023 return (1); 9024 } 9025 9026 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 9027 if (cur_version > cbp->cb_version) { 9028 (void) printf(gettext("Pool '%s' is already formatted " 9029 "using more current version '%llu'.\n\n"), 9030 zpool_get_name(zhp), (u_longlong_t)cur_version); 9031 return (0); 9032 } 9033 9034 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 9035 (void) printf(gettext("Pool '%s' is already formatted " 9036 "using version %llu.\n\n"), zpool_get_name(zhp), 9037 (u_longlong_t)cbp->cb_version); 9038 return (0); 9039 } 9040 9041 if (cur_version != cbp->cb_version) { 9042 modified_pool = B_TRUE; 9043 ret = upgrade_version(zhp, cbp->cb_version); 9044 if (ret != 0) 9045 return (ret); 9046 } 9047 9048 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 9049 int count = 0; 9050 ret = upgrade_enable_all(zhp, &count); 9051 if (ret != 0) 9052 return (ret); 9053 9054 if (count != 0) { 9055 modified_pool = B_TRUE; 9056 } else if (cur_version == SPA_VERSION) { 9057 (void) printf(gettext("Pool '%s' already has all " 9058 "supported and requested features enabled.\n"), 9059 zpool_get_name(zhp)); 9060 } 9061 } 9062 9063 if (modified_pool) { 9064 (void) printf("\n"); 9065 (void) after_zpool_upgrade(zhp); 9066 } 9067 9068 return (0); 9069} 9070 9071/* 9072 * zpool upgrade 9073 * zpool upgrade -v 9074 * zpool upgrade [-V version] <-a | pool ...> 9075 * 9076 * With no arguments, display downrev'd ZFS pool available for upgrade. 9077 * Individual pools can be upgraded by specifying the pool, and '-a' will 9078 * upgrade all pools. 9079 */ 9080int 9081zpool_do_upgrade(int argc, char **argv) 9082{ 9083 int c; 9084 upgrade_cbdata_t cb = { 0 }; 9085 int ret = 0; 9086 boolean_t showversions = B_FALSE; 9087 boolean_t upgradeall = B_FALSE; 9088 char *end; 9089 9090 9091 /* check options */ 9092 while ((c = getopt(argc, argv, ":avV:")) != -1) { 9093 switch (c) { 9094 case 'a': 9095 upgradeall = B_TRUE; 9096 break; 9097 case 'v': 9098 showversions = B_TRUE; 9099 break; 9100 case 'V': 9101 cb.cb_version = strtoll(optarg, &end, 10); 9102 if (*end != '\0' || 9103 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 9104 (void) fprintf(stderr, 9105 gettext("invalid version '%s'\n"), optarg); 9106 usage(B_FALSE); 9107 } 9108 break; 9109 case ':': 9110 (void) fprintf(stderr, gettext("missing argument for " 9111 "'%c' option\n"), optopt); 9112 usage(B_FALSE); 9113 break; 9114 case '?': 9115 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 9116 optopt); 9117 usage(B_FALSE); 9118 } 9119 } 9120 9121 cb.cb_argc = argc; 9122 cb.cb_argv = argv; 9123 argc -= optind; 9124 argv += optind; 9125 9126 if (cb.cb_version == 0) { 9127 cb.cb_version = SPA_VERSION; 9128 } else if (!upgradeall && argc == 0) { 9129 (void) fprintf(stderr, gettext("-V option is " 9130 "incompatible with other arguments\n")); 9131 usage(B_FALSE); 9132 } 9133 9134 if (showversions) { 9135 if (upgradeall || argc != 0) { 9136 (void) fprintf(stderr, gettext("-v option is " 9137 "incompatible with other arguments\n")); 9138 usage(B_FALSE); 9139 } 9140 } else if (upgradeall) { 9141 if (argc != 0) { 9142 (void) fprintf(stderr, gettext("-a option should not " 9143 "be used along with a pool name\n")); 9144 usage(B_FALSE); 9145 } 9146 } 9147 9148 (void) printf(gettext("This system supports ZFS pool feature " 9149 "flags.\n\n")); 9150 if (showversions) { 9151 int i; 9152 9153 (void) printf(gettext("The following features are " 9154 "supported:\n\n")); 9155 (void) printf(gettext("FEAT DESCRIPTION\n")); 9156 (void) printf("----------------------------------------------" 9157 "---------------\n"); 9158 for (i = 0; i < SPA_FEATURES; i++) { 9159 zfeature_info_t *fi = &spa_feature_table[i]; 9160 if (!fi->fi_zfs_mod_supported) 9161 continue; 9162 const char *ro = 9163 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 9164 " (read-only compatible)" : ""; 9165 9166 (void) printf("%-37s%s\n", fi->fi_uname, ro); 9167 (void) printf(" %s\n", fi->fi_desc); 9168 } 9169 (void) printf("\n"); 9170 9171 (void) printf(gettext("The following legacy versions are also " 9172 "supported:\n\n")); 9173 (void) printf(gettext("VER DESCRIPTION\n")); 9174 (void) printf("--- -----------------------------------------" 9175 "---------------\n"); 9176 (void) printf(gettext(" 1 Initial ZFS version\n")); 9177 (void) printf(gettext(" 2 Ditto blocks " 9178 "(replicated metadata)\n")); 9179 (void) printf(gettext(" 3 Hot spares and double parity " 9180 "RAID-Z\n")); 9181 (void) printf(gettext(" 4 zpool history\n")); 9182 (void) printf(gettext(" 5 Compression using the gzip " 9183 "algorithm\n")); 9184 (void) printf(gettext(" 6 bootfs pool property\n")); 9185 (void) printf(gettext(" 7 Separate intent log devices\n")); 9186 (void) printf(gettext(" 8 Delegated administration\n")); 9187 (void) printf(gettext(" 9 refquota and refreservation " 9188 "properties\n")); 9189 (void) printf(gettext(" 10 Cache devices\n")); 9190 (void) printf(gettext(" 11 Improved scrub performance\n")); 9191 (void) printf(gettext(" 12 Snapshot properties\n")); 9192 (void) printf(gettext(" 13 snapused property\n")); 9193 (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 9194 (void) printf(gettext(" 15 user/group space accounting\n")); 9195 (void) printf(gettext(" 16 stmf property support\n")); 9196 (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 9197 (void) printf(gettext(" 18 Snapshot user holds\n")); 9198 (void) printf(gettext(" 19 Log device removal\n")); 9199 (void) printf(gettext(" 20 Compression using zle " 9200 "(zero-length encoding)\n")); 9201 (void) printf(gettext(" 21 Deduplication\n")); 9202 (void) printf(gettext(" 22 Received properties\n")); 9203 (void) printf(gettext(" 23 Slim ZIL\n")); 9204 (void) printf(gettext(" 24 System attributes\n")); 9205 (void) printf(gettext(" 25 Improved scrub stats\n")); 9206 (void) printf(gettext(" 26 Improved snapshot deletion " 9207 "performance\n")); 9208 (void) printf(gettext(" 27 Improved snapshot creation " 9209 "performance\n")); 9210 (void) printf(gettext(" 28 Multiple vdev replacements\n")); 9211 (void) printf(gettext("\nFor more information on a particular " 9212 "version, including supported releases,\n")); 9213 (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 9214 } else if (argc == 0 && upgradeall) { 9215 cb.cb_first = B_TRUE; 9216 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 9217 if (ret == 0 && cb.cb_first) { 9218 if (cb.cb_version == SPA_VERSION) { 9219 (void) printf(gettext("All pools are already " 9220 "formatted using feature flags.\n\n")); 9221 (void) printf(gettext("Every feature flags " 9222 "pool already has all supported and " 9223 "requested features enabled.\n")); 9224 } else { 9225 (void) printf(gettext("All pools are already " 9226 "formatted with version %llu or higher.\n"), 9227 (u_longlong_t)cb.cb_version); 9228 } 9229 } 9230 } else if (argc == 0) { 9231 cb.cb_first = B_TRUE; 9232 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 9233 assert(ret == 0); 9234 9235 if (cb.cb_first) { 9236 (void) printf(gettext("All pools are formatted " 9237 "using feature flags.\n\n")); 9238 } else { 9239 (void) printf(gettext("\nUse 'zpool upgrade -v' " 9240 "for a list of available legacy versions.\n")); 9241 } 9242 9243 cb.cb_first = B_TRUE; 9244 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 9245 assert(ret == 0); 9246 9247 if (cb.cb_first) { 9248 (void) printf(gettext("Every feature flags pool has " 9249 "all supported and requested features enabled.\n")); 9250 } else { 9251 (void) printf(gettext("\n")); 9252 } 9253 } else { 9254 ret = for_each_pool(argc, argv, B_FALSE, NULL, B_FALSE, 9255 upgrade_one, &cb); 9256 } 9257 9258 return (ret); 9259} 9260 9261typedef struct hist_cbdata { 9262 boolean_t first; 9263 boolean_t longfmt; 9264 boolean_t internal; 9265} hist_cbdata_t; 9266 9267static void 9268print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb) 9269{ 9270 nvlist_t **records; 9271 uint_t numrecords; 9272 int i; 9273 9274 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 9275 &records, &numrecords) == 0); 9276 for (i = 0; i < numrecords; i++) { 9277 nvlist_t *rec = records[i]; 9278 char tbuf[64] = ""; 9279 9280 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 9281 time_t tsec; 9282 struct tm t; 9283 9284 tsec = fnvlist_lookup_uint64(records[i], 9285 ZPOOL_HIST_TIME); 9286 (void) localtime_r(&tsec, &t); 9287 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 9288 } 9289 9290 if (nvlist_exists(rec, ZPOOL_HIST_ELAPSED_NS)) { 9291 uint64_t elapsed_ns = fnvlist_lookup_int64(records[i], 9292 ZPOOL_HIST_ELAPSED_NS); 9293 (void) snprintf(tbuf + strlen(tbuf), 9294 sizeof (tbuf) - strlen(tbuf), 9295 " (%lldms)", (long long)elapsed_ns / 1000 / 1000); 9296 } 9297 9298 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 9299 (void) printf("%s %s", tbuf, 9300 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 9301 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 9302 int ievent = 9303 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 9304 if (!cb->internal) 9305 continue; 9306 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 9307 (void) printf("%s unrecognized record:\n", 9308 tbuf); 9309 dump_nvlist(rec, 4); 9310 continue; 9311 } 9312 (void) printf("%s [internal %s txg:%lld] %s", tbuf, 9313 zfs_history_event_names[ievent], 9314 (longlong_t)fnvlist_lookup_uint64( 9315 rec, ZPOOL_HIST_TXG), 9316 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 9317 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 9318 if (!cb->internal) 9319 continue; 9320 (void) printf("%s [txg:%lld] %s", tbuf, 9321 (longlong_t)fnvlist_lookup_uint64( 9322 rec, ZPOOL_HIST_TXG), 9323 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 9324 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 9325 (void) printf(" %s (%llu)", 9326 fnvlist_lookup_string(rec, 9327 ZPOOL_HIST_DSNAME), 9328 (u_longlong_t)fnvlist_lookup_uint64(rec, 9329 ZPOOL_HIST_DSID)); 9330 } 9331 (void) printf(" %s", fnvlist_lookup_string(rec, 9332 ZPOOL_HIST_INT_STR)); 9333 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 9334 if (!cb->internal) 9335 continue; 9336 (void) printf("%s ioctl %s\n", tbuf, 9337 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 9338 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 9339 (void) printf(" input:\n"); 9340 dump_nvlist(fnvlist_lookup_nvlist(rec, 9341 ZPOOL_HIST_INPUT_NVL), 8); 9342 } 9343 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 9344 (void) printf(" output:\n"); 9345 dump_nvlist(fnvlist_lookup_nvlist(rec, 9346 ZPOOL_HIST_OUTPUT_NVL), 8); 9347 } 9348 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_SIZE)) { 9349 (void) printf(" output nvlist omitted; " 9350 "original size: %lldKB\n", 9351 (longlong_t)fnvlist_lookup_int64(rec, 9352 ZPOOL_HIST_OUTPUT_SIZE) / 1024); 9353 } 9354 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 9355 (void) printf(" errno: %lld\n", 9356 (longlong_t)fnvlist_lookup_int64(rec, 9357 ZPOOL_HIST_ERRNO)); 9358 } 9359 } else { 9360 if (!cb->internal) 9361 continue; 9362 (void) printf("%s unrecognized record:\n", tbuf); 9363 dump_nvlist(rec, 4); 9364 } 9365 9366 if (!cb->longfmt) { 9367 (void) printf("\n"); 9368 continue; 9369 } 9370 (void) printf(" ["); 9371 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 9372 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 9373 struct passwd *pwd = getpwuid(who); 9374 (void) printf("user %d ", (int)who); 9375 if (pwd != NULL) 9376 (void) printf("(%s) ", pwd->pw_name); 9377 } 9378 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 9379 (void) printf("on %s", 9380 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 9381 } 9382 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 9383 (void) printf(":%s", 9384 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 9385 } 9386 9387 (void) printf("]"); 9388 (void) printf("\n"); 9389 } 9390} 9391 9392/* 9393 * Print out the command history for a specific pool. 9394 */ 9395static int 9396get_history_one(zpool_handle_t *zhp, void *data) 9397{ 9398 nvlist_t *nvhis; 9399 int ret; 9400 hist_cbdata_t *cb = (hist_cbdata_t *)data; 9401 uint64_t off = 0; 9402 boolean_t eof = B_FALSE; 9403 9404 cb->first = B_FALSE; 9405 9406 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 9407 9408 while (!eof) { 9409 if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0) 9410 return (ret); 9411 9412 print_history_records(nvhis, cb); 9413 nvlist_free(nvhis); 9414 } 9415 (void) printf("\n"); 9416 9417 return (ret); 9418} 9419 9420/* 9421 * zpool history <pool> 9422 * 9423 * Displays the history of commands that modified pools. 9424 */ 9425int 9426zpool_do_history(int argc, char **argv) 9427{ 9428 hist_cbdata_t cbdata = { 0 }; 9429 int ret; 9430 int c; 9431 9432 cbdata.first = B_TRUE; 9433 /* check options */ 9434 while ((c = getopt(argc, argv, "li")) != -1) { 9435 switch (c) { 9436 case 'l': 9437 cbdata.longfmt = B_TRUE; 9438 break; 9439 case 'i': 9440 cbdata.internal = B_TRUE; 9441 break; 9442 case '?': 9443 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 9444 optopt); 9445 usage(B_FALSE); 9446 } 9447 } 9448 argc -= optind; 9449 argv += optind; 9450 9451 ret = for_each_pool(argc, argv, B_FALSE, NULL, B_FALSE, get_history_one, 9452 &cbdata); 9453 9454 if (argc == 0 && cbdata.first == B_TRUE) { 9455 (void) fprintf(stderr, gettext("no pools available\n")); 9456 return (0); 9457 } 9458 9459 return (ret); 9460} 9461 9462typedef struct ev_opts { 9463 int verbose; 9464 int scripted; 9465 int follow; 9466 int clear; 9467 char poolname[ZFS_MAX_DATASET_NAME_LEN]; 9468} ev_opts_t; 9469 9470static void 9471zpool_do_events_short(nvlist_t *nvl, ev_opts_t *opts) 9472{ 9473 char ctime_str[26], str[32], *ptr; 9474 int64_t *tv; 9475 uint_t n; 9476 9477 verify(nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0); 9478 memset(str, ' ', 32); 9479 (void) ctime_r((const time_t *)&tv[0], ctime_str); 9480 (void) memcpy(str, ctime_str+4, 6); /* 'Jun 30' */ 9481 (void) memcpy(str+7, ctime_str+20, 4); /* '1993' */ 9482 (void) memcpy(str+12, ctime_str+11, 8); /* '21:49:08' */ 9483 (void) sprintf(str+20, ".%09lld", (longlong_t)tv[1]); /* '.123456789' */ 9484 if (opts->scripted) 9485 (void) printf(gettext("%s\t"), str); 9486 else 9487 (void) printf(gettext("%s "), str); 9488 9489 verify(nvlist_lookup_string(nvl, FM_CLASS, &ptr) == 0); 9490 (void) printf(gettext("%s\n"), ptr); 9491} 9492 9493static void 9494zpool_do_events_nvprint(nvlist_t *nvl, int depth) 9495{ 9496 nvpair_t *nvp; 9497 9498 for (nvp = nvlist_next_nvpair(nvl, NULL); 9499 nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) { 9500 9501 data_type_t type = nvpair_type(nvp); 9502 const char *name = nvpair_name(nvp); 9503 9504 boolean_t b; 9505 uint8_t i8; 9506 uint16_t i16; 9507 uint32_t i32; 9508 uint64_t i64; 9509 char *str; 9510 nvlist_t *cnv; 9511 9512 printf(gettext("%*s%s = "), depth, "", name); 9513 9514 switch (type) { 9515 case DATA_TYPE_BOOLEAN: 9516 printf(gettext("%s"), "1"); 9517 break; 9518 9519 case DATA_TYPE_BOOLEAN_VALUE: 9520 (void) nvpair_value_boolean_value(nvp, &b); 9521 printf(gettext("%s"), b ? "1" : "0"); 9522 break; 9523 9524 case DATA_TYPE_BYTE: 9525 (void) nvpair_value_byte(nvp, &i8); 9526 printf(gettext("0x%x"), i8); 9527 break; 9528 9529 case DATA_TYPE_INT8: 9530 (void) nvpair_value_int8(nvp, (void *)&i8); 9531 printf(gettext("0x%x"), i8); 9532 break; 9533 9534 case DATA_TYPE_UINT8: 9535 (void) nvpair_value_uint8(nvp, &i8); 9536 printf(gettext("0x%x"), i8); 9537 break; 9538 9539 case DATA_TYPE_INT16: 9540 (void) nvpair_value_int16(nvp, (void *)&i16); 9541 printf(gettext("0x%x"), i16); 9542 break; 9543 9544 case DATA_TYPE_UINT16: 9545 (void) nvpair_value_uint16(nvp, &i16); 9546 printf(gettext("0x%x"), i16); 9547 break; 9548 9549 case DATA_TYPE_INT32: 9550 (void) nvpair_value_int32(nvp, (void *)&i32); 9551 printf(gettext("0x%x"), i32); 9552 break; 9553 9554 case DATA_TYPE_UINT32: 9555 (void) nvpair_value_uint32(nvp, &i32); 9556 printf(gettext("0x%x"), i32); 9557 break; 9558 9559 case DATA_TYPE_INT64: 9560 (void) nvpair_value_int64(nvp, (void *)&i64); 9561 printf(gettext("0x%llx"), (u_longlong_t)i64); 9562 break; 9563 9564 case DATA_TYPE_UINT64: 9565 (void) nvpair_value_uint64(nvp, &i64); 9566 /* 9567 * translate vdev state values to readable 9568 * strings to aide zpool events consumers 9569 */ 9570 if (strcmp(name, 9571 FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 || 9572 strcmp(name, 9573 FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) { 9574 printf(gettext("\"%s\" (0x%llx)"), 9575 zpool_state_to_name(i64, VDEV_AUX_NONE), 9576 (u_longlong_t)i64); 9577 } else { 9578 printf(gettext("0x%llx"), (u_longlong_t)i64); 9579 } 9580 break; 9581 9582 case DATA_TYPE_HRTIME: 9583 (void) nvpair_value_hrtime(nvp, (void *)&i64); 9584 printf(gettext("0x%llx"), (u_longlong_t)i64); 9585 break; 9586 9587 case DATA_TYPE_STRING: 9588 (void) nvpair_value_string(nvp, &str); 9589 printf(gettext("\"%s\""), str ? str : "<NULL>"); 9590 break; 9591 9592 case DATA_TYPE_NVLIST: 9593 printf(gettext("(embedded nvlist)\n")); 9594 (void) nvpair_value_nvlist(nvp, &cnv); 9595 zpool_do_events_nvprint(cnv, depth + 8); 9596 printf(gettext("%*s(end %s)"), depth, "", name); 9597 break; 9598 9599 case DATA_TYPE_NVLIST_ARRAY: { 9600 nvlist_t **val; 9601 uint_t i, nelem; 9602 9603 (void) nvpair_value_nvlist_array(nvp, &val, &nelem); 9604 printf(gettext("(%d embedded nvlists)\n"), nelem); 9605 for (i = 0; i < nelem; i++) { 9606 printf(gettext("%*s%s[%d] = %s\n"), 9607 depth, "", name, i, "(embedded nvlist)"); 9608 zpool_do_events_nvprint(val[i], depth + 8); 9609 printf(gettext("%*s(end %s[%i])\n"), 9610 depth, "", name, i); 9611 } 9612 printf(gettext("%*s(end %s)\n"), depth, "", name); 9613 } 9614 break; 9615 9616 case DATA_TYPE_INT8_ARRAY: { 9617 int8_t *val; 9618 uint_t i, nelem; 9619 9620 (void) nvpair_value_int8_array(nvp, &val, &nelem); 9621 for (i = 0; i < nelem; i++) 9622 printf(gettext("0x%x "), val[i]); 9623 9624 break; 9625 } 9626 9627 case DATA_TYPE_UINT8_ARRAY: { 9628 uint8_t *val; 9629 uint_t i, nelem; 9630 9631 (void) nvpair_value_uint8_array(nvp, &val, &nelem); 9632 for (i = 0; i < nelem; i++) 9633 printf(gettext("0x%x "), val[i]); 9634 9635 break; 9636 } 9637 9638 case DATA_TYPE_INT16_ARRAY: { 9639 int16_t *val; 9640 uint_t i, nelem; 9641 9642 (void) nvpair_value_int16_array(nvp, &val, &nelem); 9643 for (i = 0; i < nelem; i++) 9644 printf(gettext("0x%x "), val[i]); 9645 9646 break; 9647 } 9648 9649 case DATA_TYPE_UINT16_ARRAY: { 9650 uint16_t *val; 9651 uint_t i, nelem; 9652 9653 (void) nvpair_value_uint16_array(nvp, &val, &nelem); 9654 for (i = 0; i < nelem; i++) 9655 printf(gettext("0x%x "), val[i]); 9656 9657 break; 9658 } 9659 9660 case DATA_TYPE_INT32_ARRAY: { 9661 int32_t *val; 9662 uint_t i, nelem; 9663 9664 (void) nvpair_value_int32_array(nvp, &val, &nelem); 9665 for (i = 0; i < nelem; i++) 9666 printf(gettext("0x%x "), val[i]); 9667 9668 break; 9669 } 9670 9671 case DATA_TYPE_UINT32_ARRAY: { 9672 uint32_t *val; 9673 uint_t i, nelem; 9674 9675 (void) nvpair_value_uint32_array(nvp, &val, &nelem); 9676 for (i = 0; i < nelem; i++) 9677 printf(gettext("0x%x "), val[i]); 9678 9679 break; 9680 } 9681 9682 case DATA_TYPE_INT64_ARRAY: { 9683 int64_t *val; 9684 uint_t i, nelem; 9685 9686 (void) nvpair_value_int64_array(nvp, &val, &nelem); 9687 for (i = 0; i < nelem; i++) 9688 printf(gettext("0x%llx "), 9689 (u_longlong_t)val[i]); 9690 9691 break; 9692 } 9693 9694 case DATA_TYPE_UINT64_ARRAY: { 9695 uint64_t *val; 9696 uint_t i, nelem; 9697 9698 (void) nvpair_value_uint64_array(nvp, &val, &nelem); 9699 for (i = 0; i < nelem; i++) 9700 printf(gettext("0x%llx "), 9701 (u_longlong_t)val[i]); 9702 9703 break; 9704 } 9705 9706 case DATA_TYPE_STRING_ARRAY: { 9707 char **str; 9708 uint_t i, nelem; 9709 9710 (void) nvpair_value_string_array(nvp, &str, &nelem); 9711 for (i = 0; i < nelem; i++) 9712 printf(gettext("\"%s\" "), 9713 str[i] ? str[i] : "<NULL>"); 9714 9715 break; 9716 } 9717 9718 case DATA_TYPE_BOOLEAN_ARRAY: 9719 case DATA_TYPE_BYTE_ARRAY: 9720 case DATA_TYPE_DOUBLE: 9721 case DATA_TYPE_DONTCARE: 9722 case DATA_TYPE_UNKNOWN: 9723 printf(gettext("<unknown>")); 9724 break; 9725 } 9726 9727 printf(gettext("\n")); 9728 } 9729} 9730 9731static int 9732zpool_do_events_next(ev_opts_t *opts) 9733{ 9734 nvlist_t *nvl; 9735 int zevent_fd, ret, dropped; 9736 char *pool; 9737 9738 zevent_fd = open(ZFS_DEV, O_RDWR); 9739 VERIFY(zevent_fd >= 0); 9740 9741 if (!opts->scripted) 9742 (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS"); 9743 9744 while (1) { 9745 ret = zpool_events_next(g_zfs, &nvl, &dropped, 9746 (opts->follow ? ZEVENT_NONE : ZEVENT_NONBLOCK), zevent_fd); 9747 if (ret || nvl == NULL) 9748 break; 9749 9750 if (dropped > 0) 9751 (void) printf(gettext("dropped %d events\n"), dropped); 9752 9753 if (strlen(opts->poolname) > 0 && 9754 nvlist_lookup_string(nvl, FM_FMRI_ZFS_POOL, &pool) == 0 && 9755 strcmp(opts->poolname, pool) != 0) 9756 continue; 9757 9758 zpool_do_events_short(nvl, opts); 9759 9760 if (opts->verbose) { 9761 zpool_do_events_nvprint(nvl, 8); 9762 printf(gettext("\n")); 9763 } 9764 (void) fflush(stdout); 9765 9766 nvlist_free(nvl); 9767 } 9768 9769 VERIFY(0 == close(zevent_fd)); 9770 9771 return (ret); 9772} 9773 9774static int 9775zpool_do_events_clear(ev_opts_t *opts) 9776{ 9777 int count, ret; 9778 9779 ret = zpool_events_clear(g_zfs, &count); 9780 if (!ret) 9781 (void) printf(gettext("cleared %d events\n"), count); 9782 9783 return (ret); 9784} 9785 9786/* 9787 * zpool events [-vHf [pool] | -c] 9788 * 9789 * Displays events logs by ZFS. 9790 */ 9791int 9792zpool_do_events(int argc, char **argv) 9793{ 9794 ev_opts_t opts = { 0 }; 9795 int ret; 9796 int c; 9797 9798 /* check options */ 9799 while ((c = getopt(argc, argv, "vHfc")) != -1) { 9800 switch (c) { 9801 case 'v': 9802 opts.verbose = 1; 9803 break; 9804 case 'H': 9805 opts.scripted = 1; 9806 break; 9807 case 'f': 9808 opts.follow = 1; 9809 break; 9810 case 'c': 9811 opts.clear = 1; 9812 break; 9813 case '?': 9814 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 9815 optopt); 9816 usage(B_FALSE); 9817 } 9818 } 9819 argc -= optind; 9820 argv += optind; 9821 9822 if (argc > 1) { 9823 (void) fprintf(stderr, gettext("too many arguments\n")); 9824 usage(B_FALSE); 9825 } else if (argc == 1) { 9826 (void) strlcpy(opts.poolname, argv[0], sizeof (opts.poolname)); 9827 if (!zfs_name_valid(opts.poolname, ZFS_TYPE_POOL)) { 9828 (void) fprintf(stderr, 9829 gettext("invalid pool name '%s'\n"), opts.poolname); 9830 usage(B_FALSE); 9831 } 9832 } 9833 9834 if ((argc == 1 || opts.verbose || opts.scripted || opts.follow) && 9835 opts.clear) { 9836 (void) fprintf(stderr, 9837 gettext("invalid options combined with -c\n")); 9838 usage(B_FALSE); 9839 } 9840 9841 if (opts.clear) 9842 ret = zpool_do_events_clear(&opts); 9843 else 9844 ret = zpool_do_events_next(&opts); 9845 9846 return (ret); 9847} 9848 9849static int 9850get_callback(zpool_handle_t *zhp, void *data) 9851{ 9852 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 9853 char value[MAXNAMELEN]; 9854 zprop_source_t srctype; 9855 zprop_list_t *pl; 9856 9857 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 9858 9859 /* 9860 * Skip the special fake placeholder. This will also skip 9861 * over the name property when 'all' is specified. 9862 */ 9863 if (pl->pl_prop == ZPOOL_PROP_NAME && 9864 pl == cbp->cb_proplist) 9865 continue; 9866 9867 if (pl->pl_prop == ZPROP_INVAL && 9868 (zpool_prop_feature(pl->pl_user_prop) || 9869 zpool_prop_unsupported(pl->pl_user_prop))) { 9870 srctype = ZPROP_SRC_LOCAL; 9871 9872 if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 9873 value, sizeof (value)) == 0) { 9874 zprop_print_one_property(zpool_get_name(zhp), 9875 cbp, pl->pl_user_prop, value, srctype, 9876 NULL, NULL); 9877 } 9878 } else { 9879 if (zpool_get_prop(zhp, pl->pl_prop, value, 9880 sizeof (value), &srctype, cbp->cb_literal) != 0) 9881 continue; 9882 9883 zprop_print_one_property(zpool_get_name(zhp), cbp, 9884 zpool_prop_to_name(pl->pl_prop), value, srctype, 9885 NULL, NULL); 9886 } 9887 } 9888 return (0); 9889} 9890 9891/* 9892 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 9893 * 9894 * -H Scripted mode. Don't display headers, and separate properties 9895 * by a single tab. 9896 * -o List of columns to display. Defaults to 9897 * "name,property,value,source". 9898 * -p Display values in parsable (exact) format. 9899 * 9900 * Get properties of pools in the system. Output space statistics 9901 * for each one as well as other attributes. 9902 */ 9903int 9904zpool_do_get(int argc, char **argv) 9905{ 9906 zprop_get_cbdata_t cb = { 0 }; 9907 zprop_list_t fake_name = { 0 }; 9908 int ret; 9909 int c, i; 9910 char *value; 9911 9912 cb.cb_first = B_TRUE; 9913 9914 /* 9915 * Set up default columns and sources. 9916 */ 9917 cb.cb_sources = ZPROP_SRC_ALL; 9918 cb.cb_columns[0] = GET_COL_NAME; 9919 cb.cb_columns[1] = GET_COL_PROPERTY; 9920 cb.cb_columns[2] = GET_COL_VALUE; 9921 cb.cb_columns[3] = GET_COL_SOURCE; 9922 cb.cb_type = ZFS_TYPE_POOL; 9923 9924 /* check options */ 9925 while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 9926 switch (c) { 9927 case 'p': 9928 cb.cb_literal = B_TRUE; 9929 break; 9930 case 'H': 9931 cb.cb_scripted = B_TRUE; 9932 break; 9933 case 'o': 9934 bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 9935 i = 0; 9936 while (*optarg != '\0') { 9937 static char *col_subopts[] = 9938 { "name", "property", "value", "source", 9939 "all", NULL }; 9940 9941 if (i == ZFS_GET_NCOLS) { 9942 (void) fprintf(stderr, gettext("too " 9943 "many fields given to -o " 9944 "option\n")); 9945 usage(B_FALSE); 9946 } 9947 9948 switch (getsubopt(&optarg, col_subopts, 9949 &value)) { 9950 case 0: 9951 cb.cb_columns[i++] = GET_COL_NAME; 9952 break; 9953 case 1: 9954 cb.cb_columns[i++] = GET_COL_PROPERTY; 9955 break; 9956 case 2: 9957 cb.cb_columns[i++] = GET_COL_VALUE; 9958 break; 9959 case 3: 9960 cb.cb_columns[i++] = GET_COL_SOURCE; 9961 break; 9962 case 4: 9963 if (i > 0) { 9964 (void) fprintf(stderr, 9965 gettext("\"all\" conflicts " 9966 "with specific fields " 9967 "given to -o option\n")); 9968 usage(B_FALSE); 9969 } 9970 cb.cb_columns[0] = GET_COL_NAME; 9971 cb.cb_columns[1] = GET_COL_PROPERTY; 9972 cb.cb_columns[2] = GET_COL_VALUE; 9973 cb.cb_columns[3] = GET_COL_SOURCE; 9974 i = ZFS_GET_NCOLS; 9975 break; 9976 default: 9977 (void) fprintf(stderr, 9978 gettext("invalid column name " 9979 "'%s'\n"), value); 9980 usage(B_FALSE); 9981 } 9982 } 9983 break; 9984 case '?': 9985 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 9986 optopt); 9987 usage(B_FALSE); 9988 } 9989 } 9990 9991 argc -= optind; 9992 argv += optind; 9993 9994 if (argc < 1) { 9995 (void) fprintf(stderr, gettext("missing property " 9996 "argument\n")); 9997 usage(B_FALSE); 9998 } 9999 10000 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 10001 ZFS_TYPE_POOL) != 0) 10002 usage(B_FALSE); 10003 10004 argc--; 10005 argv++; 10006 10007 if (cb.cb_proplist != NULL) { 10008 fake_name.pl_prop = ZPOOL_PROP_NAME; 10009 fake_name.pl_width = strlen(gettext("NAME")); 10010 fake_name.pl_next = cb.cb_proplist; 10011 cb.cb_proplist = &fake_name; 10012 } 10013 10014 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, cb.cb_literal, 10015 get_callback, &cb); 10016 10017 if (cb.cb_proplist == &fake_name) 10018 zprop_free_list(fake_name.pl_next); 10019 else 10020 zprop_free_list(cb.cb_proplist); 10021 10022 return (ret); 10023} 10024 10025typedef struct set_cbdata { 10026 char *cb_propname; 10027 char *cb_value; 10028 boolean_t cb_any_successful; 10029} set_cbdata_t; 10030 10031static int 10032set_callback(zpool_handle_t *zhp, void *data) 10033{ 10034 int error; 10035 set_cbdata_t *cb = (set_cbdata_t *)data; 10036 10037 /* Check if we have out-of-bounds features */ 10038 if (strcmp(cb->cb_propname, ZPOOL_CONFIG_COMPATIBILITY) == 0) { 10039 boolean_t features[SPA_FEATURES]; 10040 if (zpool_do_load_compat(cb->cb_value, features) != 10041 ZPOOL_COMPATIBILITY_OK) 10042 return (-1); 10043 10044 nvlist_t *enabled = zpool_get_features(zhp); 10045 spa_feature_t i; 10046 for (i = 0; i < SPA_FEATURES; i++) { 10047 const char *fguid = spa_feature_table[i].fi_guid; 10048 if (nvlist_exists(enabled, fguid) && !features[i]) 10049 break; 10050 } 10051 if (i < SPA_FEATURES) 10052 (void) fprintf(stderr, gettext("Warning: one or " 10053 "more features already enabled on pool '%s'\n" 10054 "are not present in this compatibility set.\n"), 10055 zpool_get_name(zhp)); 10056 } 10057 10058 /* if we're setting a feature, check it's in compatibility set */ 10059 if (zpool_prop_feature(cb->cb_propname) && 10060 strcmp(cb->cb_value, ZFS_FEATURE_ENABLED) == 0) { 10061 char *fname = strchr(cb->cb_propname, '@') + 1; 10062 spa_feature_t f; 10063 10064 if (zfeature_lookup_name(fname, &f) == 0) { 10065 char compat[ZFS_MAXPROPLEN]; 10066 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, 10067 compat, ZFS_MAXPROPLEN, NULL, B_FALSE) != 0) 10068 compat[0] = '\0'; 10069 10070 boolean_t features[SPA_FEATURES]; 10071 if (zpool_do_load_compat(compat, features) != 10072 ZPOOL_COMPATIBILITY_OK) { 10073 (void) fprintf(stderr, gettext("Error: " 10074 "cannot enable feature '%s' on pool '%s'\n" 10075 "because the pool's 'compatibility' " 10076 "property cannot be parsed.\n"), 10077 fname, zpool_get_name(zhp)); 10078 return (-1); 10079 } 10080 10081 if (!features[f]) { 10082 (void) fprintf(stderr, gettext("Error: " 10083 "cannot enable feature '%s' on pool '%s'\n" 10084 "as it is not specified in this pool's " 10085 "current compatibility set.\n" 10086 "Consider setting 'compatibility' to a " 10087 "less restrictive set, or to 'off'.\n"), 10088 fname, zpool_get_name(zhp)); 10089 return (-1); 10090 } 10091 } 10092 } 10093 10094 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 10095 10096 if (!error) 10097 cb->cb_any_successful = B_TRUE; 10098 10099 return (error); 10100} 10101 10102int 10103zpool_do_set(int argc, char **argv) 10104{ 10105 set_cbdata_t cb = { 0 }; 10106 int error; 10107 10108 if (argc > 1 && argv[1][0] == '-') { 10109 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 10110 argv[1][1]); 10111 usage(B_FALSE); 10112 } 10113 10114 if (argc < 2) { 10115 (void) fprintf(stderr, gettext("missing property=value " 10116 "argument\n")); 10117 usage(B_FALSE); 10118 } 10119 10120 if (argc < 3) { 10121 (void) fprintf(stderr, gettext("missing pool name\n")); 10122 usage(B_FALSE); 10123 } 10124 10125 if (argc > 3) { 10126 (void) fprintf(stderr, gettext("too many pool names\n")); 10127 usage(B_FALSE); 10128 } 10129 10130 cb.cb_propname = argv[1]; 10131 cb.cb_value = strchr(cb.cb_propname, '='); 10132 if (cb.cb_value == NULL) { 10133 (void) fprintf(stderr, gettext("missing value in " 10134 "property=value argument\n")); 10135 usage(B_FALSE); 10136 } 10137 10138 *(cb.cb_value) = '\0'; 10139 cb.cb_value++; 10140 10141 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, B_FALSE, 10142 set_callback, &cb); 10143 10144 return (error); 10145} 10146 10147/* Add up the total number of bytes left to initialize/trim across all vdevs */ 10148static uint64_t 10149vdev_activity_remaining(nvlist_t *nv, zpool_wait_activity_t activity) 10150{ 10151 uint64_t bytes_remaining; 10152 nvlist_t **child; 10153 uint_t c, children; 10154 vdev_stat_t *vs; 10155 10156 assert(activity == ZPOOL_WAIT_INITIALIZE || 10157 activity == ZPOOL_WAIT_TRIM); 10158 10159 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 10160 (uint64_t **)&vs, &c) == 0); 10161 10162 if (activity == ZPOOL_WAIT_INITIALIZE && 10163 vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) 10164 bytes_remaining = vs->vs_initialize_bytes_est - 10165 vs->vs_initialize_bytes_done; 10166 else if (activity == ZPOOL_WAIT_TRIM && 10167 vs->vs_trim_state == VDEV_TRIM_ACTIVE) 10168 bytes_remaining = vs->vs_trim_bytes_est - 10169 vs->vs_trim_bytes_done; 10170 else 10171 bytes_remaining = 0; 10172 10173 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 10174 &child, &children) != 0) 10175 children = 0; 10176 10177 for (c = 0; c < children; c++) 10178 bytes_remaining += vdev_activity_remaining(child[c], activity); 10179 10180 return (bytes_remaining); 10181} 10182 10183/* Add up the total number of bytes left to rebuild across top-level vdevs */ 10184static uint64_t 10185vdev_activity_top_remaining(nvlist_t *nv) 10186{ 10187 uint64_t bytes_remaining = 0; 10188 nvlist_t **child; 10189 uint_t children; 10190 int error; 10191 10192 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 10193 &child, &children) != 0) 10194 children = 0; 10195 10196 for (uint_t c = 0; c < children; c++) { 10197 vdev_rebuild_stat_t *vrs; 10198 uint_t i; 10199 10200 error = nvlist_lookup_uint64_array(child[c], 10201 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i); 10202 if (error == 0) { 10203 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) { 10204 bytes_remaining += (vrs->vrs_bytes_est - 10205 vrs->vrs_bytes_rebuilt); 10206 } 10207 } 10208 } 10209 10210 return (bytes_remaining); 10211} 10212 10213/* Whether any vdevs are 'spare' or 'replacing' vdevs */ 10214static boolean_t 10215vdev_any_spare_replacing(nvlist_t *nv) 10216{ 10217 nvlist_t **child; 10218 uint_t c, children; 10219 char *vdev_type; 10220 10221 (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &vdev_type); 10222 10223 if (strcmp(vdev_type, VDEV_TYPE_REPLACING) == 0 || 10224 strcmp(vdev_type, VDEV_TYPE_SPARE) == 0 || 10225 strcmp(vdev_type, VDEV_TYPE_DRAID_SPARE) == 0) { 10226 return (B_TRUE); 10227 } 10228 10229 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 10230 &child, &children) != 0) 10231 children = 0; 10232 10233 for (c = 0; c < children; c++) { 10234 if (vdev_any_spare_replacing(child[c])) 10235 return (B_TRUE); 10236 } 10237 10238 return (B_FALSE); 10239} 10240 10241typedef struct wait_data { 10242 char *wd_poolname; 10243 boolean_t wd_scripted; 10244 boolean_t wd_exact; 10245 boolean_t wd_headers_once; 10246 boolean_t wd_should_exit; 10247 /* Which activities to wait for */ 10248 boolean_t wd_enabled[ZPOOL_WAIT_NUM_ACTIVITIES]; 10249 float wd_interval; 10250 pthread_cond_t wd_cv; 10251 pthread_mutex_t wd_mutex; 10252} wait_data_t; 10253 10254/* 10255 * Print to stdout a single line, containing one column for each activity that 10256 * we are waiting for specifying how many bytes of work are left for that 10257 * activity. 10258 */ 10259static void 10260print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row) 10261{ 10262 nvlist_t *config, *nvroot; 10263 uint_t c; 10264 int i; 10265 pool_checkpoint_stat_t *pcs = NULL; 10266 pool_scan_stat_t *pss = NULL; 10267 pool_removal_stat_t *prs = NULL; 10268 char *headers[] = {"DISCARD", "FREE", "INITIALIZE", "REPLACE", 10269 "REMOVE", "RESILVER", "SCRUB", "TRIM"}; 10270 int col_widths[ZPOOL_WAIT_NUM_ACTIVITIES]; 10271 10272 /* Calculate the width of each column */ 10273 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) { 10274 /* 10275 * Make sure we have enough space in the col for pretty-printed 10276 * numbers and for the column header, and then leave a couple 10277 * spaces between cols for readability. 10278 */ 10279 col_widths[i] = MAX(strlen(headers[i]), 6) + 2; 10280 } 10281 10282 /* Print header if appropriate */ 10283 int term_height = terminal_height(); 10284 boolean_t reprint_header = (!wd->wd_headers_once && term_height > 0 && 10285 row % (term_height-1) == 0); 10286 if (!wd->wd_scripted && (row == 0 || reprint_header)) { 10287 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) { 10288 if (wd->wd_enabled[i]) 10289 (void) printf("%*s", col_widths[i], headers[i]); 10290 } 10291 (void) printf("\n"); 10292 } 10293 10294 /* Bytes of work remaining in each activity */ 10295 int64_t bytes_rem[ZPOOL_WAIT_NUM_ACTIVITIES] = {0}; 10296 10297 bytes_rem[ZPOOL_WAIT_FREE] = 10298 zpool_get_prop_int(zhp, ZPOOL_PROP_FREEING, NULL); 10299 10300 config = zpool_get_config(zhp, NULL); 10301 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 10302 10303 (void) nvlist_lookup_uint64_array(nvroot, 10304 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 10305 if (pcs != NULL && pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 10306 bytes_rem[ZPOOL_WAIT_CKPT_DISCARD] = pcs->pcs_space; 10307 10308 (void) nvlist_lookup_uint64_array(nvroot, 10309 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 10310 if (prs != NULL && prs->prs_state == DSS_SCANNING) 10311 bytes_rem[ZPOOL_WAIT_REMOVE] = prs->prs_to_copy - 10312 prs->prs_copied; 10313 10314 (void) nvlist_lookup_uint64_array(nvroot, 10315 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&pss, &c); 10316 if (pss != NULL && pss->pss_state == DSS_SCANNING && 10317 pss->pss_pass_scrub_pause == 0) { 10318 int64_t rem = pss->pss_to_examine - pss->pss_issued; 10319 if (pss->pss_func == POOL_SCAN_SCRUB) 10320 bytes_rem[ZPOOL_WAIT_SCRUB] = rem; 10321 else 10322 bytes_rem[ZPOOL_WAIT_RESILVER] = rem; 10323 } else if (check_rebuilding(nvroot, NULL)) { 10324 bytes_rem[ZPOOL_WAIT_RESILVER] = 10325 vdev_activity_top_remaining(nvroot); 10326 } 10327 10328 bytes_rem[ZPOOL_WAIT_INITIALIZE] = 10329 vdev_activity_remaining(nvroot, ZPOOL_WAIT_INITIALIZE); 10330 bytes_rem[ZPOOL_WAIT_TRIM] = 10331 vdev_activity_remaining(nvroot, ZPOOL_WAIT_TRIM); 10332 10333 /* 10334 * A replace finishes after resilvering finishes, so the amount of work 10335 * left for a replace is the same as for resilvering. 10336 * 10337 * It isn't quite correct to say that if we have any 'spare' or 10338 * 'replacing' vdevs and a resilver is happening, then a replace is in 10339 * progress, like we do here. When a hot spare is used, the faulted vdev 10340 * is not removed after the hot spare is resilvered, so parent 'spare' 10341 * vdev is not removed either. So we could have a 'spare' vdev, but be 10342 * resilvering for a different reason. However, we use it as a heuristic 10343 * because we don't have access to the DTLs, which could tell us whether 10344 * or not we have really finished resilvering a hot spare. 10345 */ 10346 if (vdev_any_spare_replacing(nvroot)) 10347 bytes_rem[ZPOOL_WAIT_REPLACE] = bytes_rem[ZPOOL_WAIT_RESILVER]; 10348 10349 if (timestamp_fmt != NODATE) 10350 print_timestamp(timestamp_fmt); 10351 10352 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) { 10353 char buf[64]; 10354 if (!wd->wd_enabled[i]) 10355 continue; 10356 10357 if (wd->wd_exact) 10358 (void) snprintf(buf, sizeof (buf), "%" PRIi64, 10359 bytes_rem[i]); 10360 else 10361 zfs_nicenum(bytes_rem[i], buf, sizeof (buf)); 10362 10363 if (wd->wd_scripted) 10364 (void) printf(i == 0 ? "%s" : "\t%s", buf); 10365 else 10366 (void) printf(" %*s", col_widths[i] - 1, buf); 10367 } 10368 (void) printf("\n"); 10369 (void) fflush(stdout); 10370} 10371 10372static void * 10373wait_status_thread(void *arg) 10374{ 10375 wait_data_t *wd = (wait_data_t *)arg; 10376 zpool_handle_t *zhp; 10377 10378 if ((zhp = zpool_open(g_zfs, wd->wd_poolname)) == NULL) 10379 return (void *)(1); 10380 10381 for (int row = 0; ; row++) { 10382 boolean_t missing; 10383 struct timespec timeout; 10384 int ret = 0; 10385 (void) clock_gettime(CLOCK_REALTIME, &timeout); 10386 10387 if (zpool_refresh_stats(zhp, &missing) != 0 || missing || 10388 zpool_props_refresh(zhp) != 0) { 10389 zpool_close(zhp); 10390 return (void *)(uintptr_t)(missing ? 0 : 1); 10391 } 10392 10393 print_wait_status_row(wd, zhp, row); 10394 10395 timeout.tv_sec += floor(wd->wd_interval); 10396 long nanos = timeout.tv_nsec + 10397 (wd->wd_interval - floor(wd->wd_interval)) * NANOSEC; 10398 if (nanos >= NANOSEC) { 10399 timeout.tv_sec++; 10400 timeout.tv_nsec = nanos - NANOSEC; 10401 } else { 10402 timeout.tv_nsec = nanos; 10403 } 10404 pthread_mutex_lock(&wd->wd_mutex); 10405 if (!wd->wd_should_exit) 10406 ret = pthread_cond_timedwait(&wd->wd_cv, &wd->wd_mutex, 10407 &timeout); 10408 pthread_mutex_unlock(&wd->wd_mutex); 10409 if (ret == 0) { 10410 break; /* signaled by main thread */ 10411 } else if (ret != ETIMEDOUT) { 10412 (void) fprintf(stderr, gettext("pthread_cond_timedwait " 10413 "failed: %s\n"), strerror(ret)); 10414 zpool_close(zhp); 10415 return (void *)(uintptr_t)(1); 10416 } 10417 } 10418 10419 zpool_close(zhp); 10420 return (void *)(0); 10421} 10422 10423int 10424zpool_do_wait(int argc, char **argv) 10425{ 10426 boolean_t verbose = B_FALSE; 10427 int c; 10428 char *value; 10429 int i; 10430 unsigned long count; 10431 pthread_t status_thr; 10432 int error = 0; 10433 zpool_handle_t *zhp; 10434 10435 wait_data_t wd; 10436 wd.wd_scripted = B_FALSE; 10437 wd.wd_exact = B_FALSE; 10438 wd.wd_headers_once = B_FALSE; 10439 wd.wd_should_exit = B_FALSE; 10440 10441 pthread_mutex_init(&wd.wd_mutex, NULL); 10442 pthread_cond_init(&wd.wd_cv, NULL); 10443 10444 /* By default, wait for all types of activity. */ 10445 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) 10446 wd.wd_enabled[i] = B_TRUE; 10447 10448 while ((c = getopt(argc, argv, "HpT:t:")) != -1) { 10449 switch (c) { 10450 case 'H': 10451 wd.wd_scripted = B_TRUE; 10452 break; 10453 case 'n': 10454 wd.wd_headers_once = B_TRUE; 10455 break; 10456 case 'p': 10457 wd.wd_exact = B_TRUE; 10458 break; 10459 case 'T': 10460 get_timestamp_arg(*optarg); 10461 break; 10462 case 't': 10463 { 10464 static char *col_subopts[] = { "discard", "free", 10465 "initialize", "replace", "remove", "resilver", 10466 "scrub", "trim", NULL }; 10467 10468 /* Reset activities array */ 10469 bzero(&wd.wd_enabled, sizeof (wd.wd_enabled)); 10470 while (*optarg != '\0') { 10471 int activity = getsubopt(&optarg, col_subopts, 10472 &value); 10473 10474 if (activity < 0) { 10475 (void) fprintf(stderr, 10476 gettext("invalid activity '%s'\n"), 10477 value); 10478 usage(B_FALSE); 10479 } 10480 10481 wd.wd_enabled[activity] = B_TRUE; 10482 } 10483 break; 10484 } 10485 case '?': 10486 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 10487 optopt); 10488 usage(B_FALSE); 10489 } 10490 } 10491 10492 argc -= optind; 10493 argv += optind; 10494 10495 get_interval_count(&argc, argv, &wd.wd_interval, &count); 10496 if (count != 0) { 10497 /* This subcmd only accepts an interval, not a count */ 10498 (void) fprintf(stderr, gettext("too many arguments\n")); 10499 usage(B_FALSE); 10500 } 10501 10502 if (wd.wd_interval != 0) 10503 verbose = B_TRUE; 10504 10505 if (argc < 1) { 10506 (void) fprintf(stderr, gettext("missing 'pool' argument\n")); 10507 usage(B_FALSE); 10508 } 10509 if (argc > 1) { 10510 (void) fprintf(stderr, gettext("too many arguments\n")); 10511 usage(B_FALSE); 10512 } 10513 10514 wd.wd_poolname = argv[0]; 10515 10516 if ((zhp = zpool_open(g_zfs, wd.wd_poolname)) == NULL) 10517 return (1); 10518 10519 if (verbose) { 10520 /* 10521 * We use a separate thread for printing status updates because 10522 * the main thread will call lzc_wait(), which blocks as long 10523 * as an activity is in progress, which can be a long time. 10524 */ 10525 if (pthread_create(&status_thr, NULL, wait_status_thread, &wd) 10526 != 0) { 10527 (void) fprintf(stderr, gettext("failed to create status" 10528 "thread: %s\n"), strerror(errno)); 10529 zpool_close(zhp); 10530 return (1); 10531 } 10532 } 10533 10534 /* 10535 * Loop over all activities that we are supposed to wait for until none 10536 * of them are in progress. Note that this means we can end up waiting 10537 * for more activities to complete than just those that were in progress 10538 * when we began waiting; if an activity we are interested in begins 10539 * while we are waiting for another activity, we will wait for both to 10540 * complete before exiting. 10541 */ 10542 for (;;) { 10543 boolean_t missing = B_FALSE; 10544 boolean_t any_waited = B_FALSE; 10545 10546 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) { 10547 boolean_t waited; 10548 10549 if (!wd.wd_enabled[i]) 10550 continue; 10551 10552 error = zpool_wait_status(zhp, i, &missing, &waited); 10553 if (error != 0 || missing) 10554 break; 10555 10556 any_waited = (any_waited || waited); 10557 } 10558 10559 if (error != 0 || missing || !any_waited) 10560 break; 10561 } 10562 10563 zpool_close(zhp); 10564 10565 if (verbose) { 10566 uintptr_t status; 10567 pthread_mutex_lock(&wd.wd_mutex); 10568 wd.wd_should_exit = B_TRUE; 10569 pthread_cond_signal(&wd.wd_cv); 10570 pthread_mutex_unlock(&wd.wd_mutex); 10571 (void) pthread_join(status_thr, (void *)&status); 10572 if (status != 0) 10573 error = status; 10574 } 10575 10576 pthread_mutex_destroy(&wd.wd_mutex); 10577 pthread_cond_destroy(&wd.wd_cv); 10578 return (error); 10579} 10580 10581static int 10582find_command_idx(char *command, int *idx) 10583{ 10584 int i; 10585 10586 for (i = 0; i < NCOMMAND; i++) { 10587 if (command_table[i].name == NULL) 10588 continue; 10589 10590 if (strcmp(command, command_table[i].name) == 0) { 10591 *idx = i; 10592 return (0); 10593 } 10594 } 10595 return (1); 10596} 10597 10598/* 10599 * Display version message 10600 */ 10601static int 10602zpool_do_version(int argc, char **argv) 10603{ 10604 if (zfs_version_print() == -1) 10605 return (1); 10606 10607 return (0); 10608} 10609 10610/* 10611 * Do zpool_load_compat() and print error message on failure 10612 */ 10613static zpool_compat_status_t 10614zpool_do_load_compat(const char *compat, boolean_t *list) 10615{ 10616 char report[1024]; 10617 10618 zpool_compat_status_t ret; 10619 10620 ret = zpool_load_compat(compat, list, report, 1024); 10621 switch (ret) { 10622 10623 case ZPOOL_COMPATIBILITY_OK: 10624 break; 10625 10626 case ZPOOL_COMPATIBILITY_NOFILES: 10627 case ZPOOL_COMPATIBILITY_BADFILE: 10628 case ZPOOL_COMPATIBILITY_BADTOKEN: 10629 (void) fprintf(stderr, "Error: %s\n", report); 10630 break; 10631 10632 case ZPOOL_COMPATIBILITY_WARNTOKEN: 10633 (void) fprintf(stderr, "Warning: %s\n", report); 10634 ret = ZPOOL_COMPATIBILITY_OK; 10635 break; 10636 } 10637 return (ret); 10638} 10639 10640int 10641main(int argc, char **argv) 10642{ 10643 int ret = 0; 10644 int i = 0; 10645 char *cmdname; 10646 char **newargv; 10647 10648 (void) setlocale(LC_ALL, ""); 10649 (void) setlocale(LC_NUMERIC, "C"); 10650 (void) textdomain(TEXT_DOMAIN); 10651 srand(time(NULL)); 10652 10653 opterr = 0; 10654 10655 /* 10656 * Make sure the user has specified some command. 10657 */ 10658 if (argc < 2) { 10659 (void) fprintf(stderr, gettext("missing command\n")); 10660 usage(B_FALSE); 10661 } 10662 10663 cmdname = argv[1]; 10664 10665 /* 10666 * Special case '-?' 10667 */ 10668 if ((strcmp(cmdname, "-?") == 0) || strcmp(cmdname, "--help") == 0) 10669 usage(B_TRUE); 10670 10671 /* 10672 * Special case '-V|--version' 10673 */ 10674 if ((strcmp(cmdname, "-V") == 0) || (strcmp(cmdname, "--version") == 0)) 10675 return (zpool_do_version(argc, argv)); 10676 10677 if ((g_zfs = libzfs_init()) == NULL) { 10678 (void) fprintf(stderr, "%s\n", libzfs_error_init(errno)); 10679 return (1); 10680 } 10681 10682 libzfs_print_on_error(g_zfs, B_TRUE); 10683 10684 zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 10685 10686 /* 10687 * Many commands modify input strings for string parsing reasons. 10688 * We create a copy to protect the original argv. 10689 */ 10690 newargv = malloc((argc + 1) * sizeof (newargv[0])); 10691 for (i = 0; i < argc; i++) 10692 newargv[i] = strdup(argv[i]); 10693 newargv[argc] = NULL; 10694 10695 /* 10696 * Run the appropriate command. 10697 */ 10698 if (find_command_idx(cmdname, &i) == 0) { 10699 current_command = &command_table[i]; 10700 ret = command_table[i].func(argc - 1, newargv + 1); 10701 } else if (strchr(cmdname, '=')) { 10702 verify(find_command_idx("set", &i) == 0); 10703 current_command = &command_table[i]; 10704 ret = command_table[i].func(argc, newargv); 10705 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 10706 /* 10707 * 'freeze' is a vile debugging abomination, so we treat 10708 * it as such. 10709 */ 10710 zfs_cmd_t zc = {"\0"}; 10711 10712 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name)); 10713 ret = zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc); 10714 if (ret != 0) { 10715 (void) fprintf(stderr, 10716 gettext("failed to freeze pool: %d\n"), errno); 10717 ret = 1; 10718 } 10719 10720 log_history = 0; 10721 } else { 10722 (void) fprintf(stderr, gettext("unrecognized " 10723 "command '%s'\n"), cmdname); 10724 usage(B_FALSE); 10725 ret = 1; 10726 } 10727 10728 for (i = 0; i < argc; i++) 10729 free(newargv[i]); 10730 free(newargv); 10731 10732 if (ret == 0 && log_history) 10733 (void) zpool_log_history(g_zfs, history_str); 10734 10735 libzfs_fini(g_zfs); 10736 10737 /* 10738 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 10739 * for the purposes of running ::findleaks. 10740 */ 10741 if (getenv("ZFS_ABORT") != NULL) { 10742 (void) printf("dumping core by request\n"); 10743 abort(); 10744 } 10745 10746 return (ret); 10747} 10748