xref: /illumos-gate/usr/src/cmd/zpool/zpool_main.c (revision 69a0bf0c658b89d78f2def6997ee0e7d96f13524)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 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 #include <sys/fs/zfs.h>
45 
46 #include <sys/stat.h>
47 
48 #include <libzfs.h>
49 
50 #include "zpool_util.h"
51 
52 static int zpool_do_create(int, char **);
53 static int zpool_do_destroy(int, char **);
54 
55 static int zpool_do_add(int, char **);
56 static int zpool_do_remove(int, char **);
57 
58 static int zpool_do_list(int, char **);
59 static int zpool_do_iostat(int, char **);
60 static int zpool_do_status(int, char **);
61 
62 static int zpool_do_online(int, char **);
63 static int zpool_do_offline(int, char **);
64 static int zpool_do_clear(int, char **);
65 
66 static int zpool_do_attach(int, char **);
67 static int zpool_do_detach(int, char **);
68 static int zpool_do_replace(int, char **);
69 
70 static int zpool_do_scrub(int, char **);
71 
72 static int zpool_do_import(int, char **);
73 static int zpool_do_export(int, char **);
74 
75 static int zpool_do_upgrade(int, char **);
76 
77 static int zpool_do_history(int, char **);
78 
79 static int zpool_do_get(int, char **);
80 static int zpool_do_set(int, char **);
81 
82 /*
83  * These libumem hooks provide a reasonable set of defaults for the allocator's
84  * debugging facilities.
85  */
86 const char *
87 _umem_debug_init(void)
88 {
89 	return ("default,verbose"); /* $UMEM_DEBUG setting */
90 }
91 
92 const char *
93 _umem_logging_init(void)
94 {
95 	return ("fail,contents"); /* $UMEM_LOGGING setting */
96 }
97 
98 typedef enum {
99 	HELP_ADD,
100 	HELP_ATTACH,
101 	HELP_CLEAR,
102 	HELP_CREATE,
103 	HELP_DESTROY,
104 	HELP_DETACH,
105 	HELP_EXPORT,
106 	HELP_HISTORY,
107 	HELP_IMPORT,
108 	HELP_IOSTAT,
109 	HELP_LIST,
110 	HELP_OFFLINE,
111 	HELP_ONLINE,
112 	HELP_REPLACE,
113 	HELP_REMOVE,
114 	HELP_SCRUB,
115 	HELP_STATUS,
116 	HELP_UPGRADE,
117 	HELP_GET,
118 	HELP_SET
119 } zpool_help_t;
120 
121 
122 typedef struct zpool_command {
123 	const char	*name;
124 	int		(*func)(int, char **);
125 	zpool_help_t	usage;
126 } zpool_command_t;
127 
128 /*
129  * Master command table.  Each ZFS command has a name, associated function, and
130  * usage message.  The usage messages need to be internationalized, so we have
131  * to have a function to return the usage message based on a command index.
132  *
133  * These commands are organized according to how they are displayed in the usage
134  * message.  An empty command (one with a NULL name) indicates an empty line in
135  * the generic usage message.
136  */
137 static zpool_command_t command_table[] = {
138 	{ "create",	zpool_do_create,	HELP_CREATE		},
139 	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
140 	{ NULL },
141 	{ "add",	zpool_do_add,		HELP_ADD		},
142 	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
143 	{ NULL },
144 	{ "list",	zpool_do_list,		HELP_LIST		},
145 	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
146 	{ "status",	zpool_do_status,	HELP_STATUS		},
147 	{ NULL },
148 	{ "online",	zpool_do_online,	HELP_ONLINE		},
149 	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
150 	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
151 	{ NULL },
152 	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
153 	{ "detach",	zpool_do_detach,	HELP_DETACH		},
154 	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
155 	{ NULL },
156 	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
157 	{ NULL },
158 	{ "import",	zpool_do_import,	HELP_IMPORT		},
159 	{ "export",	zpool_do_export,	HELP_EXPORT		},
160 	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
161 	{ NULL },
162 	{ "history",	zpool_do_history,	HELP_HISTORY		},
163 	{ "get",	zpool_do_get,		HELP_GET		},
164 	{ "set",	zpool_do_set,		HELP_SET		},
165 };
166 
167 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
168 
169 zpool_command_t *current_command;
170 
171 static const char *
172 get_usage(zpool_help_t idx) {
173 	switch (idx) {
174 	case HELP_ADD:
175 		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
176 	case HELP_ATTACH:
177 		return (gettext("\tattach [-f] <pool> <device> "
178 		    "<new_device>\n"));
179 	case HELP_CLEAR:
180 		return (gettext("\tclear <pool> [device]\n"));
181 	case HELP_CREATE:
182 		return (gettext("\tcreate  [-fn] [-R root] [-m mountpoint] "
183 		    "<pool> <vdev> ...\n"));
184 	case HELP_DESTROY:
185 		return (gettext("\tdestroy [-f] <pool>\n"));
186 	case HELP_DETACH:
187 		return (gettext("\tdetach <pool> <device>\n"));
188 	case HELP_EXPORT:
189 		return (gettext("\texport [-f] <pool> ...\n"));
190 	case HELP_HISTORY:
191 		return (gettext("\thistory [<pool>]\n"));
192 	case HELP_IMPORT:
193 		return (gettext("\timport [-d dir] [-D]\n"
194 		    "\timport [-d dir] [-D] [-f] [-o opts] [-R root] -a\n"
195 		    "\timport [-d dir] [-D] [-f] [-o opts] [-R root ]"
196 		    " <pool | id> [newpool]\n"));
197 	case HELP_IOSTAT:
198 		return (gettext("\tiostat [-v] [pool] ... [interval "
199 		    "[count]]\n"));
200 	case HELP_LIST:
201 		return (gettext("\tlist [-H] [-o field[,field]*] "
202 		    "[pool] ...\n"));
203 	case HELP_OFFLINE:
204 		return (gettext("\toffline [-t] <pool> <device> ...\n"));
205 	case HELP_ONLINE:
206 		return (gettext("\tonline <pool> <device> ...\n"));
207 	case HELP_REPLACE:
208 		return (gettext("\treplace [-f] <pool> <device> "
209 		    "[new_device]\n"));
210 	case HELP_REMOVE:
211 		return (gettext("\tremove <pool> <device>\n"));
212 	case HELP_SCRUB:
213 		return (gettext("\tscrub [-s] <pool> ...\n"));
214 	case HELP_STATUS:
215 		return (gettext("\tstatus [-vx] [pool] ...\n"));
216 	case HELP_UPGRADE:
217 		return (gettext("\tupgrade\n"
218 		    "\tupgrade -v\n"
219 		    "\tupgrade <-a | pool>\n"));
220 	case HELP_GET:
221 		return (gettext("\tget <all | property[,property]...> "
222 		    "<pool> ...\n"));
223 	case HELP_SET:
224 		return (gettext("\tset <property=value> <pool> \n"));
225 	}
226 
227 	abort();
228 	/* NOTREACHED */
229 }
230 
231 /*
232  * Fields available for 'zpool list'.
233  */
234 typedef enum {
235 	ZPOOL_FIELD_NAME,
236 	ZPOOL_FIELD_SIZE,
237 	ZPOOL_FIELD_USED,
238 	ZPOOL_FIELD_AVAILABLE,
239 	ZPOOL_FIELD_CAPACITY,
240 	ZPOOL_FIELD_HEALTH,
241 	ZPOOL_FIELD_ROOT
242 } zpool_field_t;
243 
244 #define	MAX_FIELDS	10
245 
246 typedef struct column_def {
247 	const char	*cd_title;
248 	size_t		cd_width;
249 	enum {
250 		left_justify,
251 		right_justify
252 	}		cd_justify;
253 } column_def_t;
254 
255 static column_def_t column_table[] = {
256 	{ "NAME",	20,	left_justify	},
257 	{ "SIZE",	6,	right_justify	},
258 	{ "USED",	6,	right_justify	},
259 	{ "AVAIL",	6,	right_justify	},
260 	{ "CAP",	5,	right_justify	},
261 	{ "HEALTH",	9,	left_justify	},
262 	{ "ALTROOT",	15,	left_justify	}
263 };
264 
265 static char *column_subopts[] = {
266 	"name",
267 	"size",
268 	"used",
269 	"available",
270 	"capacity",
271 	"health",
272 	"root",
273 	NULL
274 };
275 
276 /*
277  * Callback routine that will print out a pool property value.
278  */
279 static zpool_prop_t
280 print_prop_cb(zpool_prop_t prop, void *cb)
281 {
282 	FILE *fp = cb;
283 
284 	(void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
285 
286 	if (zpool_prop_values(prop) == NULL)
287 		(void) fprintf(fp, "-\n");
288 	else
289 		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
290 
291 	return (ZFS_PROP_CONT);
292 }
293 
294 /*
295  * Display usage message.  If we're inside a command, display only the usage for
296  * that command.  Otherwise, iterate over the entire command table and display
297  * a complete usage message.
298  */
299 void
300 usage(boolean_t requested)
301 {
302 	int i;
303 	FILE *fp = requested ? stdout : stderr;
304 
305 	if (current_command == NULL) {
306 		int i;
307 
308 		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
309 		(void) fprintf(fp,
310 		    gettext("where 'command' is one of the following:\n\n"));
311 
312 		for (i = 0; i < NCOMMAND; i++) {
313 			if (command_table[i].name == NULL)
314 				(void) fprintf(fp, "\n");
315 			else
316 				(void) fprintf(fp, "%s",
317 				    get_usage(command_table[i].usage));
318 		}
319 	} else {
320 		(void) fprintf(fp, gettext("usage:\n"));
321 		(void) fprintf(fp, "%s", get_usage(current_command->usage));
322 
323 		if (strcmp(current_command->name, "list") == 0) {
324 			(void) fprintf(fp, gettext("\nwhere 'field' is one "
325 			    "of the following:\n\n"));
326 
327 			for (i = 0; column_subopts[i] != NULL; i++)
328 				(void) fprintf(fp, "\t%s\n", column_subopts[i]);
329 		}
330 	}
331 
332 	if (current_command != NULL &&
333 	    ((strcmp(current_command->name, "set") == 0) ||
334 	    (strcmp(current_command->name, "get") == 0))) {
335 
336 		(void) fprintf(fp,
337 		    gettext("\nthe following properties are supported:\n"));
338 
339 		(void) fprintf(fp, "\n\t%-13s  %s\n\n",
340 		    "PROPERTY", "VALUES");
341 
342 		/* Iterate over all properties */
343 		(void) zpool_prop_iter(print_prop_cb, fp, B_FALSE);
344 	}
345 
346 	/*
347 	 * See comments at end of main().
348 	 */
349 	if (getenv("ZFS_ABORT") != NULL) {
350 		(void) printf("dumping core by request\n");
351 		abort();
352 	}
353 
354 	exit(requested ? 0 : 2);
355 }
356 
357 const char *
358 state_to_health(int vs_state)
359 {
360 	switch (vs_state) {
361 	case VDEV_STATE_CLOSED:
362 	case VDEV_STATE_CANT_OPEN:
363 	case VDEV_STATE_OFFLINE:
364 		return (dgettext(TEXT_DOMAIN, "FAULTED"));
365 	case VDEV_STATE_DEGRADED:
366 		return (dgettext(TEXT_DOMAIN, "DEGRADED"));
367 	case VDEV_STATE_HEALTHY:
368 		return (dgettext(TEXT_DOMAIN, "ONLINE"));
369 	}
370 
371 	return (dgettext(TEXT_DOMAIN, "UNKNOWN"));
372 }
373 
374 const char *
375 state_to_name(vdev_stat_t *vs)
376 {
377 	switch (vs->vs_state) {
378 	case VDEV_STATE_CLOSED:
379 	case VDEV_STATE_CANT_OPEN:
380 		if (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)
381 			return (gettext("FAULTED"));
382 		else
383 			return (gettext("UNAVAIL"));
384 	case VDEV_STATE_OFFLINE:
385 		return (gettext("OFFLINE"));
386 	case VDEV_STATE_REMOVED:
387 		return (gettext("REMOVED"));
388 	case VDEV_STATE_FAULTED:
389 		return (gettext("FAULTED"));
390 	case VDEV_STATE_DEGRADED:
391 		return (gettext("DEGRADED"));
392 	case VDEV_STATE_HEALTHY:
393 		return (gettext("ONLINE"));
394 	}
395 
396 	return (gettext("UNKNOWN"));
397 }
398 
399 void
400 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent)
401 {
402 	nvlist_t **child;
403 	uint_t c, children;
404 	char *vname;
405 
406 	if (name != NULL)
407 		(void) printf("\t%*s%s\n", indent, "", name);
408 
409 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
410 	    &child, &children) != 0)
411 		return;
412 
413 	for (c = 0; c < children; c++) {
414 		vname = zpool_vdev_name(g_zfs, zhp, child[c]);
415 		print_vdev_tree(zhp, vname, child[c], indent + 2);
416 		free(vname);
417 	}
418 }
419 
420 /*
421  * zpool add [-fn] <pool> <vdev> ...
422  *
423  *	-f	Force addition of devices, even if they appear in use
424  *	-n	Do not add the devices, but display the resulting layout if
425  *		they were to be added.
426  *
427  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
428  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
429  * libzfs.
430  */
431 int
432 zpool_do_add(int argc, char **argv)
433 {
434 	boolean_t force = B_FALSE;
435 	boolean_t dryrun = B_FALSE;
436 	int c;
437 	nvlist_t *nvroot;
438 	char *poolname;
439 	int ret;
440 	zpool_handle_t *zhp;
441 	nvlist_t *config;
442 
443 	/* check options */
444 	while ((c = getopt(argc, argv, "fn")) != -1) {
445 		switch (c) {
446 		case 'f':
447 			force = B_TRUE;
448 			break;
449 		case 'n':
450 			dryrun = B_TRUE;
451 			break;
452 		case '?':
453 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
454 			    optopt);
455 			usage(B_FALSE);
456 		}
457 	}
458 
459 	argc -= optind;
460 	argv += optind;
461 
462 	/* get pool name and check number of arguments */
463 	if (argc < 1) {
464 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
465 		usage(B_FALSE);
466 	}
467 	if (argc < 2) {
468 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
469 		usage(B_FALSE);
470 	}
471 
472 	poolname = argv[0];
473 
474 	argc--;
475 	argv++;
476 
477 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
478 		return (1);
479 
480 	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
481 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
482 		    poolname);
483 		zpool_close(zhp);
484 		return (1);
485 	}
486 
487 	/* pass off to get_vdev_spec for processing */
488 	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, argc, argv);
489 	if (nvroot == NULL) {
490 		zpool_close(zhp);
491 		return (1);
492 	}
493 
494 	if (dryrun) {
495 		nvlist_t *poolnvroot;
496 
497 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
498 		    &poolnvroot) == 0);
499 
500 		(void) printf(gettext("would update '%s' to the following "
501 		    "configuration:\n"), zpool_get_name(zhp));
502 
503 		print_vdev_tree(zhp, poolname, poolnvroot, 0);
504 		print_vdev_tree(zhp, NULL, nvroot, 0);
505 
506 		ret = 0;
507 	} else {
508 		ret = (zpool_add(zhp, nvroot) != 0);
509 		if (!ret) {
510 			zpool_log_history(g_zfs, argc + 1 + optind,
511 			    argv - 1 - optind, poolname, B_TRUE, B_FALSE);
512 		}
513 	}
514 
515 	nvlist_free(nvroot);
516 	zpool_close(zhp);
517 
518 	return (ret);
519 }
520 
521 /*
522  * zpool remove <pool> <vdev>
523  *
524  * Removes the given vdev from the pool.  Currently, this only supports removing
525  * spares from the pool.  Eventually, we'll want to support removing leaf vdevs
526  * (as an alias for 'detach') as well as toplevel vdevs.
527  */
528 int
529 zpool_do_remove(int argc, char **argv)
530 {
531 	char *poolname;
532 	int ret;
533 	zpool_handle_t *zhp;
534 
535 	argc--;
536 	argv++;
537 
538 	/* get pool name and check number of arguments */
539 	if (argc < 1) {
540 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
541 		usage(B_FALSE);
542 	}
543 	if (argc < 2) {
544 		(void) fprintf(stderr, gettext("missing device\n"));
545 		usage(B_FALSE);
546 	}
547 
548 	poolname = argv[0];
549 
550 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
551 		return (1);
552 
553 	ret = (zpool_vdev_remove(zhp, argv[1]) != 0);
554 	if (!ret) {
555 		zpool_log_history(g_zfs, ++argc, --argv, poolname, B_TRUE,
556 		    B_FALSE);
557 	}
558 
559 	return (ret);
560 }
561 
562 /*
563  * zpool create [-fn] [-R root] [-m mountpoint] <pool> <dev> ...
564  *
565  *	-f	Force creation, even if devices appear in use
566  *	-n	Do not create the pool, but display the resulting layout if it
567  *		were to be created.
568  *      -R	Create a pool under an alternate root
569  *      -m	Set default mountpoint for the root dataset.  By default it's
570  *      	'/<pool>'
571  *
572  * Creates the named pool according to the given vdev specification.  The
573  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
574  * we get the nvlist back from get_vdev_spec(), we either print out the contents
575  * (if '-n' was specified), or pass it to libzfs to do the creation.
576  */
577 int
578 zpool_do_create(int argc, char **argv)
579 {
580 	boolean_t force = B_FALSE;
581 	boolean_t dryrun = B_FALSE;
582 	int c;
583 	nvlist_t *nvroot;
584 	char *poolname;
585 	int ret;
586 	char *altroot = NULL;
587 	char *mountpoint = NULL;
588 	nvlist_t **child;
589 	uint_t children;
590 
591 	/* check options */
592 	while ((c = getopt(argc, argv, ":fnR:m:")) != -1) {
593 		switch (c) {
594 		case 'f':
595 			force = B_TRUE;
596 			break;
597 		case 'n':
598 			dryrun = B_TRUE;
599 			break;
600 		case 'R':
601 			altroot = optarg;
602 			break;
603 		case 'm':
604 			mountpoint = optarg;
605 			break;
606 		case ':':
607 			(void) fprintf(stderr, gettext("missing argument for "
608 			    "'%c' option\n"), optopt);
609 			usage(B_FALSE);
610 			break;
611 		case '?':
612 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
613 			    optopt);
614 			usage(B_FALSE);
615 		}
616 	}
617 
618 	argc -= optind;
619 	argv += optind;
620 
621 	/* get pool name and check number of arguments */
622 	if (argc < 1) {
623 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
624 		usage(B_FALSE);
625 	}
626 	if (argc < 2) {
627 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
628 		usage(B_FALSE);
629 	}
630 
631 	poolname = argv[0];
632 
633 	/*
634 	 * As a special case, check for use of '/' in the name, and direct the
635 	 * user to use 'zfs create' instead.
636 	 */
637 	if (strchr(poolname, '/') != NULL) {
638 		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
639 		    "character '/' in pool name\n"), poolname);
640 		(void) fprintf(stderr, gettext("use 'zfs create' to "
641 		    "create a dataset\n"));
642 		return (1);
643 	}
644 
645 	/* pass off to get_vdev_spec for bulk processing */
646 	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1,
647 	    argv + 1);
648 	if (nvroot == NULL)
649 		return (1);
650 
651 	/* make_root_vdev() allows 0 toplevel children if there are spares */
652 	verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
653 	    &child, &children) == 0);
654 	if (children == 0) {
655 		(void) fprintf(stderr, gettext("invalid vdev "
656 		    "specification: at least one toplevel vdev must be "
657 		    "specified\n"));
658 		return (1);
659 	}
660 
661 
662 	if (altroot != NULL && altroot[0] != '/') {
663 		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
664 		    "must be an absolute path\n"), altroot);
665 		nvlist_free(nvroot);
666 		return (1);
667 	}
668 
669 	/*
670 	 * Check the validity of the mountpoint and direct the user to use the
671 	 * '-m' mountpoint option if it looks like its in use.
672 	 */
673 	if (mountpoint == NULL ||
674 	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
675 	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
676 		char buf[MAXPATHLEN];
677 		struct stat64 statbuf;
678 
679 		if (mountpoint && mountpoint[0] != '/') {
680 			(void) fprintf(stderr, gettext("invalid mountpoint "
681 			    "'%s': must be an absolute path, 'legacy', or "
682 			    "'none'\n"), mountpoint);
683 			nvlist_free(nvroot);
684 			return (1);
685 		}
686 
687 		if (mountpoint == NULL) {
688 			if (altroot != NULL)
689 				(void) snprintf(buf, sizeof (buf), "%s/%s",
690 				    altroot, poolname);
691 			else
692 				(void) snprintf(buf, sizeof (buf), "/%s",
693 				    poolname);
694 		} else {
695 			if (altroot != NULL)
696 				(void) snprintf(buf, sizeof (buf), "%s%s",
697 				    altroot, mountpoint);
698 			else
699 				(void) snprintf(buf, sizeof (buf), "%s",
700 				    mountpoint);
701 		}
702 
703 		if (stat64(buf, &statbuf) == 0 &&
704 		    statbuf.st_nlink != 2) {
705 			if (mountpoint == NULL)
706 				(void) fprintf(stderr, gettext("default "
707 				    "mountpoint '%s' exists and is not "
708 				    "empty\n"), buf);
709 			else
710 				(void) fprintf(stderr, gettext("mountpoint "
711 				    "'%s' exists and is not empty\n"), buf);
712 			(void) fprintf(stderr, gettext("use '-m' "
713 			    "option to provide a different default\n"));
714 			nvlist_free(nvroot);
715 			return (1);
716 		}
717 	}
718 
719 
720 	if (dryrun) {
721 		/*
722 		 * For a dry run invocation, print out a basic message and run
723 		 * through all the vdevs in the list and print out in an
724 		 * appropriate hierarchy.
725 		 */
726 		(void) printf(gettext("would create '%s' with the "
727 		    "following layout:\n\n"), poolname);
728 
729 		print_vdev_tree(NULL, poolname, nvroot, 0);
730 
731 		ret = 0;
732 	} else {
733 		ret = 1;
734 		/*
735 		 * Hand off to libzfs.
736 		 */
737 		if (zpool_create(g_zfs, poolname, nvroot, altroot) == 0) {
738 			zfs_handle_t *pool = zfs_open(g_zfs, poolname,
739 			    ZFS_TYPE_FILESYSTEM);
740 			if (pool != NULL) {
741 				if (mountpoint != NULL)
742 					verify(zfs_prop_set(pool,
743 					    zfs_prop_to_name(
744 					    ZFS_PROP_MOUNTPOINT),
745 					    mountpoint) == 0);
746 				if (zfs_mount(pool, NULL, 0) == 0)
747 					ret = zfs_share_nfs(pool);
748 				zfs_close(pool);
749 			}
750 			zpool_log_history(g_zfs, argc + optind, argv - optind,
751 			    poolname, B_TRUE, B_TRUE);
752 		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
753 			(void) fprintf(stderr, gettext("pool name may have "
754 			    "been omitted\n"));
755 		}
756 	}
757 
758 	nvlist_free(nvroot);
759 
760 	return (ret);
761 }
762 
763 /*
764  * zpool destroy <pool>
765  *
766  * 	-f	Forcefully unmount any datasets
767  *
768  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
769  */
770 int
771 zpool_do_destroy(int argc, char **argv)
772 {
773 	boolean_t force = B_FALSE;
774 	int c;
775 	char *pool;
776 	zpool_handle_t *zhp;
777 	int ret;
778 
779 	/* check options */
780 	while ((c = getopt(argc, argv, "f")) != -1) {
781 		switch (c) {
782 		case 'f':
783 			force = B_TRUE;
784 			break;
785 		case '?':
786 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
787 			    optopt);
788 			usage(B_FALSE);
789 		}
790 	}
791 
792 	argc -= optind;
793 	argv += optind;
794 
795 	/* check arguments */
796 	if (argc < 1) {
797 		(void) fprintf(stderr, gettext("missing pool argument\n"));
798 		usage(B_FALSE);
799 	}
800 	if (argc > 1) {
801 		(void) fprintf(stderr, gettext("too many arguments\n"));
802 		usage(B_FALSE);
803 	}
804 
805 	pool = argv[0];
806 
807 	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
808 		/*
809 		 * As a special case, check for use of '/' in the name, and
810 		 * direct the user to use 'zfs destroy' instead.
811 		 */
812 		if (strchr(pool, '/') != NULL)
813 			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
814 			    "destroy a dataset\n"));
815 		return (1);
816 	}
817 
818 	if (zpool_disable_datasets(zhp, force) != 0) {
819 		(void) fprintf(stderr, gettext("could not destroy '%s': "
820 		    "could not unmount datasets\n"), zpool_get_name(zhp));
821 		return (1);
822 	}
823 
824 	zpool_log_history(g_zfs, argc + optind, argv - optind, pool, B_TRUE,
825 	    B_FALSE);
826 
827 	ret = (zpool_destroy(zhp) != 0);
828 
829 	zpool_close(zhp);
830 
831 	return (ret);
832 }
833 
834 /*
835  * zpool export [-f] <pool> ...
836  *
837  *	-f	Forcefully unmount datasets
838  *
839  * Export the given pools.  By default, the command will attempt to cleanly
840  * unmount any active datasets within the pool.  If the '-f' flag is specified,
841  * then the datasets will be forcefully unmounted.
842  */
843 int
844 zpool_do_export(int argc, char **argv)
845 {
846 	boolean_t force = B_FALSE;
847 	int c;
848 	zpool_handle_t *zhp;
849 	int ret;
850 	int i;
851 
852 	/* check options */
853 	while ((c = getopt(argc, argv, "f")) != -1) {
854 		switch (c) {
855 		case 'f':
856 			force = B_TRUE;
857 			break;
858 		case '?':
859 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
860 			    optopt);
861 			usage(B_FALSE);
862 		}
863 	}
864 
865 	argc -= optind;
866 	argv += optind;
867 
868 	/* check arguments */
869 	if (argc < 1) {
870 		(void) fprintf(stderr, gettext("missing pool argument\n"));
871 		usage(B_FALSE);
872 	}
873 
874 	ret = 0;
875 	for (i = 0; i < argc; i++) {
876 		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
877 			ret = 1;
878 			continue;
879 		}
880 
881 		if (zpool_disable_datasets(zhp, force) != 0) {
882 			ret = 1;
883 			zpool_close(zhp);
884 			continue;
885 		}
886 
887 		zpool_log_history(g_zfs, argc + optind, argv - optind, argv[i],
888 		    B_TRUE, B_FALSE);
889 
890 		if (zpool_export(zhp) != 0)
891 			ret = 1;
892 
893 		zpool_close(zhp);
894 	}
895 
896 	return (ret);
897 }
898 
899 /*
900  * Given a vdev configuration, determine the maximum width needed for the device
901  * name column.
902  */
903 static int
904 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
905 {
906 	char *name = zpool_vdev_name(g_zfs, zhp, nv);
907 	nvlist_t **child;
908 	uint_t c, children;
909 	int ret;
910 
911 	if (strlen(name) + depth > max)
912 		max = strlen(name) + depth;
913 
914 	free(name);
915 
916 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
917 	    &child, &children) == 0) {
918 		for (c = 0; c < children; c++)
919 			if ((ret = max_width(zhp, child[c], depth + 2,
920 			    max)) > max)
921 				max = ret;
922 	}
923 
924 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
925 	    &child, &children) == 0) {
926 		for (c = 0; c < children; c++)
927 			if ((ret = max_width(zhp, child[c], depth + 2,
928 			    max)) > max)
929 				max = ret;
930 	}
931 
932 
933 	return (max);
934 }
935 
936 
937 /*
938  * Print the configuration of an exported pool.  Iterate over all vdevs in the
939  * pool, printing out the name and status for each one.
940  */
941 void
942 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
943 {
944 	nvlist_t **child;
945 	uint_t c, children;
946 	vdev_stat_t *vs;
947 	char *type, *vname;
948 
949 	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
950 	if (strcmp(type, VDEV_TYPE_MISSING) == 0)
951 		return;
952 
953 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
954 	    (uint64_t **)&vs, &c) == 0);
955 
956 	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
957 	(void) printf("  %s", state_to_name(vs));
958 
959 	if (vs->vs_aux != 0) {
960 		(void) printf("  ");
961 
962 		switch (vs->vs_aux) {
963 		case VDEV_AUX_OPEN_FAILED:
964 			(void) printf(gettext("cannot open"));
965 			break;
966 
967 		case VDEV_AUX_BAD_GUID_SUM:
968 			(void) printf(gettext("missing device"));
969 			break;
970 
971 		case VDEV_AUX_NO_REPLICAS:
972 			(void) printf(gettext("insufficient replicas"));
973 			break;
974 
975 		case VDEV_AUX_VERSION_NEWER:
976 			(void) printf(gettext("newer version"));
977 			break;
978 
979 		case VDEV_AUX_ERR_EXCEEDED:
980 			(void) printf(gettext("too many errors"));
981 			break;
982 
983 		default:
984 			(void) printf(gettext("corrupted data"));
985 			break;
986 		}
987 	}
988 	(void) printf("\n");
989 
990 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
991 	    &child, &children) != 0)
992 		return;
993 
994 	for (c = 0; c < children; c++) {
995 		vname = zpool_vdev_name(g_zfs, NULL, child[c]);
996 		print_import_config(vname, child[c],
997 		    namewidth, depth + 2);
998 		free(vname);
999 	}
1000 
1001 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1002 	    &child, &children) != 0)
1003 		return;
1004 
1005 	(void) printf(gettext("\tspares\n"));
1006 	for (c = 0; c < children; c++) {
1007 		vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1008 		(void) printf("\t  %s\n", vname);
1009 		free(vname);
1010 	}
1011 }
1012 
1013 /*
1014  * Display the status for the given pool.
1015  */
1016 static void
1017 show_import(nvlist_t *config)
1018 {
1019 	uint64_t pool_state;
1020 	vdev_stat_t *vs;
1021 	char *name;
1022 	uint64_t guid;
1023 	char *msgid;
1024 	nvlist_t *nvroot;
1025 	int reason;
1026 	const char *health;
1027 	uint_t vsc;
1028 	int namewidth;
1029 
1030 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1031 	    &name) == 0);
1032 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1033 	    &guid) == 0);
1034 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1035 	    &pool_state) == 0);
1036 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1037 	    &nvroot) == 0);
1038 
1039 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1040 	    (uint64_t **)&vs, &vsc) == 0);
1041 	health = state_to_health(vs->vs_state);
1042 
1043 	reason = zpool_import_status(config, &msgid);
1044 
1045 	(void) printf(gettext("  pool: %s\n"), name);
1046 	(void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
1047 	(void) printf(gettext(" state: %s"), health);
1048 	if (pool_state == POOL_STATE_DESTROYED)
1049 		(void) printf(gettext(" (DESTROYED)"));
1050 	(void) printf("\n");
1051 
1052 	switch (reason) {
1053 	case ZPOOL_STATUS_MISSING_DEV_R:
1054 	case ZPOOL_STATUS_MISSING_DEV_NR:
1055 	case ZPOOL_STATUS_BAD_GUID_SUM:
1056 		(void) printf(gettext("status: One or more devices are missing "
1057 		    "from the system.\n"));
1058 		break;
1059 
1060 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
1061 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1062 		(void) printf(gettext("status: One or more devices contains "
1063 		    "corrupted data.\n"));
1064 		break;
1065 
1066 	case ZPOOL_STATUS_CORRUPT_DATA:
1067 		(void) printf(gettext("status: The pool data is corrupted.\n"));
1068 		break;
1069 
1070 	case ZPOOL_STATUS_OFFLINE_DEV:
1071 		(void) printf(gettext("status: One or more devices "
1072 		    "are offlined.\n"));
1073 		break;
1074 
1075 	case ZPOOL_STATUS_CORRUPT_POOL:
1076 		(void) printf(gettext("status: The pool metadata is "
1077 		    "corrupted.\n"));
1078 		break;
1079 
1080 	case ZPOOL_STATUS_VERSION_OLDER:
1081 		(void) printf(gettext("status: The pool is formatted using an "
1082 		    "older on-disk version.\n"));
1083 		break;
1084 
1085 	case ZPOOL_STATUS_VERSION_NEWER:
1086 		(void) printf(gettext("status: The pool is formatted using an "
1087 		    "incompatible version.\n"));
1088 		break;
1089 	case ZPOOL_STATUS_HOSTID_MISMATCH:
1090 		(void) printf(gettext("status: The pool was last accessed by "
1091 		    "another system.\n"));
1092 		break;
1093 	case ZPOOL_STATUS_FAULTED_DEV_R:
1094 	case ZPOOL_STATUS_FAULTED_DEV_NR:
1095 		(void) printf(gettext("status: One or more devices are "
1096 		    "faulted.\n"));
1097 		break;
1098 
1099 	default:
1100 		/*
1101 		 * No other status can be seen when importing pools.
1102 		 */
1103 		assert(reason == ZPOOL_STATUS_OK);
1104 	}
1105 
1106 	/*
1107 	 * Print out an action according to the overall state of the pool.
1108 	 */
1109 	if (vs->vs_state == VDEV_STATE_HEALTHY) {
1110 		if (reason == ZPOOL_STATUS_VERSION_OLDER)
1111 			(void) printf(gettext("action: The pool can be "
1112 			    "imported using its name or numeric identifier, "
1113 			    "though\n\tsome features will not be available "
1114 			    "without an explicit 'zpool upgrade'.\n"));
1115 		else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1116 			(void) printf(gettext("action: The pool can be "
1117 			    "imported using its name or numeric "
1118 			    "identifier and\n\tthe '-f' flag.\n"));
1119 		else
1120 			(void) printf(gettext("action: The pool can be "
1121 			    "imported using its name or numeric "
1122 			    "identifier.\n"));
1123 	} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1124 		(void) printf(gettext("action: The pool can be imported "
1125 		    "despite missing or damaged devices.  The\n\tfault "
1126 		    "tolerance of the pool may be compromised if imported.\n"));
1127 	} else {
1128 		switch (reason) {
1129 		case ZPOOL_STATUS_VERSION_NEWER:
1130 			(void) printf(gettext("action: The pool cannot be "
1131 			    "imported.  Access the pool on a system running "
1132 			    "newer\n\tsoftware, or recreate the pool from "
1133 			    "backup.\n"));
1134 			break;
1135 		case ZPOOL_STATUS_MISSING_DEV_R:
1136 		case ZPOOL_STATUS_MISSING_DEV_NR:
1137 		case ZPOOL_STATUS_BAD_GUID_SUM:
1138 			(void) printf(gettext("action: The pool cannot be "
1139 			    "imported. Attach the missing\n\tdevices and try "
1140 			    "again.\n"));
1141 			break;
1142 		default:
1143 			(void) printf(gettext("action: The pool cannot be "
1144 			    "imported due to damaged devices or data.\n"));
1145 		}
1146 	}
1147 
1148 	/*
1149 	 * If the state is "closed" or "can't open", and the aux state
1150 	 * is "corrupt data":
1151 	 */
1152 	if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1153 	    (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1154 	    (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1155 		if (pool_state == POOL_STATE_DESTROYED)
1156 			(void) printf(gettext("\tThe pool was destroyed, "
1157 			    "but can be imported using the '-Df' flags.\n"));
1158 		else if (pool_state != POOL_STATE_EXPORTED)
1159 			(void) printf(gettext("\tThe pool may be active on "
1160 			    "on another system, but can be imported using\n\t"
1161 			    "the '-f' flag.\n"));
1162 	}
1163 
1164 	if (msgid != NULL)
1165 		(void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
1166 		    msgid);
1167 
1168 	(void) printf(gettext("config:\n\n"));
1169 
1170 	namewidth = max_width(NULL, nvroot, 0, 0);
1171 	if (namewidth < 10)
1172 		namewidth = 10;
1173 	print_import_config(name, nvroot, namewidth, 0);
1174 
1175 	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1176 		(void) printf(gettext("\n\tAdditional devices are known to "
1177 		    "be part of this pool, though their\n\texact "
1178 		    "configuration cannot be determined.\n"));
1179 	}
1180 }
1181 
1182 /*
1183  * Perform the import for the given configuration.  This passes the heavy
1184  * lifting off to zpool_import(), and then mounts the datasets contained within
1185  * the pool.
1186  */
1187 static int
1188 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1189     const char *altroot, int force, int argc, char **argv)
1190 {
1191 	zpool_handle_t *zhp;
1192 	char *name;
1193 	uint64_t state;
1194 	uint64_t version;
1195 
1196 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1197 	    &name) == 0);
1198 
1199 	verify(nvlist_lookup_uint64(config,
1200 	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1201 	verify(nvlist_lookup_uint64(config,
1202 	    ZPOOL_CONFIG_VERSION, &version) == 0);
1203 	if (version > ZFS_VERSION) {
1204 		(void) fprintf(stderr, gettext("cannot import '%s': pool "
1205 		    "is formatted using a newer ZFS version\n"), name);
1206 		return (1);
1207 	} else if (state != POOL_STATE_EXPORTED && !force) {
1208 		uint64_t hostid;
1209 
1210 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1211 		    &hostid) == 0) {
1212 			if ((unsigned long)hostid != gethostid()) {
1213 				char *hostname;
1214 				uint64_t timestamp;
1215 				time_t t;
1216 
1217 				verify(nvlist_lookup_string(config,
1218 				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1219 				verify(nvlist_lookup_uint64(config,
1220 				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1221 				t = timestamp;
1222 				(void) fprintf(stderr, gettext("cannot import "
1223 				    "'%s': pool may be in use from other "
1224 				    "system, it was last accessed by %s "
1225 				    "(hostid: 0x%lx) on %s"), name, hostname,
1226 				    (unsigned long)hostid,
1227 				    asctime(localtime(&t)));
1228 				(void) fprintf(stderr, gettext("use '-f' to "
1229 				    "import anyway\n"));
1230 				return (1);
1231 			}
1232 		} else {
1233 			(void) fprintf(stderr, gettext("cannot import '%s': "
1234 			    "pool may be in use from other system\n"), name);
1235 			(void) fprintf(stderr, gettext("use '-f' to import "
1236 			    "anyway\n"));
1237 			return (1);
1238 		}
1239 	}
1240 
1241 	if (zpool_import(g_zfs, config, newname, altroot) != 0)
1242 		return (1);
1243 
1244 	if (newname != NULL)
1245 		name = (char *)newname;
1246 
1247 	zpool_log_history(g_zfs, argc, argv, name, B_TRUE, B_FALSE);
1248 
1249 	verify((zhp = zpool_open(g_zfs, name)) != NULL);
1250 
1251 	if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1252 		zpool_close(zhp);
1253 		return (1);
1254 	}
1255 
1256 	zpool_close(zhp);
1257 	return (0);
1258 }
1259 
1260 /*
1261  * zpool import [-d dir] [-D]
1262  *       import [-R root] [-D] [-d dir] [-f] -a
1263  *       import [-R root] [-D] [-d dir] [-f] <pool | id> [newpool]
1264  *
1265  *       -d	Scan in a specific directory, other than /dev/dsk.  More than
1266  *		one directory can be specified using multiple '-d' options.
1267  *
1268  *       -D     Scan for previously destroyed pools or import all or only
1269  *              specified destroyed pools.
1270  *
1271  *       -R	Temporarily import the pool, with all mountpoints relative to
1272  *		the given root.  The pool will remain exported when the machine
1273  *		is rebooted.
1274  *
1275  *       -f	Force import, even if it appears that the pool is active.
1276  *
1277  *       -a	Import all pools found.
1278  *
1279  * The import command scans for pools to import, and import pools based on pool
1280  * name and GUID.  The pool can also be renamed as part of the import process.
1281  */
1282 int
1283 zpool_do_import(int argc, char **argv)
1284 {
1285 	char **searchdirs = NULL;
1286 	int nsearch = 0;
1287 	int c;
1288 	int err;
1289 	nvlist_t *pools;
1290 	boolean_t do_all = B_FALSE;
1291 	boolean_t do_destroyed = B_FALSE;
1292 	char *altroot = NULL;
1293 	char *mntopts = NULL;
1294 	boolean_t do_force = B_FALSE;
1295 	nvpair_t *elem;
1296 	nvlist_t *config;
1297 	uint64_t searchguid;
1298 	char *searchname;
1299 	nvlist_t *found_config;
1300 	boolean_t first;
1301 	uint64_t pool_state;
1302 
1303 	/* check options */
1304 	while ((c = getopt(argc, argv, ":Dfd:R:ao:")) != -1) {
1305 		switch (c) {
1306 		case 'a':
1307 			do_all = B_TRUE;
1308 			break;
1309 		case 'd':
1310 			if (searchdirs == NULL) {
1311 				searchdirs = safe_malloc(sizeof (char *));
1312 			} else {
1313 				char **tmp = safe_malloc((nsearch + 1) *
1314 				    sizeof (char *));
1315 				bcopy(searchdirs, tmp, nsearch *
1316 				    sizeof (char *));
1317 				free(searchdirs);
1318 				searchdirs = tmp;
1319 			}
1320 			searchdirs[nsearch++] = optarg;
1321 			break;
1322 		case 'D':
1323 			do_destroyed = B_TRUE;
1324 			break;
1325 		case 'f':
1326 			do_force = B_TRUE;
1327 			break;
1328 		case 'o':
1329 			mntopts = optarg;
1330 			break;
1331 		case 'R':
1332 			altroot = optarg;
1333 			break;
1334 		case ':':
1335 			(void) fprintf(stderr, gettext("missing argument for "
1336 			    "'%c' option\n"), optopt);
1337 			usage(B_FALSE);
1338 			break;
1339 		case '?':
1340 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1341 			    optopt);
1342 			usage(B_FALSE);
1343 		}
1344 	}
1345 
1346 	argc -= optind;
1347 	argv += optind;
1348 
1349 	if (searchdirs == NULL) {
1350 		searchdirs = safe_malloc(sizeof (char *));
1351 		searchdirs[0] = "/dev/dsk";
1352 		nsearch = 1;
1353 	}
1354 
1355 	/* check argument count */
1356 	if (do_all) {
1357 		if (argc != 0) {
1358 			(void) fprintf(stderr, gettext("too many arguments\n"));
1359 			usage(B_FALSE);
1360 		}
1361 	} else {
1362 		if (argc > 2) {
1363 			(void) fprintf(stderr, gettext("too many arguments\n"));
1364 			usage(B_FALSE);
1365 		}
1366 
1367 		/*
1368 		 * Check for the SYS_CONFIG privilege.  We do this explicitly
1369 		 * here because otherwise any attempt to discover pools will
1370 		 * silently fail.
1371 		 */
1372 		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1373 			(void) fprintf(stderr, gettext("cannot "
1374 			    "discover pools: permission denied\n"));
1375 			free(searchdirs);
1376 			return (1);
1377 		}
1378 	}
1379 
1380 	if ((pools = zpool_find_import(g_zfs, nsearch, searchdirs)) == NULL) {
1381 		free(searchdirs);
1382 		return (1);
1383 	}
1384 
1385 	/*
1386 	 * We now have a list of all available pools in the given directories.
1387 	 * Depending on the arguments given, we do one of the following:
1388 	 *
1389 	 *	<none>	Iterate through all pools and display information about
1390 	 *		each one.
1391 	 *
1392 	 *	-a	Iterate through all pools and try to import each one.
1393 	 *
1394 	 *	<id>	Find the pool that corresponds to the given GUID/pool
1395 	 *		name and import that one.
1396 	 *
1397 	 *	-D	Above options applies only to destroyed pools.
1398 	 */
1399 	if (argc != 0) {
1400 		char *endptr;
1401 
1402 		errno = 0;
1403 		searchguid = strtoull(argv[0], &endptr, 10);
1404 		if (errno != 0 || *endptr != '\0')
1405 			searchname = argv[0];
1406 		else
1407 			searchname = NULL;
1408 		found_config = NULL;
1409 	}
1410 
1411 	err = 0;
1412 	elem = NULL;
1413 	first = B_TRUE;
1414 	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1415 
1416 		verify(nvpair_value_nvlist(elem, &config) == 0);
1417 
1418 		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1419 		    &pool_state) == 0);
1420 		if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1421 			continue;
1422 		if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1423 			continue;
1424 
1425 		if (argc == 0) {
1426 			if (first)
1427 				first = B_FALSE;
1428 			else if (!do_all)
1429 				(void) printf("\n");
1430 
1431 			if (do_all)
1432 				err |= do_import(config, NULL, mntopts,
1433 				    altroot, do_force, argc + optind,
1434 				    argv - optind);
1435 			else
1436 				show_import(config);
1437 		} else if (searchname != NULL) {
1438 			char *name;
1439 
1440 			/*
1441 			 * We are searching for a pool based on name.
1442 			 */
1443 			verify(nvlist_lookup_string(config,
1444 			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1445 
1446 			if (strcmp(name, searchname) == 0) {
1447 				if (found_config != NULL) {
1448 					(void) fprintf(stderr, gettext(
1449 					    "cannot import '%s': more than "
1450 					    "one matching pool\n"), searchname);
1451 					(void) fprintf(stderr, gettext(
1452 					    "import by numeric ID instead\n"));
1453 					err = B_TRUE;
1454 				}
1455 				found_config = config;
1456 			}
1457 		} else {
1458 			uint64_t guid;
1459 
1460 			/*
1461 			 * Search for a pool by guid.
1462 			 */
1463 			verify(nvlist_lookup_uint64(config,
1464 			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1465 
1466 			if (guid == searchguid)
1467 				found_config = config;
1468 		}
1469 	}
1470 
1471 	/*
1472 	 * If we were searching for a specific pool, verify that we found a
1473 	 * pool, and then do the import.
1474 	 */
1475 	if (argc != 0 && err == 0) {
1476 		if (found_config == NULL) {
1477 			(void) fprintf(stderr, gettext("cannot import '%s': "
1478 			    "no such pool available\n"), argv[0]);
1479 			err = B_TRUE;
1480 		} else {
1481 			err |= do_import(found_config, argc == 1 ? NULL :
1482 			    argv[1], mntopts, altroot, do_force, argc + optind,
1483 			    argv - optind);
1484 		}
1485 	}
1486 
1487 	/*
1488 	 * If we were just looking for pools, report an error if none were
1489 	 * found.
1490 	 */
1491 	if (argc == 0 && first)
1492 		(void) fprintf(stderr,
1493 		    gettext("no pools available to import\n"));
1494 
1495 	nvlist_free(pools);
1496 	free(searchdirs);
1497 
1498 	return (err ? 1 : 0);
1499 }
1500 
1501 typedef struct iostat_cbdata {
1502 	zpool_list_t *cb_list;
1503 	int cb_verbose;
1504 	int cb_iteration;
1505 	int cb_namewidth;
1506 } iostat_cbdata_t;
1507 
1508 static void
1509 print_iostat_separator(iostat_cbdata_t *cb)
1510 {
1511 	int i = 0;
1512 
1513 	for (i = 0; i < cb->cb_namewidth; i++)
1514 		(void) printf("-");
1515 	(void) printf("  -----  -----  -----  -----  -----  -----\n");
1516 }
1517 
1518 static void
1519 print_iostat_header(iostat_cbdata_t *cb)
1520 {
1521 	(void) printf("%*s     capacity     operations    bandwidth\n",
1522 	    cb->cb_namewidth, "");
1523 	(void) printf("%-*s   used  avail   read  write   read  write\n",
1524 	    cb->cb_namewidth, "pool");
1525 	print_iostat_separator(cb);
1526 }
1527 
1528 /*
1529  * Display a single statistic.
1530  */
1531 void
1532 print_one_stat(uint64_t value)
1533 {
1534 	char buf[64];
1535 
1536 	zfs_nicenum(value, buf, sizeof (buf));
1537 	(void) printf("  %5s", buf);
1538 }
1539 
1540 /*
1541  * Print out all the statistics for the given vdev.  This can either be the
1542  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
1543  * is a verbose output, and we don't want to display the toplevel pool stats.
1544  */
1545 void
1546 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1547     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1548 {
1549 	nvlist_t **oldchild, **newchild;
1550 	uint_t c, children;
1551 	vdev_stat_t *oldvs, *newvs;
1552 	vdev_stat_t zerovs = { 0 };
1553 	uint64_t tdelta;
1554 	double scale;
1555 	char *vname;
1556 
1557 	if (oldnv != NULL) {
1558 		verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1559 		    (uint64_t **)&oldvs, &c) == 0);
1560 	} else {
1561 		oldvs = &zerovs;
1562 	}
1563 
1564 	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1565 	    (uint64_t **)&newvs, &c) == 0);
1566 
1567 	if (strlen(name) + depth > cb->cb_namewidth)
1568 		(void) printf("%*s%s", depth, "", name);
1569 	else
1570 		(void) printf("%*s%s%*s", depth, "", name,
1571 		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
1572 
1573 	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1574 
1575 	if (tdelta == 0)
1576 		scale = 1.0;
1577 	else
1578 		scale = (double)NANOSEC / tdelta;
1579 
1580 	/* only toplevel vdevs have capacity stats */
1581 	if (newvs->vs_space == 0) {
1582 		(void) printf("      -      -");
1583 	} else {
1584 		print_one_stat(newvs->vs_alloc);
1585 		print_one_stat(newvs->vs_space - newvs->vs_alloc);
1586 	}
1587 
1588 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1589 	    oldvs->vs_ops[ZIO_TYPE_READ])));
1590 
1591 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1592 	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
1593 
1594 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1595 	    oldvs->vs_bytes[ZIO_TYPE_READ])));
1596 
1597 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1598 	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1599 
1600 	(void) printf("\n");
1601 
1602 	if (!cb->cb_verbose)
1603 		return;
1604 
1605 	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1606 	    &newchild, &children) != 0)
1607 		return;
1608 
1609 	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1610 	    &oldchild, &c) != 0)
1611 		return;
1612 
1613 	for (c = 0; c < children; c++) {
1614 		vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1615 		print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1616 		    newchild[c], cb, depth + 2);
1617 		free(vname);
1618 	}
1619 }
1620 
1621 static int
1622 refresh_iostat(zpool_handle_t *zhp, void *data)
1623 {
1624 	iostat_cbdata_t *cb = data;
1625 	boolean_t missing;
1626 
1627 	/*
1628 	 * If the pool has disappeared, remove it from the list and continue.
1629 	 */
1630 	if (zpool_refresh_stats(zhp, &missing) != 0)
1631 		return (-1);
1632 
1633 	if (missing)
1634 		pool_list_remove(cb->cb_list, zhp);
1635 
1636 	return (0);
1637 }
1638 
1639 /*
1640  * Callback to print out the iostats for the given pool.
1641  */
1642 int
1643 print_iostat(zpool_handle_t *zhp, void *data)
1644 {
1645 	iostat_cbdata_t *cb = data;
1646 	nvlist_t *oldconfig, *newconfig;
1647 	nvlist_t *oldnvroot, *newnvroot;
1648 
1649 	newconfig = zpool_get_config(zhp, &oldconfig);
1650 
1651 	if (cb->cb_iteration == 1)
1652 		oldconfig = NULL;
1653 
1654 	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1655 	    &newnvroot) == 0);
1656 
1657 	if (oldconfig == NULL)
1658 		oldnvroot = NULL;
1659 	else
1660 		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1661 		    &oldnvroot) == 0);
1662 
1663 	/*
1664 	 * Print out the statistics for the pool.
1665 	 */
1666 	print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1667 
1668 	if (cb->cb_verbose)
1669 		print_iostat_separator(cb);
1670 
1671 	return (0);
1672 }
1673 
1674 int
1675 get_namewidth(zpool_handle_t *zhp, void *data)
1676 {
1677 	iostat_cbdata_t *cb = data;
1678 	nvlist_t *config, *nvroot;
1679 
1680 	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1681 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1682 		    &nvroot) == 0);
1683 		if (!cb->cb_verbose)
1684 			cb->cb_namewidth = strlen(zpool_get_name(zhp));
1685 		else
1686 			cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1687 	}
1688 
1689 	/*
1690 	 * The width must fall into the range [10,38].  The upper limit is the
1691 	 * maximum we can have and still fit in 80 columns.
1692 	 */
1693 	if (cb->cb_namewidth < 10)
1694 		cb->cb_namewidth = 10;
1695 	if (cb->cb_namewidth > 38)
1696 		cb->cb_namewidth = 38;
1697 
1698 	return (0);
1699 }
1700 
1701 /*
1702  * zpool iostat [-v] [pool] ... [interval [count]]
1703  *
1704  *	-v	Display statistics for individual vdevs
1705  *
1706  * This command can be tricky because we want to be able to deal with pool
1707  * creation/destruction as well as vdev configuration changes.  The bulk of this
1708  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
1709  * on pool_list_update() to detect the addition of new pools.  Configuration
1710  * changes are all handled within libzfs.
1711  */
1712 int
1713 zpool_do_iostat(int argc, char **argv)
1714 {
1715 	int c;
1716 	int ret;
1717 	int npools;
1718 	unsigned long interval = 0, count = 0;
1719 	zpool_list_t *list;
1720 	boolean_t verbose = B_FALSE;
1721 	iostat_cbdata_t cb;
1722 
1723 	/* check options */
1724 	while ((c = getopt(argc, argv, "v")) != -1) {
1725 		switch (c) {
1726 		case 'v':
1727 			verbose = B_TRUE;
1728 			break;
1729 		case '?':
1730 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1731 			    optopt);
1732 			usage(B_FALSE);
1733 		}
1734 	}
1735 
1736 	argc -= optind;
1737 	argv += optind;
1738 
1739 	/*
1740 	 * Determine if the last argument is an integer or a pool name
1741 	 */
1742 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
1743 		char *end;
1744 
1745 		errno = 0;
1746 		interval = strtoul(argv[argc - 1], &end, 10);
1747 
1748 		if (*end == '\0' && errno == 0) {
1749 			if (interval == 0) {
1750 				(void) fprintf(stderr, gettext("interval "
1751 				    "cannot be zero\n"));
1752 				usage(B_FALSE);
1753 			}
1754 
1755 			/*
1756 			 * Ignore the last parameter
1757 			 */
1758 			argc--;
1759 		} else {
1760 			/*
1761 			 * If this is not a valid number, just plow on.  The
1762 			 * user will get a more informative error message later
1763 			 * on.
1764 			 */
1765 			interval = 0;
1766 		}
1767 	}
1768 
1769 	/*
1770 	 * If the last argument is also an integer, then we have both a count
1771 	 * and an integer.
1772 	 */
1773 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
1774 		char *end;
1775 
1776 		errno = 0;
1777 		count = interval;
1778 		interval = strtoul(argv[argc - 1], &end, 10);
1779 
1780 		if (*end == '\0' && errno == 0) {
1781 			if (interval == 0) {
1782 				(void) fprintf(stderr, gettext("interval "
1783 				    "cannot be zero\n"));
1784 				usage(B_FALSE);
1785 			}
1786 
1787 			/*
1788 			 * Ignore the last parameter
1789 			 */
1790 			argc--;
1791 		} else {
1792 			interval = 0;
1793 		}
1794 	}
1795 
1796 	/*
1797 	 * Construct the list of all interesting pools.
1798 	 */
1799 	ret = 0;
1800 	if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1801 		return (1);
1802 
1803 	if (pool_list_count(list) == 0 && argc != 0) {
1804 		pool_list_free(list);
1805 		return (1);
1806 	}
1807 
1808 	if (pool_list_count(list) == 0 && interval == 0) {
1809 		pool_list_free(list);
1810 		(void) fprintf(stderr, gettext("no pools available\n"));
1811 		return (1);
1812 	}
1813 
1814 	/*
1815 	 * Enter the main iostat loop.
1816 	 */
1817 	cb.cb_list = list;
1818 	cb.cb_verbose = verbose;
1819 	cb.cb_iteration = 0;
1820 	cb.cb_namewidth = 0;
1821 
1822 	for (;;) {
1823 		pool_list_update(list);
1824 
1825 		if ((npools = pool_list_count(list)) == 0)
1826 			break;
1827 
1828 		/*
1829 		 * Refresh all statistics.  This is done as an explicit step
1830 		 * before calculating the maximum name width, so that any
1831 		 * configuration changes are properly accounted for.
1832 		 */
1833 		(void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1834 
1835 		/*
1836 		 * Iterate over all pools to determine the maximum width
1837 		 * for the pool / device name column across all pools.
1838 		 */
1839 		cb.cb_namewidth = 0;
1840 		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
1841 
1842 		/*
1843 		 * If it's the first time, or verbose mode, print the header.
1844 		 */
1845 		if (++cb.cb_iteration == 1 || verbose)
1846 			print_iostat_header(&cb);
1847 
1848 		(void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
1849 
1850 		/*
1851 		 * If there's more than one pool, and we're not in verbose mode
1852 		 * (which prints a separator for us), then print a separator.
1853 		 */
1854 		if (npools > 1 && !verbose)
1855 			print_iostat_separator(&cb);
1856 
1857 		if (verbose)
1858 			(void) printf("\n");
1859 
1860 		/*
1861 		 * Flush the output so that redirection to a file isn't buffered
1862 		 * indefinitely.
1863 		 */
1864 		(void) fflush(stdout);
1865 
1866 		if (interval == 0)
1867 			break;
1868 
1869 		if (count != 0 && --count == 0)
1870 			break;
1871 
1872 		(void) sleep(interval);
1873 	}
1874 
1875 	pool_list_free(list);
1876 
1877 	return (ret);
1878 }
1879 
1880 typedef struct list_cbdata {
1881 	boolean_t	cb_scripted;
1882 	boolean_t	cb_first;
1883 	int		cb_fields[MAX_FIELDS];
1884 	int		cb_fieldcount;
1885 } list_cbdata_t;
1886 
1887 /*
1888  * Given a list of columns to display, output appropriate headers for each one.
1889  */
1890 void
1891 print_header(int *fields, size_t count)
1892 {
1893 	int i;
1894 	column_def_t *col;
1895 	const char *fmt;
1896 
1897 	for (i = 0; i < count; i++) {
1898 		col = &column_table[fields[i]];
1899 		if (i != 0)
1900 			(void) printf("  ");
1901 		if (col->cd_justify == left_justify)
1902 			fmt = "%-*s";
1903 		else
1904 			fmt = "%*s";
1905 
1906 		(void) printf(fmt, i == count - 1 ? strlen(col->cd_title) :
1907 		    col->cd_width, col->cd_title);
1908 	}
1909 
1910 	(void) printf("\n");
1911 }
1912 
1913 int
1914 list_callback(zpool_handle_t *zhp, void *data)
1915 {
1916 	list_cbdata_t *cbp = data;
1917 	nvlist_t *config;
1918 	int i;
1919 	char buf[ZPOOL_MAXNAMELEN];
1920 	uint64_t total;
1921 	uint64_t used;
1922 	const char *fmt;
1923 	column_def_t *col;
1924 
1925 	if (cbp->cb_first) {
1926 		if (!cbp->cb_scripted)
1927 			print_header(cbp->cb_fields, cbp->cb_fieldcount);
1928 		cbp->cb_first = B_FALSE;
1929 	}
1930 
1931 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
1932 		config = NULL;
1933 	} else {
1934 		config = zpool_get_config(zhp, NULL);
1935 		total = zpool_get_space_total(zhp);
1936 		used = zpool_get_space_used(zhp);
1937 	}
1938 
1939 	for (i = 0; i < cbp->cb_fieldcount; i++) {
1940 		if (i != 0) {
1941 			if (cbp->cb_scripted)
1942 				(void) printf("\t");
1943 			else
1944 				(void) printf("  ");
1945 		}
1946 
1947 		col = &column_table[cbp->cb_fields[i]];
1948 
1949 		switch (cbp->cb_fields[i]) {
1950 		case ZPOOL_FIELD_NAME:
1951 			(void) strlcpy(buf, zpool_get_name(zhp), sizeof (buf));
1952 			break;
1953 
1954 		case ZPOOL_FIELD_SIZE:
1955 			if (config == NULL)
1956 				(void) strlcpy(buf, "-", sizeof (buf));
1957 			else
1958 				zfs_nicenum(total, buf, sizeof (buf));
1959 			break;
1960 
1961 		case ZPOOL_FIELD_USED:
1962 			if (config == NULL)
1963 				(void) strlcpy(buf, "-", sizeof (buf));
1964 			else
1965 				zfs_nicenum(used, buf, sizeof (buf));
1966 			break;
1967 
1968 		case ZPOOL_FIELD_AVAILABLE:
1969 			if (config == NULL)
1970 				(void) strlcpy(buf, "-", sizeof (buf));
1971 			else
1972 				zfs_nicenum(total - used, buf, sizeof (buf));
1973 			break;
1974 
1975 		case ZPOOL_FIELD_CAPACITY:
1976 			if (config == NULL) {
1977 				(void) strlcpy(buf, "-", sizeof (buf));
1978 			} else {
1979 				uint64_t capacity = (total == 0 ? 0 :
1980 				    (used * 100 / total));
1981 				(void) snprintf(buf, sizeof (buf), "%llu%%",
1982 				    (u_longlong_t)capacity);
1983 			}
1984 			break;
1985 
1986 		case ZPOOL_FIELD_HEALTH:
1987 			if (config == NULL) {
1988 				(void) strlcpy(buf, "FAULTED", sizeof (buf));
1989 			} else {
1990 				nvlist_t *nvroot;
1991 				vdev_stat_t *vs;
1992 				uint_t vsc;
1993 
1994 				verify(nvlist_lookup_nvlist(config,
1995 				    ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
1996 				verify(nvlist_lookup_uint64_array(nvroot,
1997 				    ZPOOL_CONFIG_STATS, (uint64_t **)&vs,
1998 				    &vsc) == 0);
1999 				(void) strlcpy(buf, state_to_name(vs),
2000 				    sizeof (buf));
2001 			}
2002 			break;
2003 
2004 		case ZPOOL_FIELD_ROOT:
2005 			if (config == NULL)
2006 				(void) strlcpy(buf, "-", sizeof (buf));
2007 			else if (zpool_get_root(zhp, buf, sizeof (buf)) != 0)
2008 				(void) strlcpy(buf, "-", sizeof (buf));
2009 			break;
2010 		}
2011 
2012 		if (cbp->cb_scripted)
2013 			(void) printf("%s", buf);
2014 		else {
2015 			if (col->cd_justify == left_justify)
2016 				fmt = "%-*s";
2017 			else
2018 				fmt = "%*s";
2019 
2020 			(void) printf(fmt, i == cbp->cb_fieldcount - 1 ?
2021 			    strlen(buf) : col->cd_width, buf);
2022 		}
2023 	}
2024 
2025 	(void) printf("\n");
2026 
2027 	return (0);
2028 }
2029 
2030 /*
2031  * zpool list [-H] [-o field[,field]*] [pool] ...
2032  *
2033  *	-H	Scripted mode.  Don't display headers, and separate fields by
2034  *		a single tab.
2035  *	-o	List of fields to display.  Defaults to all fields, or
2036  *		"name,size,used,available,capacity,health,root"
2037  *
2038  * List all pools in the system, whether or not they're healthy.  Output space
2039  * statistics for each one, as well as health status summary.
2040  */
2041 int
2042 zpool_do_list(int argc, char **argv)
2043 {
2044 	int c;
2045 	int ret;
2046 	list_cbdata_t cb = { 0 };
2047 	static char default_fields[] =
2048 	    "name,size,used,available,capacity,health,root";
2049 	char *fields = default_fields;
2050 	char *value;
2051 
2052 	/* check options */
2053 	while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2054 		switch (c) {
2055 		case 'H':
2056 			cb.cb_scripted = B_TRUE;
2057 			break;
2058 		case 'o':
2059 			fields = optarg;
2060 			break;
2061 		case ':':
2062 			(void) fprintf(stderr, gettext("missing argument for "
2063 			    "'%c' option\n"), optopt);
2064 			usage(B_FALSE);
2065 			break;
2066 		case '?':
2067 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2068 			    optopt);
2069 			usage(B_FALSE);
2070 		}
2071 	}
2072 
2073 	argc -= optind;
2074 	argv += optind;
2075 
2076 	while (*fields != '\0') {
2077 		if (cb.cb_fieldcount == MAX_FIELDS) {
2078 			(void) fprintf(stderr, gettext("too many "
2079 			    "properties given to -o option\n"));
2080 			usage(B_FALSE);
2081 		}
2082 
2083 		if ((cb.cb_fields[cb.cb_fieldcount] = getsubopt(&fields,
2084 		    column_subopts, &value)) == -1) {
2085 			(void) fprintf(stderr, gettext("invalid property "
2086 			    "'%s'\n"), value);
2087 			usage(B_FALSE);
2088 		}
2089 
2090 		cb.cb_fieldcount++;
2091 	}
2092 
2093 
2094 	cb.cb_first = B_TRUE;
2095 
2096 	ret = for_each_pool(argc, argv, B_TRUE, NULL, list_callback, &cb);
2097 
2098 	if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2099 		(void) printf(gettext("no pools available\n"));
2100 		return (0);
2101 	}
2102 
2103 	return (ret);
2104 }
2105 
2106 static nvlist_t *
2107 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2108 {
2109 	nvlist_t **child;
2110 	uint_t c, children;
2111 	nvlist_t *match;
2112 	char *path;
2113 
2114 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2115 	    &child, &children) != 0) {
2116 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2117 		if (strncmp(name, "/dev/dsk/", 9) == 0)
2118 			name += 9;
2119 		if (strncmp(path, "/dev/dsk/", 9) == 0)
2120 			path += 9;
2121 		if (strcmp(name, path) == 0)
2122 			return (nv);
2123 		return (NULL);
2124 	}
2125 
2126 	for (c = 0; c < children; c++)
2127 		if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2128 			return (match);
2129 
2130 	return (NULL);
2131 }
2132 
2133 static int
2134 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2135 {
2136 	boolean_t force = B_FALSE;
2137 	int c;
2138 	nvlist_t *nvroot;
2139 	char *poolname, *old_disk, *new_disk;
2140 	zpool_handle_t *zhp;
2141 	int ret;
2142 	int log_argc;
2143 	char **log_argv;
2144 
2145 	/* check options */
2146 	while ((c = getopt(argc, argv, "f")) != -1) {
2147 		switch (c) {
2148 		case 'f':
2149 			force = B_TRUE;
2150 			break;
2151 		case '?':
2152 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2153 			    optopt);
2154 			usage(B_FALSE);
2155 		}
2156 	}
2157 
2158 	log_argc = argc;
2159 	log_argv = argv;
2160 	argc -= optind;
2161 	argv += optind;
2162 
2163 	/* get pool name and check number of arguments */
2164 	if (argc < 1) {
2165 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
2166 		usage(B_FALSE);
2167 	}
2168 
2169 	poolname = argv[0];
2170 
2171 	if (argc < 2) {
2172 		(void) fprintf(stderr,
2173 		    gettext("missing <device> specification\n"));
2174 		usage(B_FALSE);
2175 	}
2176 
2177 	old_disk = argv[1];
2178 
2179 	if (argc < 3) {
2180 		if (!replacing) {
2181 			(void) fprintf(stderr,
2182 			    gettext("missing <new_device> specification\n"));
2183 			usage(B_FALSE);
2184 		}
2185 		new_disk = old_disk;
2186 		argc -= 1;
2187 		argv += 1;
2188 	} else {
2189 		new_disk = argv[2];
2190 		argc -= 2;
2191 		argv += 2;
2192 	}
2193 
2194 	if (argc > 1) {
2195 		(void) fprintf(stderr, gettext("too many arguments\n"));
2196 		usage(B_FALSE);
2197 	}
2198 
2199 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2200 		return (1);
2201 
2202 	if (zpool_get_config(zhp, NULL) == NULL) {
2203 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2204 		    poolname);
2205 		zpool_close(zhp);
2206 		return (1);
2207 	}
2208 
2209 	nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, argc, argv);
2210 	if (nvroot == NULL) {
2211 		zpool_close(zhp);
2212 		return (1);
2213 	}
2214 
2215 	ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2216 
2217 	if (!ret) {
2218 		zpool_log_history(g_zfs, log_argc, log_argv, poolname, B_TRUE,
2219 		    B_FALSE);
2220 	}
2221 
2222 	nvlist_free(nvroot);
2223 	zpool_close(zhp);
2224 
2225 	return (ret);
2226 }
2227 
2228 /*
2229  * zpool replace [-f] <pool> <device> <new_device>
2230  *
2231  *	-f	Force attach, even if <new_device> appears to be in use.
2232  *
2233  * Replace <device> with <new_device>.
2234  */
2235 /* ARGSUSED */
2236 int
2237 zpool_do_replace(int argc, char **argv)
2238 {
2239 	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2240 }
2241 
2242 /*
2243  * zpool attach [-f] <pool> <device> <new_device>
2244  *
2245  *	-f	Force attach, even if <new_device> appears to be in use.
2246  *
2247  * Attach <new_device> to the mirror containing <device>.  If <device> is not
2248  * part of a mirror, then <device> will be transformed into a mirror of
2249  * <device> and <new_device>.  In either case, <new_device> will begin life
2250  * with a DTL of [0, now], and will immediately begin to resilver itself.
2251  */
2252 int
2253 zpool_do_attach(int argc, char **argv)
2254 {
2255 	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2256 }
2257 
2258 /*
2259  * zpool detach [-f] <pool> <device>
2260  *
2261  *	-f	Force detach of <device>, even if DTLs argue against it
2262  *		(not supported yet)
2263  *
2264  * Detach a device from a mirror.  The operation will be refused if <device>
2265  * is the last device in the mirror, or if the DTLs indicate that this device
2266  * has the only valid copy of some data.
2267  */
2268 /* ARGSUSED */
2269 int
2270 zpool_do_detach(int argc, char **argv)
2271 {
2272 	int c;
2273 	char *poolname, *path;
2274 	zpool_handle_t *zhp;
2275 	int ret;
2276 
2277 	/* check options */
2278 	while ((c = getopt(argc, argv, "f")) != -1) {
2279 		switch (c) {
2280 		case 'f':
2281 		case '?':
2282 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2283 			    optopt);
2284 			usage(B_FALSE);
2285 		}
2286 	}
2287 
2288 	argc -= optind;
2289 	argv += optind;
2290 
2291 	/* get pool name and check number of arguments */
2292 	if (argc < 1) {
2293 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
2294 		usage(B_FALSE);
2295 	}
2296 
2297 	if (argc < 2) {
2298 		(void) fprintf(stderr,
2299 		    gettext("missing <device> specification\n"));
2300 		usage(B_FALSE);
2301 	}
2302 
2303 	poolname = argv[0];
2304 	path = argv[1];
2305 
2306 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2307 		return (1);
2308 
2309 	ret = zpool_vdev_detach(zhp, path);
2310 
2311 	if (!ret) {
2312 		zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
2313 		    B_TRUE, B_FALSE);
2314 	}
2315 	zpool_close(zhp);
2316 
2317 	return (ret);
2318 }
2319 
2320 /*
2321  * zpool online <pool> <device> ...
2322  */
2323 int
2324 zpool_do_online(int argc, char **argv)
2325 {
2326 	int c, i;
2327 	char *poolname;
2328 	zpool_handle_t *zhp;
2329 	int ret = 0;
2330 	vdev_state_t newstate;
2331 
2332 	/* check options */
2333 	while ((c = getopt(argc, argv, "t")) != -1) {
2334 		switch (c) {
2335 		case 't':
2336 		case '?':
2337 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2338 			    optopt);
2339 			usage(B_FALSE);
2340 		}
2341 	}
2342 
2343 	argc -= optind;
2344 	argv += optind;
2345 
2346 	/* get pool name and check number of arguments */
2347 	if (argc < 1) {
2348 		(void) fprintf(stderr, gettext("missing pool name\n"));
2349 		usage(B_FALSE);
2350 	}
2351 	if (argc < 2) {
2352 		(void) fprintf(stderr, gettext("missing device name\n"));
2353 		usage(B_FALSE);
2354 	}
2355 
2356 	poolname = argv[0];
2357 
2358 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2359 		return (1);
2360 
2361 	for (i = 1; i < argc; i++) {
2362 		if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2363 			if (newstate != VDEV_STATE_HEALTHY) {
2364 				(void) printf(gettext("warning: device '%s' "
2365 				    "onlined, but remains in faulted state\n"),
2366 				    argv[i]);
2367 				if (newstate == VDEV_STATE_FAULTED)
2368 					(void) printf(gettext("use 'zpool "
2369 					    "clear' to restore a faulted "
2370 					    "device\n"));
2371 				else
2372 					(void) printf(gettext("use 'zpool "
2373 					    "replace' to replace devices "
2374 					    "that are no longer present\n"));
2375 			}
2376 		} else {
2377 			ret = 1;
2378 		}
2379 	}
2380 
2381 	if (!ret) {
2382 		zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
2383 		    B_TRUE, B_FALSE);
2384 	}
2385 	zpool_close(zhp);
2386 
2387 	return (ret);
2388 }
2389 
2390 /*
2391  * zpool offline [-ft] <pool> <device> ...
2392  *
2393  *	-f	Force the device into the offline state, even if doing
2394  *		so would appear to compromise pool availability.
2395  *		(not supported yet)
2396  *
2397  *	-t	Only take the device off-line temporarily.  The offline
2398  *		state will not be persistent across reboots.
2399  */
2400 /* ARGSUSED */
2401 int
2402 zpool_do_offline(int argc, char **argv)
2403 {
2404 	int c, i;
2405 	char *poolname;
2406 	zpool_handle_t *zhp;
2407 	int ret = 0;
2408 	boolean_t istmp = B_FALSE;
2409 
2410 	/* check options */
2411 	while ((c = getopt(argc, argv, "ft")) != -1) {
2412 		switch (c) {
2413 		case 't':
2414 			istmp = B_TRUE;
2415 			break;
2416 		case 'f':
2417 		case '?':
2418 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2419 			    optopt);
2420 			usage(B_FALSE);
2421 		}
2422 	}
2423 
2424 	argc -= optind;
2425 	argv += optind;
2426 
2427 	/* get pool name and check number of arguments */
2428 	if (argc < 1) {
2429 		(void) fprintf(stderr, gettext("missing pool name\n"));
2430 		usage(B_FALSE);
2431 	}
2432 	if (argc < 2) {
2433 		(void) fprintf(stderr, gettext("missing device name\n"));
2434 		usage(B_FALSE);
2435 	}
2436 
2437 	poolname = argv[0];
2438 
2439 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2440 		return (1);
2441 
2442 	for (i = 1; i < argc; i++) {
2443 		if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2444 			ret = 1;
2445 	}
2446 
2447 	if (!ret) {
2448 		zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
2449 		    B_TRUE, B_FALSE);
2450 	}
2451 	zpool_close(zhp);
2452 
2453 	return (ret);
2454 }
2455 
2456 /*
2457  * zpool clear <pool> [device]
2458  *
2459  * Clear all errors associated with a pool or a particular device.
2460  */
2461 int
2462 zpool_do_clear(int argc, char **argv)
2463 {
2464 	int ret = 0;
2465 	zpool_handle_t *zhp;
2466 	char *pool, *device;
2467 
2468 	if (argc < 2) {
2469 		(void) fprintf(stderr, gettext("missing pool name\n"));
2470 		usage(B_FALSE);
2471 	}
2472 
2473 	if (argc > 3) {
2474 		(void) fprintf(stderr, gettext("too many arguments\n"));
2475 		usage(B_FALSE);
2476 	}
2477 
2478 	pool = argv[1];
2479 	device = argc == 3 ? argv[2] : NULL;
2480 
2481 	if ((zhp = zpool_open(g_zfs, pool)) == NULL)
2482 		return (1);
2483 
2484 	if (zpool_clear(zhp, device) != 0)
2485 		ret = 1;
2486 
2487 	if (!ret)
2488 		zpool_log_history(g_zfs, argc, argv, pool, B_TRUE, B_FALSE);
2489 	zpool_close(zhp);
2490 
2491 	return (ret);
2492 }
2493 
2494 typedef struct scrub_cbdata {
2495 	int	cb_type;
2496 	int	cb_argc;
2497 	char	**cb_argv;
2498 } scrub_cbdata_t;
2499 
2500 int
2501 scrub_callback(zpool_handle_t *zhp, void *data)
2502 {
2503 	scrub_cbdata_t *cb = data;
2504 	int err;
2505 
2506 	/*
2507 	 * Ignore faulted pools.
2508 	 */
2509 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2510 		(void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2511 		    "currently unavailable\n"), zpool_get_name(zhp));
2512 		return (1);
2513 	}
2514 
2515 	err = zpool_scrub(zhp, cb->cb_type);
2516 
2517 	if (!err) {
2518 		zpool_log_history(g_zfs, cb->cb_argc, cb->cb_argv,
2519 		    zpool_get_name(zhp), B_TRUE, B_FALSE);
2520 	}
2521 
2522 	return (err != 0);
2523 }
2524 
2525 /*
2526  * zpool scrub [-s] <pool> ...
2527  *
2528  *	-s	Stop.  Stops any in-progress scrub.
2529  */
2530 int
2531 zpool_do_scrub(int argc, char **argv)
2532 {
2533 	int c;
2534 	scrub_cbdata_t cb;
2535 
2536 	cb.cb_type = POOL_SCRUB_EVERYTHING;
2537 
2538 	/* check options */
2539 	while ((c = getopt(argc, argv, "s")) != -1) {
2540 		switch (c) {
2541 		case 's':
2542 			cb.cb_type = POOL_SCRUB_NONE;
2543 			break;
2544 		case '?':
2545 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2546 			    optopt);
2547 			usage(B_FALSE);
2548 		}
2549 	}
2550 
2551 	cb.cb_argc = argc;
2552 	cb.cb_argv = argv;
2553 	argc -= optind;
2554 	argv += optind;
2555 
2556 	if (argc < 1) {
2557 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
2558 		usage(B_FALSE);
2559 	}
2560 
2561 	return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2562 }
2563 
2564 typedef struct status_cbdata {
2565 	int		cb_count;
2566 	boolean_t	cb_allpools;
2567 	boolean_t	cb_verbose;
2568 	boolean_t	cb_explain;
2569 	boolean_t	cb_first;
2570 } status_cbdata_t;
2571 
2572 /*
2573  * Print out detailed scrub status.
2574  */
2575 void
2576 print_scrub_status(nvlist_t *nvroot)
2577 {
2578 	vdev_stat_t *vs;
2579 	uint_t vsc;
2580 	time_t start, end, now;
2581 	double fraction_done;
2582 	uint64_t examined, total, minutes_left;
2583 	char *scrub_type;
2584 
2585 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2586 	    (uint64_t **)&vs, &vsc) == 0);
2587 
2588 	/*
2589 	 * If there's never been a scrub, there's not much to say.
2590 	 */
2591 	if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2592 		(void) printf(gettext("none requested\n"));
2593 		return;
2594 	}
2595 
2596 	scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2597 	    "resilver" : "scrub";
2598 
2599 	start = vs->vs_scrub_start;
2600 	end = vs->vs_scrub_end;
2601 	now = time(NULL);
2602 	examined = vs->vs_scrub_examined;
2603 	total = vs->vs_alloc;
2604 
2605 	if (end != 0) {
2606 		(void) printf(gettext("%s %s with %llu errors on %s"),
2607 		    scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2608 		    (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2609 		return;
2610 	}
2611 
2612 	if (examined == 0)
2613 		examined = 1;
2614 	if (examined > total)
2615 		total = examined;
2616 
2617 	fraction_done = (double)examined / total;
2618 	minutes_left = (uint64_t)((now - start) *
2619 	    (1 - fraction_done) / fraction_done / 60);
2620 
2621 	(void) printf(gettext("%s in progress, %.2f%% done, %lluh%um to go\n"),
2622 	    scrub_type, 100 * fraction_done,
2623 	    (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2624 }
2625 
2626 typedef struct spare_cbdata {
2627 	uint64_t	cb_guid;
2628 	zpool_handle_t	*cb_zhp;
2629 } spare_cbdata_t;
2630 
2631 static boolean_t
2632 find_vdev(nvlist_t *nv, uint64_t search)
2633 {
2634 	uint64_t guid;
2635 	nvlist_t **child;
2636 	uint_t c, children;
2637 
2638 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2639 	    search == guid)
2640 		return (B_TRUE);
2641 
2642 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2643 	    &child, &children) == 0) {
2644 		for (c = 0; c < children; c++)
2645 			if (find_vdev(child[c], search))
2646 				return (B_TRUE);
2647 	}
2648 
2649 	return (B_FALSE);
2650 }
2651 
2652 static int
2653 find_spare(zpool_handle_t *zhp, void *data)
2654 {
2655 	spare_cbdata_t *cbp = data;
2656 	nvlist_t *config, *nvroot;
2657 
2658 	config = zpool_get_config(zhp, NULL);
2659 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2660 	    &nvroot) == 0);
2661 
2662 	if (find_vdev(nvroot, cbp->cb_guid)) {
2663 		cbp->cb_zhp = zhp;
2664 		return (1);
2665 	}
2666 
2667 	zpool_close(zhp);
2668 	return (0);
2669 }
2670 
2671 /*
2672  * Print out configuration state as requested by status_callback.
2673  */
2674 void
2675 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2676     int namewidth, int depth, boolean_t isspare)
2677 {
2678 	nvlist_t **child;
2679 	uint_t c, children;
2680 	vdev_stat_t *vs;
2681 	char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2682 	char *vname;
2683 	uint64_t notpresent;
2684 	spare_cbdata_t cb;
2685 	const char *state;
2686 
2687 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2688 	    (uint64_t **)&vs, &c) == 0);
2689 
2690 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2691 	    &child, &children) != 0)
2692 		children = 0;
2693 
2694 	state = state_to_name(vs);
2695 	if (isspare) {
2696 		/*
2697 		 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2698 		 * online drives.
2699 		 */
2700 		if (vs->vs_aux == VDEV_AUX_SPARED)
2701 			state = "INUSE";
2702 		else if (vs->vs_state == VDEV_STATE_HEALTHY)
2703 			state = "AVAIL";
2704 	}
2705 
2706 	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
2707 	    name, state);
2708 
2709 	if (!isspare) {
2710 		zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2711 		zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2712 		zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2713 		(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2714 	}
2715 
2716 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2717 	    &notpresent) == 0) {
2718 		char *path;
2719 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2720 		(void) printf("  was %s", path);
2721 	} else if (vs->vs_aux != 0) {
2722 		(void) printf("  ");
2723 
2724 		switch (vs->vs_aux) {
2725 		case VDEV_AUX_OPEN_FAILED:
2726 			(void) printf(gettext("cannot open"));
2727 			break;
2728 
2729 		case VDEV_AUX_BAD_GUID_SUM:
2730 			(void) printf(gettext("missing device"));
2731 			break;
2732 
2733 		case VDEV_AUX_NO_REPLICAS:
2734 			(void) printf(gettext("insufficient replicas"));
2735 			break;
2736 
2737 		case VDEV_AUX_VERSION_NEWER:
2738 			(void) printf(gettext("newer version"));
2739 			break;
2740 
2741 		case VDEV_AUX_SPARED:
2742 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2743 			    &cb.cb_guid) == 0);
2744 			if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2745 				if (strcmp(zpool_get_name(cb.cb_zhp),
2746 				    zpool_get_name(zhp)) == 0)
2747 					(void) printf(gettext("currently in "
2748 					    "use"));
2749 				else
2750 					(void) printf(gettext("in use by "
2751 					    "pool '%s'"),
2752 					    zpool_get_name(cb.cb_zhp));
2753 				zpool_close(cb.cb_zhp);
2754 			} else {
2755 				(void) printf(gettext("currently in use"));
2756 			}
2757 			break;
2758 
2759 		case VDEV_AUX_ERR_EXCEEDED:
2760 			(void) printf(gettext("too many errors"));
2761 			break;
2762 
2763 		default:
2764 			(void) printf(gettext("corrupted data"));
2765 			break;
2766 		}
2767 	} else if (vs->vs_scrub_repaired != 0 && children == 0) {
2768 		/*
2769 		 * Report bytes resilvered/repaired on leaf devices.
2770 		 */
2771 		zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2772 		(void) printf(gettext("  %s %s"), repaired,
2773 		    (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2774 		    "resilvered" : "repaired");
2775 	}
2776 
2777 	(void) printf("\n");
2778 
2779 	for (c = 0; c < children; c++) {
2780 		vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2781 		print_status_config(zhp, vname, child[c],
2782 		    namewidth, depth + 2, isspare);
2783 		free(vname);
2784 	}
2785 }
2786 
2787 static void
2788 print_error_log(zpool_handle_t *zhp)
2789 {
2790 	nvlist_t *nverrlist;
2791 	nvpair_t *elem;
2792 	char *pathname;
2793 	size_t len = MAXPATHLEN * 2;
2794 
2795 	if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2796 		(void) printf("errors: List of errors unavailable "
2797 		    "(insufficient privileges)\n");
2798 		return;
2799 	}
2800 
2801 	(void) printf("errors: Permanent errors have been "
2802 	    "detected in the following files:\n\n");
2803 
2804 	pathname = safe_malloc(len);
2805 	elem = NULL;
2806 	while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2807 		nvlist_t *nv;
2808 		uint64_t dsobj, obj;
2809 
2810 		verify(nvpair_value_nvlist(elem, &nv) == 0);
2811 		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2812 		    &dsobj) == 0);
2813 		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2814 		    &obj) == 0);
2815 		zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2816 		(void) printf("%7s %s\n", "", pathname);
2817 	}
2818 	free(pathname);
2819 	nvlist_free(nverrlist);
2820 }
2821 
2822 static void
2823 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2824     int namewidth)
2825 {
2826 	uint_t i;
2827 	char *name;
2828 
2829 	if (nspares == 0)
2830 		return;
2831 
2832 	(void) printf(gettext("\tspares\n"));
2833 
2834 	for (i = 0; i < nspares; i++) {
2835 		name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2836 		print_status_config(zhp, name, spares[i],
2837 		    namewidth, 2, B_TRUE);
2838 		free(name);
2839 	}
2840 }
2841 
2842 /*
2843  * Display a summary of pool status.  Displays a summary such as:
2844  *
2845  *        pool: tank
2846  *	status: DEGRADED
2847  *	reason: One or more devices ...
2848  *         see: http://www.sun.com/msg/ZFS-xxxx-01
2849  *	config:
2850  *		mirror		DEGRADED
2851  *                c1t0d0	OK
2852  *                c2t0d0	UNAVAIL
2853  *
2854  * When given the '-v' option, we print out the complete config.  If the '-e'
2855  * option is specified, then we print out error rate information as well.
2856  */
2857 int
2858 status_callback(zpool_handle_t *zhp, void *data)
2859 {
2860 	status_cbdata_t *cbp = data;
2861 	nvlist_t *config, *nvroot;
2862 	char *msgid;
2863 	int reason;
2864 	const char *health;
2865 	uint_t c;
2866 	vdev_stat_t *vs;
2867 
2868 	config = zpool_get_config(zhp, NULL);
2869 	reason = zpool_get_status(zhp, &msgid);
2870 
2871 	cbp->cb_count++;
2872 
2873 	/*
2874 	 * If we were given 'zpool status -x', only report those pools with
2875 	 * problems.
2876 	 */
2877 	if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
2878 		if (!cbp->cb_allpools) {
2879 			(void) printf(gettext("pool '%s' is healthy\n"),
2880 			    zpool_get_name(zhp));
2881 			if (cbp->cb_first)
2882 				cbp->cb_first = B_FALSE;
2883 		}
2884 		return (0);
2885 	}
2886 
2887 	if (cbp->cb_first)
2888 		cbp->cb_first = B_FALSE;
2889 	else
2890 		(void) printf("\n");
2891 
2892 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2893 	    &nvroot) == 0);
2894 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2895 	    (uint64_t **)&vs, &c) == 0);
2896 	health = state_to_name(vs);
2897 
2898 	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
2899 	(void) printf(gettext(" state: %s\n"), health);
2900 
2901 	switch (reason) {
2902 	case ZPOOL_STATUS_MISSING_DEV_R:
2903 		(void) printf(gettext("status: One or more devices could not "
2904 		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
2905 		    "continue functioning in a degraded state.\n"));
2906 		(void) printf(gettext("action: Attach the missing device and "
2907 		    "online it using 'zpool online'.\n"));
2908 		break;
2909 
2910 	case ZPOOL_STATUS_MISSING_DEV_NR:
2911 		(void) printf(gettext("status: One or more devices could not "
2912 		    "be opened.  There are insufficient\n\treplicas for the "
2913 		    "pool to continue functioning.\n"));
2914 		(void) printf(gettext("action: Attach the missing device and "
2915 		    "online it using 'zpool online'.\n"));
2916 		break;
2917 
2918 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
2919 		(void) printf(gettext("status: One or more devices could not "
2920 		    "be used because the label is missing or\n\tinvalid.  "
2921 		    "Sufficient replicas exist for the pool to continue\n\t"
2922 		    "functioning in a degraded state.\n"));
2923 		(void) printf(gettext("action: Replace the device using "
2924 		    "'zpool replace'.\n"));
2925 		break;
2926 
2927 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2928 		(void) printf(gettext("status: One or more devices could not "
2929 		    "be used because the label is missing \n\tor invalid.  "
2930 		    "There are insufficient replicas for the pool to "
2931 		    "continue\n\tfunctioning.\n"));
2932 		(void) printf(gettext("action: Destroy and re-create the pool "
2933 		    "from a backup source.\n"));
2934 		break;
2935 
2936 	case ZPOOL_STATUS_FAILING_DEV:
2937 		(void) printf(gettext("status: One or more devices has "
2938 		    "experienced an unrecoverable error.  An\n\tattempt was "
2939 		    "made to correct the error.  Applications are "
2940 		    "unaffected.\n"));
2941 		(void) printf(gettext("action: Determine if the device needs "
2942 		    "to be replaced, and clear the errors\n\tusing "
2943 		    "'zpool clear' or replace the device with 'zpool "
2944 		    "replace'.\n"));
2945 		break;
2946 
2947 	case ZPOOL_STATUS_OFFLINE_DEV:
2948 		(void) printf(gettext("status: One or more devices has "
2949 		    "been taken offline by the administrator.\n\tSufficient "
2950 		    "replicas exist for the pool to continue functioning in "
2951 		    "a\n\tdegraded state.\n"));
2952 		(void) printf(gettext("action: Online the device using "
2953 		    "'zpool online' or replace the device with\n\t'zpool "
2954 		    "replace'.\n"));
2955 		break;
2956 
2957 	case ZPOOL_STATUS_RESILVERING:
2958 		(void) printf(gettext("status: One or more devices is "
2959 		    "currently being resilvered.  The pool will\n\tcontinue "
2960 		    "to function, possibly in a degraded state.\n"));
2961 		(void) printf(gettext("action: Wait for the resilver to "
2962 		    "complete.\n"));
2963 		break;
2964 
2965 	case ZPOOL_STATUS_CORRUPT_DATA:
2966 		(void) printf(gettext("status: One or more devices has "
2967 		    "experienced an error resulting in data\n\tcorruption.  "
2968 		    "Applications may be affected.\n"));
2969 		(void) printf(gettext("action: Restore the file in question "
2970 		    "if possible.  Otherwise restore the\n\tentire pool from "
2971 		    "backup.\n"));
2972 		break;
2973 
2974 	case ZPOOL_STATUS_CORRUPT_POOL:
2975 		(void) printf(gettext("status: The pool metadata is corrupted "
2976 		    "and the pool cannot be opened.\n"));
2977 		(void) printf(gettext("action: Destroy and re-create the pool "
2978 		    "from a backup source.\n"));
2979 		break;
2980 
2981 	case ZPOOL_STATUS_VERSION_OLDER:
2982 		(void) printf(gettext("status: The pool is formatted using an "
2983 		    "older on-disk format.  The pool can\n\tstill be used, but "
2984 		    "some features are unavailable.\n"));
2985 		(void) printf(gettext("action: Upgrade the pool using 'zpool "
2986 		    "upgrade'.  Once this is done, the\n\tpool will no longer "
2987 		    "be accessible on older software versions.\n"));
2988 		break;
2989 
2990 	case ZPOOL_STATUS_VERSION_NEWER:
2991 		(void) printf(gettext("status: The pool has been upgraded to a "
2992 		    "newer, incompatible on-disk version.\n\tThe pool cannot "
2993 		    "be accessed on this system.\n"));
2994 		(void) printf(gettext("action: Access the pool from a system "
2995 		    "running more recent software, or\n\trestore the pool from "
2996 		    "backup.\n"));
2997 		break;
2998 
2999 	case ZPOOL_STATUS_FAULTED_DEV_R:
3000 		(void) printf(gettext("status: One or more devices are "
3001 		    "faulted in response to persistent errors.\n\tSufficient "
3002 		    "replicas exist for the pool to continue functioning "
3003 		    "in a\n\tdegraded state.\n"));
3004 		(void) printf(gettext("action: Replace the faulted device, "
3005 		    "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3006 		break;
3007 
3008 	case ZPOOL_STATUS_FAULTED_DEV_NR:
3009 		(void) printf(gettext("status: One or more devices are "
3010 		    "faulted in response to persistent errors.  There are "
3011 		    "insufficient replicas for the pool to\n\tcontinue "
3012 		    "functioning.\n"));
3013 		(void) printf(gettext("action: Destroy and re-create the pool "
3014 		    "from a backup source.  Manually marking the device\n"
3015 		    "\trepaired using 'zpool clear' may allow some data "
3016 		    "to be recovered.\n"));
3017 		break;
3018 
3019 	default:
3020 		/*
3021 		 * The remaining errors can't actually be generated, yet.
3022 		 */
3023 		assert(reason == ZPOOL_STATUS_OK);
3024 	}
3025 
3026 	if (msgid != NULL)
3027 		(void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
3028 		    msgid);
3029 
3030 	if (config != NULL) {
3031 		int namewidth;
3032 		uint64_t nerr;
3033 		nvlist_t **spares;
3034 		uint_t nspares;
3035 
3036 
3037 		(void) printf(gettext(" scrub: "));
3038 		print_scrub_status(nvroot);
3039 
3040 		namewidth = max_width(zhp, nvroot, 0, 0);
3041 		if (namewidth < 10)
3042 			namewidth = 10;
3043 
3044 		(void) printf(gettext("config:\n\n"));
3045 		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
3046 		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
3047 		print_status_config(zhp, zpool_get_name(zhp), nvroot,
3048 		    namewidth, 0, B_FALSE);
3049 
3050 		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3051 		    &spares, &nspares) == 0)
3052 			print_spares(zhp, spares, nspares, namewidth);
3053 
3054 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3055 		    &nerr) == 0) {
3056 			nvlist_t *nverrlist = NULL;
3057 
3058 			/*
3059 			 * If the approximate error count is small, get a
3060 			 * precise count by fetching the entire log and
3061 			 * uniquifying the results.
3062 			 */
3063 			if (nerr < 100 && !cbp->cb_verbose &&
3064 			    zpool_get_errlog(zhp, &nverrlist) == 0) {
3065 				nvpair_t *elem;
3066 
3067 				elem = NULL;
3068 				nerr = 0;
3069 				while ((elem = nvlist_next_nvpair(nverrlist,
3070 				    elem)) != NULL) {
3071 					nerr++;
3072 				}
3073 			}
3074 			nvlist_free(nverrlist);
3075 
3076 			(void) printf("\n");
3077 
3078 			if (nerr == 0)
3079 				(void) printf(gettext("errors: No known data "
3080 				    "errors\n"));
3081 			else if (!cbp->cb_verbose)
3082 				(void) printf(gettext("errors: %llu data "
3083 				    "errors, use '-v' for a list\n"),
3084 				    (u_longlong_t)nerr);
3085 			else
3086 				print_error_log(zhp);
3087 		}
3088 	} else {
3089 		(void) printf(gettext("config: The configuration cannot be "
3090 		    "determined.\n"));
3091 	}
3092 
3093 	return (0);
3094 }
3095 
3096 /*
3097  * zpool status [-vx] [pool] ...
3098  *
3099  *	-v	Display complete error logs
3100  *	-x	Display only pools with potential problems
3101  *
3102  * Describes the health status of all pools or some subset.
3103  */
3104 int
3105 zpool_do_status(int argc, char **argv)
3106 {
3107 	int c;
3108 	int ret;
3109 	status_cbdata_t cb = { 0 };
3110 
3111 	/* check options */
3112 	while ((c = getopt(argc, argv, "vx")) != -1) {
3113 		switch (c) {
3114 		case 'v':
3115 			cb.cb_verbose = B_TRUE;
3116 			break;
3117 		case 'x':
3118 			cb.cb_explain = B_TRUE;
3119 			break;
3120 		case '?':
3121 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3122 			    optopt);
3123 			usage(B_FALSE);
3124 		}
3125 	}
3126 
3127 	argc -= optind;
3128 	argv += optind;
3129 
3130 	cb.cb_first = B_TRUE;
3131 
3132 	if (argc == 0)
3133 		cb.cb_allpools = B_TRUE;
3134 
3135 	ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3136 
3137 	if (argc == 0 && cb.cb_count == 0)
3138 		(void) printf(gettext("no pools available\n"));
3139 	else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3140 		(void) printf(gettext("all pools are healthy\n"));
3141 
3142 	return (ret);
3143 }
3144 
3145 typedef struct upgrade_cbdata {
3146 	int	cb_all;
3147 	int	cb_first;
3148 	int	cb_newer;
3149 	int	cb_argc;
3150 	char	**cb_argv;
3151 } upgrade_cbdata_t;
3152 
3153 static int
3154 upgrade_cb(zpool_handle_t *zhp, void *arg)
3155 {
3156 	upgrade_cbdata_t *cbp = arg;
3157 	nvlist_t *config;
3158 	uint64_t version;
3159 	int ret = 0;
3160 
3161 	config = zpool_get_config(zhp, NULL);
3162 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3163 	    &version) == 0);
3164 
3165 	if (!cbp->cb_newer && version < ZFS_VERSION) {
3166 		if (!cbp->cb_all) {
3167 			if (cbp->cb_first) {
3168 				(void) printf(gettext("The following pools are "
3169 				    "out of date, and can be upgraded.  After "
3170 				    "being\nupgraded, these pools will no "
3171 				    "longer be accessible by older software "
3172 				    "versions.\n\n"));
3173 				(void) printf(gettext("VER  POOL\n"));
3174 				(void) printf(gettext("---  ------------\n"));
3175 				cbp->cb_first = B_FALSE;
3176 			}
3177 
3178 			(void) printf("%2llu   %s\n", (u_longlong_t)version,
3179 			    zpool_get_name(zhp));
3180 		} else {
3181 			cbp->cb_first = B_FALSE;
3182 			ret = zpool_upgrade(zhp);
3183 			if (!ret) {
3184 				zpool_log_history(g_zfs, cbp->cb_argc,
3185 				    cbp->cb_argv, zpool_get_name(zhp), B_TRUE,
3186 				    B_FALSE);
3187 				(void) printf(gettext("Successfully upgraded "
3188 				    "'%s'\n"), zpool_get_name(zhp));
3189 			}
3190 		}
3191 	} else if (cbp->cb_newer && version > ZFS_VERSION) {
3192 		assert(!cbp->cb_all);
3193 
3194 		if (cbp->cb_first) {
3195 			(void) printf(gettext("The following pools are "
3196 			    "formatted using a newer software version and\n"
3197 			    "cannot be accessed on the current system.\n\n"));
3198 			(void) printf(gettext("VER  POOL\n"));
3199 			(void) printf(gettext("---  ------------\n"));
3200 			cbp->cb_first = B_FALSE;
3201 		}
3202 
3203 		(void) printf("%2llu   %s\n", (u_longlong_t)version,
3204 		    zpool_get_name(zhp));
3205 	}
3206 
3207 	zpool_close(zhp);
3208 	return (ret);
3209 }
3210 
3211 /* ARGSUSED */
3212 static int
3213 upgrade_one(zpool_handle_t *zhp, void *data)
3214 {
3215 	nvlist_t *config;
3216 	uint64_t version;
3217 	int ret;
3218 	upgrade_cbdata_t *cbp = data;
3219 
3220 	config = zpool_get_config(zhp, NULL);
3221 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3222 	    &version) == 0);
3223 
3224 	if (version == ZFS_VERSION) {
3225 		(void) printf(gettext("Pool '%s' is already formatted "
3226 		    "using the current version.\n"), zpool_get_name(zhp));
3227 		return (0);
3228 	}
3229 
3230 	ret = zpool_upgrade(zhp);
3231 
3232 	if (!ret) {
3233 		zpool_log_history(g_zfs, cbp->cb_argc, cbp->cb_argv,
3234 		    zpool_get_name(zhp), B_TRUE, B_FALSE);
3235 		(void) printf(gettext("Successfully upgraded '%s' "
3236 		    "from version %llu to version %llu\n"), zpool_get_name(zhp),
3237 		    (u_longlong_t)version, (u_longlong_t)ZFS_VERSION);
3238 	}
3239 
3240 	return (ret != 0);
3241 }
3242 
3243 /*
3244  * zpool upgrade
3245  * zpool upgrade -v
3246  * zpool upgrade <-a | pool>
3247  *
3248  * With no arguments, display downrev'd ZFS pool available for upgrade.
3249  * Individual pools can be upgraded by specifying the pool, and '-a' will
3250  * upgrade all pools.
3251  */
3252 int
3253 zpool_do_upgrade(int argc, char **argv)
3254 {
3255 	int c;
3256 	upgrade_cbdata_t cb = { 0 };
3257 	int ret = 0;
3258 	boolean_t showversions = B_FALSE;
3259 
3260 	/* check options */
3261 	while ((c = getopt(argc, argv, "av")) != -1) {
3262 		switch (c) {
3263 		case 'a':
3264 			cb.cb_all = B_TRUE;
3265 			break;
3266 		case 'v':
3267 			showversions = B_TRUE;
3268 			break;
3269 		case '?':
3270 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3271 			    optopt);
3272 			usage(B_FALSE);
3273 		}
3274 	}
3275 
3276 	cb.cb_argc = argc;
3277 	cb.cb_argv = argv;
3278 	argc -= optind;
3279 	argv += optind;
3280 
3281 	if (showversions) {
3282 		if (cb.cb_all || argc != 0) {
3283 			(void) fprintf(stderr, gettext("-v option is "
3284 			    "incompatible with other arguments\n"));
3285 			usage(B_FALSE);
3286 		}
3287 	} else if (cb.cb_all) {
3288 		if (argc != 0) {
3289 			(void) fprintf(stderr, gettext("-a option is "
3290 			    "incompatible with other arguments\n"));
3291 			usage(B_FALSE);
3292 		}
3293 	}
3294 
3295 	(void) printf(gettext("This system is currently running ZFS version "
3296 	    "%llu.\n\n"), ZFS_VERSION);
3297 	cb.cb_first = B_TRUE;
3298 	if (showversions) {
3299 		(void) printf(gettext("The following versions are "
3300 		    "supported:\n\n"));
3301 		(void) printf(gettext("VER  DESCRIPTION\n"));
3302 		(void) printf("---  -----------------------------------------"
3303 		    "---------------\n");
3304 		(void) printf(gettext(" 1   Initial ZFS version\n"));
3305 		(void) printf(gettext(" 2   Ditto blocks "
3306 		    "(replicated metadata)\n"));
3307 		(void) printf(gettext(" 3   Hot spares and double parity "
3308 		    "RAID-Z\n"));
3309 		(void) printf(gettext(" 4   zpool history\n"));
3310 		(void) printf(gettext(" 5   Compression using the gzip "
3311 		    "algorithm\n"));
3312 		(void) printf(gettext(" 6   pool properties "));
3313 		(void) printf(gettext("\nFor more information on a particular "
3314 		    "version, including supported releases, see:\n\n"));
3315 		(void) printf("http://www.opensolaris.org/os/community/zfs/"
3316 		    "version/N\n\n");
3317 		(void) printf(gettext("Where 'N' is the version number.\n"));
3318 	} else if (argc == 0) {
3319 		int notfound;
3320 
3321 		ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3322 		notfound = cb.cb_first;
3323 
3324 		if (!cb.cb_all && ret == 0) {
3325 			if (!cb.cb_first)
3326 				(void) printf("\n");
3327 			cb.cb_first = B_TRUE;
3328 			cb.cb_newer = B_TRUE;
3329 			ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3330 			if (!cb.cb_first) {
3331 				notfound = B_FALSE;
3332 				(void) printf("\n");
3333 			}
3334 		}
3335 
3336 		if (ret == 0) {
3337 			if (notfound)
3338 				(void) printf(gettext("All pools are formatted "
3339 				    "using this version.\n"));
3340 			else if (!cb.cb_all)
3341 				(void) printf(gettext("Use 'zpool upgrade -v' "
3342 				    "for a list of available versions and "
3343 				    "their associated\nfeatures.\n"));
3344 		}
3345 	} else {
3346 		ret = for_each_pool(argc, argv, B_FALSE, NULL,
3347 		    upgrade_one, &cb);
3348 	}
3349 
3350 	return (ret);
3351 }
3352 
3353 /*
3354  * Print out the command history for a specific pool.
3355  */
3356 static int
3357 get_history_one(zpool_handle_t *zhp, void *data)
3358 {
3359 	nvlist_t *nvhis;
3360 	nvlist_t **records;
3361 	uint_t numrecords;
3362 	char *cmdstr;
3363 	uint64_t dst_time;
3364 	time_t tsec;
3365 	struct tm t;
3366 	char tbuf[30];
3367 	int ret, i;
3368 
3369 	*(boolean_t *)data = B_FALSE;
3370 
3371 	(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3372 
3373 	if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3374 		return (ret);
3375 
3376 	verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3377 	    &records, &numrecords) == 0);
3378 	for (i = 0; i < numrecords; i++) {
3379 		if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3380 		    &dst_time) == 0) {
3381 			verify(nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3382 			    &cmdstr) == 0);
3383 			tsec = dst_time;
3384 			(void) localtime_r(&tsec, &t);
3385 			(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3386 			(void) printf("%s %s\n", tbuf, cmdstr);
3387 		}
3388 	}
3389 	(void) printf("\n");
3390 	nvlist_free(nvhis);
3391 
3392 	return (ret);
3393 }
3394 
3395 /*
3396  * zpool history <pool>
3397  *
3398  * Displays the history of commands that modified pools.
3399  */
3400 int
3401 zpool_do_history(int argc, char **argv)
3402 {
3403 	boolean_t first = B_TRUE;
3404 	int ret;
3405 
3406 	argc -= optind;
3407 	argv += optind;
3408 
3409 	ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
3410 	    &first);
3411 
3412 	if (argc == 0 && first == B_TRUE) {
3413 		(void) printf(gettext("no pools available\n"));
3414 		return (0);
3415 	}
3416 
3417 	return (ret);
3418 }
3419 
3420 static int
3421 get_callback(zpool_handle_t *zhp, void *data)
3422 {
3423 	libzfs_get_cbdata_t *cbp = (libzfs_get_cbdata_t *)data;
3424 	char value[MAXNAMELEN];
3425 	zfs_source_t srctype;
3426 	zpool_proplist_t *pl;
3427 
3428 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3429 
3430 		/*
3431 		 * Skip the special fake placeholder.
3432 		 */
3433 		if (pl->pl_prop == ZFS_PROP_NAME &&
3434 		    pl == cbp->cb_proplist)
3435 			continue;
3436 
3437 		if (zpool_get_prop(zhp, pl->pl_prop,
3438 		    value, sizeof (value), &srctype) != 0)
3439 			continue;
3440 
3441 		libzfs_print_one_property(zpool_get_name(zhp), cbp,
3442 		    zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3443 	}
3444 	return (0);
3445 }
3446 
3447 int
3448 zpool_do_get(int argc, char **argv)
3449 {
3450 	libzfs_get_cbdata_t cb = { 0 };
3451 	zpool_proplist_t fake_name = { 0 };
3452 	int ret;
3453 
3454 	if (argc < 3)
3455 		usage(B_FALSE);
3456 
3457 	cb.cb_first = B_TRUE;
3458 	cb.cb_sources = ZFS_SRC_ALL;
3459 	cb.cb_columns[0] = GET_COL_NAME;
3460 	cb.cb_columns[1] = GET_COL_PROPERTY;
3461 	cb.cb_columns[2] = GET_COL_VALUE;
3462 	cb.cb_columns[3] = GET_COL_SOURCE;
3463 
3464 	if (zpool_get_proplist(g_zfs, argv[1],  &cb.cb_proplist) != 0)
3465 		usage(B_FALSE);
3466 
3467 	if (cb.cb_proplist != NULL) {
3468 		fake_name.pl_prop = ZFS_PROP_NAME;
3469 		fake_name.pl_width = strlen(gettext("NAME"));
3470 		fake_name.pl_next = cb.cb_proplist;
3471 		cb.cb_proplist = &fake_name;
3472 	}
3473 
3474 	ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3475 	    get_callback, &cb);
3476 
3477 	if (cb.cb_proplist == &fake_name)
3478 		zfs_free_proplist(fake_name.pl_next);
3479 	else
3480 		zfs_free_proplist(cb.cb_proplist);
3481 
3482 	return (ret);
3483 }
3484 
3485 typedef struct set_cbdata {
3486 	char *cb_propname;
3487 	char *cb_value;
3488 	boolean_t cb_any_successful;
3489 } set_cbdata_t;
3490 
3491 int
3492 set_callback(zpool_handle_t *zhp, void *data)
3493 {
3494 	int error;
3495 	set_cbdata_t *cb = (set_cbdata_t *)data;
3496 
3497 	error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3498 
3499 	if (!error)
3500 		cb->cb_any_successful = B_TRUE;
3501 
3502 	return (error);
3503 }
3504 
3505 int
3506 zpool_do_set(int argc, char **argv)
3507 {
3508 	set_cbdata_t cb = { 0 };
3509 	int error;
3510 
3511 	if (argc > 1 && argv[1][0] == '-') {
3512 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3513 		    argv[1][1]);
3514 		usage(B_FALSE);
3515 	}
3516 
3517 	if (argc < 2) {
3518 		(void) fprintf(stderr, gettext("missing property=value "
3519 		    "argument\n"));
3520 		usage(B_FALSE);
3521 	}
3522 
3523 	if (argc < 3) {
3524 		(void) fprintf(stderr, gettext("missing pool name\n"));
3525 		usage(B_FALSE);
3526 	}
3527 
3528 	if (argc > 3) {
3529 		(void) fprintf(stderr, gettext("too many pool names\n"));
3530 		usage(B_FALSE);
3531 	}
3532 
3533 	cb.cb_propname = argv[1];
3534 	cb.cb_value = strchr(cb.cb_propname, '=');
3535 	if (cb.cb_value == NULL) {
3536 		(void) fprintf(stderr, gettext("missing value in "
3537 		    "property=value argument\n"));
3538 		usage(B_FALSE);
3539 	}
3540 
3541 	*(cb.cb_value) = '\0';
3542 	cb.cb_value++;
3543 
3544 	error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3545 	    set_callback, &cb);
3546 
3547 	if (cb.cb_any_successful) {
3548 		*(cb.cb_value - 1) = '=';
3549 		zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
3550 	}
3551 
3552 	return (error);
3553 }
3554 
3555 static int
3556 find_command_idx(char *command, int *idx)
3557 {
3558 	int i;
3559 
3560 	for (i = 0; i < NCOMMAND; i++) {
3561 		if (command_table[i].name == NULL)
3562 			continue;
3563 
3564 		if (strcmp(command, command_table[i].name) == 0) {
3565 			*idx = i;
3566 			return (0);
3567 		}
3568 	}
3569 	return (1);
3570 }
3571 
3572 int
3573 main(int argc, char **argv)
3574 {
3575 	int ret;
3576 	int i;
3577 	char *cmdname;
3578 	int found = 0;
3579 
3580 	(void) setlocale(LC_ALL, "");
3581 	(void) textdomain(TEXT_DOMAIN);
3582 
3583 	if ((g_zfs = libzfs_init()) == NULL) {
3584 		(void) fprintf(stderr, gettext("internal error: failed to "
3585 		    "initialize ZFS library\n"));
3586 		return (1);
3587 	}
3588 
3589 	libzfs_print_on_error(g_zfs, B_TRUE);
3590 
3591 	opterr = 0;
3592 
3593 	/*
3594 	 * Make sure the user has specified some command.
3595 	 */
3596 	if (argc < 2) {
3597 		(void) fprintf(stderr, gettext("missing command\n"));
3598 		usage(B_FALSE);
3599 	}
3600 
3601 	cmdname = argv[1];
3602 
3603 	/*
3604 	 * Special case '-?'
3605 	 */
3606 	if (strcmp(cmdname, "-?") == 0)
3607 		usage(B_TRUE);
3608 
3609 	/*
3610 	 * Run the appropriate command.
3611 	 */
3612 	if (find_command_idx(cmdname, &i) == 0) {
3613 		current_command = &command_table[i];
3614 		ret = command_table[i].func(argc - 1, argv + 1);
3615 		found++;
3616 	}
3617 
3618 	/*
3619 	 * 'freeze' is a vile debugging abomination, so we treat it as such.
3620 	 */
3621 	if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3622 		char buf[16384];
3623 		int fd = open(ZFS_DEV, O_RDWR);
3624 		(void) strcpy((void *)buf, argv[2]);
3625 		return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
3626 	}
3627 
3628 	if (!found) {
3629 		(void) fprintf(stderr, gettext("unrecognized "
3630 		    "command '%s'\n"), cmdname);
3631 		usage(B_FALSE);
3632 	}
3633 
3634 	libzfs_fini(g_zfs);
3635 
3636 	/*
3637 	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3638 	 * for the purposes of running ::findleaks.
3639 	 */
3640 	if (getenv("ZFS_ABORT") != NULL) {
3641 		(void) printf("dumping core by request\n");
3642 		abort();
3643 	}
3644 
3645 	return (ret);
3646 }
3647