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