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