xref: /illumos-gate/usr/src/cmd/zpool/zpool_main.c (revision f56c1286e5113aa46bd6e723da14d30c123153f2)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <assert.h>
30 #include <ctype.h>
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <libgen.h>
35 #include <libintl.h>
36 #include <libuutil.h>
37 #include <locale.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <priv.h>
44 
45 #include <sys/stat.h>
46 
47 #include <libzfs.h>
48 
49 #include "zpool_util.h"
50 
51 static int zpool_do_create(int, char **);
52 static int zpool_do_destroy(int, char **);
53 
54 static int zpool_do_add(int, char **);
55 
56 static int zpool_do_list(int, char **);
57 static int zpool_do_iostat(int, char **);
58 static int zpool_do_status(int, char **);
59 
60 static int zpool_do_online(int, char **);
61 static int zpool_do_offline(int, char **);
62 
63 static int zpool_do_attach(int, char **);
64 static int zpool_do_detach(int, char **);
65 static int zpool_do_replace(int, char **);
66 
67 static int zpool_do_scrub(int, char **);
68 
69 static int zpool_do_import(int, char **);
70 static int zpool_do_export(int, char **);
71 
72 /*
73  * These libumem hooks provide a reasonable set of defaults for the allocator's
74  * debugging facilities.
75  */
76 const char *
77 _umem_debug_init()
78 {
79 	return ("default,verbose"); /* $UMEM_DEBUG setting */
80 }
81 
82 const char *
83 _umem_logging_init(void)
84 {
85 	return ("fail,contents"); /* $UMEM_LOGGING setting */
86 }
87 
88 typedef struct zpool_command {
89 	const char	*name;
90 	int		(*func)(int, char **);
91 	const char	*usage;
92 } zpool_command_t;
93 
94 /*
95  * Master command table.  Each ZFS command has a name, associated function, and
96  * usage message.  These commands are organized according to how they are
97  * displayed in the usage message.  An empty command (one with a NULL name)
98  * indicates an empty line in the generic usage message.
99  */
100 static zpool_command_t command_table[] = {
101 	{ "create",	zpool_do_create,
102 	    "\tcreate  [-fn] [-R root] [-m mountpoint] <pool> <vdev> ...\n" },
103 	{ "destroy",	zpool_do_destroy,
104 	    "\tdestroy [-f] <pool>\n"					},
105 
106 
107 	{ NULL },
108 
109 	{ "add",	zpool_do_add,
110 	    "\tadd [-fn] <pool> <vdev> ...\n"				},
111 
112 	{ NULL },
113 
114 	{ "list",	zpool_do_list,
115 	    "\tlist [-H] [-o field[,field]*] [pool] ...\n"		},
116 	{ "iostat",	zpool_do_iostat,
117 	    "\tiostat [-v] [pool] ... [interval [count]]\n"		},
118 	{ "status",	zpool_do_status,
119 	    "\tstatus [-vx] [pool] ...\n"				},
120 
121 	{ NULL },
122 
123 	{ "online",	zpool_do_online,
124 	    "\tonline <pool> <device>\n"				},
125 	{ "offline",	zpool_do_offline,
126 	    "\toffline <pool> <device>\n"				},
127 
128 	{ NULL },
129 
130 	{ "attach",	zpool_do_attach,
131 	    "\tattach [-f] <pool> <device> <new_device>\n"		},
132 	{ "detach",	zpool_do_detach,
133 	    "\tdetach <pool> <device>\n"				},
134 	{ "replace",	zpool_do_replace,
135 	    "\treplace [-f] <pool> <device> [new_device]\n"		},
136 
137 	{ NULL },
138 
139 	{ "scrub",	zpool_do_scrub,
140 	    "\tscrub [-s] <pool> ...\n"					},
141 
142 	{ NULL },
143 
144 	{ "import",	zpool_do_import,
145 	    "\timport [-d dir]\n"
146 	    "\timport [-d dir] [-f] [-o opts] [-R root] -a\n"
147 	    "\timport [-d dir] [-f] [-o opts] [-R root ]<pool | id> "
148 	    "[newpool]\n"						},
149 	{ "export",	zpool_do_export,
150 	    "\texport [-f] <pool> ...\n"				},
151 
152 	{ NULL }
153 };
154 
155 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
156 
157 zpool_command_t *current_command;
158 
159 /*
160  * Fields available for 'zpool list'.
161  */
162 typedef enum {
163 	ZPOOL_FIELD_NAME,
164 	ZPOOL_FIELD_SIZE,
165 	ZPOOL_FIELD_USED,
166 	ZPOOL_FIELD_AVAILABLE,
167 	ZPOOL_FIELD_CAPACITY,
168 	ZPOOL_FIELD_HEALTH,
169 	ZPOOL_FIELD_ROOT
170 } zpool_field_t;
171 
172 #define	MAX_FIELDS	10
173 
174 typedef struct column_def {
175 	const char	*cd_title;
176 	size_t		cd_width;
177 	enum {
178 		left_justify,
179 		right_justify
180 	}		cd_justify;
181 } column_def_t;
182 
183 static column_def_t column_table[] = {
184 	{ "NAME",	20,	left_justify	},
185 	{ "SIZE",	6,	right_justify	},
186 	{ "USED",	6,	right_justify	},
187 	{ "AVAIL",	6,	right_justify	},
188 	{ "CAP",	5,	right_justify	},
189 	{ "HEALTH",	9,	left_justify	},
190 	{ "ALTROOT",	15,	left_justify	}
191 };
192 
193 static char *column_subopts[] = {
194 	"name",
195 	"size",
196 	"used",
197 	"available",
198 	"capacity",
199 	"health",
200 	"root",
201 	NULL
202 };
203 
204 /*
205  * Display usage message.  If we're inside a command, display only the usage for
206  * that command.  Otherwise, iterate over the entire command table and display
207  * a complete usage message.
208  */
209 void
210 usage(int requested)
211 {
212 	int i;
213 	FILE *fp = requested ? stdout : stderr;
214 
215 	if (current_command == NULL) {
216 		int i;
217 
218 		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
219 		(void) fprintf(fp,
220 		    gettext("where 'command' is one of the following:\n\n"));
221 
222 		for (i = 0; i < NCOMMAND; i++) {
223 			if (command_table[i].name == NULL)
224 				(void) fprintf(fp, "\n");
225 			else
226 				(void) fprintf(fp, "%s",
227 				    command_table[i].usage);
228 		}
229 	} else {
230 		(void) fprintf(fp, gettext("usage:\n"));
231 		(void) fprintf(fp, current_command->usage);
232 
233 		if (strcmp(current_command->name, "list") == 0) {
234 			(void) fprintf(fp, gettext("\nwhere 'field' is one "
235 			    "of the following:\n\n"));
236 
237 			for (i = 0; column_subopts[i] != NULL; i++)
238 				(void) fprintf(fp, "\t%s\n", column_subopts[i]);
239 		}
240 	}
241 
242 	exit(requested ? 0 : 2);
243 }
244 
245 const char *
246 state_to_name(int state)
247 {
248 	switch (state) {
249 	case VDEV_STATE_CLOSED:
250 	case VDEV_STATE_CANT_OPEN:
251 		return (gettext("FAULTED"));
252 	case VDEV_STATE_OFFLINE:
253 		return (gettext("OFFLINE"));
254 	case VDEV_STATE_DEGRADED:
255 		return (gettext("DEGRADED"));
256 	case VDEV_STATE_HEALTHY:
257 		return (gettext("ONLINE"));
258 	}
259 
260 	return (gettext("UNKNOWN"));
261 }
262 
263 void
264 print_vdev_tree(const char *name, nvlist_t *nv, int indent)
265 {
266 	nvlist_t **child;
267 	uint_t c, children;
268 
269 	if (name != NULL)
270 		(void) printf("\t%*s%s\n", indent, "", name);
271 
272 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
273 	    &child, &children) != 0)
274 		return;
275 
276 	for (c = 0; c < children; c++)
277 		print_vdev_tree(vdev_get_name(child[c]), child[c], indent + 2);
278 }
279 
280 /*
281  * zpool add [-fn] <pool> <vdev> ...
282  *
283  *	-f	Force addition of devices, even if they appear in use
284  *	-n	Do not add the devices, but display the resulting layout if
285  *		they were to be added.
286  *
287  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
288  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
289  * libzfs.
290  */
291 int
292 zpool_do_add(int argc, char **argv)
293 {
294 	int force = FALSE;
295 	int dryrun = FALSE;
296 	int c;
297 	nvlist_t *nvroot;
298 	char *poolname;
299 	int ret;
300 	zpool_handle_t *zhp;
301 	nvlist_t *config;
302 
303 	/* check options */
304 	while ((c = getopt(argc, argv, "fn")) != -1) {
305 		switch (c) {
306 		case 'f':
307 			force = TRUE;
308 			break;
309 		case 'n':
310 			dryrun = TRUE;
311 			break;
312 		case '?':
313 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
314 			    optopt);
315 			usage(FALSE);
316 		}
317 	}
318 
319 	argc -= optind;
320 	argv += optind;
321 
322 	/* get pool name and check number of arguments */
323 	if (argc < 1) {
324 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
325 		usage(FALSE);
326 	}
327 	if (argc < 2) {
328 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
329 		usage(FALSE);
330 	}
331 
332 	poolname = argv[0];
333 
334 	argc--;
335 	argv++;
336 
337 	if ((zhp = zpool_open(poolname)) == NULL)
338 		return (1);
339 
340 	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
341 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
342 		    poolname);
343 		zpool_close(zhp);
344 		return (1);
345 	}
346 
347 	/* pass off to get_vdev_spec for processing */
348 	nvroot = make_root_vdev(config, force, !force, argc, argv);
349 	if (nvroot == NULL) {
350 		zpool_close(zhp);
351 		return (1);
352 	}
353 
354 	if (dryrun) {
355 		nvlist_t *poolnvroot;
356 
357 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
358 		    &poolnvroot) == 0);
359 
360 		(void) printf(gettext("would update '%s' to the following "
361 		    "configuration:\n"), zpool_get_name(zhp));
362 
363 		print_vdev_tree(poolname, poolnvroot, 0);
364 		print_vdev_tree(NULL, nvroot, 0);
365 
366 		ret = 0;
367 	} else {
368 		ret = (zpool_add(zhp, nvroot) != 0);
369 	}
370 
371 	return (ret);
372 }
373 
374 /*
375  * zpool create [-fn] [-R root] [-m mountpoint] <pool> <dev> ...
376  *
377  *	-f	Force creation, even if devices appear in use
378  *	-n	Do not create the pool, but display the resulting layout if it
379  *		were to be created.
380  *      -R	Create a pool under an alternate root
381  *      -m	Set default mountpoint for the root dataset.  By default it's
382  *      	'/<pool>'
383  *
384  * Creates the the named pool according to the given vdev specification.  The
385  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
386  * we get the nvlist back from get_vdev_spec(), we either print out the contents
387  * (if '-n' was specified), or pass it to libzfs to do the creation.
388  */
389 int
390 zpool_do_create(int argc, char **argv)
391 {
392 	int force = FALSE;
393 	int dryrun = FALSE;
394 	int c;
395 	nvlist_t *nvroot;
396 	char *poolname;
397 	int ret;
398 	char *altroot = NULL;
399 	char *mountpoint = NULL;
400 
401 	/* check options */
402 	while ((c = getopt(argc, argv, ":fnR:m:")) != -1) {
403 		switch (c) {
404 		case 'f':
405 			force = TRUE;
406 			break;
407 		case 'n':
408 			dryrun = TRUE;
409 			break;
410 		case 'R':
411 			altroot = optarg;
412 			break;
413 		case 'm':
414 			mountpoint = optarg;
415 			break;
416 		case ':':
417 			(void) fprintf(stderr, gettext("missing argument for "
418 			    "'%c' option\n"), optopt);
419 			usage(FALSE);
420 			break;
421 		case '?':
422 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
423 			    optopt);
424 			usage(FALSE);
425 		}
426 	}
427 
428 	argc -= optind;
429 	argv += optind;
430 
431 	/* get pool name and check number of arguments */
432 	if (argc < 1) {
433 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
434 		usage(FALSE);
435 	}
436 	if (argc < 2) {
437 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
438 		usage(FALSE);
439 	}
440 
441 	poolname = argv[0];
442 
443 	/*
444 	 * As a special case, check for use of '/' in the name, and direct the
445 	 * user to use 'zfs create' instead.
446 	 */
447 	if (strchr(poolname, '/') != NULL) {
448 		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
449 		    "character '/' in pool name\n"), poolname);
450 		(void) fprintf(stderr, gettext("use 'zfs create' to "
451 		    "create a dataset\n"));
452 		return (1);
453 	}
454 
455 	/* pass off to get_vdev_spec for bulk processing */
456 	nvroot = make_root_vdev(NULL, force, !force, argc - 1, argv + 1);
457 	if (nvroot == NULL)
458 		return (1);
459 
460 	if (altroot != NULL && altroot[0] != '/') {
461 		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
462 		    "must be an absolute path\n"));
463 		return (1);
464 	}
465 
466 	/*
467 	 * Check the validity of the mountpoint and direct the user to use the
468 	 * '-m' mountpoint option if it looks like its in use.
469 	 */
470 	if (mountpoint == NULL ||
471 	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
472 	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
473 		char buf[MAXPATHLEN];
474 		struct stat64 statbuf;
475 
476 		if (mountpoint && mountpoint[0] != '/') {
477 			(void) fprintf(stderr, gettext("invalid mountpoint "
478 			    "'%s': must be an absolute path, 'legacy', or "
479 			    "'none'\n"), mountpoint);
480 			return (1);
481 		}
482 
483 		if (mountpoint == NULL) {
484 			if (altroot != NULL)
485 				(void) snprintf(buf, sizeof (buf), "%s/%s",
486 				    altroot, poolname);
487 			else
488 				(void) snprintf(buf, sizeof (buf), "/%s",
489 				    poolname);
490 		} else {
491 			if (altroot != NULL)
492 				(void) snprintf(buf, sizeof (buf), "%s%s",
493 				    altroot, mountpoint);
494 			else
495 				(void) snprintf(buf, sizeof (buf), "%s",
496 				    mountpoint);
497 		}
498 
499 		if (stat64(buf, &statbuf) == 0 &&
500 		    statbuf.st_nlink != 2) {
501 			if (mountpoint == NULL)
502 				(void) fprintf(stderr, gettext("default "
503 				    "mountpoint '%s' exists and is not "
504 				    "empty\n"), buf);
505 			else
506 				(void) fprintf(stderr, gettext("mountpoint "
507 				    "'%s' exists and is not empty\n"), buf);
508 			(void) fprintf(stderr, gettext("use '-m' "
509 			    "option to provide a different default\n"));
510 			return (1);
511 		}
512 	}
513 
514 
515 	if (dryrun) {
516 		/*
517 		 * For a dry run invocation, print out a basic message and run
518 		 * through all the vdevs in the list and print out in an
519 		 * appropriate hierarchy.
520 		 *
521 		 * XXZFS find out of we can create the pool?
522 		 */
523 		(void) printf(gettext("would create '%s' with the "
524 		    "following layout:\n\n"), poolname);
525 
526 		print_vdev_tree(poolname, nvroot, 0);
527 
528 		ret = 0;
529 	} else {
530 		ret = 1;
531 		/*
532 		 * Hand off to libzfs.
533 		 */
534 		if (zpool_create(poolname, nvroot, altroot) == 0) {
535 			zfs_handle_t *pool = zfs_open(poolname,
536 			    ZFS_TYPE_FILESYSTEM);
537 			if (pool != NULL) {
538 				if (mountpoint != NULL)
539 					verify(zfs_prop_set(pool,
540 					    ZFS_PROP_MOUNTPOINT,
541 					    mountpoint) == 0);
542 				if (zfs_mount(pool, NULL, 0) == 0)
543 					ret = zfs_share(pool);
544 				zfs_close(pool);
545 			}
546 		}
547 
548 	}
549 
550 	nvlist_free(nvroot);
551 
552 	return (ret);
553 }
554 
555 /*
556  * zpool destroy <pool>
557  *
558  * 	-f	Forcefully unmount any datasets
559  *
560  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
561  */
562 int
563 zpool_do_destroy(int argc, char **argv)
564 {
565 	int force = FALSE;
566 	int c;
567 	char *pool;
568 	zpool_handle_t *zhp;
569 	int ret;
570 
571 	/* check options */
572 	while ((c = getopt(argc, argv, "f")) != -1) {
573 		switch (c) {
574 		case 'f':
575 			force = TRUE;
576 			break;
577 		case '?':
578 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
579 			    optopt);
580 			usage(FALSE);
581 		}
582 	}
583 
584 	argc -= optind;
585 	argv += optind;
586 
587 	/* check arguments */
588 	if (argc < 1) {
589 		(void) fprintf(stderr, gettext("missing pool argument\n"));
590 		usage(FALSE);
591 	}
592 	if (argc > 1) {
593 		(void) fprintf(stderr, gettext("too many arguments\n"));
594 		usage(FALSE);
595 	}
596 
597 	pool = argv[0];
598 
599 	if ((zhp = zpool_open_canfail(pool)) == NULL) {
600 		/*
601 		 * As a special case, check for use of '/' in the name, and
602 		 * direct the user to use 'zfs destroy' instead.
603 		 */
604 		if (strchr(pool, '/') != NULL)
605 			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
606 			    "destroy a dataset\n"));
607 		return (1);
608 	}
609 
610 	if (unmount_datasets(zhp, force) != 0) {
611 		(void) fprintf(stderr, gettext("could not destroy '%s': "
612 		    "could not unmount datasets\n"), zpool_get_name(zhp));
613 		return (1);
614 	}
615 
616 	ret = (zpool_destroy(zhp) != 0);
617 
618 	zpool_close(zhp);
619 
620 	return (ret);
621 }
622 
623 /*
624  * zpool export [-f] <pool> ...
625  *
626  *	-f	Forcefully unmount datasets
627  *
628  * Export the the given pools.  By default, the command will attempt to cleanly
629  * unmount any active datasets within the pool.  If the '-f' flag is specified,
630  * then the datasets will be forcefully unmounted.
631  */
632 int
633 zpool_do_export(int argc, char **argv)
634 {
635 	int force = FALSE;
636 	int c;
637 	zpool_handle_t *zhp;
638 	int ret;
639 	int i;
640 
641 	/* check options */
642 	while ((c = getopt(argc, argv, "f")) != -1) {
643 		switch (c) {
644 		case 'f':
645 			force = TRUE;
646 			break;
647 		case '?':
648 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
649 			    optopt);
650 			usage(FALSE);
651 		}
652 	}
653 
654 	argc -= optind;
655 	argv += optind;
656 
657 	/* check arguments */
658 	if (argc < 1) {
659 		(void) fprintf(stderr, gettext("missing pool argument\n"));
660 		usage(FALSE);
661 	}
662 
663 	ret = 0;
664 	for (i = 0; i < argc; i++) {
665 		if ((zhp = zpool_open_canfail(argv[i])) == NULL) {
666 			ret = 1;
667 			continue;
668 		}
669 
670 		if (unmount_datasets(zhp, force) != 0) {
671 			ret = 1;
672 			zpool_close(zhp);
673 			continue;
674 		}
675 
676 		if (zpool_export(zhp) != 0)
677 			ret = 1;
678 
679 		zpool_close(zhp);
680 	}
681 
682 	return (ret);
683 }
684 
685 /*
686  * Given a vdev configuration, determine the maximum width needed for the device
687  * name column.
688  */
689 static int
690 max_width(nvlist_t *nv, int depth, int max)
691 {
692 	const char *name = vdev_get_name(nv);
693 	nvlist_t **child;
694 	uint_t c, children;
695 	int ret;
696 
697 	if (strlen(name) + depth > max)
698 		max = strlen(name) + depth;
699 
700 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
701 	    &child, &children) != 0)
702 		return (max);
703 
704 	for (c = 0; c < children; c++)
705 		if ((ret = max_width(child[c], depth + 2, max)) > max)
706 			max = ret;
707 
708 	return (max);
709 }
710 
711 
712 /*
713  * Print the configuration of an exported pool.  Iterate over all vdevs in the
714  * pool, printing out the name and status for each one.
715  */
716 void
717 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
718 {
719 	nvlist_t **child;
720 	uint_t c, children;
721 	vdev_stat_t *vs;
722 	char *type;
723 
724 	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
725 	if (strcmp(type, VDEV_TYPE_MISSING) == 0)
726 		return;
727 
728 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
729 	    (uint64_t **)&vs, &c) == 0);
730 
731 	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
732 
733 	if (vs->vs_aux != 0) {
734 		(void) printf("  %-8s  ", state_to_name(vs->vs_state));
735 
736 		switch (vs->vs_aux) {
737 		case VDEV_AUX_OPEN_FAILED:
738 			(void) printf(gettext("cannot open"));
739 			break;
740 
741 		case VDEV_AUX_BAD_GUID_SUM:
742 			(void) printf(gettext("missing device"));
743 			break;
744 
745 		case VDEV_AUX_NO_REPLICAS:
746 			(void) printf(gettext("insufficient replicas"));
747 			break;
748 
749 		default:
750 			(void) printf(gettext("corrupted data"));
751 			break;
752 		}
753 	} else {
754 		(void) printf("  %s", state_to_name(vs->vs_state));
755 	}
756 	(void) printf("\n");
757 
758 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
759 	    &child, &children) != 0)
760 		return;
761 
762 	for (c = 0; c < children; c++)
763 		print_import_config(vdev_get_name(child[c]), child[c],
764 		    namewidth, depth + 2);
765 }
766 
767 /*
768  * Display the status for the given pool.
769  */
770 static void
771 show_import(nvlist_t *config)
772 {
773 	uint64_t pool_state;
774 	vdev_stat_t *vs;
775 	char *name;
776 	uint64_t guid;
777 	char *msgid;
778 	nvlist_t *nvroot;
779 	int reason;
780 	char *health;
781 	uint_t vsc;
782 	int namewidth;
783 
784 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
785 	    &name) == 0);
786 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
787 	    &guid) == 0);
788 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
789 	    &pool_state) == 0);
790 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH,
791 	    &health) == 0);
792 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
793 	    &nvroot) == 0);
794 
795 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
796 	    (uint64_t **)&vs, &vsc) == 0);
797 
798 	reason = zpool_import_status(config, &msgid);
799 
800 	(void) printf("  pool: %s\n", name);
801 	(void) printf("    id: %llu\n", guid);
802 	(void) printf(" state: %s\n", health);
803 
804 	switch (reason) {
805 	case ZPOOL_STATUS_MISSING_DEV_R:
806 	case ZPOOL_STATUS_MISSING_DEV_NR:
807 	case ZPOOL_STATUS_BAD_GUID_SUM:
808 		(void) printf(gettext("status: One or more devices are missing "
809 		    "from the system.\n"));
810 		break;
811 
812 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
813 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
814 		(void) printf(gettext("status: One or more devices contains "
815 		    "corrupted data.\n"));
816 		break;
817 
818 	case ZPOOL_STATUS_CORRUPT_DATA:
819 		(void) printf(gettext("status: The pool data is corrupted.\n"));
820 		break;
821 
822 	default:
823 		/*
824 		 * No other status can be seen when importing pools.
825 		 */
826 		assert(reason == ZPOOL_STATUS_OK);
827 	}
828 
829 	/*
830 	 * Print out an action according to the overall state of the pool.
831 	 */
832 	if (strcmp(health, gettext("ONLINE")) == 0) {
833 		(void) printf(gettext("action: The pool can be imported"
834 		    " using its name or numeric identifier."));
835 		if (pool_state != POOL_STATE_EXPORTED)
836 			(void) printf(gettext("  The\n\tpool may be active on "
837 			    "on another system, but can be imported using\n\t"
838 			    "the '-f' flag.\n"));
839 		else
840 			(void) printf("\n");
841 	} else if (strcmp(health, gettext("DEGRADED")) == 0) {
842 		(void) printf(gettext("action: The pool can be imported "
843 		    "despite missing or damaged devices.  The\n\tfault "
844 		    "tolerance of the pool may be compromised if imported."));
845 		if (pool_state != POOL_STATE_EXPORTED)
846 			(void) printf(gettext("  The\n\tpool may be active on "
847 			    "on another system, but can be imported using\n\t"
848 			    "the '-f' flag.\n"));
849 		else
850 			(void) printf("\n");
851 	} else {
852 		if (reason == ZPOOL_STATUS_MISSING_DEV_R ||
853 		    reason == ZPOOL_STATUS_MISSING_DEV_NR ||
854 		    reason == ZPOOL_STATUS_BAD_GUID_SUM)
855 			(void) printf(gettext("action: The pool cannot be "
856 			    "imported. Attach the missing\n\tdevices and try "
857 			    "again.\n"));
858 		else
859 			(void) printf(gettext("action: The pool cannot be "
860 			    "imported due to damaged devices or data.\n"));
861 	}
862 
863 	if (msgid != NULL)
864 		(void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
865 		    msgid);
866 
867 	(void) printf(gettext("config:\n\n"));
868 
869 	namewidth = max_width(nvroot, 0, 0);
870 	if (namewidth < 10)
871 		namewidth = 10;
872 	print_import_config(name, nvroot, namewidth, 0);
873 
874 	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
875 		(void) printf("\n\tAdditional devices are known to "
876 		    "be part of this pool, though their\n\texact "
877 		    "configuration cannot be determined.\n");
878 	}
879 }
880 
881 /*
882  * Perform the import for the given configuration.  This passes the heavy
883  * lifting off to zpool_import(), and then mounts the datasets contained within
884  * the pool.
885  */
886 static int
887 do_import(nvlist_t *config, const char *newname, const char *mntopts,
888     const char *altroot, int force)
889 {
890 	zpool_handle_t *zhp;
891 	char *name;
892 	uint64_t state;
893 
894 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
895 	    &name) == 0);
896 
897 	verify(nvlist_lookup_uint64(config,
898 	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
899 	if (state != POOL_STATE_EXPORTED && !force) {
900 		(void) fprintf(stderr, gettext("cannot import '%s': pool "
901 		    "may be in use from other system\n"), name);
902 		(void) fprintf(stderr, gettext("use '-f' to import anyway\n"));
903 		return (1);
904 	}
905 
906 	if (zpool_import(config, newname, altroot) != 0)
907 		return (1);
908 
909 	if (newname != NULL)
910 		name = (char *)newname;
911 
912 	verify((zhp = zpool_open(name)) != NULL);
913 
914 	if (mount_share_datasets(zhp, mntopts) != 0) {
915 		zpool_close(zhp);
916 		return (1);
917 	}
918 
919 	zpool_close(zhp);
920 	return (0);
921 }
922 
923 /*
924  * zpool import [-d dir]
925  *       import [-R root] [-d dir] [-f] -a
926  *       import [-R root] [-d dir] [-f] <pool | id> [newpool]
927  *
928  *       -d	Scan in a specific directory, other than /dev/dsk.  More than
929  *		one directory can be specified using multiple '-d' options.
930  *
931  *       -R	Temporarily import the pool, with all mountpoints relative to
932  *		the given root.  The pool will remain exported when the machine
933  *		is rebooted.
934  *
935  *       -f	Force import, even if it appears that the pool is active.
936  *
937  *       -a	Import all pools found.
938  *
939  * The import command scans for pools to import, and import pools based on pool
940  * name and GUID.  The pool can also be renamed as part of the import process.
941  */
942 int
943 zpool_do_import(int argc, char **argv)
944 {
945 	char **searchdirs = NULL;
946 	int nsearch = 0;
947 	int c;
948 	int err;
949 	nvlist_t *pools;
950 	int do_all = FALSE;
951 	char *altroot = NULL;
952 	char *mntopts = NULL;
953 	int do_force = FALSE;
954 	nvpair_t *elem;
955 	nvlist_t *config;
956 	uint64_t searchguid;
957 	char *searchname;
958 	nvlist_t *found_config;
959 	int first;
960 
961 	/* check options */
962 	while ((c = getopt(argc, argv, ":fd:R:ao:")) != -1) {
963 		switch (c) {
964 		case 'a':
965 			do_all = TRUE;
966 			break;
967 		case 'd':
968 			if (searchdirs == NULL) {
969 				searchdirs = safe_malloc(sizeof (char *));
970 			} else {
971 				char **tmp = safe_malloc((nsearch + 1) *
972 				    sizeof (char *));
973 				bcopy(searchdirs, tmp, nsearch *
974 				    sizeof (char *));
975 				free(searchdirs);
976 				searchdirs = tmp;
977 			}
978 			searchdirs[nsearch++] = optarg;
979 			break;
980 		case 'f':
981 			do_force = TRUE;
982 			break;
983 		case 'o':
984 			mntopts = optarg;
985 			break;
986 		case 'R':
987 			altroot = optarg;
988 			break;
989 		case ':':
990 			(void) fprintf(stderr, gettext("missing argument for "
991 			    "'%c' option\n"), optopt);
992 			usage(FALSE);
993 			break;
994 		case '?':
995 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
996 			    optopt);
997 			usage(FALSE);
998 		}
999 	}
1000 
1001 	argc -= optind;
1002 	argv += optind;
1003 
1004 	if (searchdirs == NULL) {
1005 		searchdirs = safe_malloc(sizeof (char *));
1006 		searchdirs[0] = "/dev/dsk";
1007 		nsearch = 1;
1008 	}
1009 
1010 	/* check argument count */
1011 	if (do_all) {
1012 		if (argc != 0) {
1013 			(void) fprintf(stderr, gettext("too many arguments\n"));
1014 			usage(FALSE);
1015 		}
1016 	} else {
1017 		if (argc > 2) {
1018 			(void) fprintf(stderr, gettext("too many arguments\n"));
1019 			usage(FALSE);
1020 		}
1021 
1022 		/*
1023 		 * Check for the SYS_CONFIG privilege.  We do this explicitly
1024 		 * here because otherwise any attempt to discover pools will
1025 		 * silently fail.
1026 		 */
1027 		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1028 			(void) fprintf(stderr, gettext("cannot "
1029 			    "discover pools: permission denied\n"));
1030 			return (1);
1031 		}
1032 	}
1033 
1034 	if ((pools = zpool_find_import(nsearch, searchdirs)) == NULL)
1035 		return (1);
1036 
1037 	/*
1038 	 * We now have a list of all available pools in the given directories.
1039 	 * Depending on the arguments given, we do one of the following:
1040 	 *
1041 	 *	<none>	Iterate through all pools and display information about
1042 	 *		each one.
1043 	 *
1044 	 *	-a	Iterate through all pools and try to import each one.
1045 	 *
1046 	 *	<id>	Find the pool that corresponds to the given GUID/pool
1047 	 *		name and import that one.
1048 	 */
1049 	if (argc != 0) {
1050 		char *endptr;
1051 
1052 		errno = 0;
1053 		searchguid = strtoull(argv[0], &endptr, 10);
1054 		if (errno != 0 || *endptr != '\0')
1055 			searchname = argv[0];
1056 		else
1057 			searchname = NULL;
1058 		found_config = NULL;
1059 	}
1060 
1061 	err = 0;
1062 	elem = NULL;
1063 	first = TRUE;
1064 	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1065 
1066 		verify(nvpair_value_nvlist(elem, &config) == 0);
1067 
1068 		if (argc == 0) {
1069 			if (first)
1070 				first = FALSE;
1071 			else
1072 				(void) printf("\n");
1073 
1074 			if (do_all)
1075 				err |= do_import(config, NULL, mntopts,
1076 				    altroot, do_force);
1077 			else
1078 				show_import(config);
1079 		} else if (searchname != NULL) {
1080 			char *name;
1081 
1082 			/*
1083 			 * We are searching for a pool based on name.
1084 			 */
1085 			verify(nvlist_lookup_string(config,
1086 			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1087 
1088 			if (strcmp(name, searchname) == 0) {
1089 				if (found_config != NULL) {
1090 					(void) fprintf(stderr, gettext(
1091 					    "cannot import '%s': more than "
1092 					    "one matching pool\n"), searchname);
1093 					(void) fprintf(stderr, gettext(
1094 					    "import by numeric ID instead\n"));
1095 					err = TRUE;
1096 				}
1097 				found_config = config;
1098 			}
1099 		} else {
1100 			uint64_t guid;
1101 
1102 			/*
1103 			 * Search for a pool by guid.
1104 			 */
1105 			verify(nvlist_lookup_uint64(config,
1106 			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1107 
1108 			if (guid == searchguid)
1109 				found_config = config;
1110 		}
1111 	}
1112 
1113 	/*
1114 	 * If we were searching for a specific pool, verify that we found a
1115 	 * pool, and then do the import.
1116 	 */
1117 	if (argc != 0 && err == 0) {
1118 		if (found_config == NULL) {
1119 			(void) fprintf(stderr, gettext("cannot import '%s': "
1120 			    "no such pool available\n"), argv[0]);
1121 			err = TRUE;
1122 		} else {
1123 			err |= do_import(found_config, argc == 1 ? NULL :
1124 			    argv[1], mntopts, altroot, do_force);
1125 		}
1126 	}
1127 
1128 	/*
1129 	 * If we were just looking for pools, report an error if none were
1130 	 * found.
1131 	 */
1132 	if (argc == 0 && first)
1133 		(void) fprintf(stderr,
1134 		    gettext("no pools available to import\n"));
1135 
1136 	nvlist_free(pools);
1137 
1138 	return (err ? 1 : 0);
1139 }
1140 
1141 typedef struct iostat_cbdata {
1142 	zpool_list_t *cb_list;
1143 	int cb_verbose;
1144 	int cb_iteration;
1145 	int cb_namewidth;
1146 } iostat_cbdata_t;
1147 
1148 static void
1149 print_iostat_separator(iostat_cbdata_t *cb)
1150 {
1151 	int i = 0;
1152 
1153 	for (i = 0; i < cb->cb_namewidth; i++)
1154 		(void) printf("-");
1155 	(void) printf("  -----  -----  -----  -----  -----  -----\n");
1156 }
1157 
1158 static void
1159 print_iostat_header(iostat_cbdata_t *cb)
1160 {
1161 	(void) printf("%*s     capacity     operations    bandwidth\n",
1162 	    cb->cb_namewidth, "");
1163 	(void) printf("%-*s   used  avail   read  write   read  write\n",
1164 	    cb->cb_namewidth, "pool");
1165 	print_iostat_separator(cb);
1166 }
1167 
1168 /*
1169  * Display a single statistic.
1170  */
1171 void
1172 print_one_stat(uint64_t value)
1173 {
1174 	char buf[64];
1175 
1176 	zfs_nicenum(value, buf, sizeof (buf));
1177 	(void) printf("  %5s", buf);
1178 }
1179 
1180 /*
1181  * Print out all the statistics for the given vdev.  This can either be the
1182  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
1183  * is a verbose output, and we don't want to display the toplevel pool stats.
1184  */
1185 void
1186 print_vdev_stats(const char *name, nvlist_t *oldnv, nvlist_t *newnv,
1187 	iostat_cbdata_t *cb, int depth)
1188 {
1189 	nvlist_t **oldchild, **newchild;
1190 	uint_t c, children;
1191 	vdev_stat_t *oldvs, *newvs;
1192 	vdev_stat_t zerovs = { 0 };
1193 	uint64_t tdelta;
1194 	double scale;
1195 
1196 	if (oldnv != NULL) {
1197 		verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1198 		    (uint64_t **)&oldvs, &c) == 0);
1199 	} else {
1200 		oldvs = &zerovs;
1201 	}
1202 
1203 	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1204 	    (uint64_t **)&newvs, &c) == 0);
1205 
1206 	if (strlen(name) + depth > cb->cb_namewidth)
1207 		(void) printf("%*s%s", depth, "", name);
1208 	else
1209 		(void) printf("%*s%s%*s", depth, "", name,
1210 		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
1211 
1212 	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1213 
1214 	if (tdelta == 0)
1215 		scale = 1.0;
1216 	else
1217 		scale = (double)NANOSEC / tdelta;
1218 
1219 	/* only toplevel vdevs have capacity stats */
1220 	if (newvs->vs_space == 0) {
1221 		(void) printf("      -      -");
1222 	} else {
1223 		print_one_stat(newvs->vs_alloc);
1224 		print_one_stat(newvs->vs_space - newvs->vs_alloc);
1225 	}
1226 
1227 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1228 	    oldvs->vs_ops[ZIO_TYPE_READ])));
1229 
1230 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1231 	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
1232 
1233 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1234 	    oldvs->vs_bytes[ZIO_TYPE_READ])));
1235 
1236 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1237 	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1238 
1239 	(void) printf("\n");
1240 
1241 	if (!cb->cb_verbose)
1242 		return;
1243 
1244 	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1245 	    &newchild, &children) != 0)
1246 		return;
1247 
1248 	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1249 	    &oldchild, &c) != 0)
1250 		return;
1251 
1252 	for (c = 0; c < children; c++)
1253 		print_vdev_stats(vdev_get_name(newchild[c]),
1254 		    oldnv ? oldchild[c] : NULL, newchild[c], cb, depth + 2);
1255 }
1256 
1257 static int
1258 refresh_iostat(zpool_handle_t *zhp, void *data)
1259 {
1260 	iostat_cbdata_t *cb = data;
1261 
1262 	/*
1263 	 * If the pool has disappeared, remove it from the list and continue.
1264 	 */
1265 	if (zpool_refresh_stats(zhp) != 0)
1266 		pool_list_remove(cb->cb_list, zhp);
1267 
1268 	return (0);
1269 }
1270 
1271 /*
1272  * Callback to print out the iostats for the given pool.
1273  */
1274 int
1275 print_iostat(zpool_handle_t *zhp, void *data)
1276 {
1277 	iostat_cbdata_t *cb = data;
1278 	nvlist_t *oldconfig, *newconfig;
1279 	nvlist_t *oldnvroot, *newnvroot;
1280 
1281 	newconfig = zpool_get_config(zhp, &oldconfig);
1282 
1283 	if (cb->cb_iteration == 1)
1284 		oldconfig = NULL;
1285 
1286 	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1287 	    &newnvroot) == 0);
1288 
1289 	if (oldconfig == NULL)
1290 		oldnvroot = NULL;
1291 	else
1292 		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1293 		    &oldnvroot) == 0);
1294 
1295 	/*
1296 	 * Print out the statistics for the pool.
1297 	 */
1298 	print_vdev_stats(zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1299 
1300 	if (cb->cb_verbose)
1301 		print_iostat_separator(cb);
1302 
1303 	return (0);
1304 }
1305 
1306 int
1307 get_namewidth(zpool_handle_t *zhp, void *data)
1308 {
1309 	iostat_cbdata_t *cb = data;
1310 	nvlist_t *config, *nvroot;
1311 
1312 	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1313 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1314 		    &nvroot) == 0);
1315 		if (!cb->cb_verbose)
1316 			cb->cb_namewidth = strlen(zpool_get_name(zhp));
1317 		else
1318 			cb->cb_namewidth = max_width(nvroot, 0, 0);
1319 	}
1320 
1321 	/*
1322 	 * The width must fall into the range [10,38].  The upper limit is the
1323 	 * maximum we can have and still fit in 80 columns.
1324 	 */
1325 	if (cb->cb_namewidth < 10)
1326 		cb->cb_namewidth = 10;
1327 	if (cb->cb_namewidth > 38)
1328 		cb->cb_namewidth = 38;
1329 
1330 	return (0);
1331 }
1332 
1333 /*
1334  * zpool iostat [-v] [pool] ... [interval [count]]
1335  *
1336  *	-v	Display statistics for individual vdevs
1337  *
1338  * This command can be tricky because we want to be able to deal with pool
1339  * creation/destruction as well as vdev configuration changes.  The bulk of this
1340  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
1341  * on pool_list_update() to detect the addition of new pools.  Configuration
1342  * changes are all handled within libzfs.
1343  */
1344 int
1345 zpool_do_iostat(int argc, char **argv)
1346 {
1347 	int c;
1348 	int ret;
1349 	int npools;
1350 	unsigned long interval = 0, count = 0;
1351 	zpool_list_t *list;
1352 	int verbose = FALSE;
1353 	iostat_cbdata_t cb;
1354 
1355 	/* check options */
1356 	while ((c = getopt(argc, argv, "v")) != -1) {
1357 		switch (c) {
1358 		case 'v':
1359 			verbose = TRUE;
1360 			break;
1361 		case '?':
1362 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1363 			    optopt);
1364 			usage(FALSE);
1365 		}
1366 	}
1367 
1368 	argc -= optind;
1369 	argv += optind;
1370 
1371 	/*
1372 	 * Determine if the last argument is an integer or a pool name
1373 	 */
1374 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
1375 		char *end;
1376 
1377 		errno = 0;
1378 		interval = strtoul(argv[argc - 1], &end, 10);
1379 
1380 		if (*end == '\0' && errno == 0) {
1381 			if (interval == 0) {
1382 				(void) fprintf(stderr, gettext("interval "
1383 				    "cannot be zero\n"));
1384 				usage(FALSE);
1385 			}
1386 
1387 			/*
1388 			 * Ignore the last parameter
1389 			 */
1390 			argc--;
1391 		} else {
1392 			/*
1393 			 * If this is not a valid number, just plow on.  The
1394 			 * user will get a more informative error message later
1395 			 * on.
1396 			 */
1397 			interval = 0;
1398 		}
1399 	}
1400 
1401 	/*
1402 	 * If the last argument is also an integer, then we have both a count
1403 	 * and an integer.
1404 	 */
1405 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
1406 		char *end;
1407 
1408 		errno = 0;
1409 		count = interval;
1410 		interval = strtoul(argv[argc - 1], &end, 10);
1411 
1412 		if (*end == '\0' && errno == 0) {
1413 			if (interval == 0) {
1414 				(void) fprintf(stderr, gettext("interval "
1415 				    "cannot be zero\n"));
1416 				usage(FALSE);
1417 			}
1418 
1419 			/*
1420 			 * Ignore the last parameter
1421 			 */
1422 			argc--;
1423 		} else {
1424 			interval = 0;
1425 		}
1426 	}
1427 
1428 	/*
1429 	 * Construct the list of all interesting pools.
1430 	 */
1431 	ret = 0;
1432 	if ((list = pool_list_get(argc, argv, &ret)) == NULL)
1433 		return (1);
1434 
1435 	if (pool_list_count(list) == 0 && argc != 0)
1436 		return (1);
1437 
1438 	if (pool_list_count(list) == 0 && interval == 0) {
1439 		(void) fprintf(stderr, gettext("no pools available\n"));
1440 		return (1);
1441 	}
1442 
1443 	/*
1444 	 * Enter the main iostat loop.
1445 	 */
1446 	cb.cb_list = list;
1447 	cb.cb_verbose = verbose;
1448 	cb.cb_iteration = 0;
1449 	cb.cb_namewidth = 0;
1450 
1451 	for (;;) {
1452 		pool_list_update(list);
1453 
1454 		if ((npools = pool_list_count(list)) == 0)
1455 			break;
1456 
1457 		/*
1458 		 * Refresh all statistics.  This is done as an explicit step
1459 		 * before calculating the maximum name width, so that any
1460 		 * configuration changes are properly accounted for.
1461 		 */
1462 		(void) pool_list_iter(list, FALSE, refresh_iostat, &cb);
1463 
1464 		/*
1465 		 * Iterate over all pools to determine the maximum width
1466 		 * for the pool / device name column across all pools.
1467 		 */
1468 		cb.cb_namewidth = 0;
1469 		(void) pool_list_iter(list, FALSE, get_namewidth, &cb);
1470 
1471 		/*
1472 		 * If it's the first time, or verbose mode, print the header.
1473 		 */
1474 		if (++cb.cb_iteration == 1 || verbose)
1475 			print_iostat_header(&cb);
1476 
1477 		(void) pool_list_iter(list, FALSE, print_iostat, &cb);
1478 
1479 		/*
1480 		 * If there's more than one pool, and we're not in verbose mode
1481 		 * (which prints a separator for us), then print a separator.
1482 		 */
1483 		if (npools > 1 && !verbose)
1484 			print_iostat_separator(&cb);
1485 
1486 		if (verbose)
1487 			(void) printf("\n");
1488 
1489 		if (interval == 0)
1490 			break;
1491 
1492 		if (count != 0 && --count == 0)
1493 			break;
1494 
1495 		(void) sleep(interval);
1496 	}
1497 
1498 	pool_list_free(list);
1499 
1500 	return (ret);
1501 }
1502 
1503 typedef struct list_cbdata {
1504 	int	cb_scripted;
1505 	int	cb_first;
1506 	int	cb_fields[MAX_FIELDS];
1507 	int	cb_fieldcount;
1508 } list_cbdata_t;
1509 
1510 /*
1511  * Given a list of columns to display, output appropriate headers for each one.
1512  */
1513 void
1514 print_header(int *fields, size_t count)
1515 {
1516 	int i;
1517 	column_def_t *col;
1518 	const char *fmt;
1519 
1520 	for (i = 0; i < count; i++) {
1521 		col = &column_table[fields[i]];
1522 		if (i != 0)
1523 			(void) printf("  ");
1524 		if (col->cd_justify == left_justify)
1525 			fmt = "%-*s";
1526 		else
1527 			fmt = "%*s";
1528 
1529 		(void) printf(fmt, i == count - 1 ? strlen(col->cd_title) :
1530 		    col->cd_width, col->cd_title);
1531 	}
1532 
1533 	(void) printf("\n");
1534 }
1535 
1536 int
1537 list_callback(zpool_handle_t *zhp, void *data)
1538 {
1539 	list_cbdata_t *cbp = data;
1540 	nvlist_t *config;
1541 	int i;
1542 	char buf[ZPOOL_MAXNAMELEN];
1543 	uint64_t total;
1544 	uint64_t used;
1545 	const char *fmt;
1546 	column_def_t *col;
1547 
1548 	if (cbp->cb_first) {
1549 		if (!cbp->cb_scripted)
1550 			print_header(cbp->cb_fields, cbp->cb_fieldcount);
1551 		cbp->cb_first = FALSE;
1552 	}
1553 
1554 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
1555 		config = NULL;
1556 	} else {
1557 		config = zpool_get_config(zhp, NULL);
1558 		total = zpool_get_space_total(zhp);
1559 		used = zpool_get_space_used(zhp);
1560 	}
1561 
1562 	for (i = 0; i < cbp->cb_fieldcount; i++) {
1563 		if (i != 0) {
1564 			if (cbp->cb_scripted)
1565 				(void) printf("\t");
1566 			else
1567 				(void) printf("  ");
1568 		}
1569 
1570 		col = &column_table[cbp->cb_fields[i]];
1571 
1572 		switch (cbp->cb_fields[i]) {
1573 		case ZPOOL_FIELD_NAME:
1574 			(void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf));
1575 			break;
1576 
1577 		case ZPOOL_FIELD_SIZE:
1578 			if (config == NULL)
1579 				(void) strlcpy(buf, "-", sizeof (buf));
1580 			else
1581 				zfs_nicenum(total, buf, sizeof (buf));
1582 			break;
1583 
1584 		case ZPOOL_FIELD_USED:
1585 			if (config == NULL)
1586 				(void) strlcpy(buf, "-", sizeof (buf));
1587 			else
1588 				zfs_nicenum(used, buf, sizeof (buf));
1589 			break;
1590 
1591 		case ZPOOL_FIELD_AVAILABLE:
1592 			if (config == NULL)
1593 				(void) strlcpy(buf, "-", sizeof (buf));
1594 			else
1595 				zfs_nicenum(total - used, buf, sizeof (buf));
1596 			break;
1597 
1598 		case ZPOOL_FIELD_CAPACITY:
1599 			if (config == NULL) {
1600 				(void) strlcpy(buf, "-", sizeof (buf));
1601 			} else {
1602 				uint64_t capacity = (total == 0 ? 0 :
1603 				    (used * 100 / total));
1604 				(void) snprintf(buf, sizeof (buf), "%llu%%",
1605 				    capacity);
1606 			}
1607 			break;
1608 
1609 		case ZPOOL_FIELD_HEALTH:
1610 			if (config == NULL) {
1611 				(void) strlcpy(buf, "FAULTED", sizeof (buf));
1612 			} else {
1613 				nvlist_t *nvroot;
1614 				vdev_stat_t *vs;
1615 				uint_t vsc;
1616 
1617 				verify(nvlist_lookup_nvlist(config,
1618 				    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
1619 				verify(nvlist_lookup_uint64_array(nvroot,
1620 				    ZPOOL_CONFIG_STATS, (uint64_t **)&vs,
1621 				    &vsc) == 0);
1622 				(void) strlcpy(buf, state_to_name(vs->vs_state),
1623 				    sizeof (buf));
1624 			}
1625 			break;
1626 
1627 		case ZPOOL_FIELD_ROOT:
1628 			if (config == NULL)
1629 				(void) strlcpy(buf, "-", sizeof (buf));
1630 			else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0)
1631 				(void) strlcpy(buf, "-", sizeof (buf));
1632 			break;
1633 		}
1634 
1635 		if (cbp->cb_scripted)
1636 			(void) printf("%s", buf);
1637 		else {
1638 			if (col->cd_justify == left_justify)
1639 				fmt = "%-*s";
1640 			else
1641 				fmt = "%*s";
1642 
1643 			(void) printf(fmt, i == cbp->cb_fieldcount - 1 ?
1644 			    strlen(buf) : col->cd_width, buf);
1645 		}
1646 	}
1647 
1648 	(void) printf("\n");
1649 
1650 	return (0);
1651 }
1652 
1653 /*
1654  * zpool list [-H] [-o field[,field]*] [pool] ...
1655  *
1656  *	-H	Scripted mode.  Don't display headers, and separate fields by
1657  *		a single tab.
1658  *	-o	List of fields to display.  Defaults to all fields, or
1659  *		"name,size,used,available,capacity,health,root"
1660  *
1661  * List all pools in the system, whether or not they're healthy.  Output space
1662  * statistics for each one, as well as health status summary.
1663  */
1664 int
1665 zpool_do_list(int argc, char **argv)
1666 {
1667 	int c;
1668 	int ret;
1669 	list_cbdata_t cb = { 0 };
1670 	static char default_fields[] =
1671 	    "name,size,used,available,capacity,health,root";
1672 	char *fields = default_fields;
1673 	char *value;
1674 
1675 	/* check options */
1676 	while ((c = getopt(argc, argv, ":Ho:")) != -1) {
1677 		switch (c) {
1678 		case 'H':
1679 			cb.cb_scripted = TRUE;
1680 			break;
1681 		case 'o':
1682 			fields = optarg;
1683 			break;
1684 		case ':':
1685 			(void) fprintf(stderr, gettext("missing argument for "
1686 			    "'%c' option\n"), optopt);
1687 			usage(FALSE);
1688 			break;
1689 		case '?':
1690 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1691 			    optopt);
1692 			usage(FALSE);
1693 		}
1694 	}
1695 
1696 	argc -= optind;
1697 	argv += optind;
1698 
1699 	while (*fields != '\0') {
1700 		if (cb.cb_fieldcount == MAX_FIELDS) {
1701 			(void) fprintf(stderr, gettext("too many "
1702 			    "properties given to -o option\n"));
1703 			usage(FALSE);
1704 		}
1705 
1706 		if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields,
1707 		    column_subopts, &value)) == -1) {
1708 			(void) fprintf(stderr, gettext("invalid property "
1709 			    "'%s'\n"), value);
1710 			usage(FALSE);
1711 		}
1712 
1713 		cb.cb_fieldcount++;
1714 	}
1715 
1716 
1717 	cb.cb_first = TRUE;
1718 
1719 	ret = for_each_pool(argc, argv, TRUE, list_callback, &cb);
1720 
1721 	if (argc == 0 && cb.cb_first) {
1722 		(void) printf(gettext("no pools available\n"));
1723 		return (0);
1724 	}
1725 
1726 	return (ret);
1727 }
1728 
1729 static nvlist_t *
1730 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
1731 {
1732 	nvlist_t **child;
1733 	uint_t c, children;
1734 	nvlist_t *match;
1735 	char *path;
1736 
1737 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1738 	    &child, &children) != 0) {
1739 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1740 		if (strncmp(name, "/dev/dsk/", 9) == 0)
1741 			name += 9;
1742 		if (strncmp(path, "/dev/dsk/", 9) == 0)
1743 			path += 9;
1744 		if (strcmp(name, path) == 0)
1745 			return (nv);
1746 		return (NULL);
1747 	}
1748 
1749 	for (c = 0; c < children; c++)
1750 		if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
1751 			return (match);
1752 
1753 	return (NULL);
1754 }
1755 
1756 static int
1757 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
1758 {
1759 	int force = FALSE;
1760 	int c;
1761 	nvlist_t *nvroot;
1762 	char *poolname, *old_disk, *new_disk;
1763 	zpool_handle_t *zhp;
1764 	nvlist_t *config;
1765 
1766 	/* check options */
1767 	while ((c = getopt(argc, argv, "f")) != -1) {
1768 		switch (c) {
1769 		case 'f':
1770 			force = TRUE;
1771 			break;
1772 		case '?':
1773 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1774 			    optopt);
1775 			usage(FALSE);
1776 		}
1777 	}
1778 
1779 	argc -= optind;
1780 	argv += optind;
1781 
1782 	/* get pool name and check number of arguments */
1783 	if (argc < 1) {
1784 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
1785 		usage(FALSE);
1786 	}
1787 
1788 	poolname = argv[0];
1789 
1790 	if (argc < 2) {
1791 		(void) fprintf(stderr,
1792 		    gettext("missing <device> specification\n"));
1793 		usage(FALSE);
1794 	}
1795 
1796 	old_disk = argv[1];
1797 
1798 	if (argc < 3) {
1799 		if (!replacing) {
1800 			(void) fprintf(stderr,
1801 			    gettext("missing <new_device> specification\n"));
1802 			usage(FALSE);
1803 		}
1804 		new_disk = old_disk;
1805 		argc -= 1;
1806 		argv += 1;
1807 	} else {
1808 		new_disk = argv[2];
1809 		argc -= 2;
1810 		argv += 2;
1811 	}
1812 
1813 	if (argc > 1) {
1814 		(void) fprintf(stderr, gettext("too many arguments\n"));
1815 		usage(FALSE);
1816 	}
1817 
1818 	if ((zhp = zpool_open(poolname)) == NULL)
1819 		return (1);
1820 
1821 	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
1822 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
1823 		    poolname);
1824 		zpool_close(zhp);
1825 		return (1);
1826 	}
1827 
1828 	nvroot = make_root_vdev(config, force, B_FALSE, argc, argv);
1829 	if (nvroot == NULL) {
1830 		zpool_close(zhp);
1831 		return (1);
1832 	}
1833 
1834 	return (zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing));
1835 }
1836 
1837 /*
1838  * zpool replace [-f] <pool> <device> <new_device>
1839  *
1840  *	-f	Force attach, even if <new_device> appears to be in use.
1841  *
1842  * Replace <device> with <new_device>.
1843  */
1844 /* ARGSUSED */
1845 int
1846 zpool_do_replace(int argc, char **argv)
1847 {
1848 	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
1849 }
1850 
1851 /*
1852  * zpool attach [-f] <pool> <device> <new_device>
1853  *
1854  *	-f	Force attach, even if <new_device> appears to be in use.
1855  *
1856  * Attach <new_device> to the mirror containing <device>.  If <device> is not
1857  * part of a mirror, then <device> will be transformed into a mirror of
1858  * <device> and <new_device>.  In either case, <new_device> will begin life
1859  * with a DTL of [0, now], and will immediately begin to resilver itself.
1860  */
1861 int
1862 zpool_do_attach(int argc, char **argv)
1863 {
1864 	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
1865 }
1866 
1867 /*
1868  * zpool detach [-f] <pool> <device>
1869  *
1870  *	-f	Force detach of <device>, even if DTLs argue against it
1871  *		(not supported yet)
1872  *
1873  * Detach a device from a mirror.  The operation will be refused if <device>
1874  * is the last device in the mirror, or if the DTLs indicate that this device
1875  * has the only valid copy of some data.
1876  */
1877 /* ARGSUSED */
1878 int
1879 zpool_do_detach(int argc, char **argv)
1880 {
1881 	int c;
1882 	char *poolname, *path;
1883 	zpool_handle_t *zhp;
1884 
1885 	/* check options */
1886 	while ((c = getopt(argc, argv, "f")) != -1) {
1887 		switch (c) {
1888 		case 'f':
1889 		case '?':
1890 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1891 			    optopt);
1892 			usage(FALSE);
1893 		}
1894 	}
1895 
1896 	argc -= optind;
1897 	argv += optind;
1898 
1899 	/* get pool name and check number of arguments */
1900 	if (argc < 1) {
1901 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
1902 		usage(FALSE);
1903 	}
1904 
1905 	if (argc < 2) {
1906 		(void) fprintf(stderr,
1907 		    gettext("missing <device> specification\n"));
1908 		usage(FALSE);
1909 	}
1910 
1911 	poolname = argv[0];
1912 	path = argv[1];
1913 
1914 	if ((zhp = zpool_open(poolname)) == NULL)
1915 		return (1);
1916 
1917 	return (zpool_vdev_detach(zhp, path));
1918 }
1919 
1920 /*
1921  * zpool online [-t] <pool> <device>
1922  *
1923  *	-t	Only bring the device on-line temporarily.  The online
1924  *		state will not be persistent across reboots.
1925  */
1926 /* ARGSUSED */
1927 int
1928 zpool_do_online(int argc, char **argv)
1929 {
1930 	int c, i;
1931 	char *poolname;
1932 	zpool_handle_t *zhp;
1933 	int ret = 0;
1934 
1935 	/* check options */
1936 	while ((c = getopt(argc, argv, "t")) != -1) {
1937 		switch (c) {
1938 		case 't':
1939 		case '?':
1940 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1941 			    optopt);
1942 			usage(FALSE);
1943 		}
1944 	}
1945 
1946 	argc -= optind;
1947 	argv += optind;
1948 
1949 	/* get pool name and check number of arguments */
1950 	if (argc < 1) {
1951 		(void) fprintf(stderr, gettext("missing pool name\n"));
1952 		usage(FALSE);
1953 	}
1954 	if (argc < 2) {
1955 		(void) fprintf(stderr, gettext("missing device name\n"));
1956 		usage(FALSE);
1957 	}
1958 
1959 	poolname = argv[0];
1960 
1961 	if ((zhp = zpool_open(poolname)) == NULL)
1962 		return (1);
1963 
1964 	for (i = 1; i < argc; i++)
1965 		if (zpool_vdev_online(zhp, argv[i]) == 0)
1966 			(void) printf(gettext("Bringing device %s online\n"),
1967 			    argv[i]);
1968 		else
1969 			ret = 1;
1970 
1971 	return (ret);
1972 }
1973 
1974 /*
1975  * zpool offline [-ft] <pool> <device>
1976  *
1977  *	-f	Force the device into the offline state, even if doing
1978  *		so would appear to compromise pool availability.
1979  *		(not supported yet)
1980  *
1981  *	-t	Only take the device off-line temporarily.  The offline
1982  *		state will not be persistent across reboots.
1983  *		(not supported yet)
1984  */
1985 /* ARGSUSED */
1986 int
1987 zpool_do_offline(int argc, char **argv)
1988 {
1989 	int c, i;
1990 	char *poolname;
1991 	zpool_handle_t *zhp;
1992 	int ret = 0;
1993 
1994 	/* check options */
1995 	while ((c = getopt(argc, argv, "ft")) != -1) {
1996 		switch (c) {
1997 		case 'f':
1998 		case 't':
1999 		case '?':
2000 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2001 			    optopt);
2002 			usage(FALSE);
2003 		}
2004 	}
2005 
2006 	argc -= optind;
2007 	argv += optind;
2008 
2009 	/* get pool name and check number of arguments */
2010 	if (argc < 1) {
2011 		(void) fprintf(stderr, gettext("missing pool name\n"));
2012 		usage(FALSE);
2013 	}
2014 	if (argc < 2) {
2015 		(void) fprintf(stderr, gettext("missing device name\n"));
2016 		usage(FALSE);
2017 	}
2018 
2019 	poolname = argv[0];
2020 
2021 	if ((zhp = zpool_open(poolname)) == NULL)
2022 		return (1);
2023 
2024 	for (i = 1; i < argc; i++)
2025 		if (zpool_vdev_offline(zhp, argv[i]) == 0)
2026 			(void) printf(gettext("Bringing device %s offline\n"),
2027 			    argv[i]);
2028 		else
2029 			ret = 1;
2030 
2031 	return (ret);
2032 }
2033 
2034 typedef struct scrub_cbdata {
2035 	int	cb_type;
2036 } scrub_cbdata_t;
2037 
2038 int
2039 scrub_callback(zpool_handle_t *zhp, void *data)
2040 {
2041 	scrub_cbdata_t *cb = data;
2042 
2043 	return (zpool_scrub(zhp, cb->cb_type) != 0);
2044 }
2045 
2046 /*
2047  * zpool scrub [-s] <pool> ...
2048  *
2049  *	-s	Stop.  Stops any in-progress scrub.
2050  */
2051 int
2052 zpool_do_scrub(int argc, char **argv)
2053 {
2054 	int c;
2055 	scrub_cbdata_t cb;
2056 
2057 	cb.cb_type = POOL_SCRUB_EVERYTHING;
2058 
2059 	/* check options */
2060 	while ((c = getopt(argc, argv, "s")) != -1) {
2061 		switch (c) {
2062 		case 's':
2063 			cb.cb_type = POOL_SCRUB_NONE;
2064 			break;
2065 		case '?':
2066 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2067 			    optopt);
2068 			usage(FALSE);
2069 		}
2070 	}
2071 
2072 	argc -= optind;
2073 	argv += optind;
2074 
2075 	if (argc < 1) {
2076 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
2077 		usage(FALSE);
2078 	}
2079 
2080 	return (for_each_pool(argc, argv, TRUE, scrub_callback, &cb));
2081 }
2082 
2083 typedef struct status_cbdata {
2084 	int	cb_verbose;
2085 	int	cb_explain;
2086 	int	cb_count;
2087 	int	cb_first;
2088 } status_cbdata_t;
2089 
2090 /*
2091  * Print out detailed scrub status.
2092  */
2093 void
2094 print_scrub_status(nvlist_t *nvroot)
2095 {
2096 	vdev_stat_t *vs;
2097 	uint_t vsc;
2098 	time_t start, end, now;
2099 	double fraction_done;
2100 	uint64_t examined, total, minutes_left;
2101 	char *scrub_type;
2102 
2103 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2104 	    (uint64_t **)&vs, &vsc) == 0);
2105 
2106 	/*
2107 	 * If there's never been a scrub, there's not much to say.
2108 	 */
2109 	if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2110 		(void) printf(gettext("none requested\n"));
2111 		return;
2112 	}
2113 
2114 	scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2115 	    "resilver" : "scrub";
2116 
2117 	start = vs->vs_scrub_start;
2118 	end = vs->vs_scrub_end;
2119 	now = time(NULL);
2120 	examined = vs->vs_scrub_examined;
2121 	total = vs->vs_alloc;
2122 
2123 	if (end != 0) {
2124 		(void) printf(gettext("%s %s with %llu errors on %s"),
2125 		    scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2126 		    (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2127 		return;
2128 	}
2129 
2130 	if (examined == 0)
2131 		examined = 1;
2132 	if (examined > total)
2133 		total = examined;
2134 
2135 	fraction_done = (double)examined / total;
2136 	minutes_left = (uint64_t)((now - start) *
2137 	    (1 - fraction_done) / fraction_done / 60);
2138 
2139 	(void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"),
2140 	    scrub_type, 100 * fraction_done,
2141 	    (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2142 }
2143 
2144 /*
2145  * Print out configuration state as requested by status_callback.
2146  */
2147 void
2148 print_status_config(const char *name, nvlist_t *nv, int namewidth, int depth)
2149 {
2150 	nvlist_t **child;
2151 	uint_t c, children;
2152 	vdev_stat_t *vs;
2153 	char rbuf[6], wbuf[6], cbuf[6], repaired[6];
2154 
2155 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2156 	    (uint64_t **)&vs, &c) == 0);
2157 
2158 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2159 	    &child, &children) != 0)
2160 		children = 0;
2161 
2162 	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
2163 	    name, state_to_name(vs->vs_state));
2164 
2165 	zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2166 	zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2167 	zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2168 	(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2169 
2170 	if (vs->vs_aux != 0) {
2171 		(void) printf("  ");
2172 
2173 		switch (vs->vs_aux) {
2174 		case VDEV_AUX_OPEN_FAILED:
2175 			(void) printf(gettext("cannot open"));
2176 			break;
2177 
2178 		case VDEV_AUX_BAD_GUID_SUM:
2179 			(void) printf(gettext("missing device"));
2180 			break;
2181 
2182 		case VDEV_AUX_NO_REPLICAS:
2183 			(void) printf(gettext("insufficient replicas"));
2184 			break;
2185 
2186 		default:
2187 			(void) printf(gettext("corrupted data"));
2188 			break;
2189 		}
2190 	} else if (vs->vs_scrub_repaired != 0 && children == 0) {
2191 		/*
2192 		 * Report bytes resilvered/repaired on leaf devices.
2193 		 */
2194 		zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2195 		(void) printf(gettext("  %s %s"), repaired,
2196 		    (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2197 		    "resilvered" : "repaired");
2198 	}
2199 
2200 	(void) printf("\n");
2201 
2202 	for (c = 0; c < children; c++)
2203 		print_status_config(vdev_get_name(child[c]), child[c],
2204 		    namewidth, depth + 2);
2205 }
2206 
2207 /*
2208  * Display a summary of pool status.  Displays a summary such as:
2209  *
2210  *        pool: tank
2211  *	status: DEGRADED
2212  *	reason: One or more devices ...
2213  *         see: http://www.sun.com/msg/ZFS-xxxx-01
2214  *	config:
2215  *		mirror		DEGRADED
2216  *                c1t0d0	OK
2217  *                c2t0d0	FAULTED
2218  *
2219  * When given the '-v' option, we print out the complete config.  If the '-e'
2220  * option is specified, then we print out error rate information as well.
2221  */
2222 int
2223 status_callback(zpool_handle_t *zhp, void *data)
2224 {
2225 	status_cbdata_t *cbp = data;
2226 	nvlist_t *config, *nvroot;
2227 	char *msgid;
2228 	int reason;
2229 	char *health;
2230 
2231 	config = zpool_get_config(zhp, NULL);
2232 	reason = zpool_get_status(zhp, &msgid);
2233 
2234 	cbp->cb_count++;
2235 
2236 	/*
2237 	 * If we were given 'zpool status -x', only report those pools with
2238 	 * problems.
2239 	 */
2240 	if (reason == ZPOOL_STATUS_OK && cbp->cb_explain)
2241 		return (0);
2242 
2243 	if (cbp->cb_first)
2244 		cbp->cb_first = FALSE;
2245 	else
2246 		(void) printf("\n");
2247 
2248 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_HEALTH,
2249 	    &health) == 0);
2250 
2251 	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
2252 	(void) printf(gettext(" state: %s\n"), health);
2253 
2254 	switch (reason) {
2255 	case ZPOOL_STATUS_MISSING_DEV_R:
2256 		(void) printf(gettext("status: One or more devices could not "
2257 		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
2258 		    "continue functioning in a degraded state.\n"));
2259 		(void) printf(gettext("action: Attach the missing device and "
2260 		    "online it using 'zpool online'.\n"));
2261 		break;
2262 
2263 	case ZPOOL_STATUS_MISSING_DEV_NR:
2264 		(void) printf(gettext("status: One or more devices could not "
2265 		    "be opened.  There are insufficient\n\treplicas for the "
2266 		    "pool to continue functioning.\n"));
2267 		(void) printf(gettext("action: Attach the missing device and "
2268 		    "online it using 'zpool online'.\n"));
2269 		break;
2270 
2271 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
2272 		(void) printf(gettext("status: One or more devices could not "
2273 		    "be used because the label is missing or\n\tinvalid.  "
2274 		    "Sufficient replicas exist for the pool to continue\n\t"
2275 		    "functioning in a degraded state.\n"));
2276 		(void) printf(gettext("action: Replace the device using "
2277 		    "'zpool replace'.\n"));
2278 		break;
2279 
2280 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2281 		(void) printf(gettext("status: One or more devices could not "
2282 		    "be used because the the label is missing \n\tor invalid.  "
2283 		    "There are insufficient replicas for the pool to "
2284 		    "continue\n\tfunctioning.\n"));
2285 		(void) printf(gettext("action: Destroy and re-create the pool "
2286 		    "from a backup source.\n"));
2287 		break;
2288 
2289 	case ZPOOL_STATUS_FAILING_DEV:
2290 		(void) printf(gettext("status: One or more devices has "
2291 		    "experienced an unrecoverable error.  An\n\tattempt was "
2292 		    "made to correct the error.  Applications are "
2293 		    "unaffected.\n"));
2294 		(void) printf(gettext("action: Determine if the device needs "
2295 		    "to be replaced, and clear the errors\n\tusing "
2296 		    "'zpool online' or replace the device with 'zpool "
2297 		    "replace'.\n"));
2298 		break;
2299 
2300 	case ZPOOL_STATUS_OFFLINE_DEV:
2301 		(void) printf(gettext("status: One or more devices has "
2302 		    "been taken offline by the adminstrator.\n\tSufficient "
2303 		    "replicas exist for the pool to continue functioning in "
2304 		    "a\n\tdegraded state.\n"));
2305 		(void) printf(gettext("action: Online the device using "
2306 		    "'zpool online' or replace the device with\n\t'zpool "
2307 		    "replace'.\n"));
2308 		break;
2309 
2310 	case ZPOOL_STATUS_RESILVERING:
2311 		(void) printf(gettext("status: One or more devices is "
2312 		    "currently being resilvered.  The pool will\n\tcontinue "
2313 		    "to function, possibly in a degraded state.\n"));
2314 		(void) printf(gettext("action: Wait for the resilver to "
2315 		    "complete.\n"));
2316 		break;
2317 
2318 	default:
2319 		/*
2320 		 * The remaining errors can't actually be generated, yet.
2321 		 */
2322 		assert(reason == ZPOOL_STATUS_OK);
2323 	}
2324 
2325 	if (msgid != NULL)
2326 		(void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
2327 		    msgid);
2328 
2329 	if (config != NULL) {
2330 		int namewidth;
2331 
2332 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2333 		    &nvroot) == 0);
2334 
2335 		(void) printf(gettext(" scrub: "));
2336 		print_scrub_status(nvroot);
2337 
2338 		namewidth = max_width(nvroot, 0, 0);
2339 		if (namewidth < 10)
2340 			namewidth = 10;
2341 
2342 		(void) printf(gettext("config:\n\n"));
2343 		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
2344 		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
2345 		print_status_config(zpool_get_name(zhp), nvroot, namewidth, 0);
2346 	} else {
2347 		(void) printf(gettext("config: The configuration cannot be "
2348 		    "determined.\n"));
2349 	}
2350 
2351 	return (0);
2352 }
2353 
2354 /*
2355  * zpool status [-vx] [pool] ...
2356  *
2357  *	-v	Display complete error logs
2358  *	-x	Display only pools with potential problems
2359  *
2360  * Describes the health status of all pools or some subset.
2361  */
2362 int
2363 zpool_do_status(int argc, char **argv)
2364 {
2365 	int c;
2366 	int ret;
2367 	status_cbdata_t cb = { 0 };
2368 
2369 	/* check options */
2370 	while ((c = getopt(argc, argv, "vx")) != -1) {
2371 		switch (c) {
2372 		case 'v':
2373 			cb.cb_verbose = TRUE;
2374 			break;
2375 		case 'x':
2376 			cb.cb_explain = TRUE;
2377 			break;
2378 		case '?':
2379 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2380 			    optopt);
2381 			usage(FALSE);
2382 		}
2383 	}
2384 
2385 	argc -= optind;
2386 	argv += optind;
2387 
2388 	cb.cb_first = TRUE;
2389 
2390 	ret = for_each_pool(argc, argv, TRUE, status_callback, &cb);
2391 
2392 	if (argc == 0 && cb.cb_count == 0)
2393 		(void) printf(gettext("no pools available\n"));
2394 	else if (cb.cb_explain && cb.cb_first) {
2395 		if (argc == 0) {
2396 			(void) printf(gettext("all pools are healthy\n"));
2397 		} else {
2398 			int i;
2399 			for (i = 0; i < argc; i++)
2400 				(void) printf(gettext("pool '%s' is healthy\n"),
2401 				    argv[i]);
2402 		}
2403 	}
2404 
2405 	return (ret);
2406 }
2407 
2408 int
2409 main(int argc, char **argv)
2410 {
2411 	int ret;
2412 	int i;
2413 	char *cmdname;
2414 
2415 	(void) setlocale(LC_ALL, "");
2416 	(void) textdomain(TEXT_DOMAIN);
2417 
2418 	opterr = 0;
2419 
2420 	/*
2421 	 * Make sure the user has specified some command.
2422 	 */
2423 	if (argc < 2) {
2424 		(void) fprintf(stderr, gettext("missing command\n"));
2425 		usage(FALSE);
2426 	}
2427 
2428 	cmdname = argv[1];
2429 
2430 	/*
2431 	 * Special case '-?'
2432 	 */
2433 	if (strcmp(cmdname, "-?") == 0)
2434 		usage(TRUE);
2435 
2436 	/*
2437 	 * Run the appropriate command.
2438 	 */
2439 	for (i = 0; i < NCOMMAND; i++) {
2440 		if (command_table[i].name == NULL)
2441 			continue;
2442 
2443 		if (strcmp(cmdname, command_table[i].name) == 0) {
2444 			current_command = &command_table[i];
2445 			ret = command_table[i].func(argc - 1, argv + 1);
2446 			break;
2447 		}
2448 	}
2449 
2450 	/*
2451 	 * 'freeze' is a vile debugging abomination, so we treat it as such.
2452 	 */
2453 	if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
2454 		char buf[8192];
2455 		int fd = open("/dev/zpoolctl", O_RDWR);
2456 		(void) strcpy((void *)buf, argv[2]);
2457 		return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
2458 	}
2459 
2460 	if (i == NCOMMAND) {
2461 		(void) fprintf(stderr, gettext("unrecognized "
2462 		    "command '%s'\n"), cmdname);
2463 		usage(FALSE);
2464 	}
2465 
2466 	/*
2467 	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
2468 	 * for the purposes of running ::findleaks.
2469 	 */
2470 	if (getenv("ZFS_ABORT") != NULL) {
2471 		(void) printf("dumping core by request\n");
2472 		abort();
2473 	}
2474 
2475 	return (ret);
2476 }
2477