Rescan enclosure sysfs path on import
[zfs.git] / cmd / zpool / zpool_main.c
blobd42ff18d83f8de7f73b839849521db3d69caa26b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
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
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>
69 #include <math.h>
71 #include <libzfs.h>
72 #include <libzutil.h>
74 #include "zpool_util.h"
75 #include "zfs_comutil.h"
76 #include "zfeature_common.h"
78 #include "statcommon.h"
80 libzfs_handle_t *g_zfs;
82 static int zpool_do_create(int, char **);
83 static int zpool_do_destroy(int, char **);
85 static int zpool_do_add(int, char **);
86 static int zpool_do_remove(int, char **);
87 static int zpool_do_labelclear(int, char **);
89 static int zpool_do_checkpoint(int, char **);
91 static int zpool_do_list(int, char **);
92 static int zpool_do_iostat(int, char **);
93 static int zpool_do_status(int, char **);
95 static int zpool_do_online(int, char **);
96 static int zpool_do_offline(int, char **);
97 static int zpool_do_clear(int, char **);
98 static int zpool_do_reopen(int, char **);
100 static int zpool_do_reguid(int, char **);
102 static int zpool_do_attach(int, char **);
103 static int zpool_do_detach(int, char **);
104 static int zpool_do_replace(int, char **);
105 static int zpool_do_split(int, char **);
107 static int zpool_do_initialize(int, char **);
108 static int zpool_do_scrub(int, char **);
109 static int zpool_do_resilver(int, char **);
110 static int zpool_do_trim(int, char **);
112 static int zpool_do_import(int, char **);
113 static int zpool_do_export(int, char **);
115 static int zpool_do_upgrade(int, char **);
117 static int zpool_do_history(int, char **);
118 static int zpool_do_events(int, char **);
120 static int zpool_do_get(int, char **);
121 static int zpool_do_set(int, char **);
123 static int zpool_do_sync(int, char **);
125 static int zpool_do_version(int, char **);
127 static int zpool_do_wait(int, char **);
129 static zpool_compat_status_t zpool_do_load_compat(
130 const char *, boolean_t *);
133 * These libumem hooks provide a reasonable set of defaults for the allocator's
134 * debugging facilities.
137 #ifdef DEBUG
138 const char *
139 _umem_debug_init(void)
141 return ("default,verbose"); /* $UMEM_DEBUG setting */
144 const char *
145 _umem_logging_init(void)
147 return ("fail,contents"); /* $UMEM_LOGGING setting */
149 #endif
151 typedef 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;
188 * Flags for stats to display with "zpool iostats"
190 enum 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 */
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)
206 /* Mask of all the histo bits */
207 #define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
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.
214 static const char *vsx_type_to_nvlist[IOS_COUNT][15] = {
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 ZPOOL_CONFIG_VDEV_REBUILD_LAT_HISTO,
227 NULL},
228 [IOS_LATENCY] = {
229 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
230 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
231 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
232 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
233 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
234 ZPOOL_CONFIG_VDEV_REBUILD_LAT_HISTO,
235 NULL},
236 [IOS_QUEUES] = {
237 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
238 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
239 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
240 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
241 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
242 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
243 ZPOOL_CONFIG_VDEV_REBUILD_ACTIVE_QUEUE,
244 NULL},
245 [IOS_RQ_HISTO] = {
246 ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
247 ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
248 ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
249 ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
250 ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
251 ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
252 ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
253 ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
254 ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
255 ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
256 ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
257 ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
258 ZPOOL_CONFIG_VDEV_IND_REBUILD_HISTO,
259 ZPOOL_CONFIG_VDEV_AGG_REBUILD_HISTO,
260 NULL},
265 * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
266 * Right now, only one histo bit is ever set at one time, so we can
267 * just do a highbit64(a)
269 #define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1)
271 typedef struct zpool_command {
272 const char *name;
273 int (*func)(int, char **);
274 zpool_help_t usage;
275 } zpool_command_t;
278 * Master command table. Each ZFS command has a name, associated function, and
279 * usage message. The usage messages need to be internationalized, so we have
280 * to have a function to return the usage message based on a command index.
282 * These commands are organized according to how they are displayed in the usage
283 * message. An empty command (one with a NULL name) indicates an empty line in
284 * the generic usage message.
286 static zpool_command_t command_table[] = {
287 { "version", zpool_do_version, HELP_VERSION },
288 { NULL },
289 { "create", zpool_do_create, HELP_CREATE },
290 { "destroy", zpool_do_destroy, HELP_DESTROY },
291 { NULL },
292 { "add", zpool_do_add, HELP_ADD },
293 { "remove", zpool_do_remove, HELP_REMOVE },
294 { NULL },
295 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
296 { NULL },
297 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT },
298 { NULL },
299 { "list", zpool_do_list, HELP_LIST },
300 { "iostat", zpool_do_iostat, HELP_IOSTAT },
301 { "status", zpool_do_status, HELP_STATUS },
302 { NULL },
303 { "online", zpool_do_online, HELP_ONLINE },
304 { "offline", zpool_do_offline, HELP_OFFLINE },
305 { "clear", zpool_do_clear, HELP_CLEAR },
306 { "reopen", zpool_do_reopen, HELP_REOPEN },
307 { NULL },
308 { "attach", zpool_do_attach, HELP_ATTACH },
309 { "detach", zpool_do_detach, HELP_DETACH },
310 { "replace", zpool_do_replace, HELP_REPLACE },
311 { "split", zpool_do_split, HELP_SPLIT },
312 { NULL },
313 { "initialize", zpool_do_initialize, HELP_INITIALIZE },
314 { "resilver", zpool_do_resilver, HELP_RESILVER },
315 { "scrub", zpool_do_scrub, HELP_SCRUB },
316 { "trim", zpool_do_trim, HELP_TRIM },
317 { NULL },
318 { "import", zpool_do_import, HELP_IMPORT },
319 { "export", zpool_do_export, HELP_EXPORT },
320 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
321 { "reguid", zpool_do_reguid, HELP_REGUID },
322 { NULL },
323 { "history", zpool_do_history, HELP_HISTORY },
324 { "events", zpool_do_events, HELP_EVENTS },
325 { NULL },
326 { "get", zpool_do_get, HELP_GET },
327 { "set", zpool_do_set, HELP_SET },
328 { "sync", zpool_do_sync, HELP_SYNC },
329 { NULL },
330 { "wait", zpool_do_wait, HELP_WAIT },
333 #define NCOMMAND (ARRAY_SIZE(command_table))
335 #define VDEV_ALLOC_CLASS_LOGS "logs"
337 static zpool_command_t *current_command;
338 static char history_str[HIS_MAX_RECORD_LEN];
339 static boolean_t log_history = B_TRUE;
340 static uint_t timestamp_fmt = NODATE;
342 static const char *
343 get_usage(zpool_help_t idx)
345 switch (idx) {
346 case HELP_ADD:
347 return (gettext("\tadd [-fgLnP] [-o property=value] "
348 "<pool> <vdev> ...\n"));
349 case HELP_ATTACH:
350 return (gettext("\tattach [-fsw] [-o property=value] "
351 "<pool> <device> <new-device>\n"));
352 case HELP_CLEAR:
353 return (gettext("\tclear [-nF] <pool> [device]\n"));
354 case HELP_CREATE:
355 return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
356 "\t [-O file-system-property=value] ... \n"
357 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
358 case HELP_CHECKPOINT:
359 return (gettext("\tcheckpoint [-d [-w]] <pool> ...\n"));
360 case HELP_DESTROY:
361 return (gettext("\tdestroy [-f] <pool>\n"));
362 case HELP_DETACH:
363 return (gettext("\tdetach <pool> <device>\n"));
364 case HELP_EXPORT:
365 return (gettext("\texport [-af] <pool> ...\n"));
366 case HELP_HISTORY:
367 return (gettext("\thistory [-il] [<pool>] ...\n"));
368 case HELP_IMPORT:
369 return (gettext("\timport [-d dir] [-D]\n"
370 "\timport [-o mntopts] [-o property=value] ... \n"
371 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
372 "[-R root] [-F [-n]] -a\n"
373 "\timport [-o mntopts] [-o property=value] ... \n"
374 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
375 "[-R root] [-F [-n]]\n"
376 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
377 case HELP_IOSTAT:
378 return (gettext("\tiostat [[[-c [script1,script2,...]"
379 "[-lq]]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
380 "\t [[pool ...]|[pool vdev ...]|[vdev ...]]"
381 " [[-n] interval [count]]\n"));
382 case HELP_LABELCLEAR:
383 return (gettext("\tlabelclear [-f] <vdev>\n"));
384 case HELP_LIST:
385 return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
386 "[-T d|u] [pool] ... \n"
387 "\t [interval [count]]\n"));
388 case HELP_OFFLINE:
389 return (gettext("\toffline [-f] [-t] <pool> <device> ...\n"));
390 case HELP_ONLINE:
391 return (gettext("\tonline [-e] <pool> <device> ...\n"));
392 case HELP_REPLACE:
393 return (gettext("\treplace [-fsw] [-o property=value] "
394 "<pool> <device> [new-device]\n"));
395 case HELP_REMOVE:
396 return (gettext("\tremove [-npsw] <pool> <device> ...\n"));
397 case HELP_REOPEN:
398 return (gettext("\treopen [-n] <pool>\n"));
399 case HELP_INITIALIZE:
400 return (gettext("\tinitialize [-c | -s] [-w] <pool> "
401 "[<device> ...]\n"));
402 case HELP_SCRUB:
403 return (gettext("\tscrub [-s | -p] [-w] <pool> ...\n"));
404 case HELP_RESILVER:
405 return (gettext("\tresilver <pool> ...\n"));
406 case HELP_TRIM:
407 return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
408 "[<device> ...]\n"));
409 case HELP_STATUS:
410 return (gettext("\tstatus [-c [script1,script2,...]] "
411 "[-igLpPstvxD] [-T d|u] [pool] ... \n"
412 "\t [interval [count]]\n"));
413 case HELP_UPGRADE:
414 return (gettext("\tupgrade\n"
415 "\tupgrade -v\n"
416 "\tupgrade [-V version] <-a | pool ...>\n"));
417 case HELP_EVENTS:
418 return (gettext("\tevents [-vHf [pool] | -c]\n"));
419 case HELP_GET:
420 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
421 "<\"all\" | property[,...]> <pool> ...\n"));
422 case HELP_SET:
423 return (gettext("\tset <property=value> <pool> \n"));
424 case HELP_SPLIT:
425 return (gettext("\tsplit [-gLnPl] [-R altroot] [-o mntopts]\n"
426 "\t [-o property=value] <pool> <newpool> "
427 "[<device> ...]\n"));
428 case HELP_REGUID:
429 return (gettext("\treguid <pool>\n"));
430 case HELP_SYNC:
431 return (gettext("\tsync [pool] ...\n"));
432 case HELP_VERSION:
433 return (gettext("\tversion\n"));
434 case HELP_WAIT:
435 return (gettext("\twait [-Hp] [-T d|u] [-t <activity>[,...]] "
436 "<pool> [interval]\n"));
437 default:
438 __builtin_unreachable();
442 static void
443 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
445 uint_t children = 0;
446 nvlist_t **child;
447 uint_t i;
449 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
450 &child, &children);
452 if (children == 0) {
453 char *path = zpool_vdev_name(g_zfs, zhp, nvroot,
454 VDEV_NAME_PATH);
456 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
457 strcmp(path, VDEV_TYPE_HOLE) != 0)
458 fnvlist_add_boolean(res, path);
460 free(path);
461 return;
464 for (i = 0; i < children; i++) {
465 zpool_collect_leaves(zhp, child[i], res);
470 * Callback routine that will print out a pool property value.
472 static int
473 print_prop_cb(int prop, void *cb)
475 FILE *fp = cb;
477 (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop));
479 if (zpool_prop_readonly(prop))
480 (void) fprintf(fp, " NO ");
481 else
482 (void) fprintf(fp, " YES ");
484 if (zpool_prop_values(prop) == NULL)
485 (void) fprintf(fp, "-\n");
486 else
487 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
489 return (ZPROP_CONT);
493 * Display usage message. If we're inside a command, display only the usage for
494 * that command. Otherwise, iterate over the entire command table and display
495 * a complete usage message.
497 static void
498 usage(boolean_t requested)
500 FILE *fp = requested ? stdout : stderr;
502 if (current_command == NULL) {
503 int i;
505 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
506 (void) fprintf(fp,
507 gettext("where 'command' is one of the following:\n\n"));
509 for (i = 0; i < NCOMMAND; i++) {
510 if (command_table[i].name == NULL)
511 (void) fprintf(fp, "\n");
512 else
513 (void) fprintf(fp, "%s",
514 get_usage(command_table[i].usage));
516 } else {
517 (void) fprintf(fp, gettext("usage:\n"));
518 (void) fprintf(fp, "%s", get_usage(current_command->usage));
521 if (current_command != NULL &&
522 ((strcmp(current_command->name, "set") == 0) ||
523 (strcmp(current_command->name, "get") == 0) ||
524 (strcmp(current_command->name, "list") == 0))) {
526 (void) fprintf(fp,
527 gettext("\nthe following properties are supported:\n"));
529 (void) fprintf(fp, "\n\t%-19s %s %s\n\n",
530 "PROPERTY", "EDIT", "VALUES");
532 /* Iterate over all properties */
533 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
534 ZFS_TYPE_POOL);
536 (void) fprintf(fp, "\t%-19s ", "feature@...");
537 (void) fprintf(fp, "YES disabled | enabled | active\n");
539 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
540 "appended with a feature name.\nSee zpool-features(7).\n"));
544 * See comments at end of main().
546 if (getenv("ZFS_ABORT") != NULL) {
547 (void) printf("dumping core by request\n");
548 abort();
551 exit(requested ? 0 : 2);
555 * zpool initialize [-c | -s] [-w] <pool> [<vdev> ...]
556 * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
557 * if none specified.
559 * -c Cancel. Ends active initializing.
560 * -s Suspend. Initializing can then be restarted with no flags.
561 * -w Wait. Blocks until initializing has completed.
564 zpool_do_initialize(int argc, char **argv)
566 int c;
567 char *poolname;
568 zpool_handle_t *zhp;
569 nvlist_t *vdevs;
570 int err = 0;
571 boolean_t wait = B_FALSE;
573 struct option long_options[] = {
574 {"cancel", no_argument, NULL, 'c'},
575 {"suspend", no_argument, NULL, 's'},
576 {"wait", no_argument, NULL, 'w'},
577 {0, 0, 0, 0}
580 pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
581 while ((c = getopt_long(argc, argv, "csw", long_options, NULL)) != -1) {
582 switch (c) {
583 case 'c':
584 if (cmd_type != POOL_INITIALIZE_START &&
585 cmd_type != POOL_INITIALIZE_CANCEL) {
586 (void) fprintf(stderr, gettext("-c cannot be "
587 "combined with other options\n"));
588 usage(B_FALSE);
590 cmd_type = POOL_INITIALIZE_CANCEL;
591 break;
592 case 's':
593 if (cmd_type != POOL_INITIALIZE_START &&
594 cmd_type != POOL_INITIALIZE_SUSPEND) {
595 (void) fprintf(stderr, gettext("-s cannot be "
596 "combined with other options\n"));
597 usage(B_FALSE);
599 cmd_type = POOL_INITIALIZE_SUSPEND;
600 break;
601 case 'w':
602 wait = B_TRUE;
603 break;
604 case '?':
605 if (optopt != 0) {
606 (void) fprintf(stderr,
607 gettext("invalid option '%c'\n"), optopt);
608 } else {
609 (void) fprintf(stderr,
610 gettext("invalid option '%s'\n"),
611 argv[optind - 1]);
613 usage(B_FALSE);
617 argc -= optind;
618 argv += optind;
620 if (argc < 1) {
621 (void) fprintf(stderr, gettext("missing pool name argument\n"));
622 usage(B_FALSE);
623 return (-1);
626 if (wait && (cmd_type != POOL_INITIALIZE_START)) {
627 (void) fprintf(stderr, gettext("-w cannot be used with -c or "
628 "-s\n"));
629 usage(B_FALSE);
632 poolname = argv[0];
633 zhp = zpool_open(g_zfs, poolname);
634 if (zhp == NULL)
635 return (-1);
637 vdevs = fnvlist_alloc();
638 if (argc == 1) {
639 /* no individual leaf vdevs specified, so add them all */
640 nvlist_t *config = zpool_get_config(zhp, NULL);
641 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
642 ZPOOL_CONFIG_VDEV_TREE);
643 zpool_collect_leaves(zhp, nvroot, vdevs);
644 } else {
645 for (int i = 1; i < argc; i++) {
646 fnvlist_add_boolean(vdevs, argv[i]);
650 if (wait)
651 err = zpool_initialize_wait(zhp, cmd_type, vdevs);
652 else
653 err = zpool_initialize(zhp, cmd_type, vdevs);
655 fnvlist_free(vdevs);
656 zpool_close(zhp);
658 return (err);
662 * print a pool vdev config for dry runs
664 static void
665 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
666 const char *match, int name_flags)
668 nvlist_t **child;
669 uint_t c, children;
670 char *vname;
671 boolean_t printed = B_FALSE;
673 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
674 &child, &children) != 0) {
675 if (name != NULL)
676 (void) printf("\t%*s%s\n", indent, "", name);
677 return;
680 for (c = 0; c < children; c++) {
681 uint64_t is_log = B_FALSE, is_hole = B_FALSE;
682 char *class = "";
684 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
685 &is_hole);
687 if (is_hole == B_TRUE) {
688 continue;
691 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
692 &is_log);
693 if (is_log)
694 class = VDEV_ALLOC_BIAS_LOG;
695 (void) nvlist_lookup_string(child[c],
696 ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
697 if (strcmp(match, class) != 0)
698 continue;
700 if (!printed && name != NULL) {
701 (void) printf("\t%*s%s\n", indent, "", name);
702 printed = B_TRUE;
704 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
705 print_vdev_tree(zhp, vname, child[c], indent + 2, "",
706 name_flags);
707 free(vname);
712 * Print the list of l2cache devices for dry runs.
714 static void
715 print_cache_list(nvlist_t *nv, int indent)
717 nvlist_t **child;
718 uint_t c, children;
720 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
721 &child, &children) == 0 && children > 0) {
722 (void) printf("\t%*s%s\n", indent, "", "cache");
723 } else {
724 return;
726 for (c = 0; c < children; c++) {
727 char *vname;
729 vname = zpool_vdev_name(g_zfs, NULL, child[c], 0);
730 (void) printf("\t%*s%s\n", indent + 2, "", vname);
731 free(vname);
736 * Print the list of spares for dry runs.
738 static void
739 print_spare_list(nvlist_t *nv, int indent)
741 nvlist_t **child;
742 uint_t c, children;
744 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
745 &child, &children) == 0 && children > 0) {
746 (void) printf("\t%*s%s\n", indent, "", "spares");
747 } else {
748 return;
750 for (c = 0; c < children; c++) {
751 char *vname;
753 vname = zpool_vdev_name(g_zfs, NULL, child[c], 0);
754 (void) printf("\t%*s%s\n", indent + 2, "", vname);
755 free(vname);
759 static boolean_t
760 prop_list_contains_feature(nvlist_t *proplist)
762 nvpair_t *nvp;
763 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
764 nvp = nvlist_next_nvpair(proplist, nvp)) {
765 if (zpool_prop_feature(nvpair_name(nvp)))
766 return (B_TRUE);
768 return (B_FALSE);
772 * Add a property pair (name, string-value) into a property nvlist.
774 static int
775 add_prop_list(const char *propname, char *propval, nvlist_t **props,
776 boolean_t poolprop)
778 zpool_prop_t prop = ZPOOL_PROP_INVAL;
779 nvlist_t *proplist;
780 const char *normnm;
781 char *strval;
783 if (*props == NULL &&
784 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
785 (void) fprintf(stderr,
786 gettext("internal error: out of memory\n"));
787 return (1);
790 proplist = *props;
792 if (poolprop) {
793 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
794 const char *cname =
795 zpool_prop_to_name(ZPOOL_PROP_COMPATIBILITY);
797 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
798 !zpool_prop_feature(propname)) {
799 (void) fprintf(stderr, gettext("property '%s' is "
800 "not a valid pool property\n"), propname);
801 return (2);
805 * feature@ properties and version should not be specified
806 * at the same time.
808 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
809 nvlist_exists(proplist, vname)) ||
810 (prop == ZPOOL_PROP_VERSION &&
811 prop_list_contains_feature(proplist))) {
812 (void) fprintf(stderr, gettext("'feature@' and "
813 "'version' properties cannot be specified "
814 "together\n"));
815 return (2);
819 * if version is specified, only "legacy" compatibility
820 * may be requested
822 if ((prop == ZPOOL_PROP_COMPATIBILITY &&
823 strcmp(propval, ZPOOL_COMPAT_LEGACY) != 0 &&
824 nvlist_exists(proplist, vname)) ||
825 (prop == ZPOOL_PROP_VERSION &&
826 nvlist_exists(proplist, cname) &&
827 strcmp(fnvlist_lookup_string(proplist, cname),
828 ZPOOL_COMPAT_LEGACY) != 0)) {
829 (void) fprintf(stderr, gettext("when 'version' is "
830 "specified, the 'compatibility' feature may only "
831 "be set to '" ZPOOL_COMPAT_LEGACY "'\n"));
832 return (2);
835 if (zpool_prop_feature(propname))
836 normnm = propname;
837 else
838 normnm = zpool_prop_to_name(prop);
839 } else {
840 zfs_prop_t fsprop = zfs_name_to_prop(propname);
842 if (zfs_prop_valid_for_type(fsprop, ZFS_TYPE_FILESYSTEM,
843 B_FALSE)) {
844 normnm = zfs_prop_to_name(fsprop);
845 } else if (zfs_prop_user(propname) ||
846 zfs_prop_userquota(propname)) {
847 normnm = propname;
848 } else {
849 (void) fprintf(stderr, gettext("property '%s' is "
850 "not a valid filesystem property\n"), propname);
851 return (2);
855 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
856 prop != ZPOOL_PROP_CACHEFILE) {
857 (void) fprintf(stderr, gettext("property '%s' "
858 "specified multiple times\n"), propname);
859 return (2);
862 if (nvlist_add_string(proplist, normnm, propval) != 0) {
863 (void) fprintf(stderr, gettext("internal "
864 "error: out of memory\n"));
865 return (1);
868 return (0);
872 * Set a default property pair (name, string-value) in a property nvlist
874 static int
875 add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
876 boolean_t poolprop)
878 char *pval;
880 if (nvlist_lookup_string(*props, propname, &pval) == 0)
881 return (0);
883 return (add_prop_list(propname, propval, props, B_TRUE));
887 * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
889 * -f Force addition of devices, even if they appear in use
890 * -g Display guid for individual vdev name.
891 * -L Follow links when resolving vdev path name.
892 * -n Do not add the devices, but display the resulting layout if
893 * they were to be added.
894 * -o Set property=value.
895 * -P Display full path for vdev name.
897 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
898 * handled by make_root_vdev(), which constructs the nvlist needed to pass to
899 * libzfs.
902 zpool_do_add(int argc, char **argv)
904 boolean_t force = B_FALSE;
905 boolean_t dryrun = B_FALSE;
906 int name_flags = 0;
907 int c;
908 nvlist_t *nvroot;
909 char *poolname;
910 int ret;
911 zpool_handle_t *zhp;
912 nvlist_t *config;
913 nvlist_t *props = NULL;
914 char *propval;
916 /* check options */
917 while ((c = getopt(argc, argv, "fgLno:P")) != -1) {
918 switch (c) {
919 case 'f':
920 force = B_TRUE;
921 break;
922 case 'g':
923 name_flags |= VDEV_NAME_GUID;
924 break;
925 case 'L':
926 name_flags |= VDEV_NAME_FOLLOW_LINKS;
927 break;
928 case 'n':
929 dryrun = B_TRUE;
930 break;
931 case 'o':
932 if ((propval = strchr(optarg, '=')) == NULL) {
933 (void) fprintf(stderr, gettext("missing "
934 "'=' for -o option\n"));
935 usage(B_FALSE);
937 *propval = '\0';
938 propval++;
940 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
941 (add_prop_list(optarg, propval, &props, B_TRUE)))
942 usage(B_FALSE);
943 break;
944 case 'P':
945 name_flags |= VDEV_NAME_PATH;
946 break;
947 case '?':
948 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
949 optopt);
950 usage(B_FALSE);
954 argc -= optind;
955 argv += optind;
957 /* get pool name and check number of arguments */
958 if (argc < 1) {
959 (void) fprintf(stderr, gettext("missing pool name argument\n"));
960 usage(B_FALSE);
962 if (argc < 2) {
963 (void) fprintf(stderr, gettext("missing vdev specification\n"));
964 usage(B_FALSE);
967 poolname = argv[0];
969 argc--;
970 argv++;
972 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
973 return (1);
975 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
976 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
977 poolname);
978 zpool_close(zhp);
979 return (1);
982 /* unless manually specified use "ashift" pool property (if set) */
983 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
984 int intval;
985 zprop_source_t src;
986 char strval[ZPOOL_MAXPROPLEN];
988 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
989 if (src != ZPROP_SRC_DEFAULT) {
990 (void) sprintf(strval, "%" PRId32, intval);
991 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
992 &props, B_TRUE) == 0);
996 /* pass off to make_root_vdev for processing */
997 nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
998 argc, argv);
999 if (nvroot == NULL) {
1000 zpool_close(zhp);
1001 return (1);
1004 if (dryrun) {
1005 nvlist_t *poolnvroot;
1006 nvlist_t **l2child, **sparechild;
1007 uint_t l2children, sparechildren, c;
1008 char *vname;
1009 boolean_t hadcache = B_FALSE, hadspare = B_FALSE;
1011 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1012 &poolnvroot) == 0);
1014 (void) printf(gettext("would update '%s' to the following "
1015 "configuration:\n\n"), zpool_get_name(zhp));
1017 /* print original main pool and new tree */
1018 print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
1019 name_flags | VDEV_NAME_TYPE_ID);
1020 print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
1022 /* print other classes: 'dedup', 'special', and 'log' */
1023 if (zfs_special_devs(poolnvroot, VDEV_ALLOC_BIAS_DEDUP)) {
1024 print_vdev_tree(zhp, "dedup", poolnvroot, 0,
1025 VDEV_ALLOC_BIAS_DEDUP, name_flags);
1026 print_vdev_tree(zhp, NULL, nvroot, 0,
1027 VDEV_ALLOC_BIAS_DEDUP, name_flags);
1028 } else if (zfs_special_devs(nvroot, VDEV_ALLOC_BIAS_DEDUP)) {
1029 print_vdev_tree(zhp, "dedup", nvroot, 0,
1030 VDEV_ALLOC_BIAS_DEDUP, name_flags);
1033 if (zfs_special_devs(poolnvroot, VDEV_ALLOC_BIAS_SPECIAL)) {
1034 print_vdev_tree(zhp, "special", poolnvroot, 0,
1035 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
1036 print_vdev_tree(zhp, NULL, nvroot, 0,
1037 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
1038 } else if (zfs_special_devs(nvroot, VDEV_ALLOC_BIAS_SPECIAL)) {
1039 print_vdev_tree(zhp, "special", nvroot, 0,
1040 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
1043 if (num_logs(poolnvroot) > 0) {
1044 print_vdev_tree(zhp, "logs", poolnvroot, 0,
1045 VDEV_ALLOC_BIAS_LOG, name_flags);
1046 print_vdev_tree(zhp, NULL, nvroot, 0,
1047 VDEV_ALLOC_BIAS_LOG, name_flags);
1048 } else if (num_logs(nvroot) > 0) {
1049 print_vdev_tree(zhp, "logs", nvroot, 0,
1050 VDEV_ALLOC_BIAS_LOG, name_flags);
1053 /* Do the same for the caches */
1054 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_L2CACHE,
1055 &l2child, &l2children) == 0 && l2children) {
1056 hadcache = B_TRUE;
1057 (void) printf(gettext("\tcache\n"));
1058 for (c = 0; c < l2children; c++) {
1059 vname = zpool_vdev_name(g_zfs, NULL,
1060 l2child[c], name_flags);
1061 (void) printf("\t %s\n", vname);
1062 free(vname);
1065 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1066 &l2child, &l2children) == 0 && l2children) {
1067 if (!hadcache)
1068 (void) printf(gettext("\tcache\n"));
1069 for (c = 0; c < l2children; c++) {
1070 vname = zpool_vdev_name(g_zfs, NULL,
1071 l2child[c], name_flags);
1072 (void) printf("\t %s\n", vname);
1073 free(vname);
1076 /* And finally the spares */
1077 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_SPARES,
1078 &sparechild, &sparechildren) == 0 && sparechildren > 0) {
1079 hadspare = B_TRUE;
1080 (void) printf(gettext("\tspares\n"));
1081 for (c = 0; c < sparechildren; c++) {
1082 vname = zpool_vdev_name(g_zfs, NULL,
1083 sparechild[c], name_flags);
1084 (void) printf("\t %s\n", vname);
1085 free(vname);
1088 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1089 &sparechild, &sparechildren) == 0 && sparechildren > 0) {
1090 if (!hadspare)
1091 (void) printf(gettext("\tspares\n"));
1092 for (c = 0; c < sparechildren; c++) {
1093 vname = zpool_vdev_name(g_zfs, NULL,
1094 sparechild[c], name_flags);
1095 (void) printf("\t %s\n", vname);
1096 free(vname);
1100 ret = 0;
1101 } else {
1102 ret = (zpool_add(zhp, nvroot) != 0);
1105 nvlist_free(props);
1106 nvlist_free(nvroot);
1107 zpool_close(zhp);
1109 return (ret);
1113 * zpool remove [-npsw] <pool> <vdev> ...
1115 * Removes the given vdev from the pool.
1118 zpool_do_remove(int argc, char **argv)
1120 char *poolname;
1121 int i, ret = 0;
1122 zpool_handle_t *zhp = NULL;
1123 boolean_t stop = B_FALSE;
1124 int c;
1125 boolean_t noop = B_FALSE;
1126 boolean_t parsable = B_FALSE;
1127 boolean_t wait = B_FALSE;
1129 /* check options */
1130 while ((c = getopt(argc, argv, "npsw")) != -1) {
1131 switch (c) {
1132 case 'n':
1133 noop = B_TRUE;
1134 break;
1135 case 'p':
1136 parsable = B_TRUE;
1137 break;
1138 case 's':
1139 stop = B_TRUE;
1140 break;
1141 case 'w':
1142 wait = B_TRUE;
1143 break;
1144 case '?':
1145 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1146 optopt);
1147 usage(B_FALSE);
1151 argc -= optind;
1152 argv += optind;
1154 /* get pool name and check number of arguments */
1155 if (argc < 1) {
1156 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1157 usage(B_FALSE);
1160 poolname = argv[0];
1162 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
1163 return (1);
1165 if (stop && noop) {
1166 (void) fprintf(stderr, gettext("stop request ignored\n"));
1167 return (0);
1170 if (stop) {
1171 if (argc > 1) {
1172 (void) fprintf(stderr, gettext("too many arguments\n"));
1173 usage(B_FALSE);
1175 if (zpool_vdev_remove_cancel(zhp) != 0)
1176 ret = 1;
1177 if (wait) {
1178 (void) fprintf(stderr, gettext("invalid option "
1179 "combination: -w cannot be used with -s\n"));
1180 usage(B_FALSE);
1182 } else {
1183 if (argc < 2) {
1184 (void) fprintf(stderr, gettext("missing device\n"));
1185 usage(B_FALSE);
1188 for (i = 1; i < argc; i++) {
1189 if (noop) {
1190 uint64_t size;
1192 if (zpool_vdev_indirect_size(zhp, argv[i],
1193 &size) != 0) {
1194 ret = 1;
1195 break;
1197 if (parsable) {
1198 (void) printf("%s %llu\n",
1199 argv[i], (unsigned long long)size);
1200 } else {
1201 char valstr[32];
1202 zfs_nicenum(size, valstr,
1203 sizeof (valstr));
1204 (void) printf("Memory that will be "
1205 "used after removing %s: %s\n",
1206 argv[i], valstr);
1208 } else {
1209 if (zpool_vdev_remove(zhp, argv[i]) != 0)
1210 ret = 1;
1214 if (ret == 0 && wait)
1215 ret = zpool_wait(zhp, ZPOOL_WAIT_REMOVE);
1217 zpool_close(zhp);
1219 return (ret);
1223 * Return 1 if a vdev is active (being used in a pool)
1224 * Return 0 if a vdev is inactive (offlined or faulted, or not in active pool)
1226 * This is useful for checking if a disk in an active pool is offlined or
1227 * faulted.
1229 static int
1230 vdev_is_active(char *vdev_path)
1232 int fd;
1233 fd = open(vdev_path, O_EXCL);
1234 if (fd < 0) {
1235 return (1); /* cant open O_EXCL - disk is active */
1238 close(fd);
1239 return (0); /* disk is inactive in the pool */
1243 * zpool labelclear [-f] <vdev>
1245 * -f Force clearing the label for the vdevs which are members of
1246 * the exported or foreign pools.
1248 * Verifies that the vdev is not active and zeros out the label information
1249 * on the device.
1252 zpool_do_labelclear(int argc, char **argv)
1254 char vdev[MAXPATHLEN];
1255 char *name = NULL;
1256 struct stat st;
1257 int c, fd = -1, ret = 0;
1258 nvlist_t *config;
1259 pool_state_t state;
1260 boolean_t inuse = B_FALSE;
1261 boolean_t force = B_FALSE;
1263 /* check options */
1264 while ((c = getopt(argc, argv, "f")) != -1) {
1265 switch (c) {
1266 case 'f':
1267 force = B_TRUE;
1268 break;
1269 default:
1270 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1271 optopt);
1272 usage(B_FALSE);
1276 argc -= optind;
1277 argv += optind;
1279 /* get vdev name */
1280 if (argc < 1) {
1281 (void) fprintf(stderr, gettext("missing vdev name\n"));
1282 usage(B_FALSE);
1284 if (argc > 1) {
1285 (void) fprintf(stderr, gettext("too many arguments\n"));
1286 usage(B_FALSE);
1290 * Check if we were given absolute path and use it as is.
1291 * Otherwise if the provided vdev name doesn't point to a file,
1292 * try prepending expected disk paths and partition numbers.
1294 (void) strlcpy(vdev, argv[0], sizeof (vdev));
1295 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
1296 int error;
1298 error = zfs_resolve_shortname(argv[0], vdev, MAXPATHLEN);
1299 if (error == 0 && zfs_dev_is_whole_disk(vdev)) {
1300 if (zfs_append_partition(vdev, MAXPATHLEN) == -1)
1301 error = ENOENT;
1304 if (error || (stat(vdev, &st) != 0)) {
1305 (void) fprintf(stderr, gettext(
1306 "failed to find device %s, try specifying absolute "
1307 "path instead\n"), argv[0]);
1308 return (1);
1312 if ((fd = open(vdev, O_RDWR)) < 0) {
1313 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
1314 vdev, strerror(errno));
1315 return (1);
1319 * Flush all dirty pages for the block device. This should not be
1320 * fatal when the device does not support BLKFLSBUF as would be the
1321 * case for a file vdev.
1323 if ((zfs_dev_flush(fd) != 0) && (errno != ENOTTY))
1324 (void) fprintf(stderr, gettext("failed to invalidate "
1325 "cache for %s: %s\n"), vdev, strerror(errno));
1327 if (zpool_read_label(fd, &config, NULL) != 0) {
1328 (void) fprintf(stderr,
1329 gettext("failed to read label from %s\n"), vdev);
1330 ret = 1;
1331 goto errout;
1333 nvlist_free(config);
1335 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
1336 if (ret != 0) {
1337 (void) fprintf(stderr,
1338 gettext("failed to check state for %s\n"), vdev);
1339 ret = 1;
1340 goto errout;
1343 if (!inuse)
1344 goto wipe_label;
1346 switch (state) {
1347 default:
1348 case POOL_STATE_ACTIVE:
1349 case POOL_STATE_SPARE:
1350 case POOL_STATE_L2CACHE:
1352 * We allow the user to call 'zpool offline -f'
1353 * on an offlined disk in an active pool. We can check if
1354 * the disk is online by calling vdev_is_active().
1356 if (force && !vdev_is_active(vdev))
1357 break;
1359 (void) fprintf(stderr, gettext(
1360 "%s is a member (%s) of pool \"%s\""),
1361 vdev, zpool_pool_state_to_name(state), name);
1363 if (force) {
1364 (void) fprintf(stderr, gettext(
1365 ". Offline the disk first to clear its label."));
1367 printf("\n");
1368 ret = 1;
1369 goto errout;
1371 case POOL_STATE_EXPORTED:
1372 if (force)
1373 break;
1374 (void) fprintf(stderr, gettext(
1375 "use '-f' to override the following error:\n"
1376 "%s is a member of exported pool \"%s\"\n"),
1377 vdev, name);
1378 ret = 1;
1379 goto errout;
1381 case POOL_STATE_POTENTIALLY_ACTIVE:
1382 if (force)
1383 break;
1384 (void) fprintf(stderr, gettext(
1385 "use '-f' to override the following error:\n"
1386 "%s is a member of potentially active pool \"%s\"\n"),
1387 vdev, name);
1388 ret = 1;
1389 goto errout;
1391 case POOL_STATE_DESTROYED:
1392 /* inuse should never be set for a destroyed pool */
1393 assert(0);
1394 break;
1397 wipe_label:
1398 ret = zpool_clear_label(fd);
1399 if (ret != 0) {
1400 (void) fprintf(stderr,
1401 gettext("failed to clear label for %s\n"), vdev);
1404 errout:
1405 free(name);
1406 (void) close(fd);
1408 return (ret);
1412 * zpool create [-fnd] [-o property=value] ...
1413 * [-O file-system-property=value] ...
1414 * [-R root] [-m mountpoint] <pool> <dev> ...
1416 * -f Force creation, even if devices appear in use
1417 * -n Do not create the pool, but display the resulting layout if it
1418 * were to be created.
1419 * -R Create a pool under an alternate root
1420 * -m Set default mountpoint for the root dataset. By default it's
1421 * '/<pool>'
1422 * -o Set property=value.
1423 * -o Set feature@feature=enabled|disabled.
1424 * -d Don't automatically enable all supported pool features
1425 * (individual features can be enabled with -o).
1426 * -O Set fsproperty=value in the pool's root file system
1428 * Creates the named pool according to the given vdev specification. The
1429 * bulk of the vdev processing is done in make_root_vdev() in zpool_vdev.c.
1430 * Once we get the nvlist back from make_root_vdev(), we either print out the
1431 * contents (if '-n' was specified), or pass it to libzfs to do the creation.
1434 zpool_do_create(int argc, char **argv)
1436 boolean_t force = B_FALSE;
1437 boolean_t dryrun = B_FALSE;
1438 boolean_t enable_pool_features = B_TRUE;
1440 int c;
1441 nvlist_t *nvroot = NULL;
1442 char *poolname;
1443 char *tname = NULL;
1444 int ret = 1;
1445 char *altroot = NULL;
1446 char *compat = NULL;
1447 char *mountpoint = NULL;
1448 nvlist_t *fsprops = NULL;
1449 nvlist_t *props = NULL;
1450 char *propval;
1452 /* check options */
1453 while ((c = getopt(argc, argv, ":fndR:m:o:O:t:")) != -1) {
1454 switch (c) {
1455 case 'f':
1456 force = B_TRUE;
1457 break;
1458 case 'n':
1459 dryrun = B_TRUE;
1460 break;
1461 case 'd':
1462 enable_pool_features = B_FALSE;
1463 break;
1464 case 'R':
1465 altroot = optarg;
1466 if (add_prop_list(zpool_prop_to_name(
1467 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1468 goto errout;
1469 if (add_prop_list_default(zpool_prop_to_name(
1470 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1471 goto errout;
1472 break;
1473 case 'm':
1474 /* Equivalent to -O mountpoint=optarg */
1475 mountpoint = optarg;
1476 break;
1477 case 'o':
1478 if ((propval = strchr(optarg, '=')) == NULL) {
1479 (void) fprintf(stderr, gettext("missing "
1480 "'=' for -o option\n"));
1481 goto errout;
1483 *propval = '\0';
1484 propval++;
1486 if (add_prop_list(optarg, propval, &props, B_TRUE))
1487 goto errout;
1490 * If the user is creating a pool that doesn't support
1491 * feature flags, don't enable any features.
1493 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1494 char *end;
1495 u_longlong_t ver;
1497 ver = strtoull(propval, &end, 10);
1498 if (*end == '\0' &&
1499 ver < SPA_VERSION_FEATURES) {
1500 enable_pool_features = B_FALSE;
1503 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1504 altroot = propval;
1505 if (zpool_name_to_prop(optarg) ==
1506 ZPOOL_PROP_COMPATIBILITY)
1507 compat = propval;
1508 break;
1509 case 'O':
1510 if ((propval = strchr(optarg, '=')) == NULL) {
1511 (void) fprintf(stderr, gettext("missing "
1512 "'=' for -O option\n"));
1513 goto errout;
1515 *propval = '\0';
1516 propval++;
1519 * Mountpoints are checked and then added later.
1520 * Uniquely among properties, they can be specified
1521 * more than once, to avoid conflict with -m.
1523 if (0 == strcmp(optarg,
1524 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1525 mountpoint = propval;
1526 } else if (add_prop_list(optarg, propval, &fsprops,
1527 B_FALSE)) {
1528 goto errout;
1530 break;
1531 case 't':
1533 * Sanity check temporary pool name.
1535 if (strchr(optarg, '/') != NULL) {
1536 (void) fprintf(stderr, gettext("cannot create "
1537 "'%s': invalid character '/' in temporary "
1538 "name\n"), optarg);
1539 (void) fprintf(stderr, gettext("use 'zfs "
1540 "create' to create a dataset\n"));
1541 goto errout;
1544 if (add_prop_list(zpool_prop_to_name(
1545 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1546 goto errout;
1547 if (add_prop_list_default(zpool_prop_to_name(
1548 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1549 goto errout;
1550 tname = optarg;
1551 break;
1552 case ':':
1553 (void) fprintf(stderr, gettext("missing argument for "
1554 "'%c' option\n"), optopt);
1555 goto badusage;
1556 case '?':
1557 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1558 optopt);
1559 goto badusage;
1563 argc -= optind;
1564 argv += optind;
1566 /* get pool name and check number of arguments */
1567 if (argc < 1) {
1568 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1569 goto badusage;
1571 if (argc < 2) {
1572 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1573 goto badusage;
1576 poolname = argv[0];
1579 * As a special case, check for use of '/' in the name, and direct the
1580 * user to use 'zfs create' instead.
1582 if (strchr(poolname, '/') != NULL) {
1583 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1584 "character '/' in pool name\n"), poolname);
1585 (void) fprintf(stderr, gettext("use 'zfs create' to "
1586 "create a dataset\n"));
1587 goto errout;
1590 /* pass off to make_root_vdev for bulk processing */
1591 nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
1592 argc - 1, argv + 1);
1593 if (nvroot == NULL)
1594 goto errout;
1596 /* make_root_vdev() allows 0 toplevel children if there are spares */
1597 if (!zfs_allocatable_devs(nvroot)) {
1598 (void) fprintf(stderr, gettext("invalid vdev "
1599 "specification: at least one toplevel vdev must be "
1600 "specified\n"));
1601 goto errout;
1604 if (altroot != NULL && altroot[0] != '/') {
1605 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1606 "must be an absolute path\n"), altroot);
1607 goto errout;
1611 * Check the validity of the mountpoint and direct the user to use the
1612 * '-m' mountpoint option if it looks like its in use.
1614 if (mountpoint == NULL ||
1615 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1616 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1617 char buf[MAXPATHLEN];
1618 DIR *dirp;
1620 if (mountpoint && mountpoint[0] != '/') {
1621 (void) fprintf(stderr, gettext("invalid mountpoint "
1622 "'%s': must be an absolute path, 'legacy', or "
1623 "'none'\n"), mountpoint);
1624 goto errout;
1627 if (mountpoint == NULL) {
1628 if (altroot != NULL)
1629 (void) snprintf(buf, sizeof (buf), "%s/%s",
1630 altroot, poolname);
1631 else
1632 (void) snprintf(buf, sizeof (buf), "/%s",
1633 poolname);
1634 } else {
1635 if (altroot != NULL)
1636 (void) snprintf(buf, sizeof (buf), "%s%s",
1637 altroot, mountpoint);
1638 else
1639 (void) snprintf(buf, sizeof (buf), "%s",
1640 mountpoint);
1643 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1644 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1645 "%s\n"), buf, strerror(errno));
1646 (void) fprintf(stderr, gettext("use '-m' "
1647 "option to provide a different default\n"));
1648 goto errout;
1649 } else if (dirp) {
1650 int count = 0;
1652 while (count < 3 && readdir(dirp) != NULL)
1653 count++;
1654 (void) closedir(dirp);
1656 if (count > 2) {
1657 (void) fprintf(stderr, gettext("mountpoint "
1658 "'%s' exists and is not empty\n"), buf);
1659 (void) fprintf(stderr, gettext("use '-m' "
1660 "option to provide a "
1661 "different default\n"));
1662 goto errout;
1668 * Now that the mountpoint's validity has been checked, ensure that
1669 * the property is set appropriately prior to creating the pool.
1671 if (mountpoint != NULL) {
1672 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1673 mountpoint, &fsprops, B_FALSE);
1674 if (ret != 0)
1675 goto errout;
1678 ret = 1;
1679 if (dryrun) {
1681 * For a dry run invocation, print out a basic message and run
1682 * through all the vdevs in the list and print out in an
1683 * appropriate hierarchy.
1685 (void) printf(gettext("would create '%s' with the "
1686 "following layout:\n\n"), poolname);
1688 print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
1689 print_vdev_tree(NULL, "dedup", nvroot, 0,
1690 VDEV_ALLOC_BIAS_DEDUP, 0);
1691 print_vdev_tree(NULL, "special", nvroot, 0,
1692 VDEV_ALLOC_BIAS_SPECIAL, 0);
1693 print_vdev_tree(NULL, "logs", nvroot, 0,
1694 VDEV_ALLOC_BIAS_LOG, 0);
1695 print_cache_list(nvroot, 0);
1696 print_spare_list(nvroot, 0);
1698 ret = 0;
1699 } else {
1701 * Load in feature set.
1702 * Note: if compatibility property not given, we'll have
1703 * NULL, which means 'all features'.
1705 boolean_t requested_features[SPA_FEATURES];
1706 if (zpool_do_load_compat(compat, requested_features) !=
1707 ZPOOL_COMPATIBILITY_OK)
1708 goto errout;
1711 * props contains list of features to enable.
1712 * For each feature:
1713 * - remove it if feature@name=disabled
1714 * - leave it there if feature@name=enabled
1715 * - add it if:
1716 * - enable_pool_features (ie: no '-d' or '-o version')
1717 * - it's supported by the kernel module
1718 * - it's in the requested feature set
1719 * - warn if it's enabled but not in compat
1721 for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
1722 char propname[MAXPATHLEN];
1723 char *propval;
1724 zfeature_info_t *feat = &spa_feature_table[i];
1726 (void) snprintf(propname, sizeof (propname),
1727 "feature@%s", feat->fi_uname);
1729 if (!nvlist_lookup_string(props, propname, &propval)) {
1730 if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0)
1731 (void) nvlist_remove_all(props,
1732 propname);
1733 if (strcmp(propval,
1734 ZFS_FEATURE_ENABLED) == 0 &&
1735 !requested_features[i])
1736 (void) fprintf(stderr, gettext(
1737 "Warning: feature \"%s\" enabled "
1738 "but is not in specified "
1739 "'compatibility' feature set.\n"),
1740 feat->fi_uname);
1741 } else if (
1742 enable_pool_features &&
1743 feat->fi_zfs_mod_supported &&
1744 requested_features[i]) {
1745 ret = add_prop_list(propname,
1746 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1747 if (ret != 0)
1748 goto errout;
1752 ret = 1;
1753 if (zpool_create(g_zfs, poolname,
1754 nvroot, props, fsprops) == 0) {
1755 zfs_handle_t *pool = zfs_open(g_zfs,
1756 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1757 if (pool != NULL) {
1758 if (zfs_mount(pool, NULL, 0) == 0) {
1759 ret = zfs_shareall(pool);
1760 zfs_commit_all_shares();
1762 zfs_close(pool);
1764 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1765 (void) fprintf(stderr, gettext("pool name may have "
1766 "been omitted\n"));
1770 errout:
1771 nvlist_free(nvroot);
1772 nvlist_free(fsprops);
1773 nvlist_free(props);
1774 return (ret);
1775 badusage:
1776 nvlist_free(fsprops);
1777 nvlist_free(props);
1778 usage(B_FALSE);
1779 return (2);
1783 * zpool destroy <pool>
1785 * -f Forcefully unmount any datasets
1787 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1790 zpool_do_destroy(int argc, char **argv)
1792 boolean_t force = B_FALSE;
1793 int c;
1794 char *pool;
1795 zpool_handle_t *zhp;
1796 int ret;
1798 /* check options */
1799 while ((c = getopt(argc, argv, "f")) != -1) {
1800 switch (c) {
1801 case 'f':
1802 force = B_TRUE;
1803 break;
1804 case '?':
1805 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1806 optopt);
1807 usage(B_FALSE);
1811 argc -= optind;
1812 argv += optind;
1814 /* check arguments */
1815 if (argc < 1) {
1816 (void) fprintf(stderr, gettext("missing pool argument\n"));
1817 usage(B_FALSE);
1819 if (argc > 1) {
1820 (void) fprintf(stderr, gettext("too many arguments\n"));
1821 usage(B_FALSE);
1824 pool = argv[0];
1826 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1828 * As a special case, check for use of '/' in the name, and
1829 * direct the user to use 'zfs destroy' instead.
1831 if (strchr(pool, '/') != NULL)
1832 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1833 "destroy a dataset\n"));
1834 return (1);
1837 if (zpool_disable_datasets(zhp, force) != 0) {
1838 (void) fprintf(stderr, gettext("could not destroy '%s': "
1839 "could not unmount datasets\n"), zpool_get_name(zhp));
1840 zpool_close(zhp);
1841 return (1);
1844 /* The history must be logged as part of the export */
1845 log_history = B_FALSE;
1847 ret = (zpool_destroy(zhp, history_str) != 0);
1849 zpool_close(zhp);
1851 return (ret);
1854 typedef struct export_cbdata {
1855 boolean_t force;
1856 boolean_t hardforce;
1857 } export_cbdata_t;
1860 * Export one pool
1862 static int
1863 zpool_export_one(zpool_handle_t *zhp, void *data)
1865 export_cbdata_t *cb = data;
1867 if (zpool_disable_datasets(zhp, cb->force) != 0)
1868 return (1);
1870 /* The history must be logged as part of the export */
1871 log_history = B_FALSE;
1873 if (cb->hardforce) {
1874 if (zpool_export_force(zhp, history_str) != 0)
1875 return (1);
1876 } else if (zpool_export(zhp, cb->force, history_str) != 0) {
1877 return (1);
1880 return (0);
1884 * zpool export [-f] <pool> ...
1886 * -a Export all pools
1887 * -f Forcefully unmount datasets
1889 * Export the given pools. By default, the command will attempt to cleanly
1890 * unmount any active datasets within the pool. If the '-f' flag is specified,
1891 * then the datasets will be forcefully unmounted.
1894 zpool_do_export(int argc, char **argv)
1896 export_cbdata_t cb;
1897 boolean_t do_all = B_FALSE;
1898 boolean_t force = B_FALSE;
1899 boolean_t hardforce = B_FALSE;
1900 int c, ret;
1902 /* check options */
1903 while ((c = getopt(argc, argv, "afF")) != -1) {
1904 switch (c) {
1905 case 'a':
1906 do_all = B_TRUE;
1907 break;
1908 case 'f':
1909 force = B_TRUE;
1910 break;
1911 case 'F':
1912 hardforce = B_TRUE;
1913 break;
1914 case '?':
1915 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1916 optopt);
1917 usage(B_FALSE);
1921 cb.force = force;
1922 cb.hardforce = hardforce;
1923 argc -= optind;
1924 argv += optind;
1926 if (do_all) {
1927 if (argc != 0) {
1928 (void) fprintf(stderr, gettext("too many arguments\n"));
1929 usage(B_FALSE);
1932 return (for_each_pool(argc, argv, B_TRUE, NULL,
1933 B_FALSE, zpool_export_one, &cb));
1936 /* check arguments */
1937 if (argc < 1) {
1938 (void) fprintf(stderr, gettext("missing pool argument\n"));
1939 usage(B_FALSE);
1942 ret = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, zpool_export_one,
1943 &cb);
1945 return (ret);
1949 * Given a vdev configuration, determine the maximum width needed for the device
1950 * name column.
1952 static int
1953 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1954 int name_flags)
1956 char *name;
1957 nvlist_t **child;
1958 uint_t c, children;
1959 int ret;
1961 name = zpool_vdev_name(g_zfs, zhp, nv, name_flags);
1962 if (strlen(name) + depth > max)
1963 max = strlen(name) + depth;
1965 free(name);
1967 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1968 &child, &children) == 0) {
1969 for (c = 0; c < children; c++)
1970 if ((ret = max_width(zhp, child[c], depth + 2,
1971 max, name_flags)) > max)
1972 max = ret;
1975 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1976 &child, &children) == 0) {
1977 for (c = 0; c < children; c++)
1978 if ((ret = max_width(zhp, child[c], depth + 2,
1979 max, name_flags)) > max)
1980 max = ret;
1983 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1984 &child, &children) == 0) {
1985 for (c = 0; c < children; c++)
1986 if ((ret = max_width(zhp, child[c], depth + 2,
1987 max, name_flags)) > max)
1988 max = ret;
1991 return (max);
1994 typedef struct spare_cbdata {
1995 uint64_t cb_guid;
1996 zpool_handle_t *cb_zhp;
1997 } spare_cbdata_t;
1999 static boolean_t
2000 find_vdev(nvlist_t *nv, uint64_t search)
2002 uint64_t guid;
2003 nvlist_t **child;
2004 uint_t c, children;
2006 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2007 search == guid)
2008 return (B_TRUE);
2010 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2011 &child, &children) == 0) {
2012 for (c = 0; c < children; c++)
2013 if (find_vdev(child[c], search))
2014 return (B_TRUE);
2017 return (B_FALSE);
2020 static int
2021 find_spare(zpool_handle_t *zhp, void *data)
2023 spare_cbdata_t *cbp = data;
2024 nvlist_t *config, *nvroot;
2026 config = zpool_get_config(zhp, NULL);
2027 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2028 &nvroot) == 0);
2030 if (find_vdev(nvroot, cbp->cb_guid)) {
2031 cbp->cb_zhp = zhp;
2032 return (1);
2035 zpool_close(zhp);
2036 return (0);
2039 typedef struct status_cbdata {
2040 int cb_count;
2041 int cb_name_flags;
2042 int cb_namewidth;
2043 boolean_t cb_allpools;
2044 boolean_t cb_verbose;
2045 boolean_t cb_literal;
2046 boolean_t cb_explain;
2047 boolean_t cb_first;
2048 boolean_t cb_dedup_stats;
2049 boolean_t cb_print_status;
2050 boolean_t cb_print_slow_ios;
2051 boolean_t cb_print_vdev_init;
2052 boolean_t cb_print_vdev_trim;
2053 vdev_cmd_data_list_t *vcdl;
2054 } status_cbdata_t;
2056 /* Return 1 if string is NULL, empty, or whitespace; return 0 otherwise. */
2057 static int
2058 is_blank_str(char *str)
2060 while (str != NULL && *str != '\0') {
2061 if (!isblank(*str))
2062 return (0);
2063 str++;
2065 return (1);
2068 /* Print command output lines for specific vdev in a specific pool */
2069 static void
2070 zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, char *path)
2072 vdev_cmd_data_t *data;
2073 int i, j;
2074 char *val;
2076 for (i = 0; i < vcdl->count; i++) {
2077 if ((strcmp(vcdl->data[i].path, path) != 0) ||
2078 (strcmp(vcdl->data[i].pool, pool) != 0)) {
2079 /* Not the vdev we're looking for */
2080 continue;
2083 data = &vcdl->data[i];
2084 /* Print out all the output values for this vdev */
2085 for (j = 0; j < vcdl->uniq_cols_cnt; j++) {
2086 val = NULL;
2087 /* Does this vdev have values for this column? */
2088 for (int k = 0; k < data->cols_cnt; k++) {
2089 if (strcmp(data->cols[k],
2090 vcdl->uniq_cols[j]) == 0) {
2091 /* yes it does, record the value */
2092 val = data->lines[k];
2093 break;
2097 * Mark empty values with dashes to make output
2098 * awk-able.
2100 if (val == NULL || is_blank_str(val))
2101 val = "-";
2103 printf("%*s", vcdl->uniq_cols_width[j], val);
2104 if (j < vcdl->uniq_cols_cnt - 1)
2105 printf(" ");
2108 /* Print out any values that aren't in a column at the end */
2109 for (j = data->cols_cnt; j < data->lines_cnt; j++) {
2110 /* Did we have any columns? If so print a spacer. */
2111 if (vcdl->uniq_cols_cnt > 0)
2112 printf(" ");
2114 val = data->lines[j];
2115 printf("%s", val ? val : "");
2117 break;
2122 * Print vdev initialization status for leaves
2124 static void
2125 print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
2127 if (verbose) {
2128 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
2129 vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
2130 vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
2131 !vs->vs_scan_removing) {
2132 char zbuf[1024];
2133 char tbuf[256];
2134 struct tm zaction_ts;
2136 time_t t = vs->vs_initialize_action_time;
2137 int initialize_pct = 100;
2138 if (vs->vs_initialize_state !=
2139 VDEV_INITIALIZE_COMPLETE) {
2140 initialize_pct = (vs->vs_initialize_bytes_done *
2141 100 / (vs->vs_initialize_bytes_est + 1));
2144 (void) localtime_r(&t, &zaction_ts);
2145 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
2147 switch (vs->vs_initialize_state) {
2148 case VDEV_INITIALIZE_SUSPENDED:
2149 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2150 gettext("suspended, started at"), tbuf);
2151 break;
2152 case VDEV_INITIALIZE_ACTIVE:
2153 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2154 gettext("started at"), tbuf);
2155 break;
2156 case VDEV_INITIALIZE_COMPLETE:
2157 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2158 gettext("completed at"), tbuf);
2159 break;
2162 (void) printf(gettext(" (%d%% initialized%s)"),
2163 initialize_pct, zbuf);
2164 } else {
2165 (void) printf(gettext(" (uninitialized)"));
2167 } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) {
2168 (void) printf(gettext(" (initializing)"));
2173 * Print vdev TRIM status for leaves
2175 static void
2176 print_status_trim(vdev_stat_t *vs, boolean_t verbose)
2178 if (verbose) {
2179 if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE ||
2180 vs->vs_trim_state == VDEV_TRIM_SUSPENDED ||
2181 vs->vs_trim_state == VDEV_TRIM_COMPLETE) &&
2182 !vs->vs_scan_removing) {
2183 char zbuf[1024];
2184 char tbuf[256];
2185 struct tm zaction_ts;
2187 time_t t = vs->vs_trim_action_time;
2188 int trim_pct = 100;
2189 if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) {
2190 trim_pct = (vs->vs_trim_bytes_done *
2191 100 / (vs->vs_trim_bytes_est + 1));
2194 (void) localtime_r(&t, &zaction_ts);
2195 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
2197 switch (vs->vs_trim_state) {
2198 case VDEV_TRIM_SUSPENDED:
2199 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2200 gettext("suspended, started at"), tbuf);
2201 break;
2202 case VDEV_TRIM_ACTIVE:
2203 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2204 gettext("started at"), tbuf);
2205 break;
2206 case VDEV_TRIM_COMPLETE:
2207 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2208 gettext("completed at"), tbuf);
2209 break;
2212 (void) printf(gettext(" (%d%% trimmed%s)"),
2213 trim_pct, zbuf);
2214 } else if (vs->vs_trim_notsup) {
2215 (void) printf(gettext(" (trim unsupported)"));
2216 } else {
2217 (void) printf(gettext(" (untrimmed)"));
2219 } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) {
2220 (void) printf(gettext(" (trimming)"));
2225 * Return the color associated with a health string. This includes returning
2226 * NULL for no color change.
2228 static char *
2229 health_str_to_color(const char *health)
2231 if (strcmp(health, gettext("FAULTED")) == 0 ||
2232 strcmp(health, gettext("SUSPENDED")) == 0 ||
2233 strcmp(health, gettext("UNAVAIL")) == 0) {
2234 return (ANSI_RED);
2237 if (strcmp(health, gettext("OFFLINE")) == 0 ||
2238 strcmp(health, gettext("DEGRADED")) == 0 ||
2239 strcmp(health, gettext("REMOVED")) == 0) {
2240 return (ANSI_YELLOW);
2243 return (NULL);
2247 * Print out configuration state as requested by status_callback.
2249 static void
2250 print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
2251 nvlist_t *nv, int depth, boolean_t isspare, vdev_rebuild_stat_t *vrs)
2253 nvlist_t **child, *root;
2254 uint_t c, i, vsc, children;
2255 pool_scan_stat_t *ps = NULL;
2256 vdev_stat_t *vs;
2257 char rbuf[6], wbuf[6], cbuf[6];
2258 char *vname;
2259 uint64_t notpresent;
2260 spare_cbdata_t spare_cb;
2261 const char *state;
2262 char *type;
2263 char *path = NULL;
2264 char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL;
2266 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2267 &child, &children) != 0)
2268 children = 0;
2270 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2271 (uint64_t **)&vs, &vsc) == 0);
2273 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
2275 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
2276 return;
2278 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2280 if (isspare) {
2282 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2283 * online drives.
2285 if (vs->vs_aux == VDEV_AUX_SPARED)
2286 state = gettext("INUSE");
2287 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2288 state = gettext("AVAIL");
2291 printf_color(health_str_to_color(state),
2292 "\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
2293 name, state);
2295 if (!isspare) {
2296 if (vs->vs_read_errors)
2297 rcolor = ANSI_RED;
2299 if (vs->vs_write_errors)
2300 wcolor = ANSI_RED;
2302 if (vs->vs_checksum_errors)
2303 ccolor = ANSI_RED;
2305 if (cb->cb_literal) {
2306 printf(" ");
2307 printf_color(rcolor, "%5llu",
2308 (u_longlong_t)vs->vs_read_errors);
2309 printf(" ");
2310 printf_color(wcolor, "%5llu",
2311 (u_longlong_t)vs->vs_write_errors);
2312 printf(" ");
2313 printf_color(ccolor, "%5llu",
2314 (u_longlong_t)vs->vs_checksum_errors);
2315 } else {
2316 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2317 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2318 zfs_nicenum(vs->vs_checksum_errors, cbuf,
2319 sizeof (cbuf));
2320 printf(" ");
2321 printf_color(rcolor, "%5s", rbuf);
2322 printf(" ");
2323 printf_color(wcolor, "%5s", wbuf);
2324 printf(" ");
2325 printf_color(ccolor, "%5s", cbuf);
2327 if (cb->cb_print_slow_ios) {
2328 if (children == 0) {
2329 /* Only leafs vdevs have slow IOs */
2330 zfs_nicenum(vs->vs_slow_ios, rbuf,
2331 sizeof (rbuf));
2332 } else {
2333 snprintf(rbuf, sizeof (rbuf), "-");
2336 if (cb->cb_literal)
2337 printf(" %5llu", (u_longlong_t)vs->vs_slow_ios);
2338 else
2339 printf(" %5s", rbuf);
2343 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2344 &notpresent) == 0) {
2345 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2346 (void) printf(" %s %s", gettext("was"), path);
2347 } else if (vs->vs_aux != 0) {
2348 (void) printf(" ");
2349 color_start(ANSI_RED);
2350 switch (vs->vs_aux) {
2351 case VDEV_AUX_OPEN_FAILED:
2352 (void) printf(gettext("cannot open"));
2353 break;
2355 case VDEV_AUX_BAD_GUID_SUM:
2356 (void) printf(gettext("missing device"));
2357 break;
2359 case VDEV_AUX_NO_REPLICAS:
2360 (void) printf(gettext("insufficient replicas"));
2361 break;
2363 case VDEV_AUX_VERSION_NEWER:
2364 (void) printf(gettext("newer version"));
2365 break;
2367 case VDEV_AUX_UNSUP_FEAT:
2368 (void) printf(gettext("unsupported feature(s)"));
2369 break;
2371 case VDEV_AUX_ASHIFT_TOO_BIG:
2372 (void) printf(gettext("unsupported minimum blocksize"));
2373 break;
2375 case VDEV_AUX_SPARED:
2376 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2377 &spare_cb.cb_guid) == 0);
2378 if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
2379 if (strcmp(zpool_get_name(spare_cb.cb_zhp),
2380 zpool_get_name(zhp)) == 0)
2381 (void) printf(gettext("currently in "
2382 "use"));
2383 else
2384 (void) printf(gettext("in use by "
2385 "pool '%s'"),
2386 zpool_get_name(spare_cb.cb_zhp));
2387 zpool_close(spare_cb.cb_zhp);
2388 } else {
2389 (void) printf(gettext("currently in use"));
2391 break;
2393 case VDEV_AUX_ERR_EXCEEDED:
2394 (void) printf(gettext("too many errors"));
2395 break;
2397 case VDEV_AUX_IO_FAILURE:
2398 (void) printf(gettext("experienced I/O failures"));
2399 break;
2401 case VDEV_AUX_BAD_LOG:
2402 (void) printf(gettext("bad intent log"));
2403 break;
2405 case VDEV_AUX_EXTERNAL:
2406 (void) printf(gettext("external device fault"));
2407 break;
2409 case VDEV_AUX_SPLIT_POOL:
2410 (void) printf(gettext("split into new pool"));
2411 break;
2413 case VDEV_AUX_ACTIVE:
2414 (void) printf(gettext("currently in use"));
2415 break;
2417 case VDEV_AUX_CHILDREN_OFFLINE:
2418 (void) printf(gettext("all children offline"));
2419 break;
2421 case VDEV_AUX_BAD_LABEL:
2422 (void) printf(gettext("invalid label"));
2423 break;
2425 default:
2426 (void) printf(gettext("corrupted data"));
2427 break;
2429 color_end();
2430 } else if (children == 0 && !isspare &&
2431 getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") == NULL &&
2432 VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
2433 vs->vs_configured_ashift < vs->vs_physical_ashift) {
2434 (void) printf(
2435 gettext(" block size: %dB configured, %dB native"),
2436 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
2439 /* The root vdev has the scrub/resilver stats */
2440 root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
2441 ZPOOL_CONFIG_VDEV_TREE);
2442 (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
2443 (uint64_t **)&ps, &c);
2445 if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) {
2446 if (vs->vs_scan_processed != 0) {
2447 (void) printf(gettext(" (%s)"),
2448 (ps->pss_func == POOL_SCAN_RESILVER) ?
2449 "resilvering" : "repairing");
2450 } else if (vs->vs_resilver_deferred) {
2451 (void) printf(gettext(" (awaiting resilver)"));
2455 /* The top-level vdevs have the rebuild stats */
2456 if (vrs != NULL && vrs->vrs_state == VDEV_REBUILD_ACTIVE &&
2457 children == 0) {
2458 if (vs->vs_rebuild_processed != 0) {
2459 (void) printf(gettext(" (resilvering)"));
2463 if (cb->vcdl != NULL) {
2464 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
2465 printf(" ");
2466 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path);
2470 /* Display vdev initialization and trim status for leaves. */
2471 if (children == 0) {
2472 print_status_initialize(vs, cb->cb_print_vdev_init);
2473 print_status_trim(vs, cb->cb_print_vdev_trim);
2476 (void) printf("\n");
2478 for (c = 0; c < children; c++) {
2479 uint64_t islog = B_FALSE, ishole = B_FALSE;
2481 /* Don't print logs or holes here */
2482 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2483 &islog);
2484 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
2485 &ishole);
2486 if (islog || ishole)
2487 continue;
2488 /* Only print normal classes here */
2489 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2490 continue;
2492 /* Provide vdev_rebuild_stats to children if available */
2493 if (vrs == NULL) {
2494 (void) nvlist_lookup_uint64_array(nv,
2495 ZPOOL_CONFIG_REBUILD_STATS,
2496 (uint64_t **)&vrs, &i);
2499 vname = zpool_vdev_name(g_zfs, zhp, child[c],
2500 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2501 print_status_config(zhp, cb, vname, child[c], depth + 2,
2502 isspare, vrs);
2503 free(vname);
2508 * Print the configuration of an exported pool. Iterate over all vdevs in the
2509 * pool, printing out the name and status for each one.
2511 static void
2512 print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
2513 int depth)
2515 nvlist_t **child;
2516 uint_t c, children;
2517 vdev_stat_t *vs;
2518 char *type, *vname;
2520 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
2521 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
2522 strcmp(type, VDEV_TYPE_HOLE) == 0)
2523 return;
2525 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2526 (uint64_t **)&vs, &c) == 0);
2528 (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
2529 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
2531 if (vs->vs_aux != 0) {
2532 (void) printf(" ");
2534 switch (vs->vs_aux) {
2535 case VDEV_AUX_OPEN_FAILED:
2536 (void) printf(gettext("cannot open"));
2537 break;
2539 case VDEV_AUX_BAD_GUID_SUM:
2540 (void) printf(gettext("missing device"));
2541 break;
2543 case VDEV_AUX_NO_REPLICAS:
2544 (void) printf(gettext("insufficient replicas"));
2545 break;
2547 case VDEV_AUX_VERSION_NEWER:
2548 (void) printf(gettext("newer version"));
2549 break;
2551 case VDEV_AUX_UNSUP_FEAT:
2552 (void) printf(gettext("unsupported feature(s)"));
2553 break;
2555 case VDEV_AUX_ERR_EXCEEDED:
2556 (void) printf(gettext("too many errors"));
2557 break;
2559 case VDEV_AUX_ACTIVE:
2560 (void) printf(gettext("currently in use"));
2561 break;
2563 case VDEV_AUX_CHILDREN_OFFLINE:
2564 (void) printf(gettext("all children offline"));
2565 break;
2567 case VDEV_AUX_BAD_LABEL:
2568 (void) printf(gettext("invalid label"));
2569 break;
2571 default:
2572 (void) printf(gettext("corrupted data"));
2573 break;
2576 (void) printf("\n");
2578 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2579 &child, &children) != 0)
2580 return;
2582 for (c = 0; c < children; c++) {
2583 uint64_t is_log = B_FALSE;
2585 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2586 &is_log);
2587 if (is_log)
2588 continue;
2589 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2590 continue;
2592 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2593 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2594 print_import_config(cb, vname, child[c], depth + 2);
2595 free(vname);
2598 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2599 &child, &children) == 0) {
2600 (void) printf(gettext("\tcache\n"));
2601 for (c = 0; c < children; c++) {
2602 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2603 cb->cb_name_flags);
2604 (void) printf("\t %s\n", vname);
2605 free(vname);
2609 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2610 &child, &children) == 0) {
2611 (void) printf(gettext("\tspares\n"));
2612 for (c = 0; c < children; c++) {
2613 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2614 cb->cb_name_flags);
2615 (void) printf("\t %s\n", vname);
2616 free(vname);
2622 * Print specialized class vdevs.
2624 * These are recorded as top level vdevs in the main pool child array
2625 * but with "is_log" set to 1 or an "alloc_bias" string. We use either
2626 * print_status_config() or print_import_config() to print the top level
2627 * class vdevs then any of their children (eg mirrored slogs) are printed
2628 * recursively - which works because only the top level vdev is marked.
2630 static void
2631 print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
2632 const char *class)
2634 uint_t c, children;
2635 nvlist_t **child;
2636 boolean_t printed = B_FALSE;
2638 assert(zhp != NULL || !cb->cb_verbose);
2640 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
2641 &children) != 0)
2642 return;
2644 for (c = 0; c < children; c++) {
2645 uint64_t is_log = B_FALSE;
2646 char *bias = NULL;
2647 char *type = NULL;
2649 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2650 &is_log);
2652 if (is_log) {
2653 bias = VDEV_ALLOC_CLASS_LOGS;
2654 } else {
2655 (void) nvlist_lookup_string(child[c],
2656 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
2657 (void) nvlist_lookup_string(child[c],
2658 ZPOOL_CONFIG_TYPE, &type);
2661 if (bias == NULL || strcmp(bias, class) != 0)
2662 continue;
2663 if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
2664 continue;
2666 if (!printed) {
2667 (void) printf("\t%s\t\n", gettext(class));
2668 printed = B_TRUE;
2671 char *name = zpool_vdev_name(g_zfs, zhp, child[c],
2672 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2673 if (cb->cb_print_status)
2674 print_status_config(zhp, cb, name, child[c], 2,
2675 B_FALSE, NULL);
2676 else
2677 print_import_config(cb, name, child[c], 2);
2678 free(name);
2683 * Display the status for the given pool.
2685 static int
2686 show_import(nvlist_t *config, boolean_t report_error)
2688 uint64_t pool_state;
2689 vdev_stat_t *vs;
2690 char *name;
2691 uint64_t guid;
2692 uint64_t hostid = 0;
2693 char *msgid;
2694 char *hostname = "unknown";
2695 nvlist_t *nvroot, *nvinfo;
2696 zpool_status_t reason;
2697 zpool_errata_t errata;
2698 const char *health;
2699 uint_t vsc;
2700 char *comment;
2701 status_cbdata_t cb = { 0 };
2703 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2704 &name) == 0);
2705 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2706 &guid) == 0);
2707 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2708 &pool_state) == 0);
2709 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2710 &nvroot) == 0);
2712 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
2713 (uint64_t **)&vs, &vsc) == 0);
2714 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2716 reason = zpool_import_status(config, &msgid, &errata);
2719 * If we're importing using a cachefile, then we won't report any
2720 * errors unless we are in the scan phase of the import.
2722 if (reason != ZPOOL_STATUS_OK && !report_error)
2723 return (reason);
2725 (void) printf(gettext(" pool: %s\n"), name);
2726 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
2727 (void) printf(gettext(" state: %s"), health);
2728 if (pool_state == POOL_STATE_DESTROYED)
2729 (void) printf(gettext(" (DESTROYED)"));
2730 (void) printf("\n");
2732 switch (reason) {
2733 case ZPOOL_STATUS_MISSING_DEV_R:
2734 case ZPOOL_STATUS_MISSING_DEV_NR:
2735 case ZPOOL_STATUS_BAD_GUID_SUM:
2736 printf_color(ANSI_BOLD, gettext("status: "));
2737 printf_color(ANSI_YELLOW, gettext("One or more devices are "
2738 "missing from the system.\n"));
2739 break;
2741 case ZPOOL_STATUS_CORRUPT_LABEL_R:
2742 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2743 printf_color(ANSI_BOLD, gettext("status: "));
2744 printf_color(ANSI_YELLOW, gettext("One or more devices contains"
2745 " corrupted data.\n"));
2746 break;
2748 case ZPOOL_STATUS_CORRUPT_DATA:
2749 (void) printf(
2750 gettext(" status: The pool data is corrupted.\n"));
2751 break;
2753 case ZPOOL_STATUS_OFFLINE_DEV:
2754 printf_color(ANSI_BOLD, gettext("status: "));
2755 printf_color(ANSI_YELLOW, gettext("One or more devices "
2756 "are offlined.\n"));
2757 break;
2759 case ZPOOL_STATUS_CORRUPT_POOL:
2760 printf_color(ANSI_BOLD, gettext("status: "));
2761 printf_color(ANSI_YELLOW, gettext("The pool metadata is "
2762 "corrupted.\n"));
2763 break;
2765 case ZPOOL_STATUS_VERSION_OLDER:
2766 printf_color(ANSI_BOLD, gettext("status: "));
2767 printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
2768 "a legacy on-disk version.\n"));
2769 break;
2771 case ZPOOL_STATUS_VERSION_NEWER:
2772 printf_color(ANSI_BOLD, gettext("status: "));
2773 printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
2774 "an incompatible version.\n"));
2775 break;
2777 case ZPOOL_STATUS_FEAT_DISABLED:
2778 printf_color(ANSI_BOLD, gettext("status: "));
2779 printf_color(ANSI_YELLOW, gettext("Some supported "
2780 "features are not enabled on the pool.\n\t"
2781 "(Note that they may be intentionally disabled "
2782 "if the\n\t'compatibility' property is set.)\n"));
2783 break;
2785 case ZPOOL_STATUS_COMPATIBILITY_ERR:
2786 printf_color(ANSI_BOLD, gettext("status: "));
2787 printf_color(ANSI_YELLOW, gettext("Error reading or parsing "
2788 "the file(s) indicated by the 'compatibility'\n"
2789 "property.\n"));
2790 break;
2792 case ZPOOL_STATUS_INCOMPATIBLE_FEAT:
2793 printf_color(ANSI_BOLD, gettext("status: "));
2794 printf_color(ANSI_YELLOW, gettext("One or more features "
2795 "are enabled on the pool despite not being\n"
2796 "requested by the 'compatibility' property.\n"));
2797 break;
2799 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2800 printf_color(ANSI_BOLD, gettext("status: "));
2801 printf_color(ANSI_YELLOW, gettext("The pool uses the following "
2802 "feature(s) not supported on this system:\n"));
2803 color_start(ANSI_YELLOW);
2804 zpool_print_unsup_feat(config);
2805 color_end();
2806 break;
2808 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2809 printf_color(ANSI_BOLD, gettext("status: "));
2810 printf_color(ANSI_YELLOW, gettext("The pool can only be "
2811 "accessed in read-only mode on this system. It\n\tcannot be"
2812 " accessed in read-write mode because it uses the "
2813 "following\n\tfeature(s) not supported on this system:\n"));
2814 color_start(ANSI_YELLOW);
2815 zpool_print_unsup_feat(config);
2816 color_end();
2817 break;
2819 case ZPOOL_STATUS_HOSTID_ACTIVE:
2820 printf_color(ANSI_BOLD, gettext("status: "));
2821 printf_color(ANSI_YELLOW, gettext("The pool is currently "
2822 "imported by another system.\n"));
2823 break;
2825 case ZPOOL_STATUS_HOSTID_REQUIRED:
2826 printf_color(ANSI_BOLD, gettext("status: "));
2827 printf_color(ANSI_YELLOW, gettext("The pool has the "
2828 "multihost property on. It cannot\n\tbe safely imported "
2829 "when the system hostid is not set.\n"));
2830 break;
2832 case ZPOOL_STATUS_HOSTID_MISMATCH:
2833 printf_color(ANSI_BOLD, gettext("status: "));
2834 printf_color(ANSI_YELLOW, gettext("The pool was last accessed "
2835 "by another system.\n"));
2836 break;
2838 case ZPOOL_STATUS_FAULTED_DEV_R:
2839 case ZPOOL_STATUS_FAULTED_DEV_NR:
2840 printf_color(ANSI_BOLD, gettext("status: "));
2841 printf_color(ANSI_YELLOW, gettext("One or more devices are "
2842 "faulted.\n"));
2843 break;
2845 case ZPOOL_STATUS_BAD_LOG:
2846 printf_color(ANSI_BOLD, gettext("status: "));
2847 printf_color(ANSI_YELLOW, gettext("An intent log record cannot "
2848 "be read.\n"));
2849 break;
2851 case ZPOOL_STATUS_RESILVERING:
2852 case ZPOOL_STATUS_REBUILDING:
2853 printf_color(ANSI_BOLD, gettext("status: "));
2854 printf_color(ANSI_YELLOW, gettext("One or more devices were "
2855 "being resilvered.\n"));
2856 break;
2858 case ZPOOL_STATUS_ERRATA:
2859 printf_color(ANSI_BOLD, gettext("status: "));
2860 printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
2861 errata);
2862 break;
2864 case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
2865 printf_color(ANSI_BOLD, gettext("status: "));
2866 printf_color(ANSI_YELLOW, gettext("One or more devices are "
2867 "configured to use a non-native block size.\n"
2868 "\tExpect reduced performance.\n"));
2869 break;
2871 default:
2873 * No other status can be seen when importing pools.
2875 assert(reason == ZPOOL_STATUS_OK);
2879 * Print out an action according to the overall state of the pool.
2881 if (vs->vs_state == VDEV_STATE_HEALTHY) {
2882 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2883 reason == ZPOOL_STATUS_FEAT_DISABLED) {
2884 (void) printf(gettext(" action: The pool can be "
2885 "imported using its name or numeric identifier, "
2886 "though\n\tsome features will not be available "
2887 "without an explicit 'zpool upgrade'.\n"));
2888 } else if (reason == ZPOOL_STATUS_COMPATIBILITY_ERR) {
2889 (void) printf(gettext(" action: The pool can be "
2890 "imported using its name or numeric\n\tidentifier, "
2891 "though the file(s) indicated by its "
2892 "'compatibility'\n\tproperty cannot be parsed at "
2893 "this time.\n"));
2894 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
2895 (void) printf(gettext(" action: The pool can be "
2896 "imported using its name or numeric "
2897 "identifier and\n\tthe '-f' flag.\n"));
2898 } else if (reason == ZPOOL_STATUS_ERRATA) {
2899 switch (errata) {
2900 case ZPOOL_ERRATA_NONE:
2901 break;
2903 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
2904 (void) printf(gettext(" action: The pool can "
2905 "be imported using its name or numeric "
2906 "identifier,\n\thowever there is a compat"
2907 "ibility issue which should be corrected"
2908 "\n\tby running 'zpool scrub'\n"));
2909 break;
2911 case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
2912 (void) printf(gettext(" action: The pool can"
2913 "not be imported with this version of ZFS "
2914 "due to\n\tan active asynchronous destroy. "
2915 "Revert to an earlier version\n\tand "
2916 "allow the destroy to complete before "
2917 "updating.\n"));
2918 break;
2920 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
2921 (void) printf(gettext(" action: Existing "
2922 "encrypted datasets contain an on-disk "
2923 "incompatibility, which\n\tneeds to be "
2924 "corrected. Backup these datasets to new "
2925 "encrypted datasets\n\tand destroy the "
2926 "old ones.\n"));
2927 break;
2929 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
2930 (void) printf(gettext(" action: Existing "
2931 "encrypted snapshots and bookmarks contain "
2932 "an on-disk\n\tincompatibility. This may "
2933 "cause on-disk corruption if they are used"
2934 "\n\twith 'zfs recv'. To correct the "
2935 "issue, enable the bookmark_v2 feature.\n\t"
2936 "No additional action is needed if there "
2937 "are no encrypted snapshots or\n\t"
2938 "bookmarks. If preserving the encrypted "
2939 "snapshots and bookmarks is\n\trequired, "
2940 "use a non-raw send to backup and restore "
2941 "them. Alternately,\n\tthey may be removed"
2942 " to resolve the incompatibility.\n"));
2943 break;
2944 default:
2946 * All errata must contain an action message.
2948 assert(0);
2950 } else {
2951 (void) printf(gettext(" action: The pool can be "
2952 "imported using its name or numeric "
2953 "identifier.\n"));
2955 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2956 (void) printf(gettext(" action: The pool can be imported "
2957 "despite missing or damaged devices. The\n\tfault "
2958 "tolerance of the pool may be compromised if imported.\n"));
2959 } else {
2960 switch (reason) {
2961 case ZPOOL_STATUS_VERSION_NEWER:
2962 (void) printf(gettext(" action: The pool cannot be "
2963 "imported. Access the pool on a system running "
2964 "newer\n\tsoftware, or recreate the pool from "
2965 "backup.\n"));
2966 break;
2967 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2968 printf_color(ANSI_BOLD, gettext("action: "));
2969 printf_color(ANSI_YELLOW, gettext("The pool cannot be "
2970 "imported. Access the pool on a system that "
2971 "supports\n\tthe required feature(s), or recreate "
2972 "the pool from backup.\n"));
2973 break;
2974 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2975 printf_color(ANSI_BOLD, gettext("action: "));
2976 printf_color(ANSI_YELLOW, gettext("The pool cannot be "
2977 "imported in read-write mode. Import the pool "
2978 "with\n"
2979 "\t\"-o readonly=on\", access the pool on a system "
2980 "that supports the\n\trequired feature(s), or "
2981 "recreate the pool from backup.\n"));
2982 break;
2983 case ZPOOL_STATUS_MISSING_DEV_R:
2984 case ZPOOL_STATUS_MISSING_DEV_NR:
2985 case ZPOOL_STATUS_BAD_GUID_SUM:
2986 (void) printf(gettext(" action: The pool cannot be "
2987 "imported. Attach the missing\n\tdevices and try "
2988 "again.\n"));
2989 break;
2990 case ZPOOL_STATUS_HOSTID_ACTIVE:
2991 VERIFY0(nvlist_lookup_nvlist(config,
2992 ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
2994 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2995 hostname = fnvlist_lookup_string(nvinfo,
2996 ZPOOL_CONFIG_MMP_HOSTNAME);
2998 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2999 hostid = fnvlist_lookup_uint64(nvinfo,
3000 ZPOOL_CONFIG_MMP_HOSTID);
3002 (void) printf(gettext(" action: The pool must be "
3003 "exported from %s (hostid=%lx)\n\tbefore it "
3004 "can be safely imported.\n"), hostname,
3005 (unsigned long) hostid);
3006 break;
3007 case ZPOOL_STATUS_HOSTID_REQUIRED:
3008 (void) printf(gettext(" action: Set a unique system "
3009 "hostid with the zgenhostid(8) command.\n"));
3010 break;
3011 default:
3012 (void) printf(gettext(" action: The pool cannot be "
3013 "imported due to damaged devices or data.\n"));
3017 /* Print the comment attached to the pool. */
3018 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
3019 (void) printf(gettext("comment: %s\n"), comment);
3022 * If the state is "closed" or "can't open", and the aux state
3023 * is "corrupt data":
3025 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
3026 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
3027 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
3028 if (pool_state == POOL_STATE_DESTROYED)
3029 (void) printf(gettext("\tThe pool was destroyed, "
3030 "but can be imported using the '-Df' flags.\n"));
3031 else if (pool_state != POOL_STATE_EXPORTED)
3032 (void) printf(gettext("\tThe pool may be active on "
3033 "another system, but can be imported using\n\t"
3034 "the '-f' flag.\n"));
3037 if (msgid != NULL) {
3038 (void) printf(gettext(
3039 " see: https://openzfs.github.io/openzfs-docs/msg/%s\n"),
3040 msgid);
3043 (void) printf(gettext(" config:\n\n"));
3045 cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
3046 VDEV_NAME_TYPE_ID);
3047 if (cb.cb_namewidth < 10)
3048 cb.cb_namewidth = 10;
3050 print_import_config(&cb, name, nvroot, 0);
3052 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
3053 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
3054 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
3056 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
3057 (void) printf(gettext("\n\tAdditional devices are known to "
3058 "be part of this pool, though their\n\texact "
3059 "configuration cannot be determined.\n"));
3061 return (0);
3064 static boolean_t
3065 zfs_force_import_required(nvlist_t *config)
3067 uint64_t state;
3068 uint64_t hostid = 0;
3069 nvlist_t *nvinfo;
3071 state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
3072 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
3074 if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
3075 return (B_TRUE);
3077 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
3078 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
3079 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
3080 ZPOOL_CONFIG_MMP_STATE);
3082 if (mmp_state != MMP_STATE_INACTIVE)
3083 return (B_TRUE);
3086 return (B_FALSE);
3090 * Perform the import for the given configuration. This passes the heavy
3091 * lifting off to zpool_import_props(), and then mounts the datasets contained
3092 * within the pool.
3094 static int
3095 do_import(nvlist_t *config, const char *newname, const char *mntopts,
3096 nvlist_t *props, int flags)
3098 int ret = 0;
3099 zpool_handle_t *zhp;
3100 char *name;
3101 uint64_t version;
3103 name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
3104 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
3106 if (!SPA_VERSION_IS_SUPPORTED(version)) {
3107 (void) fprintf(stderr, gettext("cannot import '%s': pool "
3108 "is formatted using an unsupported ZFS version\n"), name);
3109 return (1);
3110 } else if (zfs_force_import_required(config) &&
3111 !(flags & ZFS_IMPORT_ANY_HOST)) {
3112 mmp_state_t mmp_state = MMP_STATE_INACTIVE;
3113 nvlist_t *nvinfo;
3115 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
3116 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
3117 mmp_state = fnvlist_lookup_uint64(nvinfo,
3118 ZPOOL_CONFIG_MMP_STATE);
3120 if (mmp_state == MMP_STATE_ACTIVE) {
3121 char *hostname = "<unknown>";
3122 uint64_t hostid = 0;
3124 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
3125 hostname = fnvlist_lookup_string(nvinfo,
3126 ZPOOL_CONFIG_MMP_HOSTNAME);
3128 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
3129 hostid = fnvlist_lookup_uint64(nvinfo,
3130 ZPOOL_CONFIG_MMP_HOSTID);
3132 (void) fprintf(stderr, gettext("cannot import '%s': "
3133 "pool is imported on %s (hostid: "
3134 "0x%lx)\nExport the pool on the other system, "
3135 "then run 'zpool import'.\n"),
3136 name, hostname, (unsigned long) hostid);
3137 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
3138 (void) fprintf(stderr, gettext("Cannot import '%s': "
3139 "pool has the multihost property on and the\n"
3140 "system's hostid is not set. Set a unique hostid "
3141 "with the zgenhostid(8) command.\n"), name);
3142 } else {
3143 char *hostname = "<unknown>";
3144 uint64_t timestamp = 0;
3145 uint64_t hostid = 0;
3147 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
3148 hostname = fnvlist_lookup_string(config,
3149 ZPOOL_CONFIG_HOSTNAME);
3151 if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
3152 timestamp = fnvlist_lookup_uint64(config,
3153 ZPOOL_CONFIG_TIMESTAMP);
3155 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
3156 hostid = fnvlist_lookup_uint64(config,
3157 ZPOOL_CONFIG_HOSTID);
3159 (void) fprintf(stderr, gettext("cannot import '%s': "
3160 "pool was previously in use from another system.\n"
3161 "Last accessed by %s (hostid=%lx) at %s"
3162 "The pool can be imported, use 'zpool import -f' "
3163 "to import the pool.\n"), name, hostname,
3164 (unsigned long)hostid, ctime((time_t *)&timestamp));
3167 return (1);
3170 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
3171 return (1);
3173 if (newname != NULL)
3174 name = (char *)newname;
3176 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
3177 return (1);
3180 * Loading keys is best effort. We don't want to return immediately
3181 * if it fails but we do want to give the error to the caller.
3183 if (flags & ZFS_IMPORT_LOAD_KEYS) {
3184 ret = zfs_crypto_attempt_load_keys(g_zfs, name);
3185 if (ret != 0)
3186 ret = 1;
3189 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3190 !(flags & ZFS_IMPORT_ONLY) &&
3191 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3192 zpool_close(zhp);
3193 return (1);
3196 zpool_close(zhp);
3197 return (ret);
3200 static int
3201 import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
3202 char *orig_name, char *new_name,
3203 boolean_t do_destroyed, boolean_t pool_specified, boolean_t do_all,
3204 importargs_t *import)
3206 nvlist_t *config = NULL;
3207 nvlist_t *found_config = NULL;
3208 uint64_t pool_state;
3211 * At this point we have a list of import candidate configs. Even if
3212 * we were searching by pool name or guid, we still need to
3213 * post-process the list to deal with pool state and possible
3214 * duplicate names.
3216 int err = 0;
3217 nvpair_t *elem = NULL;
3218 boolean_t first = B_TRUE;
3219 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
3221 verify(nvpair_value_nvlist(elem, &config) == 0);
3223 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
3224 &pool_state) == 0);
3225 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
3226 continue;
3227 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
3228 continue;
3230 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
3231 import->policy) == 0);
3233 if (!pool_specified) {
3234 if (first)
3235 first = B_FALSE;
3236 else if (!do_all)
3237 (void) printf("\n");
3239 if (do_all) {
3240 err |= do_import(config, NULL, mntopts,
3241 props, flags);
3242 } else {
3244 * If we're importing from cachefile, then
3245 * we don't want to report errors until we
3246 * are in the scan phase of the import. If
3247 * we get an error, then we return that error
3248 * to invoke the scan phase.
3250 if (import->cachefile && !import->scan)
3251 err = show_import(config, B_FALSE);
3252 else
3253 (void) show_import(config, B_TRUE);
3255 } else if (import->poolname != NULL) {
3256 char *name;
3259 * We are searching for a pool based on name.
3261 verify(nvlist_lookup_string(config,
3262 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
3264 if (strcmp(name, import->poolname) == 0) {
3265 if (found_config != NULL) {
3266 (void) fprintf(stderr, gettext(
3267 "cannot import '%s': more than "
3268 "one matching pool\n"),
3269 import->poolname);
3270 (void) fprintf(stderr, gettext(
3271 "import by numeric ID instead\n"));
3272 err = B_TRUE;
3274 found_config = config;
3276 } else {
3277 uint64_t guid;
3280 * Search for a pool by guid.
3282 verify(nvlist_lookup_uint64(config,
3283 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
3285 if (guid == import->guid)
3286 found_config = config;
3291 * If we were searching for a specific pool, verify that we found a
3292 * pool, and then do the import.
3294 if (pool_specified && err == 0) {
3295 if (found_config == NULL) {
3296 (void) fprintf(stderr, gettext("cannot import '%s': "
3297 "no such pool available\n"), orig_name);
3298 err = B_TRUE;
3299 } else {
3300 err |= do_import(found_config, new_name,
3301 mntopts, props, flags);
3306 * If we were just looking for pools, report an error if none were
3307 * found.
3309 if (!pool_specified && first)
3310 (void) fprintf(stderr,
3311 gettext("no pools available to import\n"));
3312 return (err);
3315 typedef struct target_exists_args {
3316 const char *poolname;
3317 uint64_t poolguid;
3318 } target_exists_args_t;
3320 static int
3321 name_or_guid_exists(zpool_handle_t *zhp, void *data)
3323 target_exists_args_t *args = data;
3324 nvlist_t *config = zpool_get_config(zhp, NULL);
3325 int found = 0;
3327 if (config == NULL)
3328 return (0);
3330 if (args->poolname != NULL) {
3331 char *pool_name;
3333 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
3334 &pool_name) == 0);
3335 if (strcmp(pool_name, args->poolname) == 0)
3336 found = 1;
3337 } else {
3338 uint64_t pool_guid;
3340 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
3341 &pool_guid) == 0);
3342 if (pool_guid == args->poolguid)
3343 found = 1;
3345 zpool_close(zhp);
3347 return (found);
3350 * zpool checkpoint <pool>
3351 * checkpoint --discard <pool>
3353 * -d Discard the checkpoint from a checkpointed
3354 * --discard pool.
3356 * -w Wait for discarding a checkpoint to complete.
3357 * --wait
3359 * Checkpoints the specified pool, by taking a "snapshot" of its
3360 * current state. A pool can only have one checkpoint at a time.
3363 zpool_do_checkpoint(int argc, char **argv)
3365 boolean_t discard, wait;
3366 char *pool;
3367 zpool_handle_t *zhp;
3368 int c, err;
3370 struct option long_options[] = {
3371 {"discard", no_argument, NULL, 'd'},
3372 {"wait", no_argument, NULL, 'w'},
3373 {0, 0, 0, 0}
3376 discard = B_FALSE;
3377 wait = B_FALSE;
3378 while ((c = getopt_long(argc, argv, ":dw", long_options, NULL)) != -1) {
3379 switch (c) {
3380 case 'd':
3381 discard = B_TRUE;
3382 break;
3383 case 'w':
3384 wait = B_TRUE;
3385 break;
3386 case '?':
3387 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3388 optopt);
3389 usage(B_FALSE);
3393 if (wait && !discard) {
3394 (void) fprintf(stderr, gettext("--wait only valid when "
3395 "--discard also specified\n"));
3396 usage(B_FALSE);
3399 argc -= optind;
3400 argv += optind;
3402 if (argc < 1) {
3403 (void) fprintf(stderr, gettext("missing pool argument\n"));
3404 usage(B_FALSE);
3407 if (argc > 1) {
3408 (void) fprintf(stderr, gettext("too many arguments\n"));
3409 usage(B_FALSE);
3412 pool = argv[0];
3414 if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
3415 /* As a special case, check for use of '/' in the name */
3416 if (strchr(pool, '/') != NULL)
3417 (void) fprintf(stderr, gettext("'zpool checkpoint' "
3418 "doesn't work on datasets. To save the state "
3419 "of a dataset from a specific point in time "
3420 "please use 'zfs snapshot'\n"));
3421 return (1);
3424 if (discard) {
3425 err = (zpool_discard_checkpoint(zhp) != 0);
3426 if (err == 0 && wait)
3427 err = zpool_wait(zhp, ZPOOL_WAIT_CKPT_DISCARD);
3428 } else {
3429 err = (zpool_checkpoint(zhp) != 0);
3432 zpool_close(zhp);
3434 return (err);
3437 #define CHECKPOINT_OPT 1024
3440 * zpool import [-d dir] [-D]
3441 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
3442 * [-d dir | -c cachefile | -s] [-f] -a
3443 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
3444 * [-d dir | -c cachefile | -s] [-f] [-n] [-F] <pool | id>
3445 * [newpool]
3447 * -c Read pool information from a cachefile instead of searching
3448 * devices. If importing from a cachefile config fails, then
3449 * fallback to searching for devices only in the directories that
3450 * exist in the cachefile.
3452 * -d Scan in a specific directory, other than /dev/. More than
3453 * one directory can be specified using multiple '-d' options.
3455 * -D Scan for previously destroyed pools or import all or only
3456 * specified destroyed pools.
3458 * -R Temporarily import the pool, with all mountpoints relative to
3459 * the given root. The pool will remain exported when the machine
3460 * is rebooted.
3462 * -V Import even in the presence of faulted vdevs. This is an
3463 * intentionally undocumented option for testing purposes, and
3464 * treats the pool configuration as complete, leaving any bad
3465 * vdevs in the FAULTED state. In other words, it does verbatim
3466 * import.
3468 * -f Force import, even if it appears that the pool is active.
3470 * -F Attempt rewind if necessary.
3472 * -n See if rewind would work, but don't actually rewind.
3474 * -N Import the pool but don't mount datasets.
3476 * -T Specify a starting txg to use for import. This option is
3477 * intentionally undocumented option for testing purposes.
3479 * -a Import all pools found.
3481 * -l Load encryption keys while importing.
3483 * -o Set property=value and/or temporary mount options (without '=').
3485 * -s Scan using the default search path, the libblkid cache will
3486 * not be consulted.
3488 * --rewind-to-checkpoint
3489 * Import the pool and revert back to the checkpoint.
3491 * The import command scans for pools to import, and import pools based on pool
3492 * name and GUID. The pool can also be renamed as part of the import process.
3495 zpool_do_import(int argc, char **argv)
3497 char **searchdirs = NULL;
3498 char *env, *envdup = NULL;
3499 int nsearch = 0;
3500 int c;
3501 int err = 0;
3502 nvlist_t *pools = NULL;
3503 boolean_t do_all = B_FALSE;
3504 boolean_t do_destroyed = B_FALSE;
3505 char *mntopts = NULL;
3506 uint64_t searchguid = 0;
3507 char *searchname = NULL;
3508 char *propval;
3509 nvlist_t *policy = NULL;
3510 nvlist_t *props = NULL;
3511 int flags = ZFS_IMPORT_NORMAL;
3512 uint32_t rewind_policy = ZPOOL_NO_REWIND;
3513 boolean_t dryrun = B_FALSE;
3514 boolean_t do_rewind = B_FALSE;
3515 boolean_t xtreme_rewind = B_FALSE;
3516 boolean_t do_scan = B_FALSE;
3517 boolean_t pool_exists = B_FALSE;
3518 boolean_t pool_specified = B_FALSE;
3519 uint64_t txg = -1ULL;
3520 char *cachefile = NULL;
3521 importargs_t idata = { 0 };
3522 char *endptr;
3524 struct option long_options[] = {
3525 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
3526 {0, 0, 0, 0}
3529 /* check options */
3530 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:R:stT:VX",
3531 long_options, NULL)) != -1) {
3532 switch (c) {
3533 case 'a':
3534 do_all = B_TRUE;
3535 break;
3536 case 'c':
3537 cachefile = optarg;
3538 break;
3539 case 'd':
3540 searchdirs = safe_realloc(searchdirs,
3541 (nsearch + 1) * sizeof (char *));
3542 searchdirs[nsearch++] = optarg;
3543 break;
3544 case 'D':
3545 do_destroyed = B_TRUE;
3546 break;
3547 case 'f':
3548 flags |= ZFS_IMPORT_ANY_HOST;
3549 break;
3550 case 'F':
3551 do_rewind = B_TRUE;
3552 break;
3553 case 'l':
3554 flags |= ZFS_IMPORT_LOAD_KEYS;
3555 break;
3556 case 'm':
3557 flags |= ZFS_IMPORT_MISSING_LOG;
3558 break;
3559 case 'n':
3560 dryrun = B_TRUE;
3561 break;
3562 case 'N':
3563 flags |= ZFS_IMPORT_ONLY;
3564 break;
3565 case 'o':
3566 if ((propval = strchr(optarg, '=')) != NULL) {
3567 *propval = '\0';
3568 propval++;
3569 if (add_prop_list(optarg, propval,
3570 &props, B_TRUE))
3571 goto error;
3572 } else {
3573 mntopts = optarg;
3575 break;
3576 case 'R':
3577 if (add_prop_list(zpool_prop_to_name(
3578 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
3579 goto error;
3580 if (add_prop_list_default(zpool_prop_to_name(
3581 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
3582 goto error;
3583 break;
3584 case 's':
3585 do_scan = B_TRUE;
3586 break;
3587 case 't':
3588 flags |= ZFS_IMPORT_TEMP_NAME;
3589 if (add_prop_list_default(zpool_prop_to_name(
3590 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
3591 goto error;
3592 break;
3594 case 'T':
3595 errno = 0;
3596 txg = strtoull(optarg, &endptr, 0);
3597 if (errno != 0 || *endptr != '\0') {
3598 (void) fprintf(stderr,
3599 gettext("invalid txg value\n"));
3600 usage(B_FALSE);
3602 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
3603 break;
3604 case 'V':
3605 flags |= ZFS_IMPORT_VERBATIM;
3606 break;
3607 case 'X':
3608 xtreme_rewind = B_TRUE;
3609 break;
3610 case CHECKPOINT_OPT:
3611 flags |= ZFS_IMPORT_CHECKPOINT;
3612 break;
3613 case ':':
3614 (void) fprintf(stderr, gettext("missing argument for "
3615 "'%c' option\n"), optopt);
3616 usage(B_FALSE);
3617 break;
3618 case '?':
3619 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3620 optopt);
3621 usage(B_FALSE);
3625 argc -= optind;
3626 argv += optind;
3628 if (cachefile && nsearch != 0) {
3629 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
3630 usage(B_FALSE);
3633 if (cachefile && do_scan) {
3634 (void) fprintf(stderr, gettext("-c is incompatible with -s\n"));
3635 usage(B_FALSE);
3638 if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
3639 (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
3640 usage(B_FALSE);
3643 if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
3644 (void) fprintf(stderr, gettext("-l is only meaningful during "
3645 "an import\n"));
3646 usage(B_FALSE);
3649 if ((dryrun || xtreme_rewind) && !do_rewind) {
3650 (void) fprintf(stderr,
3651 gettext("-n or -X only meaningful with -F\n"));
3652 usage(B_FALSE);
3654 if (dryrun)
3655 rewind_policy = ZPOOL_TRY_REWIND;
3656 else if (do_rewind)
3657 rewind_policy = ZPOOL_DO_REWIND;
3658 if (xtreme_rewind)
3659 rewind_policy |= ZPOOL_EXTREME_REWIND;
3661 /* In the future, we can capture further policy and include it here */
3662 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3663 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
3664 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
3665 rewind_policy) != 0)
3666 goto error;
3668 /* check argument count */
3669 if (do_all) {
3670 if (argc != 0) {
3671 (void) fprintf(stderr, gettext("too many arguments\n"));
3672 usage(B_FALSE);
3674 } else {
3675 if (argc > 2) {
3676 (void) fprintf(stderr, gettext("too many arguments\n"));
3677 usage(B_FALSE);
3682 * Check for the effective uid. We do this explicitly here because
3683 * otherwise any attempt to discover pools will silently fail.
3685 if (argc == 0 && geteuid() != 0) {
3686 (void) fprintf(stderr, gettext("cannot "
3687 "discover pools: permission denied\n"));
3688 if (searchdirs != NULL)
3689 free(searchdirs);
3691 nvlist_free(props);
3692 nvlist_free(policy);
3693 return (1);
3697 * Depending on the arguments given, we do one of the following:
3699 * <none> Iterate through all pools and display information about
3700 * each one.
3702 * -a Iterate through all pools and try to import each one.
3704 * <id> Find the pool that corresponds to the given GUID/pool
3705 * name and import that one.
3707 * -D Above options applies only to destroyed pools.
3709 if (argc != 0) {
3710 char *endptr;
3712 errno = 0;
3713 searchguid = strtoull(argv[0], &endptr, 10);
3714 if (errno != 0 || *endptr != '\0') {
3715 searchname = argv[0];
3716 searchguid = 0;
3718 pool_specified = B_TRUE;
3721 * User specified a name or guid. Ensure it's unique.
3723 target_exists_args_t search = {searchname, searchguid};
3724 pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search);
3728 * Check the environment for the preferred search path.
3730 if ((searchdirs == NULL) && (env = getenv("ZPOOL_IMPORT_PATH"))) {
3731 char *dir, *tmp = NULL;
3733 envdup = strdup(env);
3735 for (dir = strtok_r(envdup, ":", &tmp);
3736 dir != NULL;
3737 dir = strtok_r(NULL, ":", &tmp)) {
3738 searchdirs = safe_realloc(searchdirs,
3739 (nsearch + 1) * sizeof (char *));
3740 searchdirs[nsearch++] = dir;
3744 idata.path = searchdirs;
3745 idata.paths = nsearch;
3746 idata.poolname = searchname;
3747 idata.guid = searchguid;
3748 idata.cachefile = cachefile;
3749 idata.scan = do_scan;
3750 idata.policy = policy;
3752 pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
3754 if (pools != NULL && pool_exists &&
3755 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
3756 (void) fprintf(stderr, gettext("cannot import '%s': "
3757 "a pool with that name already exists\n"),
3758 argv[0]);
3759 (void) fprintf(stderr, gettext("use the form '%s "
3760 "<pool | id> <newpool>' to give it a new name\n"),
3761 "zpool import");
3762 err = 1;
3763 } else if (pools == NULL && pool_exists) {
3764 (void) fprintf(stderr, gettext("cannot import '%s': "
3765 "a pool with that name is already created/imported,\n"),
3766 argv[0]);
3767 (void) fprintf(stderr, gettext("and no additional pools "
3768 "with that name were found\n"));
3769 err = 1;
3770 } else if (pools == NULL) {
3771 if (argc != 0) {
3772 (void) fprintf(stderr, gettext("cannot import '%s': "
3773 "no such pool available\n"), argv[0]);
3775 err = 1;
3778 if (err == 1) {
3779 free(searchdirs);
3780 free(envdup);
3781 nvlist_free(policy);
3782 nvlist_free(pools);
3783 nvlist_free(props);
3784 return (1);
3787 err = import_pools(pools, props, mntopts, flags,
3788 argc >= 1 ? argv[0] : NULL,
3789 argc >= 2 ? argv[1] : NULL,
3790 do_destroyed, pool_specified, do_all, &idata);
3793 * If we're using the cachefile and we failed to import, then
3794 * fallback to scanning the directory for pools that match
3795 * those in the cachefile.
3797 if (err != 0 && cachefile != NULL) {
3798 (void) printf(gettext("cachefile import failed, retrying\n"));
3801 * We use the scan flag to gather the directories that exist
3802 * in the cachefile. If we need to fallback to searching for
3803 * the pool config, we will only search devices in these
3804 * directories.
3806 idata.scan = B_TRUE;
3807 nvlist_free(pools);
3808 pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
3810 err = import_pools(pools, props, mntopts, flags,
3811 argc >= 1 ? argv[0] : NULL,
3812 argc >= 2 ? argv[1] : NULL,
3813 do_destroyed, pool_specified, do_all, &idata);
3816 error:
3817 nvlist_free(props);
3818 nvlist_free(pools);
3819 nvlist_free(policy);
3820 free(searchdirs);
3821 free(envdup);
3823 return (err ? 1 : 0);
3827 * zpool sync [-f] [pool] ...
3829 * -f (undocumented) force uberblock (and config including zpool cache file)
3830 * update.
3832 * Sync the specified pool(s).
3833 * Without arguments "zpool sync" will sync all pools.
3834 * This command initiates TXG sync(s) and will return after the TXG(s) commit.
3837 static int
3838 zpool_do_sync(int argc, char **argv)
3840 int ret;
3841 boolean_t force = B_FALSE;
3843 /* check options */
3844 while ((ret = getopt(argc, argv, "f")) != -1) {
3845 switch (ret) {
3846 case 'f':
3847 force = B_TRUE;
3848 break;
3849 case '?':
3850 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3851 optopt);
3852 usage(B_FALSE);
3856 argc -= optind;
3857 argv += optind;
3859 /* if argc == 0 we will execute zpool_sync_one on all pools */
3860 ret = for_each_pool(argc, argv, B_FALSE, NULL, B_FALSE, zpool_sync_one,
3861 &force);
3863 return (ret);
3866 typedef struct iostat_cbdata {
3867 uint64_t cb_flags;
3868 int cb_name_flags;
3869 int cb_namewidth;
3870 int cb_iteration;
3871 char **cb_vdev_names; /* Only show these vdevs */
3872 unsigned int cb_vdev_names_count;
3873 boolean_t cb_verbose;
3874 boolean_t cb_literal;
3875 boolean_t cb_scripted;
3876 zpool_list_t *cb_list;
3877 vdev_cmd_data_list_t *vcdl;
3878 } iostat_cbdata_t;
3880 /* iostat labels */
3881 typedef struct name_and_columns {
3882 const char *name; /* Column name */
3883 unsigned int columns; /* Center name to this number of columns */
3884 } name_and_columns_t;
3886 #define IOSTAT_MAX_LABELS 15 /* Max number of labels on one line */
3888 static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
3890 [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2},
3891 {NULL}},
3892 [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3893 {"asyncq_wait", 2}, {"scrub", 1}, {"trim", 1}, {"rebuild", 1},
3894 {NULL}},
3895 [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
3896 {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
3897 {"trimq_write", 2}, {"rebuildq_write", 2}, {NULL}},
3898 [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3899 {"asyncq_wait", 2}, {NULL}},
3900 [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
3901 {"async_read", 2}, {"async_write", 2}, {"scrub", 2},
3902 {"trim", 2}, {"rebuild", 2}, {NULL}},
3905 /* Shorthand - if "columns" field not set, default to 1 column */
3906 static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
3908 [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"},
3909 {"write"}, {NULL}},
3910 [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3911 {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {"wait"},
3912 {NULL}},
3913 [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
3914 {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"},
3915 {"pend"}, {"activ"}, {"pend"}, {"activ"}, {NULL}},
3916 [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3917 {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {"rebuild"},
3918 {NULL}},
3919 [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
3920 {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
3921 {"ind"}, {"agg"}, {NULL}},
3924 static const char *histo_to_title[] = {
3925 [IOS_L_HISTO] = "latency",
3926 [IOS_RQ_HISTO] = "req_size",
3930 * Return the number of labels in a null-terminated name_and_columns_t
3931 * array.
3934 static unsigned int
3935 label_array_len(const name_and_columns_t *labels)
3937 int i = 0;
3939 while (labels[i].name)
3940 i++;
3942 return (i);
3946 * Return the number of strings in a null-terminated string array.
3947 * For example:
3949 * const char foo[] = {"bar", "baz", NULL}
3951 * returns 2
3953 static uint64_t
3954 str_array_len(const char *array[])
3956 uint64_t i = 0;
3957 while (array[i])
3958 i++;
3960 return (i);
3965 * Return a default column width for default/latency/queue columns. This does
3966 * not include histograms, which have their columns autosized.
3968 static unsigned int
3969 default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
3971 unsigned long column_width = 5; /* Normal niceprint */
3972 static unsigned long widths[] = {
3974 * Choose some sane default column sizes for printing the
3975 * raw numbers.
3977 [IOS_DEFAULT] = 15, /* 1PB capacity */
3978 [IOS_LATENCY] = 10, /* 1B ns = 10sec */
3979 [IOS_QUEUES] = 6, /* 1M queue entries */
3980 [IOS_L_HISTO] = 10, /* 1B ns = 10sec */
3981 [IOS_RQ_HISTO] = 6, /* 1M queue entries */
3984 if (cb->cb_literal)
3985 column_width = widths[type];
3987 return (column_width);
3991 * Print the column labels, i.e:
3993 * capacity operations bandwidth
3994 * alloc free read write read write ...
3996 * If force_column_width is set, use it for the column width. If not set, use
3997 * the default column width.
3999 static void
4000 print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width,
4001 const name_and_columns_t labels[][IOSTAT_MAX_LABELS])
4003 int i, idx, s;
4004 int text_start, rw_column_width, spaces_to_end;
4005 uint64_t flags = cb->cb_flags;
4006 uint64_t f;
4007 unsigned int column_width = force_column_width;
4009 /* For each bit set in flags */
4010 for (f = flags; f; f &= ~(1ULL << idx)) {
4011 idx = lowbit64(f) - 1;
4012 if (!force_column_width)
4013 column_width = default_column_width(cb, idx);
4014 /* Print our top labels centered over "read write" label. */
4015 for (i = 0; i < label_array_len(labels[idx]); i++) {
4016 const char *name = labels[idx][i].name;
4018 * We treat labels[][].columns == 0 as shorthand
4019 * for one column. It makes writing out the label
4020 * tables more concise.
4022 unsigned int columns = MAX(1, labels[idx][i].columns);
4023 unsigned int slen = strlen(name);
4025 rw_column_width = (column_width * columns) +
4026 (2 * (columns - 1));
4028 text_start = (int)((rw_column_width) / columns -
4029 slen / columns);
4030 if (text_start < 0)
4031 text_start = 0;
4033 printf(" "); /* Two spaces between columns */
4035 /* Space from beginning of column to label */
4036 for (s = 0; s < text_start; s++)
4037 printf(" ");
4039 printf("%s", name);
4041 /* Print space after label to end of column */
4042 spaces_to_end = rw_column_width - text_start - slen;
4043 if (spaces_to_end < 0)
4044 spaces_to_end = 0;
4046 for (s = 0; s < spaces_to_end; s++)
4047 printf(" ");
4054 * print_cmd_columns - Print custom column titles from -c
4056 * If the user specified the "zpool status|iostat -c" then print their custom
4057 * column titles in the header. For example, print_cmd_columns() would print
4058 * the " col1 col2" part of this:
4060 * $ zpool iostat -vc 'echo col1=val1; echo col2=val2'
4061 * ...
4062 * capacity operations bandwidth
4063 * pool alloc free read write read write col1 col2
4064 * ---------- ----- ----- ----- ----- ----- ----- ---- ----
4065 * mypool 269K 1008M 0 0 107 946
4066 * mirror 269K 1008M 0 0 107 946
4067 * sdb - - 0 0 102 473 val1 val2
4068 * sdc - - 0 0 5 473 val1 val2
4069 * ---------- ----- ----- ----- ----- ----- ----- ---- ----
4071 static void
4072 print_cmd_columns(vdev_cmd_data_list_t *vcdl, int use_dashes)
4074 int i, j;
4075 vdev_cmd_data_t *data = &vcdl->data[0];
4077 if (vcdl->count == 0 || data == NULL)
4078 return;
4081 * Each vdev cmd should have the same column names unless the user did
4082 * something weird with their cmd. Just take the column names from the
4083 * first vdev and assume it works for all of them.
4085 for (i = 0; i < vcdl->uniq_cols_cnt; i++) {
4086 printf(" ");
4087 if (use_dashes) {
4088 for (j = 0; j < vcdl->uniq_cols_width[i]; j++)
4089 printf("-");
4090 } else {
4091 printf_color(ANSI_BOLD, "%*s", vcdl->uniq_cols_width[i],
4092 vcdl->uniq_cols[i]);
4099 * Utility function to print out a line of dashes like:
4101 * -------------------------------- ----- ----- ----- ----- -----
4103 * ...or a dashed named-row line like:
4105 * logs - - - - -
4107 * @cb: iostat data
4109 * @force_column_width If non-zero, use the value as the column width.
4110 * Otherwise use the default column widths.
4112 * @name: Print a dashed named-row line starting
4113 * with @name. Otherwise, print a regular
4114 * dashed line.
4116 static void
4117 print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width,
4118 const char *name)
4120 int i;
4121 unsigned int namewidth;
4122 uint64_t flags = cb->cb_flags;
4123 uint64_t f;
4124 int idx;
4125 const name_and_columns_t *labels;
4126 const char *title;
4129 if (cb->cb_flags & IOS_ANYHISTO_M) {
4130 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
4131 } else if (cb->cb_vdev_names_count) {
4132 title = "vdev";
4133 } else {
4134 title = "pool";
4137 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
4138 name ? strlen(name) : 0);
4141 if (name) {
4142 printf("%-*s", namewidth, name);
4143 } else {
4144 for (i = 0; i < namewidth; i++)
4145 (void) printf("-");
4148 /* For each bit in flags */
4149 for (f = flags; f; f &= ~(1ULL << idx)) {
4150 unsigned int column_width;
4151 idx = lowbit64(f) - 1;
4152 if (force_column_width)
4153 column_width = force_column_width;
4154 else
4155 column_width = default_column_width(cb, idx);
4157 labels = iostat_bottom_labels[idx];
4158 for (i = 0; i < label_array_len(labels); i++) {
4159 if (name)
4160 printf(" %*s-", column_width - 1, " ");
4161 else
4162 printf(" %.*s", column_width,
4163 "--------------------");
4169 static void
4170 print_iostat_separator_impl(iostat_cbdata_t *cb,
4171 unsigned int force_column_width)
4173 print_iostat_dashes(cb, force_column_width, NULL);
4176 static void
4177 print_iostat_separator(iostat_cbdata_t *cb)
4179 print_iostat_separator_impl(cb, 0);
4182 static void
4183 print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
4184 const char *histo_vdev_name)
4186 unsigned int namewidth;
4187 const char *title;
4189 if (cb->cb_flags & IOS_ANYHISTO_M) {
4190 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
4191 } else if (cb->cb_vdev_names_count) {
4192 title = "vdev";
4193 } else {
4194 title = "pool";
4197 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
4198 histo_vdev_name ? strlen(histo_vdev_name) : 0);
4200 if (histo_vdev_name)
4201 printf("%-*s", namewidth, histo_vdev_name);
4202 else
4203 printf("%*s", namewidth, "");
4206 print_iostat_labels(cb, force_column_width, iostat_top_labels);
4207 printf("\n");
4209 printf("%-*s", namewidth, title);
4211 print_iostat_labels(cb, force_column_width, iostat_bottom_labels);
4212 if (cb->vcdl != NULL)
4213 print_cmd_columns(cb->vcdl, 0);
4215 printf("\n");
4217 print_iostat_separator_impl(cb, force_column_width);
4219 if (cb->vcdl != NULL)
4220 print_cmd_columns(cb->vcdl, 1);
4222 printf("\n");
4225 static void
4226 print_iostat_header(iostat_cbdata_t *cb)
4228 print_iostat_header_impl(cb, 0, NULL);
4233 * Display a single statistic.
4235 static void
4236 print_one_stat(uint64_t value, enum zfs_nicenum_format format,
4237 unsigned int column_size, boolean_t scripted)
4239 char buf[64];
4241 zfs_nicenum_format(value, buf, sizeof (buf), format);
4243 if (scripted)
4244 printf("\t%s", buf);
4245 else
4246 printf(" %*s", column_size, buf);
4250 * Calculate the default vdev stats
4252 * Subtract oldvs from newvs, apply a scaling factor, and save the resulting
4253 * stats into calcvs.
4255 static void
4256 calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs,
4257 vdev_stat_t *calcvs)
4259 int i;
4261 memcpy(calcvs, newvs, sizeof (*calcvs));
4262 for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++)
4263 calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]);
4265 for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++)
4266 calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]);
4270 * Internal representation of the extended iostats data.
4272 * The extended iostat stats are exported in nvlists as either uint64_t arrays
4273 * or single uint64_t's. We make both look like arrays to make them easier
4274 * to process. In order to make single uint64_t's look like arrays, we set
4275 * __data to the stat data, and then set *data = &__data with count = 1. Then,
4276 * we can just use *data and count.
4278 struct stat_array {
4279 uint64_t *data;
4280 uint_t count; /* Number of entries in data[] */
4281 uint64_t __data; /* Only used when data is a single uint64_t */
4284 static uint64_t
4285 stat_histo_max(struct stat_array *nva, unsigned int len)
4287 uint64_t max = 0;
4288 int i;
4289 for (i = 0; i < len; i++)
4290 max = MAX(max, array64_max(nva[i].data, nva[i].count));
4292 return (max);
4296 * Helper function to lookup a uint64_t array or uint64_t value and store its
4297 * data as a stat_array. If the nvpair is a single uint64_t value, then we make
4298 * it look like a one element array to make it easier to process.
4300 static int
4301 nvpair64_to_stat_array(nvlist_t *nvl, const char *name,
4302 struct stat_array *nva)
4304 nvpair_t *tmp;
4305 int ret;
4307 verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0);
4308 switch (nvpair_type(tmp)) {
4309 case DATA_TYPE_UINT64_ARRAY:
4310 ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count);
4311 break;
4312 case DATA_TYPE_UINT64:
4313 ret = nvpair_value_uint64(tmp, &nva->__data);
4314 nva->data = &nva->__data;
4315 nva->count = 1;
4316 break;
4317 default:
4318 /* Not a uint64_t */
4319 ret = EINVAL;
4320 break;
4323 return (ret);
4327 * Given a list of nvlist names, look up the extended stats in newnv and oldnv,
4328 * subtract them, and return the results in a newly allocated stat_array.
4329 * You must free the returned array after you are done with it with
4330 * free_calc_stats().
4332 * Additionally, you can set "oldnv" to NULL if you simply want the newnv
4333 * values.
4335 static struct stat_array *
4336 calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv,
4337 nvlist_t *newnv)
4339 nvlist_t *oldnvx = NULL, *newnvx;
4340 struct stat_array *oldnva, *newnva, *calcnva;
4341 int i, j;
4342 unsigned int alloc_size = (sizeof (struct stat_array)) * len;
4344 /* Extract our extended stats nvlist from the main list */
4345 verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX,
4346 &newnvx) == 0);
4347 if (oldnv) {
4348 verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX,
4349 &oldnvx) == 0);
4352 newnva = safe_malloc(alloc_size);
4353 oldnva = safe_malloc(alloc_size);
4354 calcnva = safe_malloc(alloc_size);
4356 for (j = 0; j < len; j++) {
4357 verify(nvpair64_to_stat_array(newnvx, names[j],
4358 &newnva[j]) == 0);
4359 calcnva[j].count = newnva[j].count;
4360 alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]);
4361 calcnva[j].data = safe_malloc(alloc_size);
4362 memcpy(calcnva[j].data, newnva[j].data, alloc_size);
4364 if (oldnvx) {
4365 verify(nvpair64_to_stat_array(oldnvx, names[j],
4366 &oldnva[j]) == 0);
4367 for (i = 0; i < oldnva[j].count; i++)
4368 calcnva[j].data[i] -= oldnva[j].data[i];
4371 free(newnva);
4372 free(oldnva);
4373 return (calcnva);
4376 static void
4377 free_calc_stats(struct stat_array *nva, unsigned int len)
4379 int i;
4380 for (i = 0; i < len; i++)
4381 free(nva[i].data);
4383 free(nva);
4386 static void
4387 print_iostat_histo(struct stat_array *nva, unsigned int len,
4388 iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth,
4389 double scale)
4391 int i, j;
4392 char buf[6];
4393 uint64_t val;
4394 enum zfs_nicenum_format format;
4395 unsigned int buckets;
4396 unsigned int start_bucket;
4398 if (cb->cb_literal)
4399 format = ZFS_NICENUM_RAW;
4400 else
4401 format = ZFS_NICENUM_1024;
4403 /* All these histos are the same size, so just use nva[0].count */
4404 buckets = nva[0].count;
4406 if (cb->cb_flags & IOS_RQ_HISTO_M) {
4407 /* Start at 512 - req size should never be lower than this */
4408 start_bucket = 9;
4409 } else {
4410 start_bucket = 0;
4413 for (j = start_bucket; j < buckets; j++) {
4414 /* Print histogram bucket label */
4415 if (cb->cb_flags & IOS_L_HISTO_M) {
4416 /* Ending range of this bucket */
4417 val = (1UL << (j + 1)) - 1;
4418 zfs_nicetime(val, buf, sizeof (buf));
4419 } else {
4420 /* Request size (starting range of bucket) */
4421 val = (1UL << j);
4422 zfs_nicenum(val, buf, sizeof (buf));
4425 if (cb->cb_scripted)
4426 printf("%llu", (u_longlong_t)val);
4427 else
4428 printf("%-*s", namewidth, buf);
4430 /* Print the values on the line */
4431 for (i = 0; i < len; i++) {
4432 print_one_stat(nva[i].data[j] * scale, format,
4433 column_width, cb->cb_scripted);
4435 printf("\n");
4439 static void
4440 print_solid_separator(unsigned int length)
4442 while (length--)
4443 printf("-");
4444 printf("\n");
4447 static void
4448 print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv,
4449 nvlist_t *newnv, double scale, const char *name)
4451 unsigned int column_width;
4452 unsigned int namewidth;
4453 unsigned int entire_width;
4454 enum iostat_type type;
4455 struct stat_array *nva;
4456 const char **names;
4457 unsigned int names_len;
4459 /* What type of histo are we? */
4460 type = IOS_HISTO_IDX(cb->cb_flags);
4462 /* Get NULL-terminated array of nvlist names for our histo */
4463 names = vsx_type_to_nvlist[type];
4464 names_len = str_array_len(names); /* num of names */
4466 nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv);
4468 if (cb->cb_literal) {
4469 column_width = MAX(5,
4470 (unsigned int) log10(stat_histo_max(nva, names_len)) + 1);
4471 } else {
4472 column_width = 5;
4475 namewidth = MAX(cb->cb_namewidth,
4476 strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]));
4479 * Calculate the entire line width of what we're printing. The
4480 * +2 is for the two spaces between columns:
4482 /* read write */
4483 /* ----- ----- */
4484 /* |___| <---------- column_width */
4485 /* */
4486 /* |__________| <--- entire_width */
4487 /* */
4488 entire_width = namewidth + (column_width + 2) *
4489 label_array_len(iostat_bottom_labels[type]);
4491 if (cb->cb_scripted)
4492 printf("%s\n", name);
4493 else
4494 print_iostat_header_impl(cb, column_width, name);
4496 print_iostat_histo(nva, names_len, cb, column_width,
4497 namewidth, scale);
4499 free_calc_stats(nva, names_len);
4500 if (!cb->cb_scripted)
4501 print_solid_separator(entire_width);
4505 * Calculate the average latency of a power-of-two latency histogram
4507 static uint64_t
4508 single_histo_average(uint64_t *histo, unsigned int buckets)
4510 int i;
4511 uint64_t count = 0, total = 0;
4513 for (i = 0; i < buckets; i++) {
4515 * Our buckets are power-of-two latency ranges. Use the
4516 * midpoint latency of each bucket to calculate the average.
4517 * For example:
4519 * Bucket Midpoint
4520 * 8ns-15ns: 12ns
4521 * 16ns-31ns: 24ns
4522 * ...
4524 if (histo[i] != 0) {
4525 total += histo[i] * (((1UL << i) + ((1UL << i)/2)));
4526 count += histo[i];
4530 /* Prevent divide by zero */
4531 return (count == 0 ? 0 : total / count);
4534 static void
4535 print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *oldnv,
4536 nvlist_t *newnv)
4538 int i;
4539 uint64_t val;
4540 const char *names[] = {
4541 ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE,
4542 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
4543 ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE,
4544 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
4545 ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE,
4546 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
4547 ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE,
4548 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
4549 ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE,
4550 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
4551 ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE,
4552 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
4553 ZPOOL_CONFIG_VDEV_REBUILD_PEND_QUEUE,
4554 ZPOOL_CONFIG_VDEV_REBUILD_ACTIVE_QUEUE,
4557 struct stat_array *nva;
4559 unsigned int column_width = default_column_width(cb, IOS_QUEUES);
4560 enum zfs_nicenum_format format;
4562 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv);
4564 if (cb->cb_literal)
4565 format = ZFS_NICENUM_RAW;
4566 else
4567 format = ZFS_NICENUM_1024;
4569 for (i = 0; i < ARRAY_SIZE(names); i++) {
4570 val = nva[i].data[0];
4571 print_one_stat(val, format, column_width, cb->cb_scripted);
4574 free_calc_stats(nva, ARRAY_SIZE(names));
4577 static void
4578 print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv,
4579 nvlist_t *newnv)
4581 int i;
4582 uint64_t val;
4583 const char *names[] = {
4584 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
4585 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
4586 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
4587 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
4588 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
4589 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
4590 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
4591 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
4592 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
4593 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
4594 ZPOOL_CONFIG_VDEV_REBUILD_LAT_HISTO,
4596 struct stat_array *nva;
4598 unsigned int column_width = default_column_width(cb, IOS_LATENCY);
4599 enum zfs_nicenum_format format;
4601 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv);
4603 if (cb->cb_literal)
4604 format = ZFS_NICENUM_RAWTIME;
4605 else
4606 format = ZFS_NICENUM_TIME;
4608 /* Print our avg latencies on the line */
4609 for (i = 0; i < ARRAY_SIZE(names); i++) {
4610 /* Compute average latency for a latency histo */
4611 val = single_histo_average(nva[i].data, nva[i].count);
4612 print_one_stat(val, format, column_width, cb->cb_scripted);
4614 free_calc_stats(nva, ARRAY_SIZE(names));
4618 * Print default statistics (capacity/operations/bandwidth)
4620 static void
4621 print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale)
4623 unsigned int column_width = default_column_width(cb, IOS_DEFAULT);
4624 enum zfs_nicenum_format format;
4625 char na; /* char to print for "not applicable" values */
4627 if (cb->cb_literal) {
4628 format = ZFS_NICENUM_RAW;
4629 na = '0';
4630 } else {
4631 format = ZFS_NICENUM_1024;
4632 na = '-';
4635 /* only toplevel vdevs have capacity stats */
4636 if (vs->vs_space == 0) {
4637 if (cb->cb_scripted)
4638 printf("\t%c\t%c", na, na);
4639 else
4640 printf(" %*c %*c", column_width, na, column_width,
4641 na);
4642 } else {
4643 print_one_stat(vs->vs_alloc, format, column_width,
4644 cb->cb_scripted);
4645 print_one_stat(vs->vs_space - vs->vs_alloc, format,
4646 column_width, cb->cb_scripted);
4649 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale),
4650 format, column_width, cb->cb_scripted);
4651 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale),
4652 format, column_width, cb->cb_scripted);
4653 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale),
4654 format, column_width, cb->cb_scripted);
4655 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale),
4656 format, column_width, cb->cb_scripted);
4659 static const char *class_name[] = {
4660 VDEV_ALLOC_BIAS_DEDUP,
4661 VDEV_ALLOC_BIAS_SPECIAL,
4662 VDEV_ALLOC_CLASS_LOGS
4666 * Print out all the statistics for the given vdev. This can either be the
4667 * toplevel configuration, or called recursively. If 'name' is NULL, then this
4668 * is a verbose output, and we don't want to display the toplevel pool stats.
4670 * Returns the number of stat lines printed.
4672 static unsigned int
4673 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
4674 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
4676 nvlist_t **oldchild, **newchild;
4677 uint_t c, children, oldchildren;
4678 vdev_stat_t *oldvs, *newvs, *calcvs;
4679 vdev_stat_t zerovs = { 0 };
4680 char *vname;
4681 int i;
4682 int ret = 0;
4683 uint64_t tdelta;
4684 double scale;
4686 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
4687 return (ret);
4689 calcvs = safe_malloc(sizeof (*calcvs));
4691 if (oldnv != NULL) {
4692 verify(nvlist_lookup_uint64_array(oldnv,
4693 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
4694 } else {
4695 oldvs = &zerovs;
4698 /* Do we only want to see a specific vdev? */
4699 for (i = 0; i < cb->cb_vdev_names_count; i++) {
4700 /* Yes we do. Is this the vdev? */
4701 if (strcmp(name, cb->cb_vdev_names[i]) == 0) {
4703 * This is our vdev. Since it is the only vdev we
4704 * will be displaying, make depth = 0 so that it
4705 * doesn't get indented.
4707 depth = 0;
4708 break;
4712 if (cb->cb_vdev_names_count && (i == cb->cb_vdev_names_count)) {
4713 /* Couldn't match the name */
4714 goto children;
4718 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
4719 (uint64_t **)&newvs, &c) == 0);
4722 * Print the vdev name unless it's is a histogram. Histograms
4723 * display the vdev name in the header itself.
4725 if (!(cb->cb_flags & IOS_ANYHISTO_M)) {
4726 if (cb->cb_scripted) {
4727 printf("%s", name);
4728 } else {
4729 if (strlen(name) + depth > cb->cb_namewidth)
4730 (void) printf("%*s%s", depth, "", name);
4731 else
4732 (void) printf("%*s%s%*s", depth, "", name,
4733 (int)(cb->cb_namewidth - strlen(name) -
4734 depth), "");
4738 /* Calculate our scaling factor */
4739 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
4740 if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) {
4742 * If we specify printing histograms with no time interval, then
4743 * print the histogram numbers over the entire lifetime of the
4744 * vdev.
4746 scale = 1;
4747 } else {
4748 if (tdelta == 0)
4749 scale = 1.0;
4750 else
4751 scale = (double)NANOSEC / tdelta;
4754 if (cb->cb_flags & IOS_DEFAULT_M) {
4755 calc_default_iostats(oldvs, newvs, calcvs);
4756 print_iostat_default(calcvs, cb, scale);
4758 if (cb->cb_flags & IOS_LATENCY_M)
4759 print_iostat_latency(cb, oldnv, newnv);
4760 if (cb->cb_flags & IOS_QUEUES_M)
4761 print_iostat_queues(cb, oldnv, newnv);
4762 if (cb->cb_flags & IOS_ANYHISTO_M) {
4763 printf("\n");
4764 print_iostat_histos(cb, oldnv, newnv, scale, name);
4767 if (cb->vcdl != NULL) {
4768 char *path;
4769 if (nvlist_lookup_string(newnv, ZPOOL_CONFIG_PATH,
4770 &path) == 0) {
4771 printf(" ");
4772 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path);
4776 if (!(cb->cb_flags & IOS_ANYHISTO_M))
4777 printf("\n");
4779 ret++;
4781 children:
4783 free(calcvs);
4785 if (!cb->cb_verbose)
4786 return (ret);
4788 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
4789 &newchild, &children) != 0)
4790 return (ret);
4792 if (oldnv) {
4793 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
4794 &oldchild, &oldchildren) != 0)
4795 return (ret);
4797 children = MIN(oldchildren, children);
4801 * print normal top-level devices
4803 for (c = 0; c < children; c++) {
4804 uint64_t ishole = B_FALSE, islog = B_FALSE;
4806 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
4807 &ishole);
4809 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4810 &islog);
4812 if (ishole || islog)
4813 continue;
4815 if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
4816 continue;
4818 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4819 cb->cb_name_flags);
4820 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
4821 newchild[c], cb, depth + 2);
4822 free(vname);
4826 * print all other top-level devices
4828 for (uint_t n = 0; n < 3; n++) {
4829 boolean_t printed = B_FALSE;
4831 for (c = 0; c < children; c++) {
4832 uint64_t islog = B_FALSE;
4833 char *bias = NULL;
4834 char *type = NULL;
4836 (void) nvlist_lookup_uint64(newchild[c],
4837 ZPOOL_CONFIG_IS_LOG, &islog);
4838 if (islog) {
4839 bias = VDEV_ALLOC_CLASS_LOGS;
4840 } else {
4841 (void) nvlist_lookup_string(newchild[c],
4842 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
4843 (void) nvlist_lookup_string(newchild[c],
4844 ZPOOL_CONFIG_TYPE, &type);
4846 if (bias == NULL || strcmp(bias, class_name[n]) != 0)
4847 continue;
4848 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
4849 continue;
4851 if (!printed) {
4852 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) &&
4853 !cb->cb_scripted && !cb->cb_vdev_names) {
4854 print_iostat_dashes(cb, 0,
4855 class_name[n]);
4857 printf("\n");
4858 printed = B_TRUE;
4861 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4862 cb->cb_name_flags);
4863 ret += print_vdev_stats(zhp, vname, oldnv ?
4864 oldchild[c] : NULL, newchild[c], cb, depth + 2);
4865 free(vname);
4870 * Include level 2 ARC devices in iostat output
4872 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
4873 &newchild, &children) != 0)
4874 return (ret);
4876 if (oldnv) {
4877 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
4878 &oldchild, &oldchildren) != 0)
4879 return (ret);
4881 children = MIN(oldchildren, children);
4884 if (children > 0) {
4885 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted &&
4886 !cb->cb_vdev_names) {
4887 print_iostat_dashes(cb, 0, "cache");
4889 printf("\n");
4891 for (c = 0; c < children; c++) {
4892 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4893 cb->cb_name_flags);
4894 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c]
4895 : NULL, newchild[c], cb, depth + 2);
4896 free(vname);
4900 return (ret);
4903 static int
4904 refresh_iostat(zpool_handle_t *zhp, void *data)
4906 iostat_cbdata_t *cb = data;
4907 boolean_t missing;
4910 * If the pool has disappeared, remove it from the list and continue.
4912 if (zpool_refresh_stats(zhp, &missing) != 0)
4913 return (-1);
4915 if (missing)
4916 pool_list_remove(cb->cb_list, zhp);
4918 return (0);
4922 * Callback to print out the iostats for the given pool.
4924 static int
4925 print_iostat(zpool_handle_t *zhp, void *data)
4927 iostat_cbdata_t *cb = data;
4928 nvlist_t *oldconfig, *newconfig;
4929 nvlist_t *oldnvroot, *newnvroot;
4930 int ret;
4932 newconfig = zpool_get_config(zhp, &oldconfig);
4934 if (cb->cb_iteration == 1)
4935 oldconfig = NULL;
4937 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
4938 &newnvroot) == 0);
4940 if (oldconfig == NULL)
4941 oldnvroot = NULL;
4942 else
4943 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
4944 &oldnvroot) == 0);
4946 ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot,
4947 cb, 0);
4948 if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) &&
4949 !cb->cb_scripted && cb->cb_verbose && !cb->cb_vdev_names_count) {
4950 print_iostat_separator(cb);
4951 if (cb->vcdl != NULL) {
4952 print_cmd_columns(cb->vcdl, 1);
4954 printf("\n");
4957 return (ret);
4960 static int
4961 get_columns(void)
4963 struct winsize ws;
4964 int columns = 80;
4965 int error;
4967 if (isatty(STDOUT_FILENO)) {
4968 error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
4969 if (error == 0)
4970 columns = ws.ws_col;
4971 } else {
4972 columns = 999;
4975 return (columns);
4979 * Return the required length of the pool/vdev name column. The minimum
4980 * allowed width and output formatting flags must be provided.
4982 static int
4983 get_namewidth(zpool_handle_t *zhp, int min_width, int flags, boolean_t verbose)
4985 nvlist_t *config, *nvroot;
4986 int width = min_width;
4988 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
4989 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4990 &nvroot) == 0);
4991 unsigned int poolname_len = strlen(zpool_get_name(zhp));
4992 if (verbose == B_FALSE) {
4993 width = MAX(poolname_len, min_width);
4994 } else {
4995 width = MAX(poolname_len,
4996 max_width(zhp, nvroot, 0, min_width, flags));
5000 return (width);
5004 * Parse the input string, get the 'interval' and 'count' value if there is one.
5006 static void
5007 get_interval_count(int *argcp, char **argv, float *iv,
5008 unsigned long *cnt)
5010 float interval = 0;
5011 unsigned long count = 0;
5012 int argc = *argcp;
5015 * Determine if the last argument is an integer or a pool name
5017 if (argc > 0 && zfs_isnumber(argv[argc - 1])) {
5018 char *end;
5020 errno = 0;
5021 interval = strtof(argv[argc - 1], &end);
5023 if (*end == '\0' && errno == 0) {
5024 if (interval == 0) {
5025 (void) fprintf(stderr, gettext(
5026 "interval cannot be zero\n"));
5027 usage(B_FALSE);
5030 * Ignore the last parameter
5032 argc--;
5033 } else {
5035 * If this is not a valid number, just plow on. The
5036 * user will get a more informative error message later
5037 * on.
5039 interval = 0;
5044 * If the last argument is also an integer, then we have both a count
5045 * and an interval.
5047 if (argc > 0 && zfs_isnumber(argv[argc - 1])) {
5048 char *end;
5050 errno = 0;
5051 count = interval;
5052 interval = strtof(argv[argc - 1], &end);
5054 if (*end == '\0' && errno == 0) {
5055 if (interval == 0) {
5056 (void) fprintf(stderr, gettext(
5057 "interval cannot be zero\n"));
5058 usage(B_FALSE);
5062 * Ignore the last parameter
5064 argc--;
5065 } else {
5066 interval = 0;
5070 *iv = interval;
5071 *cnt = count;
5072 *argcp = argc;
5075 static void
5076 get_timestamp_arg(char c)
5078 if (c == 'u')
5079 timestamp_fmt = UDATE;
5080 else if (c == 'd')
5081 timestamp_fmt = DDATE;
5082 else
5083 usage(B_FALSE);
5087 * Return stat flags that are supported by all pools by both the module and
5088 * zpool iostat. "*data" should be initialized to all 0xFFs before running.
5089 * It will get ANDed down until only the flags that are supported on all pools
5090 * remain.
5092 static int
5093 get_stat_flags_cb(zpool_handle_t *zhp, void *data)
5095 uint64_t *mask = data;
5096 nvlist_t *config, *nvroot, *nvx;
5097 uint64_t flags = 0;
5098 int i, j;
5100 config = zpool_get_config(zhp, NULL);
5101 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5102 &nvroot) == 0);
5104 /* Default stats are always supported, but for completeness.. */
5105 if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS))
5106 flags |= IOS_DEFAULT_M;
5108 /* Get our extended stats nvlist from the main list */
5109 if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX,
5110 &nvx) != 0) {
5112 * No extended stats; they're probably running an older
5113 * module. No big deal, we support that too.
5115 goto end;
5118 /* For each extended stat, make sure all its nvpairs are supported */
5119 for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) {
5120 if (!vsx_type_to_nvlist[j][0])
5121 continue;
5123 /* Start off by assuming the flag is supported, then check */
5124 flags |= (1ULL << j);
5125 for (i = 0; vsx_type_to_nvlist[j][i]; i++) {
5126 if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) {
5127 /* flag isn't supported */
5128 flags = flags & ~(1ULL << j);
5129 break;
5133 end:
5134 *mask = *mask & flags;
5135 return (0);
5139 * Return a bitmask of stats that are supported on all pools by both the module
5140 * and zpool iostat.
5142 static uint64_t
5143 get_stat_flags(zpool_list_t *list)
5145 uint64_t mask = -1;
5148 * get_stat_flags_cb() will lop off bits from "mask" until only the
5149 * flags that are supported on all pools remain.
5151 pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask);
5152 return (mask);
5156 * Return 1 if cb_data->cb_vdev_names[0] is this vdev's name, 0 otherwise.
5158 static int
5159 is_vdev_cb(void *zhp_data, nvlist_t *nv, void *cb_data)
5161 iostat_cbdata_t *cb = cb_data;
5162 char *name = NULL;
5163 int ret = 0;
5164 zpool_handle_t *zhp = zhp_data;
5166 name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags);
5168 if (strcmp(name, cb->cb_vdev_names[0]) == 0)
5169 ret = 1; /* match */
5170 free(name);
5172 return (ret);
5176 * Returns 1 if cb_data->cb_vdev_names[0] is a vdev name, 0 otherwise.
5178 static int
5179 is_vdev(zpool_handle_t *zhp, void *cb_data)
5181 return (for_each_vdev(zhp, is_vdev_cb, cb_data));
5185 * Check if vdevs are in a pool
5187 * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise
5188 * return 0. If pool_name is NULL, then search all pools.
5190 static int
5191 are_vdevs_in_pool(int argc, char **argv, char *pool_name,
5192 iostat_cbdata_t *cb)
5194 char **tmp_name;
5195 int ret = 0;
5196 int i;
5197 int pool_count = 0;
5199 if ((argc == 0) || !*argv)
5200 return (0);
5202 if (pool_name)
5203 pool_count = 1;
5205 /* Temporarily hijack cb_vdev_names for a second... */
5206 tmp_name = cb->cb_vdev_names;
5208 /* Go though our list of prospective vdev names */
5209 for (i = 0; i < argc; i++) {
5210 cb->cb_vdev_names = argv + i;
5212 /* Is this name a vdev in our pools? */
5213 ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL,
5214 B_FALSE, is_vdev, cb);
5215 if (!ret) {
5216 /* No match */
5217 break;
5221 cb->cb_vdev_names = tmp_name;
5223 return (ret);
5226 static int
5227 is_pool_cb(zpool_handle_t *zhp, void *data)
5229 char *name = data;
5230 if (strcmp(name, zpool_get_name(zhp)) == 0)
5231 return (1);
5233 return (0);
5237 * Do we have a pool named *name? If so, return 1, otherwise 0.
5239 static int
5240 is_pool(char *name)
5242 return (for_each_pool(0, NULL, B_TRUE, NULL, B_FALSE, is_pool_cb,
5243 name));
5246 /* Are all our argv[] strings pool names? If so return 1, 0 otherwise. */
5247 static int
5248 are_all_pools(int argc, char **argv)
5250 if ((argc == 0) || !*argv)
5251 return (0);
5253 while (--argc >= 0)
5254 if (!is_pool(argv[argc]))
5255 return (0);
5257 return (1);
5261 * Helper function to print out vdev/pool names we can't resolve. Used for an
5262 * error message.
5264 static void
5265 error_list_unresolved_vdevs(int argc, char **argv, char *pool_name,
5266 iostat_cbdata_t *cb)
5268 int i;
5269 char *name;
5270 char *str;
5271 for (i = 0; i < argc; i++) {
5272 name = argv[i];
5274 if (is_pool(name))
5275 str = gettext("pool");
5276 else if (are_vdevs_in_pool(1, &name, pool_name, cb))
5277 str = gettext("vdev in this pool");
5278 else if (are_vdevs_in_pool(1, &name, NULL, cb))
5279 str = gettext("vdev in another pool");
5280 else
5281 str = gettext("unknown");
5283 fprintf(stderr, "\t%s (%s)\n", name, str);
5288 * Same as get_interval_count(), but with additional checks to not misinterpret
5289 * guids as interval/count values. Assumes VDEV_NAME_GUID is set in
5290 * cb.cb_name_flags.
5292 static void
5293 get_interval_count_filter_guids(int *argc, char **argv, float *interval,
5294 unsigned long *count, iostat_cbdata_t *cb)
5296 char **tmpargv = argv;
5297 int argc_for_interval = 0;
5299 /* Is the last arg an interval value? Or a guid? */
5300 if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL, cb)) {
5302 * The last arg is not a guid, so it's probably an
5303 * interval value.
5305 argc_for_interval++;
5307 if (*argc >= 2 &&
5308 !are_vdevs_in_pool(1, &argv[*argc - 2], NULL, cb)) {
5310 * The 2nd to last arg is not a guid, so it's probably
5311 * an interval value.
5313 argc_for_interval++;
5317 /* Point to our list of possible intervals */
5318 tmpargv = &argv[*argc - argc_for_interval];
5320 *argc = *argc - argc_for_interval;
5321 get_interval_count(&argc_for_interval, tmpargv,
5322 interval, count);
5326 * Floating point sleep(). Allows you to pass in a floating point value for
5327 * seconds.
5329 static void
5330 fsleep(float sec)
5332 struct timespec req;
5333 req.tv_sec = floor(sec);
5334 req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
5335 nanosleep(&req, NULL);
5339 * Terminal height, in rows. Returns -1 if stdout is not connected to a TTY or
5340 * if we were unable to determine its size.
5342 static int
5343 terminal_height(void)
5345 struct winsize win;
5347 if (isatty(STDOUT_FILENO) == 0)
5348 return (-1);
5350 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1 && win.ws_row > 0)
5351 return (win.ws_row);
5353 return (-1);
5357 * Run one of the zpool status/iostat -c scripts with the help (-h) option and
5358 * print the result.
5360 * name: Short name of the script ('iostat').
5361 * path: Full path to the script ('/usr/local/etc/zfs/zpool.d/iostat');
5363 static void
5364 print_zpool_script_help(char *name, char *path)
5366 char *argv[] = {path, "-h", NULL};
5367 char **lines = NULL;
5368 int lines_cnt = 0;
5369 int rc;
5371 rc = libzfs_run_process_get_stdout_nopath(path, argv, NULL, &lines,
5372 &lines_cnt);
5373 if (rc != 0 || lines == NULL || lines_cnt <= 0) {
5374 if (lines != NULL)
5375 libzfs_free_str_array(lines, lines_cnt);
5376 return;
5379 for (int i = 0; i < lines_cnt; i++)
5380 if (!is_blank_str(lines[i]))
5381 printf(" %-14s %s\n", name, lines[i]);
5383 libzfs_free_str_array(lines, lines_cnt);
5387 * Go though the zpool status/iostat -c scripts in the user's path, run their
5388 * help option (-h), and print out the results.
5390 static void
5391 print_zpool_dir_scripts(char *dirpath)
5393 DIR *dir;
5394 struct dirent *ent;
5395 char fullpath[MAXPATHLEN];
5396 struct stat dir_stat;
5398 if ((dir = opendir(dirpath)) != NULL) {
5399 /* print all the files and directories within directory */
5400 while ((ent = readdir(dir)) != NULL) {
5401 sprintf(fullpath, "%s/%s", dirpath, ent->d_name);
5403 /* Print the scripts */
5404 if (stat(fullpath, &dir_stat) == 0)
5405 if (dir_stat.st_mode & S_IXUSR &&
5406 S_ISREG(dir_stat.st_mode))
5407 print_zpool_script_help(ent->d_name,
5408 fullpath);
5410 closedir(dir);
5415 * Print out help text for all zpool status/iostat -c scripts.
5417 static void
5418 print_zpool_script_list(char *subcommand)
5420 char *dir, *sp, *tmp;
5422 printf(gettext("Available 'zpool %s -c' commands:\n"), subcommand);
5424 sp = zpool_get_cmd_search_path();
5425 if (sp == NULL)
5426 return;
5428 for (dir = strtok_r(sp, ":", &tmp);
5429 dir != NULL;
5430 dir = strtok_r(NULL, ":", &tmp))
5431 print_zpool_dir_scripts(dir);
5433 free(sp);
5437 * Set the minimum pool/vdev name column width. The width must be at least 10,
5438 * but may be as large as the column width - 42 so it still fits on one line.
5439 * NOTE: 42 is the width of the default capacity/operations/bandwidth output
5441 static int
5442 get_namewidth_iostat(zpool_handle_t *zhp, void *data)
5444 iostat_cbdata_t *cb = data;
5445 int width, available_width;
5448 * get_namewidth() returns the maximum width of any name in that column
5449 * for any pool/vdev/device line that will be output.
5451 width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
5452 cb->cb_verbose);
5455 * The width we are calculating is the width of the header and also the
5456 * padding width for names that are less than maximum width. The stats
5457 * take up 42 characters, so the width available for names is:
5459 available_width = get_columns() - 42;
5462 * If the maximum width fits on a screen, then great! Make everything
5463 * line up by justifying all lines to the same width. If that max
5464 * width is larger than what's available, the name plus stats won't fit
5465 * on one line, and justifying to that width would cause every line to
5466 * wrap on the screen. We only want lines with long names to wrap.
5467 * Limit the padding to what won't wrap.
5469 if (width > available_width)
5470 width = available_width;
5473 * And regardless of whatever the screen width is (get_columns can
5474 * return 0 if the width is not known or less than 42 for a narrow
5475 * terminal) have the width be a minimum of 10.
5477 if (width < 10)
5478 width = 10;
5480 /* Save the calculated width */
5481 cb->cb_namewidth = width;
5483 return (0);
5487 * zpool iostat [[-c [script1,script2,...]] [-lq]|[-rw]] [-ghHLpPvy] [-n name]
5488 * [-T d|u] [[ pool ...]|[pool vdev ...]|[vdev ...]]
5489 * [interval [count]]
5491 * -c CMD For each vdev, run command CMD
5492 * -g Display guid for individual vdev name.
5493 * -L Follow links when resolving vdev path name.
5494 * -P Display full path for vdev name.
5495 * -v Display statistics for individual vdevs
5496 * -h Display help
5497 * -p Display values in parsable (exact) format.
5498 * -H Scripted mode. Don't display headers, and separate properties
5499 * by a single tab.
5500 * -l Display average latency
5501 * -q Display queue depths
5502 * -w Display latency histograms
5503 * -r Display request size histogram
5504 * -T Display a timestamp in date(1) or Unix format
5505 * -n Only print headers once
5507 * This command can be tricky because we want to be able to deal with pool
5508 * creation/destruction as well as vdev configuration changes. The bulk of this
5509 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
5510 * on pool_list_update() to detect the addition of new pools. Configuration
5511 * changes are all handled within libzfs.
5514 zpool_do_iostat(int argc, char **argv)
5516 int c;
5517 int ret;
5518 int npools;
5519 float interval = 0;
5520 unsigned long count = 0;
5521 int winheight = 24;
5522 zpool_list_t *list;
5523 boolean_t verbose = B_FALSE;
5524 boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
5525 boolean_t queues = B_FALSE, parsable = B_FALSE, scripted = B_FALSE;
5526 boolean_t omit_since_boot = B_FALSE;
5527 boolean_t guid = B_FALSE;
5528 boolean_t follow_links = B_FALSE;
5529 boolean_t full_name = B_FALSE;
5530 boolean_t headers_once = B_FALSE;
5531 iostat_cbdata_t cb = { 0 };
5532 char *cmd = NULL;
5534 /* Used for printing error message */
5535 const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q',
5536 [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'};
5538 uint64_t unsupported_flags;
5540 /* check options */
5541 while ((c = getopt(argc, argv, "c:gLPT:vyhplqrwnH")) != -1) {
5542 switch (c) {
5543 case 'c':
5544 if (cmd != NULL) {
5545 fprintf(stderr,
5546 gettext("Can't set -c flag twice\n"));
5547 exit(1);
5550 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL &&
5551 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) {
5552 fprintf(stderr, gettext(
5553 "Can't run -c, disabled by "
5554 "ZPOOL_SCRIPTS_ENABLED.\n"));
5555 exit(1);
5558 if ((getuid() <= 0 || geteuid() <= 0) &&
5559 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) {
5560 fprintf(stderr, gettext(
5561 "Can't run -c with root privileges "
5562 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n"));
5563 exit(1);
5565 cmd = optarg;
5566 verbose = B_TRUE;
5567 break;
5568 case 'g':
5569 guid = B_TRUE;
5570 break;
5571 case 'L':
5572 follow_links = B_TRUE;
5573 break;
5574 case 'P':
5575 full_name = B_TRUE;
5576 break;
5577 case 'T':
5578 get_timestamp_arg(*optarg);
5579 break;
5580 case 'v':
5581 verbose = B_TRUE;
5582 break;
5583 case 'p':
5584 parsable = B_TRUE;
5585 break;
5586 case 'l':
5587 latency = B_TRUE;
5588 break;
5589 case 'q':
5590 queues = B_TRUE;
5591 break;
5592 case 'H':
5593 scripted = B_TRUE;
5594 break;
5595 case 'w':
5596 l_histo = B_TRUE;
5597 break;
5598 case 'r':
5599 rq_histo = B_TRUE;
5600 break;
5601 case 'y':
5602 omit_since_boot = B_TRUE;
5603 break;
5604 case 'n':
5605 headers_once = B_TRUE;
5606 break;
5607 case 'h':
5608 usage(B_FALSE);
5609 break;
5610 case '?':
5611 if (optopt == 'c') {
5612 print_zpool_script_list("iostat");
5613 exit(0);
5614 } else {
5615 fprintf(stderr,
5616 gettext("invalid option '%c'\n"), optopt);
5618 usage(B_FALSE);
5622 argc -= optind;
5623 argv += optind;
5625 cb.cb_literal = parsable;
5626 cb.cb_scripted = scripted;
5628 if (guid)
5629 cb.cb_name_flags |= VDEV_NAME_GUID;
5630 if (follow_links)
5631 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
5632 if (full_name)
5633 cb.cb_name_flags |= VDEV_NAME_PATH;
5634 cb.cb_iteration = 0;
5635 cb.cb_namewidth = 0;
5636 cb.cb_verbose = verbose;
5638 /* Get our interval and count values (if any) */
5639 if (guid) {
5640 get_interval_count_filter_guids(&argc, argv, &interval,
5641 &count, &cb);
5642 } else {
5643 get_interval_count(&argc, argv, &interval, &count);
5646 if (argc == 0) {
5647 /* No args, so just print the defaults. */
5648 } else if (are_all_pools(argc, argv)) {
5649 /* All the args are pool names */
5650 } else if (are_vdevs_in_pool(argc, argv, NULL, &cb)) {
5651 /* All the args are vdevs */
5652 cb.cb_vdev_names = argv;
5653 cb.cb_vdev_names_count = argc;
5654 argc = 0; /* No pools to process */
5655 } else if (are_all_pools(1, argv)) {
5656 /* The first arg is a pool name */
5657 if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb)) {
5658 /* ...and the rest are vdev names */
5659 cb.cb_vdev_names = argv + 1;
5660 cb.cb_vdev_names_count = argc - 1;
5661 argc = 1; /* One pool to process */
5662 } else {
5663 fprintf(stderr, gettext("Expected either a list of "));
5664 fprintf(stderr, gettext("pools, or list of vdevs in"));
5665 fprintf(stderr, " \"%s\", ", argv[0]);
5666 fprintf(stderr, gettext("but got:\n"));
5667 error_list_unresolved_vdevs(argc - 1, argv + 1,
5668 argv[0], &cb);
5669 fprintf(stderr, "\n");
5670 usage(B_FALSE);
5671 return (1);
5673 } else {
5675 * The args don't make sense. The first arg isn't a pool name,
5676 * nor are all the args vdevs.
5678 fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n"));
5679 fprintf(stderr, "\n");
5680 return (1);
5683 if (cb.cb_vdev_names_count != 0) {
5685 * If user specified vdevs, it implies verbose.
5687 cb.cb_verbose = B_TRUE;
5691 * Construct the list of all interesting pools.
5693 ret = 0;
5694 if ((list = pool_list_get(argc, argv, NULL, parsable, &ret)) == NULL)
5695 return (1);
5697 if (pool_list_count(list) == 0 && argc != 0) {
5698 pool_list_free(list);
5699 return (1);
5702 if (pool_list_count(list) == 0 && interval == 0) {
5703 pool_list_free(list);
5704 (void) fprintf(stderr, gettext("no pools available\n"));
5705 return (1);
5708 if ((l_histo || rq_histo) && (cmd != NULL || latency || queues)) {
5709 pool_list_free(list);
5710 (void) fprintf(stderr,
5711 gettext("[-r|-w] isn't allowed with [-c|-l|-q]\n"));
5712 usage(B_FALSE);
5713 return (1);
5716 if (l_histo && rq_histo) {
5717 pool_list_free(list);
5718 (void) fprintf(stderr,
5719 gettext("Only one of [-r|-w] can be passed at a time\n"));
5720 usage(B_FALSE);
5721 return (1);
5725 * Enter the main iostat loop.
5727 cb.cb_list = list;
5729 if (l_histo) {
5731 * Histograms tables look out of place when you try to display
5732 * them with the other stats, so make a rule that you can only
5733 * print histograms by themselves.
5735 cb.cb_flags = IOS_L_HISTO_M;
5736 } else if (rq_histo) {
5737 cb.cb_flags = IOS_RQ_HISTO_M;
5738 } else {
5739 cb.cb_flags = IOS_DEFAULT_M;
5740 if (latency)
5741 cb.cb_flags |= IOS_LATENCY_M;
5742 if (queues)
5743 cb.cb_flags |= IOS_QUEUES_M;
5747 * See if the module supports all the stats we want to display.
5749 unsupported_flags = cb.cb_flags & ~get_stat_flags(list);
5750 if (unsupported_flags) {
5751 uint64_t f;
5752 int idx;
5753 fprintf(stderr,
5754 gettext("The loaded zfs module doesn't support:"));
5756 /* for each bit set in unsupported_flags */
5757 for (f = unsupported_flags; f; f &= ~(1ULL << idx)) {
5758 idx = lowbit64(f) - 1;
5759 fprintf(stderr, " -%c", flag_to_arg[idx]);
5762 fprintf(stderr, ". Try running a newer module.\n");
5763 pool_list_free(list);
5765 return (1);
5768 for (;;) {
5769 if ((npools = pool_list_count(list)) == 0)
5770 (void) fprintf(stderr, gettext("no pools available\n"));
5771 else {
5773 * If this is the first iteration and -y was supplied
5774 * we skip any printing.
5776 boolean_t skip = (omit_since_boot &&
5777 cb.cb_iteration == 0);
5780 * Refresh all statistics. This is done as an
5781 * explicit step before calculating the maximum name
5782 * width, so that any * configuration changes are
5783 * properly accounted for.
5785 (void) pool_list_iter(list, B_FALSE, refresh_iostat,
5786 &cb);
5789 * Iterate over all pools to determine the maximum width
5790 * for the pool / device name column across all pools.
5792 cb.cb_namewidth = 0;
5793 (void) pool_list_iter(list, B_FALSE,
5794 get_namewidth_iostat, &cb);
5796 if (timestamp_fmt != NODATE)
5797 print_timestamp(timestamp_fmt);
5799 if (cmd != NULL && cb.cb_verbose &&
5800 !(cb.cb_flags & IOS_ANYHISTO_M)) {
5801 cb.vcdl = all_pools_for_each_vdev_run(argc,
5802 argv, cmd, g_zfs, cb.cb_vdev_names,
5803 cb.cb_vdev_names_count, cb.cb_name_flags);
5804 } else {
5805 cb.vcdl = NULL;
5810 * Check terminal size so we can print headers
5811 * even when terminal window has its height
5812 * changed.
5814 winheight = terminal_height();
5816 * Are we connected to TTY? If not, headers_once
5817 * should be true, to avoid breaking scripts.
5819 if (winheight < 0)
5820 headers_once = B_TRUE;
5823 * If it's the first time and we're not skipping it,
5824 * or either skip or verbose mode, print the header.
5826 * The histogram code explicitly prints its header on
5827 * every vdev, so skip this for histograms.
5829 if (((++cb.cb_iteration == 1 && !skip) ||
5830 (skip != verbose) ||
5831 (!headers_once &&
5832 (cb.cb_iteration % winheight) == 0)) &&
5833 (!(cb.cb_flags & IOS_ANYHISTO_M)) &&
5834 !cb.cb_scripted)
5835 print_iostat_header(&cb);
5837 if (skip) {
5838 (void) fsleep(interval);
5839 continue;
5842 pool_list_iter(list, B_FALSE, print_iostat, &cb);
5845 * If there's more than one pool, and we're not in
5846 * verbose mode (which prints a separator for us),
5847 * then print a separator.
5849 * In addition, if we're printing specific vdevs then
5850 * we also want an ending separator.
5852 if (((npools > 1 && !verbose &&
5853 !(cb.cb_flags & IOS_ANYHISTO_M)) ||
5854 (!(cb.cb_flags & IOS_ANYHISTO_M) &&
5855 cb.cb_vdev_names_count)) &&
5856 !cb.cb_scripted) {
5857 print_iostat_separator(&cb);
5858 if (cb.vcdl != NULL)
5859 print_cmd_columns(cb.vcdl, 1);
5860 printf("\n");
5863 if (cb.vcdl != NULL)
5864 free_vdev_cmd_data_list(cb.vcdl);
5869 * Flush the output so that redirection to a file isn't buffered
5870 * indefinitely.
5872 (void) fflush(stdout);
5874 if (interval == 0)
5875 break;
5877 if (count != 0 && --count == 0)
5878 break;
5880 (void) fsleep(interval);
5883 pool_list_free(list);
5885 return (ret);
5888 typedef struct list_cbdata {
5889 boolean_t cb_verbose;
5890 int cb_name_flags;
5891 int cb_namewidth;
5892 boolean_t cb_scripted;
5893 zprop_list_t *cb_proplist;
5894 boolean_t cb_literal;
5895 } list_cbdata_t;
5899 * Given a list of columns to display, output appropriate headers for each one.
5901 static void
5902 print_header(list_cbdata_t *cb)
5904 zprop_list_t *pl = cb->cb_proplist;
5905 char headerbuf[ZPOOL_MAXPROPLEN];
5906 const char *header;
5907 boolean_t first = B_TRUE;
5908 boolean_t right_justify;
5909 size_t width = 0;
5911 for (; pl != NULL; pl = pl->pl_next) {
5912 width = pl->pl_width;
5913 if (first && cb->cb_verbose) {
5915 * Reset the width to accommodate the verbose listing
5916 * of devices.
5918 width = cb->cb_namewidth;
5921 if (!first)
5922 (void) printf(" ");
5923 else
5924 first = B_FALSE;
5926 right_justify = B_FALSE;
5927 if (pl->pl_prop != ZPROP_INVAL) {
5928 header = zpool_prop_column_name(pl->pl_prop);
5929 right_justify = zpool_prop_align_right(pl->pl_prop);
5930 } else {
5931 int i;
5933 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
5934 headerbuf[i] = toupper(pl->pl_user_prop[i]);
5935 headerbuf[i] = '\0';
5936 header = headerbuf;
5939 if (pl->pl_next == NULL && !right_justify)
5940 (void) printf("%s", header);
5941 else if (right_justify)
5942 (void) printf("%*s", (int)width, header);
5943 else
5944 (void) printf("%-*s", (int)width, header);
5947 (void) printf("\n");
5951 * Given a pool and a list of properties, print out all the properties according
5952 * to the described layout. Used by zpool_do_list().
5954 static void
5955 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
5957 zprop_list_t *pl = cb->cb_proplist;
5958 boolean_t first = B_TRUE;
5959 char property[ZPOOL_MAXPROPLEN];
5960 char *propstr;
5961 boolean_t right_justify;
5962 size_t width;
5964 for (; pl != NULL; pl = pl->pl_next) {
5966 width = pl->pl_width;
5967 if (first && cb->cb_verbose) {
5969 * Reset the width to accommodate the verbose listing
5970 * of devices.
5972 width = cb->cb_namewidth;
5975 if (!first) {
5976 if (cb->cb_scripted)
5977 (void) printf("\t");
5978 else
5979 (void) printf(" ");
5980 } else {
5981 first = B_FALSE;
5984 right_justify = B_FALSE;
5985 if (pl->pl_prop != ZPROP_INVAL) {
5986 if (zpool_get_prop(zhp, pl->pl_prop, property,
5987 sizeof (property), NULL, cb->cb_literal) != 0)
5988 propstr = "-";
5989 else
5990 propstr = property;
5992 right_justify = zpool_prop_align_right(pl->pl_prop);
5993 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
5994 zpool_prop_unsupported(pl->pl_user_prop)) &&
5995 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
5996 sizeof (property)) == 0) {
5997 propstr = property;
5998 } else {
5999 propstr = "-";
6004 * If this is being called in scripted mode, or if this is the
6005 * last column and it is left-justified, don't include a width
6006 * format specifier.
6008 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
6009 (void) printf("%s", propstr);
6010 else if (right_justify)
6011 (void) printf("%*s", (int)width, propstr);
6012 else
6013 (void) printf("%-*s", (int)width, propstr);
6016 (void) printf("\n");
6019 static void
6020 print_one_column(zpool_prop_t prop, uint64_t value, const char *str,
6021 boolean_t scripted, boolean_t valid, enum zfs_nicenum_format format)
6023 char propval[64];
6024 boolean_t fixed;
6025 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
6027 switch (prop) {
6028 case ZPOOL_PROP_EXPANDSZ:
6029 case ZPOOL_PROP_CHECKPOINT:
6030 case ZPOOL_PROP_DEDUPRATIO:
6031 if (value == 0)
6032 (void) strlcpy(propval, "-", sizeof (propval));
6033 else
6034 zfs_nicenum_format(value, propval, sizeof (propval),
6035 format);
6036 break;
6037 case ZPOOL_PROP_FRAGMENTATION:
6038 if (value == ZFS_FRAG_INVALID) {
6039 (void) strlcpy(propval, "-", sizeof (propval));
6040 } else if (format == ZFS_NICENUM_RAW) {
6041 (void) snprintf(propval, sizeof (propval), "%llu",
6042 (unsigned long long)value);
6043 } else {
6044 (void) snprintf(propval, sizeof (propval), "%llu%%",
6045 (unsigned long long)value);
6047 break;
6048 case ZPOOL_PROP_CAPACITY:
6049 /* capacity value is in parts-per-10,000 (aka permyriad) */
6050 if (format == ZFS_NICENUM_RAW)
6051 (void) snprintf(propval, sizeof (propval), "%llu",
6052 (unsigned long long)value / 100);
6053 else
6054 (void) snprintf(propval, sizeof (propval),
6055 value < 1000 ? "%1.2f%%" : value < 10000 ?
6056 "%2.1f%%" : "%3.0f%%", value / 100.0);
6057 break;
6058 case ZPOOL_PROP_HEALTH:
6059 width = 8;
6060 (void) strlcpy(propval, str, sizeof (propval));
6061 break;
6062 default:
6063 zfs_nicenum_format(value, propval, sizeof (propval), format);
6066 if (!valid)
6067 (void) strlcpy(propval, "-", sizeof (propval));
6069 if (scripted)
6070 (void) printf("\t%s", propval);
6071 else
6072 (void) printf(" %*s", (int)width, propval);
6076 * print static default line per vdev
6077 * not compatible with '-o' <proplist> option
6079 static void
6080 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
6081 list_cbdata_t *cb, int depth, boolean_t isspare)
6083 nvlist_t **child;
6084 vdev_stat_t *vs;
6085 uint_t c, children;
6086 char *vname;
6087 boolean_t scripted = cb->cb_scripted;
6088 uint64_t islog = B_FALSE;
6089 char *dashes = "%-*s - - - - "
6090 "- - - - -\n";
6092 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
6093 (uint64_t **)&vs, &c) == 0);
6095 if (name != NULL) {
6096 boolean_t toplevel = (vs->vs_space != 0);
6097 uint64_t cap;
6098 enum zfs_nicenum_format format;
6099 const char *state;
6101 if (cb->cb_literal)
6102 format = ZFS_NICENUM_RAW;
6103 else
6104 format = ZFS_NICENUM_1024;
6106 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
6107 return;
6109 if (scripted)
6110 (void) printf("\t%s", name);
6111 else if (strlen(name) + depth > cb->cb_namewidth)
6112 (void) printf("%*s%s", depth, "", name);
6113 else
6114 (void) printf("%*s%s%*s", depth, "", name,
6115 (int)(cb->cb_namewidth - strlen(name) - depth), "");
6118 * Print the properties for the individual vdevs. Some
6119 * properties are only applicable to toplevel vdevs. The
6120 * 'toplevel' boolean value is passed to the print_one_column()
6121 * to indicate that the value is valid.
6123 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, NULL, scripted,
6124 toplevel, format);
6125 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, NULL,
6126 scripted, toplevel, format);
6127 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
6128 NULL, scripted, toplevel, format);
6129 print_one_column(ZPOOL_PROP_CHECKPOINT,
6130 vs->vs_checkpoint_space, NULL, scripted, toplevel, format);
6131 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, NULL,
6132 scripted, B_TRUE, format);
6133 print_one_column(ZPOOL_PROP_FRAGMENTATION,
6134 vs->vs_fragmentation, NULL, scripted,
6135 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel),
6136 format);
6137 cap = (vs->vs_space == 0) ? 0 :
6138 (vs->vs_alloc * 10000 / vs->vs_space);
6139 print_one_column(ZPOOL_PROP_CAPACITY, cap, NULL,
6140 scripted, toplevel, format);
6141 print_one_column(ZPOOL_PROP_DEDUPRATIO, 0, NULL,
6142 scripted, toplevel, format);
6143 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
6144 if (isspare) {
6145 if (vs->vs_aux == VDEV_AUX_SPARED)
6146 state = "INUSE";
6147 else if (vs->vs_state == VDEV_STATE_HEALTHY)
6148 state = "AVAIL";
6150 print_one_column(ZPOOL_PROP_HEALTH, 0, state, scripted,
6151 B_TRUE, format);
6152 (void) printf("\n");
6155 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
6156 &child, &children) != 0)
6157 return;
6159 /* list the normal vdevs first */
6160 for (c = 0; c < children; c++) {
6161 uint64_t ishole = B_FALSE;
6163 if (nvlist_lookup_uint64(child[c],
6164 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
6165 continue;
6167 if (nvlist_lookup_uint64(child[c],
6168 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog)
6169 continue;
6171 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
6172 continue;
6174 vname = zpool_vdev_name(g_zfs, zhp, child[c],
6175 cb->cb_name_flags);
6176 print_list_stats(zhp, vname, child[c], cb, depth + 2, B_FALSE);
6177 free(vname);
6180 /* list the classes: 'logs', 'dedup', and 'special' */
6181 for (uint_t n = 0; n < 3; n++) {
6182 boolean_t printed = B_FALSE;
6184 for (c = 0; c < children; c++) {
6185 char *bias = NULL;
6186 char *type = NULL;
6188 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
6189 &islog) == 0 && islog) {
6190 bias = VDEV_ALLOC_CLASS_LOGS;
6191 } else {
6192 (void) nvlist_lookup_string(child[c],
6193 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
6194 (void) nvlist_lookup_string(child[c],
6195 ZPOOL_CONFIG_TYPE, &type);
6197 if (bias == NULL || strcmp(bias, class_name[n]) != 0)
6198 continue;
6199 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
6200 continue;
6202 if (!printed) {
6203 /* LINTED E_SEC_PRINTF_VAR_FMT */
6204 (void) printf(dashes, cb->cb_namewidth,
6205 class_name[n]);
6206 printed = B_TRUE;
6208 vname = zpool_vdev_name(g_zfs, zhp, child[c],
6209 cb->cb_name_flags);
6210 print_list_stats(zhp, vname, child[c], cb, depth + 2,
6211 B_FALSE);
6212 free(vname);
6216 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
6217 &child, &children) == 0 && children > 0) {
6218 /* LINTED E_SEC_PRINTF_VAR_FMT */
6219 (void) printf(dashes, cb->cb_namewidth, "cache");
6220 for (c = 0; c < children; c++) {
6221 vname = zpool_vdev_name(g_zfs, zhp, child[c],
6222 cb->cb_name_flags);
6223 print_list_stats(zhp, vname, child[c], cb, depth + 2,
6224 B_FALSE);
6225 free(vname);
6229 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
6230 &children) == 0 && children > 0) {
6231 /* LINTED E_SEC_PRINTF_VAR_FMT */
6232 (void) printf(dashes, cb->cb_namewidth, "spare");
6233 for (c = 0; c < children; c++) {
6234 vname = zpool_vdev_name(g_zfs, zhp, child[c],
6235 cb->cb_name_flags);
6236 print_list_stats(zhp, vname, child[c], cb, depth + 2,
6237 B_TRUE);
6238 free(vname);
6244 * Generic callback function to list a pool.
6246 static int
6247 list_callback(zpool_handle_t *zhp, void *data)
6249 list_cbdata_t *cbp = data;
6251 print_pool(zhp, cbp);
6253 if (cbp->cb_verbose) {
6254 nvlist_t *config, *nvroot;
6256 config = zpool_get_config(zhp, NULL);
6257 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
6258 &nvroot) == 0);
6259 print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE);
6262 return (0);
6266 * Set the minimum pool/vdev name column width. The width must be at least 9,
6267 * but may be as large as needed.
6269 static int
6270 get_namewidth_list(zpool_handle_t *zhp, void *data)
6272 list_cbdata_t *cb = data;
6273 int width;
6275 width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
6276 cb->cb_verbose);
6278 if (width < 9)
6279 width = 9;
6281 cb->cb_namewidth = width;
6283 return (0);
6287 * zpool list [-gHLpP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
6289 * -g Display guid for individual vdev name.
6290 * -H Scripted mode. Don't display headers, and separate properties
6291 * by a single tab.
6292 * -L Follow links when resolving vdev path name.
6293 * -o List of properties to display. Defaults to
6294 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
6295 * "dedupratio,health,altroot"
6296 * -p Display values in parsable (exact) format.
6297 * -P Display full path for vdev name.
6298 * -T Display a timestamp in date(1) or Unix format
6300 * List all pools in the system, whether or not they're healthy. Output space
6301 * statistics for each one, as well as health status summary.
6304 zpool_do_list(int argc, char **argv)
6306 int c;
6307 int ret = 0;
6308 list_cbdata_t cb = { 0 };
6309 static char default_props[] =
6310 "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
6311 "capacity,dedupratio,health,altroot";
6312 char *props = default_props;
6313 float interval = 0;
6314 unsigned long count = 0;
6315 zpool_list_t *list;
6316 boolean_t first = B_TRUE;
6318 /* check options */
6319 while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
6320 switch (c) {
6321 case 'g':
6322 cb.cb_name_flags |= VDEV_NAME_GUID;
6323 break;
6324 case 'H':
6325 cb.cb_scripted = B_TRUE;
6326 break;
6327 case 'L':
6328 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
6329 break;
6330 case 'o':
6331 props = optarg;
6332 break;
6333 case 'P':
6334 cb.cb_name_flags |= VDEV_NAME_PATH;
6335 break;
6336 case 'p':
6337 cb.cb_literal = B_TRUE;
6338 break;
6339 case 'T':
6340 get_timestamp_arg(*optarg);
6341 break;
6342 case 'v':
6343 cb.cb_verbose = B_TRUE;
6344 cb.cb_namewidth = 8; /* 8 until precalc is avail */
6345 break;
6346 case ':':
6347 (void) fprintf(stderr, gettext("missing argument for "
6348 "'%c' option\n"), optopt);
6349 usage(B_FALSE);
6350 break;
6351 case '?':
6352 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6353 optopt);
6354 usage(B_FALSE);
6358 argc -= optind;
6359 argv += optind;
6361 get_interval_count(&argc, argv, &interval, &count);
6363 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
6364 usage(B_FALSE);
6366 for (;;) {
6367 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
6368 cb.cb_literal, &ret)) == NULL)
6369 return (1);
6371 if (pool_list_count(list) == 0)
6372 break;
6374 cb.cb_namewidth = 0;
6375 (void) pool_list_iter(list, B_FALSE, get_namewidth_list, &cb);
6377 if (timestamp_fmt != NODATE)
6378 print_timestamp(timestamp_fmt);
6380 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
6381 print_header(&cb);
6382 first = B_FALSE;
6384 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
6386 if (interval == 0)
6387 break;
6389 if (count != 0 && --count == 0)
6390 break;
6392 pool_list_free(list);
6393 (void) fsleep(interval);
6396 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
6397 (void) printf(gettext("no pools available\n"));
6398 ret = 0;
6401 pool_list_free(list);
6402 zprop_free_list(cb.cb_proplist);
6403 return (ret);
6406 static int
6407 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
6409 boolean_t force = B_FALSE;
6410 boolean_t rebuild = B_FALSE;
6411 boolean_t wait = B_FALSE;
6412 int c;
6413 nvlist_t *nvroot;
6414 char *poolname, *old_disk, *new_disk;
6415 zpool_handle_t *zhp;
6416 nvlist_t *props = NULL;
6417 char *propval;
6418 int ret;
6420 /* check options */
6421 while ((c = getopt(argc, argv, "fo:sw")) != -1) {
6422 switch (c) {
6423 case 'f':
6424 force = B_TRUE;
6425 break;
6426 case 'o':
6427 if ((propval = strchr(optarg, '=')) == NULL) {
6428 (void) fprintf(stderr, gettext("missing "
6429 "'=' for -o option\n"));
6430 usage(B_FALSE);
6432 *propval = '\0';
6433 propval++;
6435 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
6436 (add_prop_list(optarg, propval, &props, B_TRUE)))
6437 usage(B_FALSE);
6438 break;
6439 case 's':
6440 rebuild = B_TRUE;
6441 break;
6442 case 'w':
6443 wait = B_TRUE;
6444 break;
6445 case '?':
6446 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6447 optopt);
6448 usage(B_FALSE);
6452 argc -= optind;
6453 argv += optind;
6455 /* get pool name and check number of arguments */
6456 if (argc < 1) {
6457 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6458 usage(B_FALSE);
6461 poolname = argv[0];
6463 if (argc < 2) {
6464 (void) fprintf(stderr,
6465 gettext("missing <device> specification\n"));
6466 usage(B_FALSE);
6469 old_disk = argv[1];
6471 if (argc < 3) {
6472 if (!replacing) {
6473 (void) fprintf(stderr,
6474 gettext("missing <new_device> specification\n"));
6475 usage(B_FALSE);
6477 new_disk = old_disk;
6478 argc -= 1;
6479 argv += 1;
6480 } else {
6481 new_disk = argv[2];
6482 argc -= 2;
6483 argv += 2;
6486 if (argc > 1) {
6487 (void) fprintf(stderr, gettext("too many arguments\n"));
6488 usage(B_FALSE);
6491 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) {
6492 nvlist_free(props);
6493 return (1);
6496 if (zpool_get_config(zhp, NULL) == NULL) {
6497 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
6498 poolname);
6499 zpool_close(zhp);
6500 nvlist_free(props);
6501 return (1);
6504 /* unless manually specified use "ashift" pool property (if set) */
6505 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
6506 int intval;
6507 zprop_source_t src;
6508 char strval[ZPOOL_MAXPROPLEN];
6510 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
6511 if (src != ZPROP_SRC_DEFAULT) {
6512 (void) sprintf(strval, "%" PRId32, intval);
6513 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
6514 &props, B_TRUE) == 0);
6518 nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
6519 argc, argv);
6520 if (nvroot == NULL) {
6521 zpool_close(zhp);
6522 nvlist_free(props);
6523 return (1);
6526 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing,
6527 rebuild);
6529 if (ret == 0 && wait)
6530 ret = zpool_wait(zhp,
6531 replacing ? ZPOOL_WAIT_REPLACE : ZPOOL_WAIT_RESILVER);
6533 nvlist_free(props);
6534 nvlist_free(nvroot);
6535 zpool_close(zhp);
6537 return (ret);
6541 * zpool replace [-fsw] [-o property=value] <pool> <device> <new_device>
6543 * -f Force attach, even if <new_device> appears to be in use.
6544 * -s Use sequential instead of healing reconstruction for resilver.
6545 * -o Set property=value.
6546 * -w Wait for replacing to complete before returning
6548 * Replace <device> with <new_device>.
6550 /* ARGSUSED */
6552 zpool_do_replace(int argc, char **argv)
6554 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
6558 * zpool attach [-fsw] [-o property=value] <pool> <device> <new_device>
6560 * -f Force attach, even if <new_device> appears to be in use.
6561 * -s Use sequential instead of healing reconstruction for resilver.
6562 * -o Set property=value.
6563 * -w Wait for resilvering to complete before returning
6565 * Attach <new_device> to the mirror containing <device>. If <device> is not
6566 * part of a mirror, then <device> will be transformed into a mirror of
6567 * <device> and <new_device>. In either case, <new_device> will begin life
6568 * with a DTL of [0, now], and will immediately begin to resilver itself.
6571 zpool_do_attach(int argc, char **argv)
6573 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
6577 * zpool detach [-f] <pool> <device>
6579 * -f Force detach of <device>, even if DTLs argue against it
6580 * (not supported yet)
6582 * Detach a device from a mirror. The operation will be refused if <device>
6583 * is the last device in the mirror, or if the DTLs indicate that this device
6584 * has the only valid copy of some data.
6586 /* ARGSUSED */
6588 zpool_do_detach(int argc, char **argv)
6590 int c;
6591 char *poolname, *path;
6592 zpool_handle_t *zhp;
6593 int ret;
6595 /* check options */
6596 while ((c = getopt(argc, argv, "")) != -1) {
6597 switch (c) {
6598 case '?':
6599 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6600 optopt);
6601 usage(B_FALSE);
6605 argc -= optind;
6606 argv += optind;
6608 /* get pool name and check number of arguments */
6609 if (argc < 1) {
6610 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6611 usage(B_FALSE);
6614 if (argc < 2) {
6615 (void) fprintf(stderr,
6616 gettext("missing <device> specification\n"));
6617 usage(B_FALSE);
6620 poolname = argv[0];
6621 path = argv[1];
6623 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6624 return (1);
6626 ret = zpool_vdev_detach(zhp, path);
6628 zpool_close(zhp);
6630 return (ret);
6634 * zpool split [-gLnP] [-o prop=val] ...
6635 * [-o mntopt] ...
6636 * [-R altroot] <pool> <newpool> [<device> ...]
6638 * -g Display guid for individual vdev name.
6639 * -L Follow links when resolving vdev path name.
6640 * -n Do not split the pool, but display the resulting layout if
6641 * it were to be split.
6642 * -o Set property=value, or set mount options.
6643 * -P Display full path for vdev name.
6644 * -R Mount the split-off pool under an alternate root.
6645 * -l Load encryption keys while importing.
6647 * Splits the named pool and gives it the new pool name. Devices to be split
6648 * off may be listed, provided that no more than one device is specified
6649 * per top-level vdev mirror. The newly split pool is left in an exported
6650 * state unless -R is specified.
6652 * Restrictions: the top-level of the pool pool must only be made up of
6653 * mirrors; all devices in the pool must be healthy; no device may be
6654 * undergoing a resilvering operation.
6657 zpool_do_split(int argc, char **argv)
6659 char *srcpool, *newpool, *propval;
6660 char *mntopts = NULL;
6661 splitflags_t flags;
6662 int c, ret = 0;
6663 boolean_t loadkeys = B_FALSE;
6664 zpool_handle_t *zhp;
6665 nvlist_t *config, *props = NULL;
6667 flags.dryrun = B_FALSE;
6668 flags.import = B_FALSE;
6669 flags.name_flags = 0;
6671 /* check options */
6672 while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) {
6673 switch (c) {
6674 case 'g':
6675 flags.name_flags |= VDEV_NAME_GUID;
6676 break;
6677 case 'L':
6678 flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
6679 break;
6680 case 'R':
6681 flags.import = B_TRUE;
6682 if (add_prop_list(
6683 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
6684 &props, B_TRUE) != 0) {
6685 nvlist_free(props);
6686 usage(B_FALSE);
6688 break;
6689 case 'l':
6690 loadkeys = B_TRUE;
6691 break;
6692 case 'n':
6693 flags.dryrun = B_TRUE;
6694 break;
6695 case 'o':
6696 if ((propval = strchr(optarg, '=')) != NULL) {
6697 *propval = '\0';
6698 propval++;
6699 if (add_prop_list(optarg, propval,
6700 &props, B_TRUE) != 0) {
6701 nvlist_free(props);
6702 usage(B_FALSE);
6704 } else {
6705 mntopts = optarg;
6707 break;
6708 case 'P':
6709 flags.name_flags |= VDEV_NAME_PATH;
6710 break;
6711 case ':':
6712 (void) fprintf(stderr, gettext("missing argument for "
6713 "'%c' option\n"), optopt);
6714 usage(B_FALSE);
6715 break;
6716 case '?':
6717 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6718 optopt);
6719 usage(B_FALSE);
6720 break;
6724 if (!flags.import && mntopts != NULL) {
6725 (void) fprintf(stderr, gettext("setting mntopts is only "
6726 "valid when importing the pool\n"));
6727 usage(B_FALSE);
6730 if (!flags.import && loadkeys) {
6731 (void) fprintf(stderr, gettext("loading keys is only "
6732 "valid when importing the pool\n"));
6733 usage(B_FALSE);
6736 argc -= optind;
6737 argv += optind;
6739 if (argc < 1) {
6740 (void) fprintf(stderr, gettext("Missing pool name\n"));
6741 usage(B_FALSE);
6743 if (argc < 2) {
6744 (void) fprintf(stderr, gettext("Missing new pool name\n"));
6745 usage(B_FALSE);
6748 srcpool = argv[0];
6749 newpool = argv[1];
6751 argc -= 2;
6752 argv += 2;
6754 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) {
6755 nvlist_free(props);
6756 return (1);
6759 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
6760 if (config == NULL) {
6761 ret = 1;
6762 } else {
6763 if (flags.dryrun) {
6764 (void) printf(gettext("would create '%s' with the "
6765 "following layout:\n\n"), newpool);
6766 print_vdev_tree(NULL, newpool, config, 0, "",
6767 flags.name_flags);
6768 print_vdev_tree(NULL, "dedup", config, 0,
6769 VDEV_ALLOC_BIAS_DEDUP, 0);
6770 print_vdev_tree(NULL, "special", config, 0,
6771 VDEV_ALLOC_BIAS_SPECIAL, 0);
6775 zpool_close(zhp);
6777 if (ret != 0 || flags.dryrun || !flags.import) {
6778 nvlist_free(config);
6779 nvlist_free(props);
6780 return (ret);
6784 * The split was successful. Now we need to open the new
6785 * pool and import it.
6787 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) {
6788 nvlist_free(config);
6789 nvlist_free(props);
6790 return (1);
6793 if (loadkeys) {
6794 ret = zfs_crypto_attempt_load_keys(g_zfs, newpool);
6795 if (ret != 0)
6796 ret = 1;
6799 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
6800 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
6801 ret = 1;
6802 (void) fprintf(stderr, gettext("Split was successful, but "
6803 "the datasets could not all be mounted\n"));
6804 (void) fprintf(stderr, gettext("Try doing '%s' with a "
6805 "different altroot\n"), "zpool import");
6807 zpool_close(zhp);
6808 nvlist_free(config);
6809 nvlist_free(props);
6811 return (ret);
6817 * zpool online <pool> <device> ...
6820 zpool_do_online(int argc, char **argv)
6822 int c, i;
6823 char *poolname;
6824 zpool_handle_t *zhp;
6825 int ret = 0;
6826 vdev_state_t newstate;
6827 int flags = 0;
6829 /* check options */
6830 while ((c = getopt(argc, argv, "e")) != -1) {
6831 switch (c) {
6832 case 'e':
6833 flags |= ZFS_ONLINE_EXPAND;
6834 break;
6835 case '?':
6836 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6837 optopt);
6838 usage(B_FALSE);
6842 argc -= optind;
6843 argv += optind;
6845 /* get pool name and check number of arguments */
6846 if (argc < 1) {
6847 (void) fprintf(stderr, gettext("missing pool name\n"));
6848 usage(B_FALSE);
6850 if (argc < 2) {
6851 (void) fprintf(stderr, gettext("missing device name\n"));
6852 usage(B_FALSE);
6855 poolname = argv[0];
6857 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6858 return (1);
6860 for (i = 1; i < argc; i++) {
6861 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
6862 if (newstate != VDEV_STATE_HEALTHY) {
6863 (void) printf(gettext("warning: device '%s' "
6864 "onlined, but remains in faulted state\n"),
6865 argv[i]);
6866 if (newstate == VDEV_STATE_FAULTED)
6867 (void) printf(gettext("use 'zpool "
6868 "clear' to restore a faulted "
6869 "device\n"));
6870 else
6871 (void) printf(gettext("use 'zpool "
6872 "replace' to replace devices "
6873 "that are no longer present\n"));
6875 } else {
6876 ret = 1;
6880 zpool_close(zhp);
6882 return (ret);
6886 * zpool offline [-ft] <pool> <device> ...
6888 * -f Force the device into a faulted state.
6890 * -t Only take the device off-line temporarily. The offline/faulted
6891 * state will not be persistent across reboots.
6893 /* ARGSUSED */
6895 zpool_do_offline(int argc, char **argv)
6897 int c, i;
6898 char *poolname;
6899 zpool_handle_t *zhp;
6900 int ret = 0;
6901 boolean_t istmp = B_FALSE;
6902 boolean_t fault = B_FALSE;
6904 /* check options */
6905 while ((c = getopt(argc, argv, "ft")) != -1) {
6906 switch (c) {
6907 case 'f':
6908 fault = B_TRUE;
6909 break;
6910 case 't':
6911 istmp = B_TRUE;
6912 break;
6913 case '?':
6914 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6915 optopt);
6916 usage(B_FALSE);
6920 argc -= optind;
6921 argv += optind;
6923 /* get pool name and check number of arguments */
6924 if (argc < 1) {
6925 (void) fprintf(stderr, gettext("missing pool name\n"));
6926 usage(B_FALSE);
6928 if (argc < 2) {
6929 (void) fprintf(stderr, gettext("missing device name\n"));
6930 usage(B_FALSE);
6933 poolname = argv[0];
6935 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6936 return (1);
6938 for (i = 1; i < argc; i++) {
6939 if (fault) {
6940 uint64_t guid = zpool_vdev_path_to_guid(zhp, argv[i]);
6941 vdev_aux_t aux;
6942 if (istmp == B_FALSE) {
6943 /* Force the fault to persist across imports */
6944 aux = VDEV_AUX_EXTERNAL_PERSIST;
6945 } else {
6946 aux = VDEV_AUX_EXTERNAL;
6949 if (guid == 0 || zpool_vdev_fault(zhp, guid, aux) != 0)
6950 ret = 1;
6951 } else {
6952 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
6953 ret = 1;
6957 zpool_close(zhp);
6959 return (ret);
6963 * zpool clear <pool> [device]
6965 * Clear all errors associated with a pool or a particular device.
6968 zpool_do_clear(int argc, char **argv)
6970 int c;
6971 int ret = 0;
6972 boolean_t dryrun = B_FALSE;
6973 boolean_t do_rewind = B_FALSE;
6974 boolean_t xtreme_rewind = B_FALSE;
6975 uint32_t rewind_policy = ZPOOL_NO_REWIND;
6976 nvlist_t *policy = NULL;
6977 zpool_handle_t *zhp;
6978 char *pool, *device;
6980 /* check options */
6981 while ((c = getopt(argc, argv, "FnX")) != -1) {
6982 switch (c) {
6983 case 'F':
6984 do_rewind = B_TRUE;
6985 break;
6986 case 'n':
6987 dryrun = B_TRUE;
6988 break;
6989 case 'X':
6990 xtreme_rewind = B_TRUE;
6991 break;
6992 case '?':
6993 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6994 optopt);
6995 usage(B_FALSE);
6999 argc -= optind;
7000 argv += optind;
7002 if (argc < 1) {
7003 (void) fprintf(stderr, gettext("missing pool name\n"));
7004 usage(B_FALSE);
7007 if (argc > 2) {
7008 (void) fprintf(stderr, gettext("too many arguments\n"));
7009 usage(B_FALSE);
7012 if ((dryrun || xtreme_rewind) && !do_rewind) {
7013 (void) fprintf(stderr,
7014 gettext("-n or -X only meaningful with -F\n"));
7015 usage(B_FALSE);
7017 if (dryrun)
7018 rewind_policy = ZPOOL_TRY_REWIND;
7019 else if (do_rewind)
7020 rewind_policy = ZPOOL_DO_REWIND;
7021 if (xtreme_rewind)
7022 rewind_policy |= ZPOOL_EXTREME_REWIND;
7024 /* In future, further rewind policy choices can be passed along here */
7025 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
7026 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
7027 rewind_policy) != 0) {
7028 return (1);
7031 pool = argv[0];
7032 device = argc == 2 ? argv[1] : NULL;
7034 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
7035 nvlist_free(policy);
7036 return (1);
7039 if (zpool_clear(zhp, device, policy) != 0)
7040 ret = 1;
7042 zpool_close(zhp);
7044 nvlist_free(policy);
7046 return (ret);
7050 * zpool reguid <pool>
7053 zpool_do_reguid(int argc, char **argv)
7055 int c;
7056 char *poolname;
7057 zpool_handle_t *zhp;
7058 int ret = 0;
7060 /* check options */
7061 while ((c = getopt(argc, argv, "")) != -1) {
7062 switch (c) {
7063 case '?':
7064 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7065 optopt);
7066 usage(B_FALSE);
7070 argc -= optind;
7071 argv += optind;
7073 /* get pool name and check number of arguments */
7074 if (argc < 1) {
7075 (void) fprintf(stderr, gettext("missing pool name\n"));
7076 usage(B_FALSE);
7079 if (argc > 1) {
7080 (void) fprintf(stderr, gettext("too many arguments\n"));
7081 usage(B_FALSE);
7084 poolname = argv[0];
7085 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
7086 return (1);
7088 ret = zpool_reguid(zhp);
7090 zpool_close(zhp);
7091 return (ret);
7096 * zpool reopen <pool>
7098 * Reopen the pool so that the kernel can update the sizes of all vdevs.
7101 zpool_do_reopen(int argc, char **argv)
7103 int c;
7104 int ret = 0;
7105 boolean_t scrub_restart = B_TRUE;
7107 /* check options */
7108 while ((c = getopt(argc, argv, "n")) != -1) {
7109 switch (c) {
7110 case 'n':
7111 scrub_restart = B_FALSE;
7112 break;
7113 case '?':
7114 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7115 optopt);
7116 usage(B_FALSE);
7120 argc -= optind;
7121 argv += optind;
7123 /* if argc == 0 we will execute zpool_reopen_one on all pools */
7124 ret = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE, zpool_reopen_one,
7125 &scrub_restart);
7127 return (ret);
7130 typedef struct scrub_cbdata {
7131 int cb_type;
7132 pool_scrub_cmd_t cb_scrub_cmd;
7133 } scrub_cbdata_t;
7135 static boolean_t
7136 zpool_has_checkpoint(zpool_handle_t *zhp)
7138 nvlist_t *config, *nvroot;
7140 config = zpool_get_config(zhp, NULL);
7142 if (config != NULL) {
7143 pool_checkpoint_stat_t *pcs = NULL;
7144 uint_t c;
7146 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
7147 (void) nvlist_lookup_uint64_array(nvroot,
7148 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
7150 if (pcs == NULL || pcs->pcs_state == CS_NONE)
7151 return (B_FALSE);
7153 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
7154 pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
7155 return (B_TRUE);
7158 return (B_FALSE);
7161 static int
7162 scrub_callback(zpool_handle_t *zhp, void *data)
7164 scrub_cbdata_t *cb = data;
7165 int err;
7168 * Ignore faulted pools.
7170 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
7171 (void) fprintf(stderr, gettext("cannot scan '%s': pool is "
7172 "currently unavailable\n"), zpool_get_name(zhp));
7173 return (1);
7176 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
7178 if (err == 0 && zpool_has_checkpoint(zhp) &&
7179 cb->cb_type == POOL_SCAN_SCRUB) {
7180 (void) printf(gettext("warning: will not scrub state that "
7181 "belongs to the checkpoint of pool '%s'\n"),
7182 zpool_get_name(zhp));
7185 return (err != 0);
7188 static int
7189 wait_callback(zpool_handle_t *zhp, void *data)
7191 zpool_wait_activity_t *act = data;
7192 return (zpool_wait(zhp, *act));
7196 * zpool scrub [-s | -p] [-w] <pool> ...
7198 * -s Stop. Stops any in-progress scrub.
7199 * -p Pause. Pause in-progress scrub.
7200 * -w Wait. Blocks until scrub has completed.
7203 zpool_do_scrub(int argc, char **argv)
7205 int c;
7206 scrub_cbdata_t cb;
7207 boolean_t wait = B_FALSE;
7208 int error;
7210 cb.cb_type = POOL_SCAN_SCRUB;
7211 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
7213 /* check options */
7214 while ((c = getopt(argc, argv, "spw")) != -1) {
7215 switch (c) {
7216 case 's':
7217 cb.cb_type = POOL_SCAN_NONE;
7218 break;
7219 case 'p':
7220 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
7221 break;
7222 case 'w':
7223 wait = B_TRUE;
7224 break;
7225 case '?':
7226 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7227 optopt);
7228 usage(B_FALSE);
7232 if (cb.cb_type == POOL_SCAN_NONE &&
7233 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
7234 (void) fprintf(stderr, gettext("invalid option combination: "
7235 "-s and -p are mutually exclusive\n"));
7236 usage(B_FALSE);
7239 if (wait && (cb.cb_type == POOL_SCAN_NONE ||
7240 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE)) {
7241 (void) fprintf(stderr, gettext("invalid option combination: "
7242 "-w cannot be used with -p or -s\n"));
7243 usage(B_FALSE);
7246 argc -= optind;
7247 argv += optind;
7249 if (argc < 1) {
7250 (void) fprintf(stderr, gettext("missing pool name argument\n"));
7251 usage(B_FALSE);
7254 error = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE,
7255 scrub_callback, &cb);
7257 if (wait && !error) {
7258 zpool_wait_activity_t act = ZPOOL_WAIT_SCRUB;
7259 error = for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE,
7260 wait_callback, &act);
7263 return (error);
7267 * zpool resilver <pool> ...
7269 * Restarts any in-progress resilver
7272 zpool_do_resilver(int argc, char **argv)
7274 int c;
7275 scrub_cbdata_t cb;
7277 cb.cb_type = POOL_SCAN_RESILVER;
7278 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
7280 /* check options */
7281 while ((c = getopt(argc, argv, "")) != -1) {
7282 switch (c) {
7283 case '?':
7284 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7285 optopt);
7286 usage(B_FALSE);
7290 argc -= optind;
7291 argv += optind;
7293 if (argc < 1) {
7294 (void) fprintf(stderr, gettext("missing pool name argument\n"));
7295 usage(B_FALSE);
7298 return (for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE,
7299 scrub_callback, &cb));
7303 * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...]
7305 * -c Cancel. Ends any in-progress trim.
7306 * -d Secure trim. Requires kernel and device support.
7307 * -r <rate> Sets the TRIM rate in bytes (per second). Supports
7308 * adding a multiplier suffix such as 'k' or 'm'.
7309 * -s Suspend. TRIM can then be restarted with no flags.
7310 * -w Wait. Blocks until trimming has completed.
7313 zpool_do_trim(int argc, char **argv)
7315 struct option long_options[] = {
7316 {"cancel", no_argument, NULL, 'c'},
7317 {"secure", no_argument, NULL, 'd'},
7318 {"rate", required_argument, NULL, 'r'},
7319 {"suspend", no_argument, NULL, 's'},
7320 {"wait", no_argument, NULL, 'w'},
7321 {0, 0, 0, 0}
7324 pool_trim_func_t cmd_type = POOL_TRIM_START;
7325 uint64_t rate = 0;
7326 boolean_t secure = B_FALSE;
7327 boolean_t wait = B_FALSE;
7329 int c;
7330 while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
7331 != -1) {
7332 switch (c) {
7333 case 'c':
7334 if (cmd_type != POOL_TRIM_START &&
7335 cmd_type != POOL_TRIM_CANCEL) {
7336 (void) fprintf(stderr, gettext("-c cannot be "
7337 "combined with other options\n"));
7338 usage(B_FALSE);
7340 cmd_type = POOL_TRIM_CANCEL;
7341 break;
7342 case 'd':
7343 if (cmd_type != POOL_TRIM_START) {
7344 (void) fprintf(stderr, gettext("-d cannot be "
7345 "combined with the -c or -s options\n"));
7346 usage(B_FALSE);
7348 secure = B_TRUE;
7349 break;
7350 case 'r':
7351 if (cmd_type != POOL_TRIM_START) {
7352 (void) fprintf(stderr, gettext("-r cannot be "
7353 "combined with the -c or -s options\n"));
7354 usage(B_FALSE);
7356 if (zfs_nicestrtonum(NULL, optarg, &rate) == -1) {
7357 (void) fprintf(stderr,
7358 gettext("invalid value for rate\n"));
7359 usage(B_FALSE);
7361 break;
7362 case 's':
7363 if (cmd_type != POOL_TRIM_START &&
7364 cmd_type != POOL_TRIM_SUSPEND) {
7365 (void) fprintf(stderr, gettext("-s cannot be "
7366 "combined with other options\n"));
7367 usage(B_FALSE);
7369 cmd_type = POOL_TRIM_SUSPEND;
7370 break;
7371 case 'w':
7372 wait = B_TRUE;
7373 break;
7374 case '?':
7375 if (optopt != 0) {
7376 (void) fprintf(stderr,
7377 gettext("invalid option '%c'\n"), optopt);
7378 } else {
7379 (void) fprintf(stderr,
7380 gettext("invalid option '%s'\n"),
7381 argv[optind - 1]);
7383 usage(B_FALSE);
7387 argc -= optind;
7388 argv += optind;
7390 if (argc < 1) {
7391 (void) fprintf(stderr, gettext("missing pool name argument\n"));
7392 usage(B_FALSE);
7393 return (-1);
7396 if (wait && (cmd_type != POOL_TRIM_START)) {
7397 (void) fprintf(stderr, gettext("-w cannot be used with -c or "
7398 "-s\n"));
7399 usage(B_FALSE);
7402 char *poolname = argv[0];
7403 zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
7404 if (zhp == NULL)
7405 return (-1);
7407 trimflags_t trim_flags = {
7408 .secure = secure,
7409 .rate = rate,
7410 .wait = wait,
7413 nvlist_t *vdevs = fnvlist_alloc();
7414 if (argc == 1) {
7415 /* no individual leaf vdevs specified, so add them all */
7416 nvlist_t *config = zpool_get_config(zhp, NULL);
7417 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
7418 ZPOOL_CONFIG_VDEV_TREE);
7419 zpool_collect_leaves(zhp, nvroot, vdevs);
7420 trim_flags.fullpool = B_TRUE;
7421 } else {
7422 trim_flags.fullpool = B_FALSE;
7423 for (int i = 1; i < argc; i++) {
7424 fnvlist_add_boolean(vdevs, argv[i]);
7428 int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
7430 fnvlist_free(vdevs);
7431 zpool_close(zhp);
7433 return (error);
7437 * Converts a total number of seconds to a human readable string broken
7438 * down in to days/hours/minutes/seconds.
7440 static void
7441 secs_to_dhms(uint64_t total, char *buf)
7443 uint64_t days = total / 60 / 60 / 24;
7444 uint64_t hours = (total / 60 / 60) % 24;
7445 uint64_t mins = (total / 60) % 60;
7446 uint64_t secs = (total % 60);
7448 if (days > 0) {
7449 (void) sprintf(buf, "%llu days %02llu:%02llu:%02llu",
7450 (u_longlong_t)days, (u_longlong_t)hours,
7451 (u_longlong_t)mins, (u_longlong_t)secs);
7452 } else {
7453 (void) sprintf(buf, "%02llu:%02llu:%02llu",
7454 (u_longlong_t)hours, (u_longlong_t)mins,
7455 (u_longlong_t)secs);
7460 * Print out detailed scrub status.
7462 static void
7463 print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
7465 time_t start, end, pause;
7466 uint64_t pass_scanned, scanned, pass_issued, issued, total;
7467 uint64_t elapsed, scan_rate, issue_rate;
7468 double fraction_done;
7469 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
7470 char srate_buf[7], irate_buf[7], time_buf[32];
7472 printf(" ");
7473 printf_color(ANSI_BOLD, gettext("scan:"));
7474 printf(" ");
7476 /* If there's never been a scan, there's not much to say. */
7477 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
7478 ps->pss_func >= POOL_SCAN_FUNCS) {
7479 (void) printf(gettext("none requested\n"));
7480 return;
7483 start = ps->pss_start_time;
7484 end = ps->pss_end_time;
7485 pause = ps->pss_pass_scrub_pause;
7487 zfs_nicebytes(ps->pss_processed, processed_buf, sizeof (processed_buf));
7489 assert(ps->pss_func == POOL_SCAN_SCRUB ||
7490 ps->pss_func == POOL_SCAN_RESILVER);
7492 /* Scan is finished or canceled. */
7493 if (ps->pss_state == DSS_FINISHED) {
7494 secs_to_dhms(end - start, time_buf);
7496 if (ps->pss_func == POOL_SCAN_SCRUB) {
7497 (void) printf(gettext("scrub repaired %s "
7498 "in %s with %llu errors on %s"), processed_buf,
7499 time_buf, (u_longlong_t)ps->pss_errors,
7500 ctime(&end));
7501 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
7502 (void) printf(gettext("resilvered %s "
7503 "in %s with %llu errors on %s"), processed_buf,
7504 time_buf, (u_longlong_t)ps->pss_errors,
7505 ctime(&end));
7507 return;
7508 } else if (ps->pss_state == DSS_CANCELED) {
7509 if (ps->pss_func == POOL_SCAN_SCRUB) {
7510 (void) printf(gettext("scrub canceled on %s"),
7511 ctime(&end));
7512 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
7513 (void) printf(gettext("resilver canceled on %s"),
7514 ctime(&end));
7516 return;
7519 assert(ps->pss_state == DSS_SCANNING);
7521 /* Scan is in progress. Resilvers can't be paused. */
7522 if (ps->pss_func == POOL_SCAN_SCRUB) {
7523 if (pause == 0) {
7524 (void) printf(gettext("scrub in progress since %s"),
7525 ctime(&start));
7526 } else {
7527 (void) printf(gettext("scrub paused since %s"),
7528 ctime(&pause));
7529 (void) printf(gettext("\tscrub started on %s"),
7530 ctime(&start));
7532 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
7533 (void) printf(gettext("resilver in progress since %s"),
7534 ctime(&start));
7537 scanned = ps->pss_examined;
7538 pass_scanned = ps->pss_pass_exam;
7539 issued = ps->pss_issued;
7540 pass_issued = ps->pss_pass_issued;
7541 total = ps->pss_to_examine;
7543 /* we are only done with a block once we have issued the IO for it */
7544 fraction_done = (double)issued / total;
7546 /* elapsed time for this pass, rounding up to 1 if it's 0 */
7547 elapsed = time(NULL) - ps->pss_pass_start;
7548 elapsed -= ps->pss_pass_scrub_spent_paused;
7549 elapsed = (elapsed != 0) ? elapsed : 1;
7551 scan_rate = pass_scanned / elapsed;
7552 issue_rate = pass_issued / elapsed;
7553 uint64_t total_secs_left = (issue_rate != 0 && total >= issued) ?
7554 ((total - issued) / issue_rate) : UINT64_MAX;
7555 secs_to_dhms(total_secs_left, time_buf);
7557 /* format all of the numbers we will be reporting */
7558 zfs_nicebytes(scanned, scanned_buf, sizeof (scanned_buf));
7559 zfs_nicebytes(issued, issued_buf, sizeof (issued_buf));
7560 zfs_nicebytes(total, total_buf, sizeof (total_buf));
7561 zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf));
7562 zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf));
7564 /* do not print estimated time if we have a paused scrub */
7565 if (pause == 0) {
7566 (void) printf(gettext("\t%s scanned at %s/s, "
7567 "%s issued at %s/s, %s total\n"),
7568 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
7569 } else {
7570 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
7571 scanned_buf, issued_buf, total_buf);
7574 if (ps->pss_func == POOL_SCAN_RESILVER) {
7575 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
7576 processed_buf, 100 * fraction_done);
7577 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
7578 (void) printf(gettext("\t%s repaired, %.2f%% done"),
7579 processed_buf, 100 * fraction_done);
7582 if (pause == 0) {
7583 if (total_secs_left != UINT64_MAX &&
7584 issue_rate >= 10 * 1024 * 1024) {
7585 (void) printf(gettext(", %s to go\n"), time_buf);
7586 } else {
7587 (void) printf(gettext(", no estimated "
7588 "completion time\n"));
7590 } else {
7591 (void) printf(gettext("\n"));
7595 static void
7596 print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name)
7598 if (vrs == NULL || vrs->vrs_state == VDEV_REBUILD_NONE)
7599 return;
7601 printf(" ");
7602 printf_color(ANSI_BOLD, gettext("scan:"));
7603 printf(" ");
7605 uint64_t bytes_scanned = vrs->vrs_bytes_scanned;
7606 uint64_t bytes_issued = vrs->vrs_bytes_issued;
7607 uint64_t bytes_rebuilt = vrs->vrs_bytes_rebuilt;
7608 uint64_t bytes_est = vrs->vrs_bytes_est;
7609 uint64_t scan_rate = (vrs->vrs_pass_bytes_scanned /
7610 (vrs->vrs_pass_time_ms + 1)) * 1000;
7611 uint64_t issue_rate = (vrs->vrs_pass_bytes_issued /
7612 (vrs->vrs_pass_time_ms + 1)) * 1000;
7613 double scan_pct = MIN((double)bytes_scanned * 100 /
7614 (bytes_est + 1), 100);
7616 /* Format all of the numbers we will be reporting */
7617 char bytes_scanned_buf[7], bytes_issued_buf[7];
7618 char bytes_rebuilt_buf[7], bytes_est_buf[7];
7619 char scan_rate_buf[7], issue_rate_buf[7], time_buf[32];
7620 zfs_nicebytes(bytes_scanned, bytes_scanned_buf,
7621 sizeof (bytes_scanned_buf));
7622 zfs_nicebytes(bytes_issued, bytes_issued_buf,
7623 sizeof (bytes_issued_buf));
7624 zfs_nicebytes(bytes_rebuilt, bytes_rebuilt_buf,
7625 sizeof (bytes_rebuilt_buf));
7626 zfs_nicebytes(bytes_est, bytes_est_buf, sizeof (bytes_est_buf));
7627 zfs_nicebytes(scan_rate, scan_rate_buf, sizeof (scan_rate_buf));
7628 zfs_nicebytes(issue_rate, issue_rate_buf, sizeof (issue_rate_buf));
7630 time_t start = vrs->vrs_start_time;
7631 time_t end = vrs->vrs_end_time;
7633 /* Rebuild is finished or canceled. */
7634 if (vrs->vrs_state == VDEV_REBUILD_COMPLETE) {
7635 secs_to_dhms(vrs->vrs_scan_time_ms / 1000, time_buf);
7636 (void) printf(gettext("resilvered (%s) %s in %s "
7637 "with %llu errors on %s"), vdev_name, bytes_rebuilt_buf,
7638 time_buf, (u_longlong_t)vrs->vrs_errors, ctime(&end));
7639 return;
7640 } else if (vrs->vrs_state == VDEV_REBUILD_CANCELED) {
7641 (void) printf(gettext("resilver (%s) canceled on %s"),
7642 vdev_name, ctime(&end));
7643 return;
7644 } else if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
7645 (void) printf(gettext("resilver (%s) in progress since %s"),
7646 vdev_name, ctime(&start));
7649 assert(vrs->vrs_state == VDEV_REBUILD_ACTIVE);
7651 secs_to_dhms(MAX((int64_t)bytes_est - (int64_t)bytes_scanned, 0) /
7652 MAX(scan_rate, 1), time_buf);
7654 (void) printf(gettext("\t%s scanned at %s/s, %s issued %s/s, "
7655 "%s total\n"), bytes_scanned_buf, scan_rate_buf,
7656 bytes_issued_buf, issue_rate_buf, bytes_est_buf);
7657 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
7658 bytes_rebuilt_buf, scan_pct);
7660 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
7661 if (scan_rate >= 10 * 1024 * 1024) {
7662 (void) printf(gettext(", %s to go\n"), time_buf);
7663 } else {
7664 (void) printf(gettext(", no estimated "
7665 "completion time\n"));
7667 } else {
7668 (void) printf(gettext("\n"));
7673 * Print rebuild status for top-level vdevs.
7675 static void
7676 print_rebuild_status(zpool_handle_t *zhp, nvlist_t *nvroot)
7678 nvlist_t **child;
7679 uint_t children;
7681 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
7682 &child, &children) != 0)
7683 children = 0;
7685 for (uint_t c = 0; c < children; c++) {
7686 vdev_rebuild_stat_t *vrs;
7687 uint_t i;
7689 if (nvlist_lookup_uint64_array(child[c],
7690 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) {
7691 char *name = zpool_vdev_name(g_zfs, zhp,
7692 child[c], VDEV_NAME_TYPE_ID);
7693 print_rebuild_status_impl(vrs, name);
7694 free(name);
7700 * As we don't scrub checkpointed blocks, we want to warn the user that we
7701 * skipped scanning some blocks if a checkpoint exists or existed at any
7702 * time during the scan. If a sequential instead of healing reconstruction
7703 * was performed then the blocks were reconstructed. However, their checksums
7704 * have not been verified so we still print the warning.
7706 static void
7707 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
7709 if (ps == NULL || pcs == NULL)
7710 return;
7712 if (pcs->pcs_state == CS_NONE ||
7713 pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
7714 return;
7716 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
7718 if (ps->pss_state == DSS_NONE)
7719 return;
7721 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
7722 ps->pss_end_time < pcs->pcs_start_time)
7723 return;
7725 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
7726 (void) printf(gettext(" scan warning: skipped blocks "
7727 "that are only referenced by the checkpoint.\n"));
7728 } else {
7729 assert(ps->pss_state == DSS_SCANNING);
7730 (void) printf(gettext(" scan warning: skipping blocks "
7731 "that are only referenced by the checkpoint.\n"));
7736 * Returns B_TRUE if there is an active rebuild in progress. Otherwise,
7737 * B_FALSE is returned and 'rebuild_end_time' is set to the end time for
7738 * the last completed (or cancelled) rebuild.
7740 static boolean_t
7741 check_rebuilding(nvlist_t *nvroot, uint64_t *rebuild_end_time)
7743 nvlist_t **child;
7744 uint_t children;
7745 boolean_t rebuilding = B_FALSE;
7746 uint64_t end_time = 0;
7748 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
7749 &child, &children) != 0)
7750 children = 0;
7752 for (uint_t c = 0; c < children; c++) {
7753 vdev_rebuild_stat_t *vrs;
7754 uint_t i;
7756 if (nvlist_lookup_uint64_array(child[c],
7757 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) {
7759 if (vrs->vrs_end_time > end_time)
7760 end_time = vrs->vrs_end_time;
7762 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
7763 rebuilding = B_TRUE;
7764 end_time = 0;
7765 break;
7770 if (rebuild_end_time != NULL)
7771 *rebuild_end_time = end_time;
7773 return (rebuilding);
7777 * Print the scan status.
7779 static void
7780 print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
7782 uint64_t rebuild_end_time = 0, resilver_end_time = 0;
7783 boolean_t have_resilver = B_FALSE, have_scrub = B_FALSE;
7784 boolean_t active_resilver = B_FALSE;
7785 pool_checkpoint_stat_t *pcs = NULL;
7786 pool_scan_stat_t *ps = NULL;
7787 uint_t c;
7789 if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
7790 (uint64_t **)&ps, &c) == 0) {
7791 if (ps->pss_func == POOL_SCAN_RESILVER) {
7792 resilver_end_time = ps->pss_end_time;
7793 active_resilver = (ps->pss_state == DSS_SCANNING);
7796 have_resilver = (ps->pss_func == POOL_SCAN_RESILVER);
7797 have_scrub = (ps->pss_func == POOL_SCAN_SCRUB);
7800 boolean_t active_rebuild = check_rebuilding(nvroot, &rebuild_end_time);
7801 boolean_t have_rebuild = (active_rebuild || (rebuild_end_time > 0));
7803 /* Always print the scrub status when available. */
7804 if (have_scrub)
7805 print_scan_scrub_resilver_status(ps);
7808 * When there is an active resilver or rebuild print its status.
7809 * Otherwise print the status of the last resilver or rebuild.
7811 if (active_resilver || (!active_rebuild && have_resilver &&
7812 resilver_end_time && resilver_end_time > rebuild_end_time)) {
7813 print_scan_scrub_resilver_status(ps);
7814 } else if (active_rebuild || (!active_resilver && have_rebuild &&
7815 rebuild_end_time && rebuild_end_time > resilver_end_time)) {
7816 print_rebuild_status(zhp, nvroot);
7819 (void) nvlist_lookup_uint64_array(nvroot,
7820 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
7821 print_checkpoint_scan_warning(ps, pcs);
7825 * Print out detailed removal status.
7827 static void
7828 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
7830 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
7831 time_t start, end;
7832 nvlist_t *config, *nvroot;
7833 nvlist_t **child;
7834 uint_t children;
7835 char *vdev_name;
7837 if (prs == NULL || prs->prs_state == DSS_NONE)
7838 return;
7841 * Determine name of vdev.
7843 config = zpool_get_config(zhp, NULL);
7844 nvroot = fnvlist_lookup_nvlist(config,
7845 ZPOOL_CONFIG_VDEV_TREE);
7846 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
7847 &child, &children) == 0);
7848 assert(prs->prs_removing_vdev < children);
7849 vdev_name = zpool_vdev_name(g_zfs, zhp,
7850 child[prs->prs_removing_vdev], B_TRUE);
7852 printf_color(ANSI_BOLD, gettext("remove: "));
7854 start = prs->prs_start_time;
7855 end = prs->prs_end_time;
7856 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
7859 * Removal is finished or canceled.
7861 if (prs->prs_state == DSS_FINISHED) {
7862 uint64_t minutes_taken = (end - start) / 60;
7864 (void) printf(gettext("Removal of vdev %llu copied %s "
7865 "in %lluh%um, completed on %s"),
7866 (longlong_t)prs->prs_removing_vdev,
7867 copied_buf,
7868 (u_longlong_t)(minutes_taken / 60),
7869 (uint_t)(minutes_taken % 60),
7870 ctime((time_t *)&end));
7871 } else if (prs->prs_state == DSS_CANCELED) {
7872 (void) printf(gettext("Removal of %s canceled on %s"),
7873 vdev_name, ctime(&end));
7874 } else {
7875 uint64_t copied, total, elapsed, mins_left, hours_left;
7876 double fraction_done;
7877 uint_t rate;
7879 assert(prs->prs_state == DSS_SCANNING);
7882 * Removal is in progress.
7884 (void) printf(gettext(
7885 "Evacuation of %s in progress since %s"),
7886 vdev_name, ctime(&start));
7888 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
7889 total = prs->prs_to_copy;
7890 fraction_done = (double)copied / total;
7892 /* elapsed time for this pass */
7893 elapsed = time(NULL) - prs->prs_start_time;
7894 elapsed = elapsed > 0 ? elapsed : 1;
7895 rate = copied / elapsed;
7896 rate = rate > 0 ? rate : 1;
7897 mins_left = ((total - copied) / rate) / 60;
7898 hours_left = mins_left / 60;
7900 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
7901 zfs_nicenum(total, total_buf, sizeof (total_buf));
7902 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
7905 * do not print estimated time if hours_left is more than
7906 * 30 days
7908 (void) printf(gettext(
7909 "\t%s copied out of %s at %s/s, %.2f%% done"),
7910 examined_buf, total_buf, rate_buf, 100 * fraction_done);
7911 if (hours_left < (30 * 24)) {
7912 (void) printf(gettext(", %lluh%um to go\n"),
7913 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
7914 } else {
7915 (void) printf(gettext(
7916 ", (copy is slow, no estimated time)\n"));
7919 free(vdev_name);
7921 if (prs->prs_mapping_memory > 0) {
7922 char mem_buf[7];
7923 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
7924 (void) printf(gettext(
7925 "\t%s memory used for removed device mappings\n"),
7926 mem_buf);
7930 static void
7931 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
7933 time_t start;
7934 char space_buf[7];
7936 if (pcs == NULL || pcs->pcs_state == CS_NONE)
7937 return;
7939 (void) printf(gettext("checkpoint: "));
7941 start = pcs->pcs_start_time;
7942 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
7944 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
7945 char *date = ctime(&start);
7948 * ctime() adds a newline at the end of the generated
7949 * string, thus the weird format specifier and the
7950 * strlen() call used to chop it off from the output.
7952 (void) printf(gettext("created %.*s, consumes %s\n"),
7953 (int)(strlen(date) - 1), date, space_buf);
7954 return;
7957 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
7959 (void) printf(gettext("discarding, %s remaining.\n"),
7960 space_buf);
7963 static void
7964 print_error_log(zpool_handle_t *zhp)
7966 nvlist_t *nverrlist = NULL;
7967 nvpair_t *elem;
7968 char *pathname;
7969 size_t len = MAXPATHLEN * 2;
7971 if (zpool_get_errlog(zhp, &nverrlist) != 0)
7972 return;
7974 (void) printf("errors: Permanent errors have been "
7975 "detected in the following files:\n\n");
7977 pathname = safe_malloc(len);
7978 elem = NULL;
7979 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
7980 nvlist_t *nv;
7981 uint64_t dsobj, obj;
7983 verify(nvpair_value_nvlist(elem, &nv) == 0);
7984 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
7985 &dsobj) == 0);
7986 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
7987 &obj) == 0);
7988 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
7989 (void) printf("%7s %s\n", "", pathname);
7991 free(pathname);
7992 nvlist_free(nverrlist);
7995 static void
7996 print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
7997 uint_t nspares)
7999 uint_t i;
8000 char *name;
8002 if (nspares == 0)
8003 return;
8005 (void) printf(gettext("\tspares\n"));
8007 for (i = 0; i < nspares; i++) {
8008 name = zpool_vdev_name(g_zfs, zhp, spares[i],
8009 cb->cb_name_flags);
8010 print_status_config(zhp, cb, name, spares[i], 2, B_TRUE, NULL);
8011 free(name);
8015 static void
8016 print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
8017 uint_t nl2cache)
8019 uint_t i;
8020 char *name;
8022 if (nl2cache == 0)
8023 return;
8025 (void) printf(gettext("\tcache\n"));
8027 for (i = 0; i < nl2cache; i++) {
8028 name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
8029 cb->cb_name_flags);
8030 print_status_config(zhp, cb, name, l2cache[i], 2,
8031 B_FALSE, NULL);
8032 free(name);
8036 static void
8037 print_dedup_stats(nvlist_t *config)
8039 ddt_histogram_t *ddh;
8040 ddt_stat_t *dds;
8041 ddt_object_t *ddo;
8042 uint_t c;
8043 char dspace[6], mspace[6];
8046 * If the pool was faulted then we may not have been able to
8047 * obtain the config. Otherwise, if we have anything in the dedup
8048 * table continue processing the stats.
8050 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
8051 (uint64_t **)&ddo, &c) != 0)
8052 return;
8054 (void) printf("\n");
8055 (void) printf(gettext(" dedup: "));
8056 if (ddo->ddo_count == 0) {
8057 (void) printf(gettext("no DDT entries\n"));
8058 return;
8061 zfs_nicebytes(ddo->ddo_dspace, dspace, sizeof (dspace));
8062 zfs_nicebytes(ddo->ddo_mspace, mspace, sizeof (mspace));
8063 (void) printf("DDT entries %llu, size %s on disk, %s in core\n",
8064 (u_longlong_t)ddo->ddo_count,
8065 dspace,
8066 mspace);
8068 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
8069 (uint64_t **)&dds, &c) == 0);
8070 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
8071 (uint64_t **)&ddh, &c) == 0);
8072 zpool_dump_ddt(dds, ddh);
8076 * Display a summary of pool status. Displays a summary such as:
8078 * pool: tank
8079 * status: DEGRADED
8080 * reason: One or more devices ...
8081 * see: https://openzfs.github.io/openzfs-docs/msg/ZFS-xxxx-01
8082 * config:
8083 * mirror DEGRADED
8084 * c1t0d0 OK
8085 * c2t0d0 UNAVAIL
8087 * When given the '-v' option, we print out the complete config. If the '-e'
8088 * option is specified, then we print out error rate information as well.
8090 static int
8091 status_callback(zpool_handle_t *zhp, void *data)
8093 status_cbdata_t *cbp = data;
8094 nvlist_t *config, *nvroot;
8095 char *msgid;
8096 zpool_status_t reason;
8097 zpool_errata_t errata;
8098 const char *health;
8099 uint_t c;
8100 vdev_stat_t *vs;
8102 config = zpool_get_config(zhp, NULL);
8103 reason = zpool_get_status(zhp, &msgid, &errata);
8105 cbp->cb_count++;
8108 * If we were given 'zpool status -x', only report those pools with
8109 * problems.
8111 if (cbp->cb_explain &&
8112 (reason == ZPOOL_STATUS_OK ||
8113 reason == ZPOOL_STATUS_VERSION_OLDER ||
8114 reason == ZPOOL_STATUS_FEAT_DISABLED ||
8115 reason == ZPOOL_STATUS_COMPATIBILITY_ERR ||
8116 reason == ZPOOL_STATUS_INCOMPATIBLE_FEAT)) {
8117 if (!cbp->cb_allpools) {
8118 (void) printf(gettext("pool '%s' is healthy\n"),
8119 zpool_get_name(zhp));
8120 if (cbp->cb_first)
8121 cbp->cb_first = B_FALSE;
8123 return (0);
8126 if (cbp->cb_first)
8127 cbp->cb_first = B_FALSE;
8128 else
8129 (void) printf("\n");
8131 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
8132 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
8133 (uint64_t **)&vs, &c) == 0);
8135 health = zpool_get_state_str(zhp);
8137 printf(" ");
8138 printf_color(ANSI_BOLD, gettext("pool:"));
8139 printf(" %s\n", zpool_get_name(zhp));
8140 printf(" ");
8141 printf_color(ANSI_BOLD, gettext("state: "));
8143 printf_color(health_str_to_color(health), "%s", health);
8145 printf("\n");
8147 switch (reason) {
8148 case ZPOOL_STATUS_MISSING_DEV_R:
8149 printf_color(ANSI_BOLD, gettext("status: "));
8150 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8151 "not be opened. Sufficient replicas exist for\n\tthe pool "
8152 "to continue functioning in a degraded state.\n"));
8153 printf_color(ANSI_BOLD, gettext("action: "));
8154 printf_color(ANSI_YELLOW, gettext("Attach the missing device "
8155 "and online it using 'zpool online'.\n"));
8156 break;
8158 case ZPOOL_STATUS_MISSING_DEV_NR:
8159 printf_color(ANSI_BOLD, gettext("status: "));
8160 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8161 "not be opened. There are insufficient\n\treplicas for the"
8162 " pool to continue functioning.\n"));
8163 printf_color(ANSI_BOLD, gettext("action: "));
8164 printf_color(ANSI_YELLOW, gettext("Attach the missing device "
8165 "and online it using 'zpool online'.\n"));
8166 break;
8168 case ZPOOL_STATUS_CORRUPT_LABEL_R:
8169 printf_color(ANSI_BOLD, gettext("status: "));
8170 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8171 "not be used because the label is missing or\n\tinvalid. "
8172 "Sufficient replicas exist for the pool to continue\n\t"
8173 "functioning in a degraded state.\n"));
8174 printf_color(ANSI_BOLD, gettext("action: "));
8175 printf_color(ANSI_YELLOW, gettext("Replace the device using "
8176 "'zpool replace'.\n"));
8177 break;
8179 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
8180 printf_color(ANSI_BOLD, gettext("status: "));
8181 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8182 "not be used because the label is missing \n\tor invalid. "
8183 "There are insufficient replicas for the pool to "
8184 "continue\n\tfunctioning.\n"));
8185 zpool_explain_recover(zpool_get_handle(zhp),
8186 zpool_get_name(zhp), reason, config);
8187 break;
8189 case ZPOOL_STATUS_FAILING_DEV:
8190 printf_color(ANSI_BOLD, gettext("status: "));
8191 printf_color(ANSI_YELLOW, gettext("One or more devices has "
8192 "experienced an unrecoverable error. An\n\tattempt was "
8193 "made to correct the error. Applications are "
8194 "unaffected.\n"));
8195 printf_color(ANSI_BOLD, gettext("action: "));
8196 printf_color(ANSI_YELLOW, gettext("Determine if the "
8197 "device needs to be replaced, and clear the errors\n\tusing"
8198 " 'zpool clear' or replace the device with 'zpool "
8199 "replace'.\n"));
8200 break;
8202 case ZPOOL_STATUS_OFFLINE_DEV:
8203 printf_color(ANSI_BOLD, gettext("status: "));
8204 printf_color(ANSI_YELLOW, gettext("One or more devices has "
8205 "been taken offline by the administrator.\n\tSufficient "
8206 "replicas exist for the pool to continue functioning in "
8207 "a\n\tdegraded state.\n"));
8208 printf_color(ANSI_BOLD, gettext("action: "));
8209 printf_color(ANSI_YELLOW, gettext("Online the device "
8210 "using 'zpool online' or replace the device with\n\t'zpool "
8211 "replace'.\n"));
8212 break;
8214 case ZPOOL_STATUS_REMOVED_DEV:
8215 printf_color(ANSI_BOLD, gettext("status: "));
8216 printf_color(ANSI_YELLOW, gettext("One or more devices has "
8217 "been removed by the administrator.\n\tSufficient "
8218 "replicas exist for the pool to continue functioning in "
8219 "a\n\tdegraded state.\n"));
8220 printf_color(ANSI_BOLD, gettext("action: "));
8221 printf_color(ANSI_YELLOW, gettext("Online the device "
8222 "using zpool online' or replace the device with\n\t'zpool "
8223 "replace'.\n"));
8224 break;
8226 case ZPOOL_STATUS_RESILVERING:
8227 case ZPOOL_STATUS_REBUILDING:
8228 printf_color(ANSI_BOLD, gettext("status: "));
8229 printf_color(ANSI_YELLOW, gettext("One or more devices is "
8230 "currently being resilvered. The pool will\n\tcontinue "
8231 "to function, possibly in a degraded state.\n"));
8232 printf_color(ANSI_BOLD, gettext("action: "));
8233 printf_color(ANSI_YELLOW, gettext("Wait for the resilver to "
8234 "complete.\n"));
8235 break;
8237 case ZPOOL_STATUS_REBUILD_SCRUB:
8238 printf_color(ANSI_BOLD, gettext("status: "));
8239 printf_color(ANSI_YELLOW, gettext("One or more devices have "
8240 "been sequentially resilvered, scrubbing\n\tthe pool "
8241 "is recommended.\n"));
8242 printf_color(ANSI_BOLD, gettext("action: "));
8243 printf_color(ANSI_YELLOW, gettext("Use 'zpool scrub' to "
8244 "verify all data checksums.\n"));
8245 break;
8247 case ZPOOL_STATUS_CORRUPT_DATA:
8248 printf_color(ANSI_BOLD, gettext("status: "));
8249 printf_color(ANSI_YELLOW, gettext("One or more devices has "
8250 "experienced an error resulting in data\n\tcorruption. "
8251 "Applications may be affected.\n"));
8252 printf_color(ANSI_BOLD, gettext("action: "));
8253 printf_color(ANSI_YELLOW, gettext("Restore the file in question"
8254 " if possible. Otherwise restore the\n\tentire pool from "
8255 "backup.\n"));
8256 break;
8258 case ZPOOL_STATUS_CORRUPT_POOL:
8259 printf_color(ANSI_BOLD, gettext("status: "));
8260 printf_color(ANSI_YELLOW, gettext("The pool metadata is "
8261 "corrupted and the pool cannot be opened.\n"));
8262 zpool_explain_recover(zpool_get_handle(zhp),
8263 zpool_get_name(zhp), reason, config);
8264 break;
8266 case ZPOOL_STATUS_VERSION_OLDER:
8267 printf_color(ANSI_BOLD, gettext("status: "));
8268 printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
8269 "a legacy on-disk format. The pool can\n\tstill be used, "
8270 "but some features are unavailable.\n"));
8271 printf_color(ANSI_BOLD, gettext("action: "));
8272 printf_color(ANSI_YELLOW, gettext("Upgrade the pool using "
8273 "'zpool upgrade'. Once this is done, the\n\tpool will no "
8274 "longer be accessible on software that does not support\n\t"
8275 "feature flags.\n"));
8276 break;
8278 case ZPOOL_STATUS_VERSION_NEWER:
8279 printf_color(ANSI_BOLD, gettext("status: "));
8280 printf_color(ANSI_YELLOW, gettext("The pool has been upgraded "
8281 "to a newer, incompatible on-disk version.\n\tThe pool "
8282 "cannot be accessed on this system.\n"));
8283 printf_color(ANSI_BOLD, gettext("action: "));
8284 printf_color(ANSI_YELLOW, gettext("Access the pool from a "
8285 "system running more recent software, or\n\trestore the "
8286 "pool from backup.\n"));
8287 break;
8289 case ZPOOL_STATUS_FEAT_DISABLED:
8290 printf_color(ANSI_BOLD, gettext("status: "));
8291 printf_color(ANSI_YELLOW, gettext("Some supported and "
8292 "requested features are not enabled on the pool.\n\t"
8293 "The pool can still be used, but some features are "
8294 "unavailable.\n"));
8295 printf_color(ANSI_BOLD, gettext("action: "));
8296 printf_color(ANSI_YELLOW, gettext("Enable all features using "
8297 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
8298 "longer be accessible by software that does not support\n\t"
8299 "the features. See zpool-features(7) for details.\n"));
8300 break;
8302 case ZPOOL_STATUS_COMPATIBILITY_ERR:
8303 printf_color(ANSI_BOLD, gettext("status: "));
8304 printf_color(ANSI_YELLOW, gettext("This pool has a "
8305 "compatibility list specified, but it could not be\n\t"
8306 "read/parsed at this time. The pool can still be used, "
8307 "but this\n\tshould be investigated.\n"));
8308 printf_color(ANSI_BOLD, gettext("action: "));
8309 printf_color(ANSI_YELLOW, gettext("Check the value of the "
8310 "'compatibility' property against the\n\t"
8311 "appropriate file in " ZPOOL_SYSCONF_COMPAT_D " or "
8312 ZPOOL_DATA_COMPAT_D ".\n"));
8313 break;
8315 case ZPOOL_STATUS_INCOMPATIBLE_FEAT:
8316 printf_color(ANSI_BOLD, gettext("status: "));
8317 printf_color(ANSI_YELLOW, gettext("One or more features "
8318 "are enabled on the pool despite not being\n\t"
8319 "requested by the 'compatibility' property.\n"));
8320 printf_color(ANSI_BOLD, gettext("action: "));
8321 printf_color(ANSI_YELLOW, gettext("Consider setting "
8322 "'compatibility' to an appropriate value, or\n\t"
8323 "adding needed features to the relevant file in\n\t"
8324 ZPOOL_SYSCONF_COMPAT_D " or " ZPOOL_DATA_COMPAT_D ".\n"));
8325 break;
8327 case ZPOOL_STATUS_UNSUP_FEAT_READ:
8328 printf_color(ANSI_BOLD, gettext("status: "));
8329 printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed "
8330 "on this system because it uses the\n\tfollowing feature(s)"
8331 " not supported on this system:\n"));
8332 zpool_print_unsup_feat(config);
8333 (void) printf("\n");
8334 printf_color(ANSI_BOLD, gettext("action: "));
8335 printf_color(ANSI_YELLOW, gettext("Access the pool from a "
8336 "system that supports the required feature(s),\n\tor "
8337 "restore the pool from backup.\n"));
8338 break;
8340 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
8341 printf_color(ANSI_BOLD, gettext("status: "));
8342 printf_color(ANSI_YELLOW, gettext("The pool can only be "
8343 "accessed in read-only mode on this system. It\n\tcannot be"
8344 " accessed in read-write mode because it uses the "
8345 "following\n\tfeature(s) not supported on this system:\n"));
8346 zpool_print_unsup_feat(config);
8347 (void) printf("\n");
8348 printf_color(ANSI_BOLD, gettext("action: "));
8349 printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed "
8350 "in read-write mode. Import the pool with\n"
8351 "\t\"-o readonly=on\", access the pool from a system that "
8352 "supports the\n\trequired feature(s), or restore the "
8353 "pool from backup.\n"));
8354 break;
8356 case ZPOOL_STATUS_FAULTED_DEV_R:
8357 printf_color(ANSI_BOLD, gettext("status: "));
8358 printf_color(ANSI_YELLOW, gettext("One or more devices are "
8359 "faulted in response to persistent errors.\n\tSufficient "
8360 "replicas exist for the pool to continue functioning "
8361 "in a\n\tdegraded state.\n"));
8362 printf_color(ANSI_BOLD, gettext("action: "));
8363 printf_color(ANSI_YELLOW, gettext("Replace the faulted device, "
8364 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
8365 break;
8367 case ZPOOL_STATUS_FAULTED_DEV_NR:
8368 printf_color(ANSI_BOLD, gettext("status: "));
8369 printf_color(ANSI_YELLOW, gettext("One or more devices are "
8370 "faulted in response to persistent errors. There are "
8371 "insufficient replicas for the pool to\n\tcontinue "
8372 "functioning.\n"));
8373 printf_color(ANSI_BOLD, gettext("action: "));
8374 printf_color(ANSI_YELLOW, gettext("Destroy and re-create the "
8375 "pool from a backup source. Manually marking the device\n"
8376 "\trepaired using 'zpool clear' may allow some data "
8377 "to be recovered.\n"));
8378 break;
8380 case ZPOOL_STATUS_IO_FAILURE_MMP:
8381 printf_color(ANSI_BOLD, gettext("status: "));
8382 printf_color(ANSI_YELLOW, gettext("The pool is suspended "
8383 "because multihost writes failed or were delayed;\n\t"
8384 "another system could import the pool undetected.\n"));
8385 printf_color(ANSI_BOLD, gettext("action: "));
8386 printf_color(ANSI_YELLOW, gettext("Make sure the pool's devices"
8387 " are connected, then reboot your system and\n\timport the "
8388 "pool.\n"));
8389 break;
8391 case ZPOOL_STATUS_IO_FAILURE_WAIT:
8392 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
8393 printf_color(ANSI_BOLD, gettext("status: "));
8394 printf_color(ANSI_YELLOW, gettext("One or more devices are "
8395 "faulted in response to IO failures.\n"));
8396 printf_color(ANSI_BOLD, gettext("action: "));
8397 printf_color(ANSI_YELLOW, gettext("Make sure the affected "
8398 "devices are connected, then run 'zpool clear'.\n"));
8399 break;
8401 case ZPOOL_STATUS_BAD_LOG:
8402 printf_color(ANSI_BOLD, gettext("status: "));
8403 printf_color(ANSI_YELLOW, gettext("An intent log record "
8404 "could not be read.\n"
8405 "\tWaiting for administrator intervention to fix the "
8406 "faulted pool.\n"));
8407 printf_color(ANSI_BOLD, gettext("action: "));
8408 printf_color(ANSI_YELLOW, gettext("Either restore the affected "
8409 "device(s) and run 'zpool online',\n"
8410 "\tor ignore the intent log records by running "
8411 "'zpool clear'.\n"));
8412 break;
8414 case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
8415 (void) printf(gettext("status: One or more devices are "
8416 "configured to use a non-native block size.\n"
8417 "\tExpect reduced performance.\n"));
8418 (void) printf(gettext("action: Replace affected devices with "
8419 "devices that support the\n\tconfigured block size, or "
8420 "migrate data to a properly configured\n\tpool.\n"));
8421 break;
8423 case ZPOOL_STATUS_HOSTID_MISMATCH:
8424 printf_color(ANSI_BOLD, gettext("status: "));
8425 printf_color(ANSI_YELLOW, gettext("Mismatch between pool hostid"
8426 " and system hostid on imported pool.\n\tThis pool was "
8427 "previously imported into a system with a different "
8428 "hostid,\n\tand then was verbatim imported into this "
8429 "system.\n"));
8430 printf_color(ANSI_BOLD, gettext("action: "));
8431 printf_color(ANSI_YELLOW, gettext("Export this pool on all "
8432 "systems on which it is imported.\n"
8433 "\tThen import it to correct the mismatch.\n"));
8434 break;
8436 case ZPOOL_STATUS_ERRATA:
8437 printf_color(ANSI_BOLD, gettext("status: "));
8438 printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
8439 errata);
8441 switch (errata) {
8442 case ZPOOL_ERRATA_NONE:
8443 break;
8445 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
8446 printf_color(ANSI_BOLD, gettext("action: "));
8447 printf_color(ANSI_YELLOW, gettext("To correct the issue"
8448 " run 'zpool scrub'.\n"));
8449 break;
8451 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
8452 (void) printf(gettext("\tExisting encrypted datasets "
8453 "contain an on-disk incompatibility\n\twhich "
8454 "needs to be corrected.\n"));
8455 printf_color(ANSI_BOLD, gettext("action: "));
8456 printf_color(ANSI_YELLOW, gettext("To correct the issue"
8457 " backup existing encrypted datasets to new\n\t"
8458 "encrypted datasets and destroy the old ones. "
8459 "'zfs mount -o ro' can\n\tbe used to temporarily "
8460 "mount existing encrypted datasets readonly.\n"));
8461 break;
8463 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
8464 (void) printf(gettext("\tExisting encrypted snapshots "
8465 "and bookmarks contain an on-disk\n\tincompat"
8466 "ibility. This may cause on-disk corruption if "
8467 "they are used\n\twith 'zfs recv'.\n"));
8468 printf_color(ANSI_BOLD, gettext("action: "));
8469 printf_color(ANSI_YELLOW, gettext("To correct the"
8470 "issue, enable the bookmark_v2 feature. No "
8471 "additional\n\taction is needed if there are no "
8472 "encrypted snapshots or bookmarks.\n\tIf preserving"
8473 "the encrypted snapshots and bookmarks is required,"
8474 " use\n\ta non-raw send to backup and restore them."
8475 " Alternately, they may be\n\tremoved to resolve "
8476 "the incompatibility.\n"));
8477 break;
8479 default:
8481 * All errata which allow the pool to be imported
8482 * must contain an action message.
8484 assert(0);
8486 break;
8488 default:
8490 * The remaining errors can't actually be generated, yet.
8492 assert(reason == ZPOOL_STATUS_OK);
8495 if (msgid != NULL) {
8496 printf(" ");
8497 printf_color(ANSI_BOLD, gettext("see:"));
8498 printf(gettext(
8499 " https://openzfs.github.io/openzfs-docs/msg/%s\n"),
8500 msgid);
8503 if (config != NULL) {
8504 uint64_t nerr;
8505 nvlist_t **spares, **l2cache;
8506 uint_t nspares, nl2cache;
8507 pool_checkpoint_stat_t *pcs = NULL;
8508 pool_removal_stat_t *prs = NULL;
8510 print_scan_status(zhp, nvroot);
8512 (void) nvlist_lookup_uint64_array(nvroot,
8513 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
8514 print_removal_status(zhp, prs);
8516 (void) nvlist_lookup_uint64_array(nvroot,
8517 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
8518 print_checkpoint_status(pcs);
8520 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
8521 cbp->cb_name_flags | VDEV_NAME_TYPE_ID);
8522 if (cbp->cb_namewidth < 10)
8523 cbp->cb_namewidth = 10;
8525 color_start(ANSI_BOLD);
8526 (void) printf(gettext("config:\n\n"));
8527 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s"),
8528 cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
8529 "CKSUM");
8530 color_end();
8532 if (cbp->cb_print_slow_ios) {
8533 printf_color(ANSI_BOLD, " %5s", gettext("SLOW"));
8536 if (cbp->vcdl != NULL)
8537 print_cmd_columns(cbp->vcdl, 0);
8539 printf("\n");
8541 print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
8542 B_FALSE, NULL);
8544 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
8545 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
8546 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
8548 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
8549 &l2cache, &nl2cache) == 0)
8550 print_l2cache(zhp, cbp, l2cache, nl2cache);
8552 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
8553 &spares, &nspares) == 0)
8554 print_spares(zhp, cbp, spares, nspares);
8556 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
8557 &nerr) == 0) {
8558 nvlist_t *nverrlist = NULL;
8561 * If the approximate error count is small, get a
8562 * precise count by fetching the entire log and
8563 * uniquifying the results.
8565 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
8566 zpool_get_errlog(zhp, &nverrlist) == 0) {
8567 nvpair_t *elem;
8569 elem = NULL;
8570 nerr = 0;
8571 while ((elem = nvlist_next_nvpair(nverrlist,
8572 elem)) != NULL) {
8573 nerr++;
8576 nvlist_free(nverrlist);
8578 (void) printf("\n");
8580 if (nerr == 0)
8581 (void) printf(gettext("errors: No known data "
8582 "errors\n"));
8583 else if (!cbp->cb_verbose)
8584 (void) printf(gettext("errors: %llu data "
8585 "errors, use '-v' for a list\n"),
8586 (u_longlong_t)nerr);
8587 else
8588 print_error_log(zhp);
8591 if (cbp->cb_dedup_stats)
8592 print_dedup_stats(config);
8593 } else {
8594 (void) printf(gettext("config: The configuration cannot be "
8595 "determined.\n"));
8598 return (0);
8602 * zpool status [-c [script1,script2,...]] [-igLpPstvx] [-T d|u] [pool] ...
8603 * [interval [count]]
8605 * -c CMD For each vdev, run command CMD
8606 * -i Display vdev initialization status.
8607 * -g Display guid for individual vdev name.
8608 * -L Follow links when resolving vdev path name.
8609 * -p Display values in parsable (exact) format.
8610 * -P Display full path for vdev name.
8611 * -s Display slow IOs column.
8612 * -v Display complete error logs
8613 * -x Display only pools with potential problems
8614 * -D Display dedup status (undocumented)
8615 * -t Display vdev TRIM status.
8616 * -T Display a timestamp in date(1) or Unix format
8618 * Describes the health status of all pools or some subset.
8621 zpool_do_status(int argc, char **argv)
8623 int c;
8624 int ret;
8625 float interval = 0;
8626 unsigned long count = 0;
8627 status_cbdata_t cb = { 0 };
8628 char *cmd = NULL;
8630 /* check options */
8631 while ((c = getopt(argc, argv, "c:igLpPsvxDtT:")) != -1) {
8632 switch (c) {
8633 case 'c':
8634 if (cmd != NULL) {
8635 fprintf(stderr,
8636 gettext("Can't set -c flag twice\n"));
8637 exit(1);
8640 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL &&
8641 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) {
8642 fprintf(stderr, gettext(
8643 "Can't run -c, disabled by "
8644 "ZPOOL_SCRIPTS_ENABLED.\n"));
8645 exit(1);
8648 if ((getuid() <= 0 || geteuid() <= 0) &&
8649 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) {
8650 fprintf(stderr, gettext(
8651 "Can't run -c with root privileges "
8652 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n"));
8653 exit(1);
8655 cmd = optarg;
8656 break;
8657 case 'i':
8658 cb.cb_print_vdev_init = B_TRUE;
8659 break;
8660 case 'g':
8661 cb.cb_name_flags |= VDEV_NAME_GUID;
8662 break;
8663 case 'L':
8664 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
8665 break;
8666 case 'p':
8667 cb.cb_literal = B_TRUE;
8668 break;
8669 case 'P':
8670 cb.cb_name_flags |= VDEV_NAME_PATH;
8671 break;
8672 case 's':
8673 cb.cb_print_slow_ios = B_TRUE;
8674 break;
8675 case 'v':
8676 cb.cb_verbose = B_TRUE;
8677 break;
8678 case 'x':
8679 cb.cb_explain = B_TRUE;
8680 break;
8681 case 'D':
8682 cb.cb_dedup_stats = B_TRUE;
8683 break;
8684 case 't':
8685 cb.cb_print_vdev_trim = B_TRUE;
8686 break;
8687 case 'T':
8688 get_timestamp_arg(*optarg);
8689 break;
8690 case '?':
8691 if (optopt == 'c') {
8692 print_zpool_script_list("status");
8693 exit(0);
8694 } else {
8695 fprintf(stderr,
8696 gettext("invalid option '%c'\n"), optopt);
8698 usage(B_FALSE);
8702 argc -= optind;
8703 argv += optind;
8705 get_interval_count(&argc, argv, &interval, &count);
8707 if (argc == 0)
8708 cb.cb_allpools = B_TRUE;
8710 cb.cb_first = B_TRUE;
8711 cb.cb_print_status = B_TRUE;
8713 for (;;) {
8714 if (timestamp_fmt != NODATE)
8715 print_timestamp(timestamp_fmt);
8717 if (cmd != NULL)
8718 cb.vcdl = all_pools_for_each_vdev_run(argc, argv, cmd,
8719 NULL, NULL, 0, 0);
8721 ret = for_each_pool(argc, argv, B_TRUE, NULL, cb.cb_literal,
8722 status_callback, &cb);
8724 if (cb.vcdl != NULL)
8725 free_vdev_cmd_data_list(cb.vcdl);
8727 if (argc == 0 && cb.cb_count == 0)
8728 (void) fprintf(stderr, gettext("no pools available\n"));
8729 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
8730 (void) printf(gettext("all pools are healthy\n"));
8732 if (ret != 0)
8733 return (ret);
8735 if (interval == 0)
8736 break;
8738 if (count != 0 && --count == 0)
8739 break;
8741 (void) fsleep(interval);
8744 return (0);
8747 typedef struct upgrade_cbdata {
8748 int cb_first;
8749 int cb_argc;
8750 uint64_t cb_version;
8751 char **cb_argv;
8752 } upgrade_cbdata_t;
8754 static int
8755 check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs)
8757 int zfs_version = (int)zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
8758 int *count = (int *)unsupp_fs;
8760 if (zfs_version > ZPL_VERSION) {
8761 (void) printf(gettext("%s (v%d) is not supported by this "
8762 "implementation of ZFS.\n"),
8763 zfs_get_name(zhp), zfs_version);
8764 (*count)++;
8767 zfs_iter_filesystems(zhp, check_unsupp_fs, unsupp_fs);
8769 zfs_close(zhp);
8771 return (0);
8774 static int
8775 upgrade_version(zpool_handle_t *zhp, uint64_t version)
8777 int ret;
8778 nvlist_t *config;
8779 uint64_t oldversion;
8780 int unsupp_fs = 0;
8782 config = zpool_get_config(zhp, NULL);
8783 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
8784 &oldversion) == 0);
8786 char compat[ZFS_MAXPROPLEN];
8787 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat,
8788 ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
8789 compat[0] = '\0';
8791 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
8792 assert(oldversion < version);
8794 ret = zfs_iter_root(zpool_get_handle(zhp), check_unsupp_fs, &unsupp_fs);
8795 if (ret != 0)
8796 return (ret);
8798 if (unsupp_fs) {
8799 (void) fprintf(stderr, gettext("Upgrade not performed due "
8800 "to %d unsupported filesystems (max v%d).\n"),
8801 unsupp_fs, (int)ZPL_VERSION);
8802 return (1);
8805 if (strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) {
8806 (void) fprintf(stderr, gettext("Upgrade not performed because "
8807 "'compatibility' property set to '"
8808 ZPOOL_COMPAT_LEGACY "'.\n"));
8809 return (1);
8812 ret = zpool_upgrade(zhp, version);
8813 if (ret != 0)
8814 return (ret);
8816 if (version >= SPA_VERSION_FEATURES) {
8817 (void) printf(gettext("Successfully upgraded "
8818 "'%s' from version %llu to feature flags.\n"),
8819 zpool_get_name(zhp), (u_longlong_t)oldversion);
8820 } else {
8821 (void) printf(gettext("Successfully upgraded "
8822 "'%s' from version %llu to version %llu.\n"),
8823 zpool_get_name(zhp), (u_longlong_t)oldversion,
8824 (u_longlong_t)version);
8827 return (0);
8830 static int
8831 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
8833 int i, ret, count;
8834 boolean_t firstff = B_TRUE;
8835 nvlist_t *enabled = zpool_get_features(zhp);
8837 char compat[ZFS_MAXPROPLEN];
8838 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat,
8839 ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
8840 compat[0] = '\0';
8842 boolean_t requested_features[SPA_FEATURES];
8843 if (zpool_do_load_compat(compat, requested_features) !=
8844 ZPOOL_COMPATIBILITY_OK)
8845 return (-1);
8847 count = 0;
8848 for (i = 0; i < SPA_FEATURES; i++) {
8849 const char *fname = spa_feature_table[i].fi_uname;
8850 const char *fguid = spa_feature_table[i].fi_guid;
8852 if (!spa_feature_table[i].fi_zfs_mod_supported)
8853 continue;
8855 if (!nvlist_exists(enabled, fguid) && requested_features[i]) {
8856 char *propname;
8857 verify(-1 != asprintf(&propname, "feature@%s", fname));
8858 ret = zpool_set_prop(zhp, propname,
8859 ZFS_FEATURE_ENABLED);
8860 if (ret != 0) {
8861 free(propname);
8862 return (ret);
8864 count++;
8866 if (firstff) {
8867 (void) printf(gettext("Enabled the "
8868 "following features on '%s':\n"),
8869 zpool_get_name(zhp));
8870 firstff = B_FALSE;
8872 (void) printf(gettext(" %s\n"), fname);
8873 free(propname);
8877 if (countp != NULL)
8878 *countp = count;
8879 return (0);
8882 static int
8883 upgrade_cb(zpool_handle_t *zhp, void *arg)
8885 upgrade_cbdata_t *cbp = arg;
8886 nvlist_t *config;
8887 uint64_t version;
8888 boolean_t modified_pool = B_FALSE;
8889 int ret;
8891 config = zpool_get_config(zhp, NULL);
8892 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
8893 &version) == 0);
8895 assert(SPA_VERSION_IS_SUPPORTED(version));
8897 if (version < cbp->cb_version) {
8898 cbp->cb_first = B_FALSE;
8899 ret = upgrade_version(zhp, cbp->cb_version);
8900 if (ret != 0)
8901 return (ret);
8902 modified_pool = B_TRUE;
8905 * If they did "zpool upgrade -a", then we could
8906 * be doing ioctls to different pools. We need
8907 * to log this history once to each pool, and bypass
8908 * the normal history logging that happens in main().
8910 (void) zpool_log_history(g_zfs, history_str);
8911 log_history = B_FALSE;
8914 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
8915 int count;
8916 ret = upgrade_enable_all(zhp, &count);
8917 if (ret != 0)
8918 return (ret);
8920 if (count > 0) {
8921 cbp->cb_first = B_FALSE;
8922 modified_pool = B_TRUE;
8926 if (modified_pool) {
8927 (void) printf("\n");
8928 (void) after_zpool_upgrade(zhp);
8931 return (0);
8934 static int
8935 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
8937 upgrade_cbdata_t *cbp = arg;
8938 nvlist_t *config;
8939 uint64_t version;
8941 config = zpool_get_config(zhp, NULL);
8942 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
8943 &version) == 0);
8945 assert(SPA_VERSION_IS_SUPPORTED(version));
8947 if (version < SPA_VERSION_FEATURES) {
8948 if (cbp->cb_first) {
8949 (void) printf(gettext("The following pools are "
8950 "formatted with legacy version numbers and can\n"
8951 "be upgraded to use feature flags. After "
8952 "being upgraded, these pools\nwill no "
8953 "longer be accessible by software that does not "
8954 "support feature\nflags.\n\n"
8955 "Note that setting a pool's 'compatibility' "
8956 "feature to '" ZPOOL_COMPAT_LEGACY "' will\n"
8957 "inhibit upgrades.\n\n"));
8958 (void) printf(gettext("VER POOL\n"));
8959 (void) printf(gettext("--- ------------\n"));
8960 cbp->cb_first = B_FALSE;
8963 (void) printf("%2llu %s\n", (u_longlong_t)version,
8964 zpool_get_name(zhp));
8967 return (0);
8970 static int
8971 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
8973 upgrade_cbdata_t *cbp = arg;
8974 nvlist_t *config;
8975 uint64_t version;
8977 config = zpool_get_config(zhp, NULL);
8978 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
8979 &version) == 0);
8981 if (version >= SPA_VERSION_FEATURES) {
8982 int i;
8983 boolean_t poolfirst = B_TRUE;
8984 nvlist_t *enabled = zpool_get_features(zhp);
8986 for (i = 0; i < SPA_FEATURES; i++) {
8987 const char *fguid = spa_feature_table[i].fi_guid;
8988 const char *fname = spa_feature_table[i].fi_uname;
8990 if (!spa_feature_table[i].fi_zfs_mod_supported)
8991 continue;
8993 if (!nvlist_exists(enabled, fguid)) {
8994 if (cbp->cb_first) {
8995 (void) printf(gettext("\nSome "
8996 "supported features are not "
8997 "enabled on the following pools. "
8998 "Once a\nfeature is enabled the "
8999 "pool may become incompatible with "
9000 "software\nthat does not support "
9001 "the feature. See "
9002 "zpool-features(7) for "
9003 "details.\n\n"
9004 "Note that the pool "
9005 "'compatibility' feature can be "
9006 "used to inhibit\nfeature "
9007 "upgrades.\n\n"));
9008 (void) printf(gettext("POOL "
9009 "FEATURE\n"));
9010 (void) printf(gettext("------"
9011 "---------\n"));
9012 cbp->cb_first = B_FALSE;
9015 if (poolfirst) {
9016 (void) printf(gettext("%s\n"),
9017 zpool_get_name(zhp));
9018 poolfirst = B_FALSE;
9021 (void) printf(gettext(" %s\n"), fname);
9024 * If they did "zpool upgrade -a", then we could
9025 * be doing ioctls to different pools. We need
9026 * to log this history once to each pool, and bypass
9027 * the normal history logging that happens in main().
9029 (void) zpool_log_history(g_zfs, history_str);
9030 log_history = B_FALSE;
9034 return (0);
9037 /* ARGSUSED */
9038 static int
9039 upgrade_one(zpool_handle_t *zhp, void *data)
9041 boolean_t modified_pool = B_FALSE;
9042 upgrade_cbdata_t *cbp = data;
9043 uint64_t cur_version;
9044 int ret;
9046 if (strcmp("log", zpool_get_name(zhp)) == 0) {
9047 (void) fprintf(stderr, gettext("'log' is now a reserved word\n"
9048 "Pool 'log' must be renamed using export and import"
9049 " to upgrade.\n"));
9050 return (1);
9053 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
9054 if (cur_version > cbp->cb_version) {
9055 (void) printf(gettext("Pool '%s' is already formatted "
9056 "using more current version '%llu'.\n\n"),
9057 zpool_get_name(zhp), (u_longlong_t)cur_version);
9058 return (0);
9061 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
9062 (void) printf(gettext("Pool '%s' is already formatted "
9063 "using version %llu.\n\n"), zpool_get_name(zhp),
9064 (u_longlong_t)cbp->cb_version);
9065 return (0);
9068 if (cur_version != cbp->cb_version) {
9069 modified_pool = B_TRUE;
9070 ret = upgrade_version(zhp, cbp->cb_version);
9071 if (ret != 0)
9072 return (ret);
9075 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
9076 int count = 0;
9077 ret = upgrade_enable_all(zhp, &count);
9078 if (ret != 0)
9079 return (ret);
9081 if (count != 0) {
9082 modified_pool = B_TRUE;
9083 } else if (cur_version == SPA_VERSION) {
9084 (void) printf(gettext("Pool '%s' already has all "
9085 "supported and requested features enabled.\n"),
9086 zpool_get_name(zhp));
9090 if (modified_pool) {
9091 (void) printf("\n");
9092 (void) after_zpool_upgrade(zhp);
9095 return (0);
9099 * zpool upgrade
9100 * zpool upgrade -v
9101 * zpool upgrade [-V version] <-a | pool ...>
9103 * With no arguments, display downrev'd ZFS pool available for upgrade.
9104 * Individual pools can be upgraded by specifying the pool, and '-a' will
9105 * upgrade all pools.
9108 zpool_do_upgrade(int argc, char **argv)
9110 int c;
9111 upgrade_cbdata_t cb = { 0 };
9112 int ret = 0;
9113 boolean_t showversions = B_FALSE;
9114 boolean_t upgradeall = B_FALSE;
9115 char *end;
9118 /* check options */
9119 while ((c = getopt(argc, argv, ":avV:")) != -1) {
9120 switch (c) {
9121 case 'a':
9122 upgradeall = B_TRUE;
9123 break;
9124 case 'v':
9125 showversions = B_TRUE;
9126 break;
9127 case 'V':
9128 cb.cb_version = strtoll(optarg, &end, 10);
9129 if (*end != '\0' ||
9130 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
9131 (void) fprintf(stderr,
9132 gettext("invalid version '%s'\n"), optarg);
9133 usage(B_FALSE);
9135 break;
9136 case ':':
9137 (void) fprintf(stderr, gettext("missing argument for "
9138 "'%c' option\n"), optopt);
9139 usage(B_FALSE);
9140 break;
9141 case '?':
9142 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9143 optopt);
9144 usage(B_FALSE);
9148 cb.cb_argc = argc;
9149 cb.cb_argv = argv;
9150 argc -= optind;
9151 argv += optind;
9153 if (cb.cb_version == 0) {
9154 cb.cb_version = SPA_VERSION;
9155 } else if (!upgradeall && argc == 0) {
9156 (void) fprintf(stderr, gettext("-V option is "
9157 "incompatible with other arguments\n"));
9158 usage(B_FALSE);
9161 if (showversions) {
9162 if (upgradeall || argc != 0) {
9163 (void) fprintf(stderr, gettext("-v option is "
9164 "incompatible with other arguments\n"));
9165 usage(B_FALSE);
9167 } else if (upgradeall) {
9168 if (argc != 0) {
9169 (void) fprintf(stderr, gettext("-a option should not "
9170 "be used along with a pool name\n"));
9171 usage(B_FALSE);
9175 (void) printf(gettext("This system supports ZFS pool feature "
9176 "flags.\n\n"));
9177 if (showversions) {
9178 int i;
9180 (void) printf(gettext("The following features are "
9181 "supported:\n\n"));
9182 (void) printf(gettext("FEAT DESCRIPTION\n"));
9183 (void) printf("----------------------------------------------"
9184 "---------------\n");
9185 for (i = 0; i < SPA_FEATURES; i++) {
9186 zfeature_info_t *fi = &spa_feature_table[i];
9187 if (!fi->fi_zfs_mod_supported)
9188 continue;
9189 const char *ro =
9190 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
9191 " (read-only compatible)" : "";
9193 (void) printf("%-37s%s\n", fi->fi_uname, ro);
9194 (void) printf(" %s\n", fi->fi_desc);
9196 (void) printf("\n");
9198 (void) printf(gettext("The following legacy versions are also "
9199 "supported:\n\n"));
9200 (void) printf(gettext("VER DESCRIPTION\n"));
9201 (void) printf("--- -----------------------------------------"
9202 "---------------\n");
9203 (void) printf(gettext(" 1 Initial ZFS version\n"));
9204 (void) printf(gettext(" 2 Ditto blocks "
9205 "(replicated metadata)\n"));
9206 (void) printf(gettext(" 3 Hot spares and double parity "
9207 "RAID-Z\n"));
9208 (void) printf(gettext(" 4 zpool history\n"));
9209 (void) printf(gettext(" 5 Compression using the gzip "
9210 "algorithm\n"));
9211 (void) printf(gettext(" 6 bootfs pool property\n"));
9212 (void) printf(gettext(" 7 Separate intent log devices\n"));
9213 (void) printf(gettext(" 8 Delegated administration\n"));
9214 (void) printf(gettext(" 9 refquota and refreservation "
9215 "properties\n"));
9216 (void) printf(gettext(" 10 Cache devices\n"));
9217 (void) printf(gettext(" 11 Improved scrub performance\n"));
9218 (void) printf(gettext(" 12 Snapshot properties\n"));
9219 (void) printf(gettext(" 13 snapused property\n"));
9220 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
9221 (void) printf(gettext(" 15 user/group space accounting\n"));
9222 (void) printf(gettext(" 16 stmf property support\n"));
9223 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
9224 (void) printf(gettext(" 18 Snapshot user holds\n"));
9225 (void) printf(gettext(" 19 Log device removal\n"));
9226 (void) printf(gettext(" 20 Compression using zle "
9227 "(zero-length encoding)\n"));
9228 (void) printf(gettext(" 21 Deduplication\n"));
9229 (void) printf(gettext(" 22 Received properties\n"));
9230 (void) printf(gettext(" 23 Slim ZIL\n"));
9231 (void) printf(gettext(" 24 System attributes\n"));
9232 (void) printf(gettext(" 25 Improved scrub stats\n"));
9233 (void) printf(gettext(" 26 Improved snapshot deletion "
9234 "performance\n"));
9235 (void) printf(gettext(" 27 Improved snapshot creation "
9236 "performance\n"));
9237 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
9238 (void) printf(gettext("\nFor more information on a particular "
9239 "version, including supported releases,\n"));
9240 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
9241 } else if (argc == 0 && upgradeall) {
9242 cb.cb_first = B_TRUE;
9243 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
9244 if (ret == 0 && cb.cb_first) {
9245 if (cb.cb_version == SPA_VERSION) {
9246 (void) printf(gettext("All pools are already "
9247 "formatted using feature flags.\n\n"));
9248 (void) printf(gettext("Every feature flags "
9249 "pool already has all supported and "
9250 "requested features enabled.\n"));
9251 } else {
9252 (void) printf(gettext("All pools are already "
9253 "formatted with version %llu or higher.\n"),
9254 (u_longlong_t)cb.cb_version);
9257 } else if (argc == 0) {
9258 cb.cb_first = B_TRUE;
9259 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
9260 assert(ret == 0);
9262 if (cb.cb_first) {
9263 (void) printf(gettext("All pools are formatted "
9264 "using feature flags.\n\n"));
9265 } else {
9266 (void) printf(gettext("\nUse 'zpool upgrade -v' "
9267 "for a list of available legacy versions.\n"));
9270 cb.cb_first = B_TRUE;
9271 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
9272 assert(ret == 0);
9274 if (cb.cb_first) {
9275 (void) printf(gettext("Every feature flags pool has "
9276 "all supported and requested features enabled.\n"));
9277 } else {
9278 (void) printf(gettext("\n"));
9280 } else {
9281 ret = for_each_pool(argc, argv, B_FALSE, NULL, B_FALSE,
9282 upgrade_one, &cb);
9285 return (ret);
9288 typedef struct hist_cbdata {
9289 boolean_t first;
9290 boolean_t longfmt;
9291 boolean_t internal;
9292 } hist_cbdata_t;
9294 static void
9295 print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
9297 nvlist_t **records;
9298 uint_t numrecords;
9299 int i;
9301 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
9302 &records, &numrecords) == 0);
9303 for (i = 0; i < numrecords; i++) {
9304 nvlist_t *rec = records[i];
9305 char tbuf[64] = "";
9307 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
9308 time_t tsec;
9309 struct tm t;
9311 tsec = fnvlist_lookup_uint64(records[i],
9312 ZPOOL_HIST_TIME);
9313 (void) localtime_r(&tsec, &t);
9314 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
9317 if (nvlist_exists(rec, ZPOOL_HIST_ELAPSED_NS)) {
9318 uint64_t elapsed_ns = fnvlist_lookup_int64(records[i],
9319 ZPOOL_HIST_ELAPSED_NS);
9320 (void) snprintf(tbuf + strlen(tbuf),
9321 sizeof (tbuf) - strlen(tbuf),
9322 " (%lldms)", (long long)elapsed_ns / 1000 / 1000);
9325 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
9326 (void) printf("%s %s", tbuf,
9327 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
9328 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
9329 int ievent =
9330 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
9331 if (!cb->internal)
9332 continue;
9333 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
9334 (void) printf("%s unrecognized record:\n",
9335 tbuf);
9336 dump_nvlist(rec, 4);
9337 continue;
9339 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
9340 zfs_history_event_names[ievent],
9341 (longlong_t)fnvlist_lookup_uint64(
9342 rec, ZPOOL_HIST_TXG),
9343 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
9344 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
9345 if (!cb->internal)
9346 continue;
9347 (void) printf("%s [txg:%lld] %s", tbuf,
9348 (longlong_t)fnvlist_lookup_uint64(
9349 rec, ZPOOL_HIST_TXG),
9350 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
9351 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
9352 (void) printf(" %s (%llu)",
9353 fnvlist_lookup_string(rec,
9354 ZPOOL_HIST_DSNAME),
9355 (u_longlong_t)fnvlist_lookup_uint64(rec,
9356 ZPOOL_HIST_DSID));
9358 (void) printf(" %s", fnvlist_lookup_string(rec,
9359 ZPOOL_HIST_INT_STR));
9360 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
9361 if (!cb->internal)
9362 continue;
9363 (void) printf("%s ioctl %s\n", tbuf,
9364 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
9365 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
9366 (void) printf(" input:\n");
9367 dump_nvlist(fnvlist_lookup_nvlist(rec,
9368 ZPOOL_HIST_INPUT_NVL), 8);
9370 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
9371 (void) printf(" output:\n");
9372 dump_nvlist(fnvlist_lookup_nvlist(rec,
9373 ZPOOL_HIST_OUTPUT_NVL), 8);
9375 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_SIZE)) {
9376 (void) printf(" output nvlist omitted; "
9377 "original size: %lldKB\n",
9378 (longlong_t)fnvlist_lookup_int64(rec,
9379 ZPOOL_HIST_OUTPUT_SIZE) / 1024);
9381 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
9382 (void) printf(" errno: %lld\n",
9383 (longlong_t)fnvlist_lookup_int64(rec,
9384 ZPOOL_HIST_ERRNO));
9386 } else {
9387 if (!cb->internal)
9388 continue;
9389 (void) printf("%s unrecognized record:\n", tbuf);
9390 dump_nvlist(rec, 4);
9393 if (!cb->longfmt) {
9394 (void) printf("\n");
9395 continue;
9397 (void) printf(" [");
9398 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
9399 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
9400 struct passwd *pwd = getpwuid(who);
9401 (void) printf("user %d ", (int)who);
9402 if (pwd != NULL)
9403 (void) printf("(%s) ", pwd->pw_name);
9405 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
9406 (void) printf("on %s",
9407 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
9409 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
9410 (void) printf(":%s",
9411 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
9414 (void) printf("]");
9415 (void) printf("\n");
9420 * Print out the command history for a specific pool.
9422 static int
9423 get_history_one(zpool_handle_t *zhp, void *data)
9425 nvlist_t *nvhis;
9426 int ret;
9427 hist_cbdata_t *cb = (hist_cbdata_t *)data;
9428 uint64_t off = 0;
9429 boolean_t eof = B_FALSE;
9431 cb->first = B_FALSE;
9433 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
9435 while (!eof) {
9436 if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
9437 return (ret);
9439 print_history_records(nvhis, cb);
9440 nvlist_free(nvhis);
9442 (void) printf("\n");
9444 return (ret);
9448 * zpool history <pool>
9450 * Displays the history of commands that modified pools.
9453 zpool_do_history(int argc, char **argv)
9455 hist_cbdata_t cbdata = { 0 };
9456 int ret;
9457 int c;
9459 cbdata.first = B_TRUE;
9460 /* check options */
9461 while ((c = getopt(argc, argv, "li")) != -1) {
9462 switch (c) {
9463 case 'l':
9464 cbdata.longfmt = B_TRUE;
9465 break;
9466 case 'i':
9467 cbdata.internal = B_TRUE;
9468 break;
9469 case '?':
9470 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9471 optopt);
9472 usage(B_FALSE);
9475 argc -= optind;
9476 argv += optind;
9478 ret = for_each_pool(argc, argv, B_FALSE, NULL, B_FALSE, get_history_one,
9479 &cbdata);
9481 if (argc == 0 && cbdata.first == B_TRUE) {
9482 (void) fprintf(stderr, gettext("no pools available\n"));
9483 return (0);
9486 return (ret);
9489 typedef struct ev_opts {
9490 int verbose;
9491 int scripted;
9492 int follow;
9493 int clear;
9494 char poolname[ZFS_MAX_DATASET_NAME_LEN];
9495 } ev_opts_t;
9497 static void
9498 zpool_do_events_short(nvlist_t *nvl, ev_opts_t *opts)
9500 char ctime_str[26], str[32], *ptr;
9501 int64_t *tv;
9502 uint_t n;
9504 verify(nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0);
9505 memset(str, ' ', 32);
9506 (void) ctime_r((const time_t *)&tv[0], ctime_str);
9507 (void) memcpy(str, ctime_str+4, 6); /* 'Jun 30' */
9508 (void) memcpy(str+7, ctime_str+20, 4); /* '1993' */
9509 (void) memcpy(str+12, ctime_str+11, 8); /* '21:49:08' */
9510 (void) sprintf(str+20, ".%09lld", (longlong_t)tv[1]); /* '.123456789' */
9511 if (opts->scripted)
9512 (void) printf(gettext("%s\t"), str);
9513 else
9514 (void) printf(gettext("%s "), str);
9516 verify(nvlist_lookup_string(nvl, FM_CLASS, &ptr) == 0);
9517 (void) printf(gettext("%s\n"), ptr);
9520 static void
9521 zpool_do_events_nvprint(nvlist_t *nvl, int depth)
9523 nvpair_t *nvp;
9525 for (nvp = nvlist_next_nvpair(nvl, NULL);
9526 nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) {
9528 data_type_t type = nvpair_type(nvp);
9529 const char *name = nvpair_name(nvp);
9531 boolean_t b;
9532 uint8_t i8;
9533 uint16_t i16;
9534 uint32_t i32;
9535 uint64_t i64;
9536 char *str;
9537 nvlist_t *cnv;
9539 printf(gettext("%*s%s = "), depth, "", name);
9541 switch (type) {
9542 case DATA_TYPE_BOOLEAN:
9543 printf(gettext("%s"), "1");
9544 break;
9546 case DATA_TYPE_BOOLEAN_VALUE:
9547 (void) nvpair_value_boolean_value(nvp, &b);
9548 printf(gettext("%s"), b ? "1" : "0");
9549 break;
9551 case DATA_TYPE_BYTE:
9552 (void) nvpair_value_byte(nvp, &i8);
9553 printf(gettext("0x%x"), i8);
9554 break;
9556 case DATA_TYPE_INT8:
9557 (void) nvpair_value_int8(nvp, (void *)&i8);
9558 printf(gettext("0x%x"), i8);
9559 break;
9561 case DATA_TYPE_UINT8:
9562 (void) nvpair_value_uint8(nvp, &i8);
9563 printf(gettext("0x%x"), i8);
9564 break;
9566 case DATA_TYPE_INT16:
9567 (void) nvpair_value_int16(nvp, (void *)&i16);
9568 printf(gettext("0x%x"), i16);
9569 break;
9571 case DATA_TYPE_UINT16:
9572 (void) nvpair_value_uint16(nvp, &i16);
9573 printf(gettext("0x%x"), i16);
9574 break;
9576 case DATA_TYPE_INT32:
9577 (void) nvpair_value_int32(nvp, (void *)&i32);
9578 printf(gettext("0x%x"), i32);
9579 break;
9581 case DATA_TYPE_UINT32:
9582 (void) nvpair_value_uint32(nvp, &i32);
9583 printf(gettext("0x%x"), i32);
9584 break;
9586 case DATA_TYPE_INT64:
9587 (void) nvpair_value_int64(nvp, (void *)&i64);
9588 printf(gettext("0x%llx"), (u_longlong_t)i64);
9589 break;
9591 case DATA_TYPE_UINT64:
9592 (void) nvpair_value_uint64(nvp, &i64);
9594 * translate vdev state values to readable
9595 * strings to aide zpool events consumers
9597 if (strcmp(name,
9598 FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
9599 strcmp(name,
9600 FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
9601 printf(gettext("\"%s\" (0x%llx)"),
9602 zpool_state_to_name(i64, VDEV_AUX_NONE),
9603 (u_longlong_t)i64);
9604 } else {
9605 printf(gettext("0x%llx"), (u_longlong_t)i64);
9607 break;
9609 case DATA_TYPE_HRTIME:
9610 (void) nvpair_value_hrtime(nvp, (void *)&i64);
9611 printf(gettext("0x%llx"), (u_longlong_t)i64);
9612 break;
9614 case DATA_TYPE_STRING:
9615 (void) nvpair_value_string(nvp, &str);
9616 printf(gettext("\"%s\""), str ? str : "<NULL>");
9617 break;
9619 case DATA_TYPE_NVLIST:
9620 printf(gettext("(embedded nvlist)\n"));
9621 (void) nvpair_value_nvlist(nvp, &cnv);
9622 zpool_do_events_nvprint(cnv, depth + 8);
9623 printf(gettext("%*s(end %s)"), depth, "", name);
9624 break;
9626 case DATA_TYPE_NVLIST_ARRAY: {
9627 nvlist_t **val;
9628 uint_t i, nelem;
9630 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
9631 printf(gettext("(%d embedded nvlists)\n"), nelem);
9632 for (i = 0; i < nelem; i++) {
9633 printf(gettext("%*s%s[%d] = %s\n"),
9634 depth, "", name, i, "(embedded nvlist)");
9635 zpool_do_events_nvprint(val[i], depth + 8);
9636 printf(gettext("%*s(end %s[%i])\n"),
9637 depth, "", name, i);
9639 printf(gettext("%*s(end %s)\n"), depth, "", name);
9641 break;
9643 case DATA_TYPE_INT8_ARRAY: {
9644 int8_t *val;
9645 uint_t i, nelem;
9647 (void) nvpair_value_int8_array(nvp, &val, &nelem);
9648 for (i = 0; i < nelem; i++)
9649 printf(gettext("0x%x "), val[i]);
9651 break;
9654 case DATA_TYPE_UINT8_ARRAY: {
9655 uint8_t *val;
9656 uint_t i, nelem;
9658 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
9659 for (i = 0; i < nelem; i++)
9660 printf(gettext("0x%x "), val[i]);
9662 break;
9665 case DATA_TYPE_INT16_ARRAY: {
9666 int16_t *val;
9667 uint_t i, nelem;
9669 (void) nvpair_value_int16_array(nvp, &val, &nelem);
9670 for (i = 0; i < nelem; i++)
9671 printf(gettext("0x%x "), val[i]);
9673 break;
9676 case DATA_TYPE_UINT16_ARRAY: {
9677 uint16_t *val;
9678 uint_t i, nelem;
9680 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
9681 for (i = 0; i < nelem; i++)
9682 printf(gettext("0x%x "), val[i]);
9684 break;
9687 case DATA_TYPE_INT32_ARRAY: {
9688 int32_t *val;
9689 uint_t i, nelem;
9691 (void) nvpair_value_int32_array(nvp, &val, &nelem);
9692 for (i = 0; i < nelem; i++)
9693 printf(gettext("0x%x "), val[i]);
9695 break;
9698 case DATA_TYPE_UINT32_ARRAY: {
9699 uint32_t *val;
9700 uint_t i, nelem;
9702 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
9703 for (i = 0; i < nelem; i++)
9704 printf(gettext("0x%x "), val[i]);
9706 break;
9709 case DATA_TYPE_INT64_ARRAY: {
9710 int64_t *val;
9711 uint_t i, nelem;
9713 (void) nvpair_value_int64_array(nvp, &val, &nelem);
9714 for (i = 0; i < nelem; i++)
9715 printf(gettext("0x%llx "),
9716 (u_longlong_t)val[i]);
9718 break;
9721 case DATA_TYPE_UINT64_ARRAY: {
9722 uint64_t *val;
9723 uint_t i, nelem;
9725 (void) nvpair_value_uint64_array(nvp, &val, &nelem);
9726 for (i = 0; i < nelem; i++)
9727 printf(gettext("0x%llx "),
9728 (u_longlong_t)val[i]);
9730 break;
9733 case DATA_TYPE_STRING_ARRAY: {
9734 char **str;
9735 uint_t i, nelem;
9737 (void) nvpair_value_string_array(nvp, &str, &nelem);
9738 for (i = 0; i < nelem; i++)
9739 printf(gettext("\"%s\" "),
9740 str[i] ? str[i] : "<NULL>");
9742 break;
9745 case DATA_TYPE_BOOLEAN_ARRAY:
9746 case DATA_TYPE_BYTE_ARRAY:
9747 case DATA_TYPE_DOUBLE:
9748 case DATA_TYPE_DONTCARE:
9749 case DATA_TYPE_UNKNOWN:
9750 printf(gettext("<unknown>"));
9751 break;
9754 printf(gettext("\n"));
9758 static int
9759 zpool_do_events_next(ev_opts_t *opts)
9761 nvlist_t *nvl;
9762 int zevent_fd, ret, dropped;
9763 char *pool;
9765 zevent_fd = open(ZFS_DEV, O_RDWR);
9766 VERIFY(zevent_fd >= 0);
9768 if (!opts->scripted)
9769 (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS");
9771 while (1) {
9772 ret = zpool_events_next(g_zfs, &nvl, &dropped,
9773 (opts->follow ? ZEVENT_NONE : ZEVENT_NONBLOCK), zevent_fd);
9774 if (ret || nvl == NULL)
9775 break;
9777 if (dropped > 0)
9778 (void) printf(gettext("dropped %d events\n"), dropped);
9780 if (strlen(opts->poolname) > 0 &&
9781 nvlist_lookup_string(nvl, FM_FMRI_ZFS_POOL, &pool) == 0 &&
9782 strcmp(opts->poolname, pool) != 0)
9783 continue;
9785 zpool_do_events_short(nvl, opts);
9787 if (opts->verbose) {
9788 zpool_do_events_nvprint(nvl, 8);
9789 printf(gettext("\n"));
9791 (void) fflush(stdout);
9793 nvlist_free(nvl);
9796 VERIFY(0 == close(zevent_fd));
9798 return (ret);
9801 static int
9802 zpool_do_events_clear(ev_opts_t *opts)
9804 int count, ret;
9806 ret = zpool_events_clear(g_zfs, &count);
9807 if (!ret)
9808 (void) printf(gettext("cleared %d events\n"), count);
9810 return (ret);
9814 * zpool events [-vHf [pool] | -c]
9816 * Displays events logs by ZFS.
9819 zpool_do_events(int argc, char **argv)
9821 ev_opts_t opts = { 0 };
9822 int ret;
9823 int c;
9825 /* check options */
9826 while ((c = getopt(argc, argv, "vHfc")) != -1) {
9827 switch (c) {
9828 case 'v':
9829 opts.verbose = 1;
9830 break;
9831 case 'H':
9832 opts.scripted = 1;
9833 break;
9834 case 'f':
9835 opts.follow = 1;
9836 break;
9837 case 'c':
9838 opts.clear = 1;
9839 break;
9840 case '?':
9841 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9842 optopt);
9843 usage(B_FALSE);
9846 argc -= optind;
9847 argv += optind;
9849 if (argc > 1) {
9850 (void) fprintf(stderr, gettext("too many arguments\n"));
9851 usage(B_FALSE);
9852 } else if (argc == 1) {
9853 (void) strlcpy(opts.poolname, argv[0], sizeof (opts.poolname));
9854 if (!zfs_name_valid(opts.poolname, ZFS_TYPE_POOL)) {
9855 (void) fprintf(stderr,
9856 gettext("invalid pool name '%s'\n"), opts.poolname);
9857 usage(B_FALSE);
9861 if ((argc == 1 || opts.verbose || opts.scripted || opts.follow) &&
9862 opts.clear) {
9863 (void) fprintf(stderr,
9864 gettext("invalid options combined with -c\n"));
9865 usage(B_FALSE);
9868 if (opts.clear)
9869 ret = zpool_do_events_clear(&opts);
9870 else
9871 ret = zpool_do_events_next(&opts);
9873 return (ret);
9876 static int
9877 get_callback(zpool_handle_t *zhp, void *data)
9879 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
9880 char value[MAXNAMELEN];
9881 zprop_source_t srctype;
9882 zprop_list_t *pl;
9884 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
9887 * Skip the special fake placeholder. This will also skip
9888 * over the name property when 'all' is specified.
9890 if (pl->pl_prop == ZPOOL_PROP_NAME &&
9891 pl == cbp->cb_proplist)
9892 continue;
9894 if (pl->pl_prop == ZPROP_INVAL &&
9895 (zpool_prop_feature(pl->pl_user_prop) ||
9896 zpool_prop_unsupported(pl->pl_user_prop))) {
9897 srctype = ZPROP_SRC_LOCAL;
9899 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
9900 value, sizeof (value)) == 0) {
9901 zprop_print_one_property(zpool_get_name(zhp),
9902 cbp, pl->pl_user_prop, value, srctype,
9903 NULL, NULL);
9905 } else {
9906 if (zpool_get_prop(zhp, pl->pl_prop, value,
9907 sizeof (value), &srctype, cbp->cb_literal) != 0)
9908 continue;
9910 zprop_print_one_property(zpool_get_name(zhp), cbp,
9911 zpool_prop_to_name(pl->pl_prop), value, srctype,
9912 NULL, NULL);
9915 return (0);
9919 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
9921 * -H Scripted mode. Don't display headers, and separate properties
9922 * by a single tab.
9923 * -o List of columns to display. Defaults to
9924 * "name,property,value,source".
9925 * -p Display values in parsable (exact) format.
9927 * Get properties of pools in the system. Output space statistics
9928 * for each one as well as other attributes.
9931 zpool_do_get(int argc, char **argv)
9933 zprop_get_cbdata_t cb = { 0 };
9934 zprop_list_t fake_name = { 0 };
9935 int ret;
9936 int c, i;
9937 char *value;
9939 cb.cb_first = B_TRUE;
9942 * Set up default columns and sources.
9944 cb.cb_sources = ZPROP_SRC_ALL;
9945 cb.cb_columns[0] = GET_COL_NAME;
9946 cb.cb_columns[1] = GET_COL_PROPERTY;
9947 cb.cb_columns[2] = GET_COL_VALUE;
9948 cb.cb_columns[3] = GET_COL_SOURCE;
9949 cb.cb_type = ZFS_TYPE_POOL;
9951 /* check options */
9952 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
9953 switch (c) {
9954 case 'p':
9955 cb.cb_literal = B_TRUE;
9956 break;
9957 case 'H':
9958 cb.cb_scripted = B_TRUE;
9959 break;
9960 case 'o':
9961 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
9962 i = 0;
9963 while (*optarg != '\0') {
9964 static char *col_subopts[] =
9965 { "name", "property", "value", "source",
9966 "all", NULL };
9968 if (i == ZFS_GET_NCOLS) {
9969 (void) fprintf(stderr, gettext("too "
9970 "many fields given to -o "
9971 "option\n"));
9972 usage(B_FALSE);
9975 switch (getsubopt(&optarg, col_subopts,
9976 &value)) {
9977 case 0:
9978 cb.cb_columns[i++] = GET_COL_NAME;
9979 break;
9980 case 1:
9981 cb.cb_columns[i++] = GET_COL_PROPERTY;
9982 break;
9983 case 2:
9984 cb.cb_columns[i++] = GET_COL_VALUE;
9985 break;
9986 case 3:
9987 cb.cb_columns[i++] = GET_COL_SOURCE;
9988 break;
9989 case 4:
9990 if (i > 0) {
9991 (void) fprintf(stderr,
9992 gettext("\"all\" conflicts "
9993 "with specific fields "
9994 "given to -o option\n"));
9995 usage(B_FALSE);
9997 cb.cb_columns[0] = GET_COL_NAME;
9998 cb.cb_columns[1] = GET_COL_PROPERTY;
9999 cb.cb_columns[2] = GET_COL_VALUE;
10000 cb.cb_columns[3] = GET_COL_SOURCE;
10001 i = ZFS_GET_NCOLS;
10002 break;
10003 default:
10004 (void) fprintf(stderr,
10005 gettext("invalid column name "
10006 "'%s'\n"), value);
10007 usage(B_FALSE);
10010 break;
10011 case '?':
10012 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
10013 optopt);
10014 usage(B_FALSE);
10018 argc -= optind;
10019 argv += optind;
10021 if (argc < 1) {
10022 (void) fprintf(stderr, gettext("missing property "
10023 "argument\n"));
10024 usage(B_FALSE);
10027 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
10028 ZFS_TYPE_POOL) != 0)
10029 usage(B_FALSE);
10031 argc--;
10032 argv++;
10034 if (cb.cb_proplist != NULL) {
10035 fake_name.pl_prop = ZPOOL_PROP_NAME;
10036 fake_name.pl_width = strlen(gettext("NAME"));
10037 fake_name.pl_next = cb.cb_proplist;
10038 cb.cb_proplist = &fake_name;
10041 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, cb.cb_literal,
10042 get_callback, &cb);
10044 if (cb.cb_proplist == &fake_name)
10045 zprop_free_list(fake_name.pl_next);
10046 else
10047 zprop_free_list(cb.cb_proplist);
10049 return (ret);
10052 typedef struct set_cbdata {
10053 char *cb_propname;
10054 char *cb_value;
10055 boolean_t cb_any_successful;
10056 } set_cbdata_t;
10058 static int
10059 set_callback(zpool_handle_t *zhp, void *data)
10061 int error;
10062 set_cbdata_t *cb = (set_cbdata_t *)data;
10064 /* Check if we have out-of-bounds features */
10065 if (strcmp(cb->cb_propname, ZPOOL_CONFIG_COMPATIBILITY) == 0) {
10066 boolean_t features[SPA_FEATURES];
10067 if (zpool_do_load_compat(cb->cb_value, features) !=
10068 ZPOOL_COMPATIBILITY_OK)
10069 return (-1);
10071 nvlist_t *enabled = zpool_get_features(zhp);
10072 spa_feature_t i;
10073 for (i = 0; i < SPA_FEATURES; i++) {
10074 const char *fguid = spa_feature_table[i].fi_guid;
10075 if (nvlist_exists(enabled, fguid) && !features[i])
10076 break;
10078 if (i < SPA_FEATURES)
10079 (void) fprintf(stderr, gettext("Warning: one or "
10080 "more features already enabled on pool '%s'\n"
10081 "are not present in this compatibility set.\n"),
10082 zpool_get_name(zhp));
10085 /* if we're setting a feature, check it's in compatibility set */
10086 if (zpool_prop_feature(cb->cb_propname) &&
10087 strcmp(cb->cb_value, ZFS_FEATURE_ENABLED) == 0) {
10088 char *fname = strchr(cb->cb_propname, '@') + 1;
10089 spa_feature_t f;
10091 if (zfeature_lookup_name(fname, &f) == 0) {
10092 char compat[ZFS_MAXPROPLEN];
10093 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY,
10094 compat, ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
10095 compat[0] = '\0';
10097 boolean_t features[SPA_FEATURES];
10098 if (zpool_do_load_compat(compat, features) !=
10099 ZPOOL_COMPATIBILITY_OK) {
10100 (void) fprintf(stderr, gettext("Error: "
10101 "cannot enable feature '%s' on pool '%s'\n"
10102 "because the pool's 'compatibility' "
10103 "property cannot be parsed.\n"),
10104 fname, zpool_get_name(zhp));
10105 return (-1);
10108 if (!features[f]) {
10109 (void) fprintf(stderr, gettext("Error: "
10110 "cannot enable feature '%s' on pool '%s'\n"
10111 "as it is not specified in this pool's "
10112 "current compatibility set.\n"
10113 "Consider setting 'compatibility' to a "
10114 "less restrictive set, or to 'off'.\n"),
10115 fname, zpool_get_name(zhp));
10116 return (-1);
10121 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
10123 if (!error)
10124 cb->cb_any_successful = B_TRUE;
10126 return (error);
10130 zpool_do_set(int argc, char **argv)
10132 set_cbdata_t cb = { 0 };
10133 int error;
10135 if (argc > 1 && argv[1][0] == '-') {
10136 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
10137 argv[1][1]);
10138 usage(B_FALSE);
10141 if (argc < 2) {
10142 (void) fprintf(stderr, gettext("missing property=value "
10143 "argument\n"));
10144 usage(B_FALSE);
10147 if (argc < 3) {
10148 (void) fprintf(stderr, gettext("missing pool name\n"));
10149 usage(B_FALSE);
10152 if (argc > 3) {
10153 (void) fprintf(stderr, gettext("too many pool names\n"));
10154 usage(B_FALSE);
10157 cb.cb_propname = argv[1];
10158 cb.cb_value = strchr(cb.cb_propname, '=');
10159 if (cb.cb_value == NULL) {
10160 (void) fprintf(stderr, gettext("missing value in "
10161 "property=value argument\n"));
10162 usage(B_FALSE);
10165 *(cb.cb_value) = '\0';
10166 cb.cb_value++;
10168 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, B_FALSE,
10169 set_callback, &cb);
10171 return (error);
10174 /* Add up the total number of bytes left to initialize/trim across all vdevs */
10175 static uint64_t
10176 vdev_activity_remaining(nvlist_t *nv, zpool_wait_activity_t activity)
10178 uint64_t bytes_remaining;
10179 nvlist_t **child;
10180 uint_t c, children;
10181 vdev_stat_t *vs;
10183 assert(activity == ZPOOL_WAIT_INITIALIZE ||
10184 activity == ZPOOL_WAIT_TRIM);
10186 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
10187 (uint64_t **)&vs, &c) == 0);
10189 if (activity == ZPOOL_WAIT_INITIALIZE &&
10190 vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE)
10191 bytes_remaining = vs->vs_initialize_bytes_est -
10192 vs->vs_initialize_bytes_done;
10193 else if (activity == ZPOOL_WAIT_TRIM &&
10194 vs->vs_trim_state == VDEV_TRIM_ACTIVE)
10195 bytes_remaining = vs->vs_trim_bytes_est -
10196 vs->vs_trim_bytes_done;
10197 else
10198 bytes_remaining = 0;
10200 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
10201 &child, &children) != 0)
10202 children = 0;
10204 for (c = 0; c < children; c++)
10205 bytes_remaining += vdev_activity_remaining(child[c], activity);
10207 return (bytes_remaining);
10210 /* Add up the total number of bytes left to rebuild across top-level vdevs */
10211 static uint64_t
10212 vdev_activity_top_remaining(nvlist_t *nv)
10214 uint64_t bytes_remaining = 0;
10215 nvlist_t **child;
10216 uint_t children;
10217 int error;
10219 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
10220 &child, &children) != 0)
10221 children = 0;
10223 for (uint_t c = 0; c < children; c++) {
10224 vdev_rebuild_stat_t *vrs;
10225 uint_t i;
10227 error = nvlist_lookup_uint64_array(child[c],
10228 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i);
10229 if (error == 0) {
10230 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
10231 bytes_remaining += (vrs->vrs_bytes_est -
10232 vrs->vrs_bytes_rebuilt);
10237 return (bytes_remaining);
10240 /* Whether any vdevs are 'spare' or 'replacing' vdevs */
10241 static boolean_t
10242 vdev_any_spare_replacing(nvlist_t *nv)
10244 nvlist_t **child;
10245 uint_t c, children;
10246 char *vdev_type;
10248 (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &vdev_type);
10250 if (strcmp(vdev_type, VDEV_TYPE_REPLACING) == 0 ||
10251 strcmp(vdev_type, VDEV_TYPE_SPARE) == 0 ||
10252 strcmp(vdev_type, VDEV_TYPE_DRAID_SPARE) == 0) {
10253 return (B_TRUE);
10256 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
10257 &child, &children) != 0)
10258 children = 0;
10260 for (c = 0; c < children; c++) {
10261 if (vdev_any_spare_replacing(child[c]))
10262 return (B_TRUE);
10265 return (B_FALSE);
10268 typedef struct wait_data {
10269 char *wd_poolname;
10270 boolean_t wd_scripted;
10271 boolean_t wd_exact;
10272 boolean_t wd_headers_once;
10273 boolean_t wd_should_exit;
10274 /* Which activities to wait for */
10275 boolean_t wd_enabled[ZPOOL_WAIT_NUM_ACTIVITIES];
10276 float wd_interval;
10277 pthread_cond_t wd_cv;
10278 pthread_mutex_t wd_mutex;
10279 } wait_data_t;
10282 * Print to stdout a single line, containing one column for each activity that
10283 * we are waiting for specifying how many bytes of work are left for that
10284 * activity.
10286 static void
10287 print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
10289 nvlist_t *config, *nvroot;
10290 uint_t c;
10291 int i;
10292 pool_checkpoint_stat_t *pcs = NULL;
10293 pool_scan_stat_t *pss = NULL;
10294 pool_removal_stat_t *prs = NULL;
10295 char *headers[] = {"DISCARD", "FREE", "INITIALIZE", "REPLACE",
10296 "REMOVE", "RESILVER", "SCRUB", "TRIM"};
10297 int col_widths[ZPOOL_WAIT_NUM_ACTIVITIES];
10299 /* Calculate the width of each column */
10300 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10302 * Make sure we have enough space in the col for pretty-printed
10303 * numbers and for the column header, and then leave a couple
10304 * spaces between cols for readability.
10306 col_widths[i] = MAX(strlen(headers[i]), 6) + 2;
10309 /* Print header if appropriate */
10310 int term_height = terminal_height();
10311 boolean_t reprint_header = (!wd->wd_headers_once && term_height > 0 &&
10312 row % (term_height-1) == 0);
10313 if (!wd->wd_scripted && (row == 0 || reprint_header)) {
10314 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10315 if (wd->wd_enabled[i])
10316 (void) printf("%*s", col_widths[i], headers[i]);
10318 (void) printf("\n");
10321 /* Bytes of work remaining in each activity */
10322 int64_t bytes_rem[ZPOOL_WAIT_NUM_ACTIVITIES] = {0};
10324 bytes_rem[ZPOOL_WAIT_FREE] =
10325 zpool_get_prop_int(zhp, ZPOOL_PROP_FREEING, NULL);
10327 config = zpool_get_config(zhp, NULL);
10328 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
10330 (void) nvlist_lookup_uint64_array(nvroot,
10331 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
10332 if (pcs != NULL && pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
10333 bytes_rem[ZPOOL_WAIT_CKPT_DISCARD] = pcs->pcs_space;
10335 (void) nvlist_lookup_uint64_array(nvroot,
10336 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
10337 if (prs != NULL && prs->prs_state == DSS_SCANNING)
10338 bytes_rem[ZPOOL_WAIT_REMOVE] = prs->prs_to_copy -
10339 prs->prs_copied;
10341 (void) nvlist_lookup_uint64_array(nvroot,
10342 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&pss, &c);
10343 if (pss != NULL && pss->pss_state == DSS_SCANNING &&
10344 pss->pss_pass_scrub_pause == 0) {
10345 int64_t rem = pss->pss_to_examine - pss->pss_issued;
10346 if (pss->pss_func == POOL_SCAN_SCRUB)
10347 bytes_rem[ZPOOL_WAIT_SCRUB] = rem;
10348 else
10349 bytes_rem[ZPOOL_WAIT_RESILVER] = rem;
10350 } else if (check_rebuilding(nvroot, NULL)) {
10351 bytes_rem[ZPOOL_WAIT_RESILVER] =
10352 vdev_activity_top_remaining(nvroot);
10355 bytes_rem[ZPOOL_WAIT_INITIALIZE] =
10356 vdev_activity_remaining(nvroot, ZPOOL_WAIT_INITIALIZE);
10357 bytes_rem[ZPOOL_WAIT_TRIM] =
10358 vdev_activity_remaining(nvroot, ZPOOL_WAIT_TRIM);
10361 * A replace finishes after resilvering finishes, so the amount of work
10362 * left for a replace is the same as for resilvering.
10364 * It isn't quite correct to say that if we have any 'spare' or
10365 * 'replacing' vdevs and a resilver is happening, then a replace is in
10366 * progress, like we do here. When a hot spare is used, the faulted vdev
10367 * is not removed after the hot spare is resilvered, so parent 'spare'
10368 * vdev is not removed either. So we could have a 'spare' vdev, but be
10369 * resilvering for a different reason. However, we use it as a heuristic
10370 * because we don't have access to the DTLs, which could tell us whether
10371 * or not we have really finished resilvering a hot spare.
10373 if (vdev_any_spare_replacing(nvroot))
10374 bytes_rem[ZPOOL_WAIT_REPLACE] = bytes_rem[ZPOOL_WAIT_RESILVER];
10376 if (timestamp_fmt != NODATE)
10377 print_timestamp(timestamp_fmt);
10379 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10380 char buf[64];
10381 if (!wd->wd_enabled[i])
10382 continue;
10384 if (wd->wd_exact)
10385 (void) snprintf(buf, sizeof (buf), "%" PRIi64,
10386 bytes_rem[i]);
10387 else
10388 zfs_nicenum(bytes_rem[i], buf, sizeof (buf));
10390 if (wd->wd_scripted)
10391 (void) printf(i == 0 ? "%s" : "\t%s", buf);
10392 else
10393 (void) printf(" %*s", col_widths[i] - 1, buf);
10395 (void) printf("\n");
10396 (void) fflush(stdout);
10399 static void *
10400 wait_status_thread(void *arg)
10402 wait_data_t *wd = (wait_data_t *)arg;
10403 zpool_handle_t *zhp;
10405 if ((zhp = zpool_open(g_zfs, wd->wd_poolname)) == NULL)
10406 return (void *)(1);
10408 for (int row = 0; ; row++) {
10409 boolean_t missing;
10410 struct timespec timeout;
10411 int ret = 0;
10412 (void) clock_gettime(CLOCK_REALTIME, &timeout);
10414 if (zpool_refresh_stats(zhp, &missing) != 0 || missing ||
10415 zpool_props_refresh(zhp) != 0) {
10416 zpool_close(zhp);
10417 return (void *)(uintptr_t)(missing ? 0 : 1);
10420 print_wait_status_row(wd, zhp, row);
10422 timeout.tv_sec += floor(wd->wd_interval);
10423 long nanos = timeout.tv_nsec +
10424 (wd->wd_interval - floor(wd->wd_interval)) * NANOSEC;
10425 if (nanos >= NANOSEC) {
10426 timeout.tv_sec++;
10427 timeout.tv_nsec = nanos - NANOSEC;
10428 } else {
10429 timeout.tv_nsec = nanos;
10431 pthread_mutex_lock(&wd->wd_mutex);
10432 if (!wd->wd_should_exit)
10433 ret = pthread_cond_timedwait(&wd->wd_cv, &wd->wd_mutex,
10434 &timeout);
10435 pthread_mutex_unlock(&wd->wd_mutex);
10436 if (ret == 0) {
10437 break; /* signaled by main thread */
10438 } else if (ret != ETIMEDOUT) {
10439 (void) fprintf(stderr, gettext("pthread_cond_timedwait "
10440 "failed: %s\n"), strerror(ret));
10441 zpool_close(zhp);
10442 return (void *)(uintptr_t)(1);
10446 zpool_close(zhp);
10447 return (void *)(0);
10451 zpool_do_wait(int argc, char **argv)
10453 boolean_t verbose = B_FALSE;
10454 int c;
10455 char *value;
10456 int i;
10457 unsigned long count;
10458 pthread_t status_thr;
10459 int error = 0;
10460 zpool_handle_t *zhp;
10462 wait_data_t wd;
10463 wd.wd_scripted = B_FALSE;
10464 wd.wd_exact = B_FALSE;
10465 wd.wd_headers_once = B_FALSE;
10466 wd.wd_should_exit = B_FALSE;
10468 pthread_mutex_init(&wd.wd_mutex, NULL);
10469 pthread_cond_init(&wd.wd_cv, NULL);
10471 /* By default, wait for all types of activity. */
10472 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++)
10473 wd.wd_enabled[i] = B_TRUE;
10475 while ((c = getopt(argc, argv, "HpT:t:")) != -1) {
10476 switch (c) {
10477 case 'H':
10478 wd.wd_scripted = B_TRUE;
10479 break;
10480 case 'n':
10481 wd.wd_headers_once = B_TRUE;
10482 break;
10483 case 'p':
10484 wd.wd_exact = B_TRUE;
10485 break;
10486 case 'T':
10487 get_timestamp_arg(*optarg);
10488 break;
10489 case 't':
10491 static char *col_subopts[] = { "discard", "free",
10492 "initialize", "replace", "remove", "resilver",
10493 "scrub", "trim", NULL };
10495 /* Reset activities array */
10496 bzero(&wd.wd_enabled, sizeof (wd.wd_enabled));
10497 while (*optarg != '\0') {
10498 int activity = getsubopt(&optarg, col_subopts,
10499 &value);
10501 if (activity < 0) {
10502 (void) fprintf(stderr,
10503 gettext("invalid activity '%s'\n"),
10504 value);
10505 usage(B_FALSE);
10508 wd.wd_enabled[activity] = B_TRUE;
10510 break;
10512 case '?':
10513 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
10514 optopt);
10515 usage(B_FALSE);
10519 argc -= optind;
10520 argv += optind;
10522 get_interval_count(&argc, argv, &wd.wd_interval, &count);
10523 if (count != 0) {
10524 /* This subcmd only accepts an interval, not a count */
10525 (void) fprintf(stderr, gettext("too many arguments\n"));
10526 usage(B_FALSE);
10529 if (wd.wd_interval != 0)
10530 verbose = B_TRUE;
10532 if (argc < 1) {
10533 (void) fprintf(stderr, gettext("missing 'pool' argument\n"));
10534 usage(B_FALSE);
10536 if (argc > 1) {
10537 (void) fprintf(stderr, gettext("too many arguments\n"));
10538 usage(B_FALSE);
10541 wd.wd_poolname = argv[0];
10543 if ((zhp = zpool_open(g_zfs, wd.wd_poolname)) == NULL)
10544 return (1);
10546 if (verbose) {
10548 * We use a separate thread for printing status updates because
10549 * the main thread will call lzc_wait(), which blocks as long
10550 * as an activity is in progress, which can be a long time.
10552 if (pthread_create(&status_thr, NULL, wait_status_thread, &wd)
10553 != 0) {
10554 (void) fprintf(stderr, gettext("failed to create status"
10555 "thread: %s\n"), strerror(errno));
10556 zpool_close(zhp);
10557 return (1);
10562 * Loop over all activities that we are supposed to wait for until none
10563 * of them are in progress. Note that this means we can end up waiting
10564 * for more activities to complete than just those that were in progress
10565 * when we began waiting; if an activity we are interested in begins
10566 * while we are waiting for another activity, we will wait for both to
10567 * complete before exiting.
10569 for (;;) {
10570 boolean_t missing = B_FALSE;
10571 boolean_t any_waited = B_FALSE;
10573 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10574 boolean_t waited;
10576 if (!wd.wd_enabled[i])
10577 continue;
10579 error = zpool_wait_status(zhp, i, &missing, &waited);
10580 if (error != 0 || missing)
10581 break;
10583 any_waited = (any_waited || waited);
10586 if (error != 0 || missing || !any_waited)
10587 break;
10590 zpool_close(zhp);
10592 if (verbose) {
10593 uintptr_t status;
10594 pthread_mutex_lock(&wd.wd_mutex);
10595 wd.wd_should_exit = B_TRUE;
10596 pthread_cond_signal(&wd.wd_cv);
10597 pthread_mutex_unlock(&wd.wd_mutex);
10598 (void) pthread_join(status_thr, (void *)&status);
10599 if (status != 0)
10600 error = status;
10603 pthread_mutex_destroy(&wd.wd_mutex);
10604 pthread_cond_destroy(&wd.wd_cv);
10605 return (error);
10608 static int
10609 find_command_idx(char *command, int *idx)
10611 int i;
10613 for (i = 0; i < NCOMMAND; i++) {
10614 if (command_table[i].name == NULL)
10615 continue;
10617 if (strcmp(command, command_table[i].name) == 0) {
10618 *idx = i;
10619 return (0);
10622 return (1);
10626 * Display version message
10628 static int
10629 zpool_do_version(int argc, char **argv)
10631 if (zfs_version_print() == -1)
10632 return (1);
10634 return (0);
10638 * Do zpool_load_compat() and print error message on failure
10640 static zpool_compat_status_t
10641 zpool_do_load_compat(const char *compat, boolean_t *list)
10643 char report[1024];
10645 zpool_compat_status_t ret;
10647 ret = zpool_load_compat(compat, list, report, 1024);
10648 switch (ret) {
10650 case ZPOOL_COMPATIBILITY_OK:
10651 break;
10653 case ZPOOL_COMPATIBILITY_NOFILES:
10654 case ZPOOL_COMPATIBILITY_BADFILE:
10655 case ZPOOL_COMPATIBILITY_BADTOKEN:
10656 (void) fprintf(stderr, "Error: %s\n", report);
10657 break;
10659 case ZPOOL_COMPATIBILITY_WARNTOKEN:
10660 (void) fprintf(stderr, "Warning: %s\n", report);
10661 ret = ZPOOL_COMPATIBILITY_OK;
10662 break;
10664 return (ret);
10668 main(int argc, char **argv)
10670 int ret = 0;
10671 int i = 0;
10672 char *cmdname;
10673 char **newargv;
10675 (void) setlocale(LC_ALL, "");
10676 (void) setlocale(LC_NUMERIC, "C");
10677 (void) textdomain(TEXT_DOMAIN);
10678 srand(time(NULL));
10680 opterr = 0;
10683 * Make sure the user has specified some command.
10685 if (argc < 2) {
10686 (void) fprintf(stderr, gettext("missing command\n"));
10687 usage(B_FALSE);
10690 cmdname = argv[1];
10693 * Special case '-?'
10695 if ((strcmp(cmdname, "-?") == 0) || strcmp(cmdname, "--help") == 0)
10696 usage(B_TRUE);
10699 * Special case '-V|--version'
10701 if ((strcmp(cmdname, "-V") == 0) || (strcmp(cmdname, "--version") == 0))
10702 return (zpool_do_version(argc, argv));
10704 if ((g_zfs = libzfs_init()) == NULL) {
10705 (void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
10706 return (1);
10709 libzfs_print_on_error(g_zfs, B_TRUE);
10711 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
10714 * Many commands modify input strings for string parsing reasons.
10715 * We create a copy to protect the original argv.
10717 newargv = malloc((argc + 1) * sizeof (newargv[0]));
10718 for (i = 0; i < argc; i++)
10719 newargv[i] = strdup(argv[i]);
10720 newargv[argc] = NULL;
10723 * Run the appropriate command.
10725 if (find_command_idx(cmdname, &i) == 0) {
10726 current_command = &command_table[i];
10727 ret = command_table[i].func(argc - 1, newargv + 1);
10728 } else if (strchr(cmdname, '=')) {
10729 verify(find_command_idx("set", &i) == 0);
10730 current_command = &command_table[i];
10731 ret = command_table[i].func(argc, newargv);
10732 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
10734 * 'freeze' is a vile debugging abomination, so we treat
10735 * it as such.
10737 zfs_cmd_t zc = {"\0"};
10739 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
10740 ret = zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc);
10741 if (ret != 0) {
10742 (void) fprintf(stderr,
10743 gettext("failed to freeze pool: %d\n"), errno);
10744 ret = 1;
10747 log_history = 0;
10748 } else {
10749 (void) fprintf(stderr, gettext("unrecognized "
10750 "command '%s'\n"), cmdname);
10751 usage(B_FALSE);
10752 ret = 1;
10755 for (i = 0; i < argc; i++)
10756 free(newargv[i]);
10757 free(newargv);
10759 if (ret == 0 && log_history)
10760 (void) zpool_log_history(g_zfs, history_str);
10762 libzfs_fini(g_zfs);
10765 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
10766 * for the purposes of running ::findleaks.
10768 if (getenv("ZFS_ABORT") != NULL) {
10769 (void) printf("dumping core by request\n");
10770 abort();
10773 return (ret);