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