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