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