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