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