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