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