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