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