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