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