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