xref: /titanic_53/usr/src/cmd/zpool/zpool_main.c (revision 0a48a24e663a04e34e2ed4e55390ad96f178dbea)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5441d80aaSlling  * Common Development and Distribution License (the "License").
6441d80aaSlling  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
2199653d4eSeschrock 
22fa9e4066Sahrens /*
2318ce54dfSek110237  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24fa9e4066Sahrens  * Use is subject to license terms.
25fa9e4066Sahrens  */
26fa9e4066Sahrens 
27fa9e4066Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28fa9e4066Sahrens 
29fa9e4066Sahrens #include <assert.h>
30fa9e4066Sahrens #include <ctype.h>
31fa9e4066Sahrens #include <dirent.h>
32fa9e4066Sahrens #include <errno.h>
33fa9e4066Sahrens #include <fcntl.h>
34fa9e4066Sahrens #include <libgen.h>
35fa9e4066Sahrens #include <libintl.h>
36fa9e4066Sahrens #include <libuutil.h>
37fa9e4066Sahrens #include <locale.h>
38fa9e4066Sahrens #include <stdio.h>
39fa9e4066Sahrens #include <stdlib.h>
40fa9e4066Sahrens #include <string.h>
41fa9e4066Sahrens #include <strings.h>
42fa9e4066Sahrens #include <unistd.h>
43fa9e4066Sahrens #include <priv.h>
44ecd6cf80Smarks #include <pwd.h>
45ecd6cf80Smarks #include <zone.h>
46b1b8ab34Slling #include <sys/fs/zfs.h>
47fa9e4066Sahrens 
48fa9e4066Sahrens #include <sys/stat.h>
49fa9e4066Sahrens 
50fa9e4066Sahrens #include <libzfs.h>
51fa9e4066Sahrens 
52fa9e4066Sahrens #include "zpool_util.h"
53b7b97454Sperrin #include "zfs_comutil.h"
54fa9e4066Sahrens 
55fa9e4066Sahrens static int zpool_do_create(int, char **);
56fa9e4066Sahrens static int zpool_do_destroy(int, char **);
57fa9e4066Sahrens 
58fa9e4066Sahrens static int zpool_do_add(int, char **);
5999653d4eSeschrock static int zpool_do_remove(int, char **);
60fa9e4066Sahrens 
61fa9e4066Sahrens static int zpool_do_list(int, char **);
62fa9e4066Sahrens static int zpool_do_iostat(int, char **);
63fa9e4066Sahrens static int zpool_do_status(int, char **);
64fa9e4066Sahrens 
65fa9e4066Sahrens static int zpool_do_online(int, char **);
66fa9e4066Sahrens static int zpool_do_offline(int, char **);
67ea8dc4b6Seschrock static int zpool_do_clear(int, char **);
68fa9e4066Sahrens 
69fa9e4066Sahrens static int zpool_do_attach(int, char **);
70fa9e4066Sahrens static int zpool_do_detach(int, char **);
71fa9e4066Sahrens static int zpool_do_replace(int, char **);
72fa9e4066Sahrens 
73fa9e4066Sahrens static int zpool_do_scrub(int, char **);
74fa9e4066Sahrens 
75fa9e4066Sahrens static int zpool_do_import(int, char **);
76fa9e4066Sahrens static int zpool_do_export(int, char **);
77fa9e4066Sahrens 
78eaca9bbdSeschrock static int zpool_do_upgrade(int, char **);
79eaca9bbdSeschrock 
8006eeb2adSek110237 static int zpool_do_history(int, char **);
8106eeb2adSek110237 
82b1b8ab34Slling static int zpool_do_get(int, char **);
83b1b8ab34Slling static int zpool_do_set(int, char **);
84b1b8ab34Slling 
85fa9e4066Sahrens /*
86fa9e4066Sahrens  * These libumem hooks provide a reasonable set of defaults for the allocator's
87fa9e4066Sahrens  * debugging facilities.
88fa9e4066Sahrens  */
8929ab75c9Srm160521 
9029ab75c9Srm160521 #ifdef DEBUG
91fa9e4066Sahrens const char *
9299653d4eSeschrock _umem_debug_init(void)
93fa9e4066Sahrens {
94fa9e4066Sahrens 	return ("default,verbose"); /* $UMEM_DEBUG setting */
95fa9e4066Sahrens }
96fa9e4066Sahrens 
97fa9e4066Sahrens const char *
98fa9e4066Sahrens _umem_logging_init(void)
99fa9e4066Sahrens {
100fa9e4066Sahrens 	return ("fail,contents"); /* $UMEM_LOGGING setting */
101fa9e4066Sahrens }
10229ab75c9Srm160521 #endif
103fa9e4066Sahrens 
10465cd9f28Seschrock typedef enum {
10565cd9f28Seschrock 	HELP_ADD,
10665cd9f28Seschrock 	HELP_ATTACH,
107ea8dc4b6Seschrock 	HELP_CLEAR,
10865cd9f28Seschrock 	HELP_CREATE,
10965cd9f28Seschrock 	HELP_DESTROY,
11065cd9f28Seschrock 	HELP_DETACH,
11165cd9f28Seschrock 	HELP_EXPORT,
11206eeb2adSek110237 	HELP_HISTORY,
11365cd9f28Seschrock 	HELP_IMPORT,
11465cd9f28Seschrock 	HELP_IOSTAT,
11565cd9f28Seschrock 	HELP_LIST,
11665cd9f28Seschrock 	HELP_OFFLINE,
11765cd9f28Seschrock 	HELP_ONLINE,
11865cd9f28Seschrock 	HELP_REPLACE,
11999653d4eSeschrock 	HELP_REMOVE,
12065cd9f28Seschrock 	HELP_SCRUB,
121eaca9bbdSeschrock 	HELP_STATUS,
122b1b8ab34Slling 	HELP_UPGRADE,
123b1b8ab34Slling 	HELP_GET,
124b1b8ab34Slling 	HELP_SET
12565cd9f28Seschrock } zpool_help_t;
12665cd9f28Seschrock 
12765cd9f28Seschrock 
128fa9e4066Sahrens typedef struct zpool_command {
129fa9e4066Sahrens 	const char	*name;
130fa9e4066Sahrens 	int		(*func)(int, char **);
13165cd9f28Seschrock 	zpool_help_t	usage;
132fa9e4066Sahrens } zpool_command_t;
133fa9e4066Sahrens 
134fa9e4066Sahrens /*
135fa9e4066Sahrens  * Master command table.  Each ZFS command has a name, associated function, and
136ea8dc4b6Seschrock  * usage message.  The usage messages need to be internationalized, so we have
137ea8dc4b6Seschrock  * to have a function to return the usage message based on a command index.
13865cd9f28Seschrock  *
13965cd9f28Seschrock  * These commands are organized according to how they are displayed in the usage
14065cd9f28Seschrock  * message.  An empty command (one with a NULL name) indicates an empty line in
14165cd9f28Seschrock  * the generic usage message.
142fa9e4066Sahrens  */
143fa9e4066Sahrens static zpool_command_t command_table[] = {
14465cd9f28Seschrock 	{ "create",	zpool_do_create,	HELP_CREATE		},
14565cd9f28Seschrock 	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
146fa9e4066Sahrens 	{ NULL },
14765cd9f28Seschrock 	{ "add",	zpool_do_add,		HELP_ADD		},
14899653d4eSeschrock 	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
149fa9e4066Sahrens 	{ NULL },
15065cd9f28Seschrock 	{ "list",	zpool_do_list,		HELP_LIST		},
15165cd9f28Seschrock 	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
15265cd9f28Seschrock 	{ "status",	zpool_do_status,	HELP_STATUS		},
153fa9e4066Sahrens 	{ NULL },
15465cd9f28Seschrock 	{ "online",	zpool_do_online,	HELP_ONLINE		},
15565cd9f28Seschrock 	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
156ea8dc4b6Seschrock 	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
157fa9e4066Sahrens 	{ NULL },
15865cd9f28Seschrock 	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
15965cd9f28Seschrock 	{ "detach",	zpool_do_detach,	HELP_DETACH		},
16065cd9f28Seschrock 	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
161fa9e4066Sahrens 	{ NULL },
16265cd9f28Seschrock 	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
163fa9e4066Sahrens 	{ NULL },
16465cd9f28Seschrock 	{ "import",	zpool_do_import,	HELP_IMPORT		},
16565cd9f28Seschrock 	{ "export",	zpool_do_export,	HELP_EXPORT		},
16606eeb2adSek110237 	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
16706eeb2adSek110237 	{ NULL },
168b1b8ab34Slling 	{ "history",	zpool_do_history,	HELP_HISTORY		},
169b1b8ab34Slling 	{ "get",	zpool_do_get,		HELP_GET		},
170b1b8ab34Slling 	{ "set",	zpool_do_set,		HELP_SET		},
171fa9e4066Sahrens };
172fa9e4066Sahrens 
173fa9e4066Sahrens #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
174fa9e4066Sahrens 
175fa9e4066Sahrens zpool_command_t *current_command;
1762a6b87f0Sek110237 static char history_str[HIS_MAX_RECORD_LEN];
177fa9e4066Sahrens 
17865cd9f28Seschrock static const char *
17965cd9f28Seschrock get_usage(zpool_help_t idx) {
18065cd9f28Seschrock 	switch (idx) {
18165cd9f28Seschrock 	case HELP_ADD:
18265cd9f28Seschrock 		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
18365cd9f28Seschrock 	case HELP_ATTACH:
18465cd9f28Seschrock 		return (gettext("\tattach [-f] <pool> <device> "
185e45ce728Sahrens 		    "<new-device>\n"));
186ea8dc4b6Seschrock 	case HELP_CLEAR:
187ea8dc4b6Seschrock 		return (gettext("\tclear <pool> [device]\n"));
18865cd9f28Seschrock 	case HELP_CREATE:
189990b4856Slling 		return (gettext("\tcreate [-fn] [-o property=value] ... \n"
190*0a48a24eStimh 		    "\t    [-O file-system-property=value] ... \n"
191990b4856Slling 		    "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
19265cd9f28Seschrock 	case HELP_DESTROY:
19365cd9f28Seschrock 		return (gettext("\tdestroy [-f] <pool>\n"));
19465cd9f28Seschrock 	case HELP_DETACH:
19565cd9f28Seschrock 		return (gettext("\tdetach <pool> <device>\n"));
19665cd9f28Seschrock 	case HELP_EXPORT:
19765cd9f28Seschrock 		return (gettext("\texport [-f] <pool> ...\n"));
19806eeb2adSek110237 	case HELP_HISTORY:
199ecd6cf80Smarks 		return (gettext("\thistory [-il] [<pool>] ...\n"));
20065cd9f28Seschrock 	case HELP_IMPORT:
2014c58d714Sdarrenm 		return (gettext("\timport [-d dir] [-D]\n"
2022f8aaab3Seschrock 		    "\timport [-o mntopts] [-o property=value] ... \n"
2032f8aaab3Seschrock 		    "\t    [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
2042f8aaab3Seschrock 		    "\timport [-o mntopts] [-o property=value] ... \n"
2052f8aaab3Seschrock 		    "\t    [-d dir | -c cachefile] [-D] [-f] [-R root] "
2062f8aaab3Seschrock 		    "<pool | id> [newpool]\n"));
20765cd9f28Seschrock 	case HELP_IOSTAT:
20865cd9f28Seschrock 		return (gettext("\tiostat [-v] [pool] ... [interval "
20965cd9f28Seschrock 		    "[count]]\n"));
21065cd9f28Seschrock 	case HELP_LIST:
211990b4856Slling 		return (gettext("\tlist [-H] [-o property[,...]] "
212990b4856Slling 		    "[pool] ...\n"));
21365cd9f28Seschrock 	case HELP_OFFLINE:
214441d80aaSlling 		return (gettext("\toffline [-t] <pool> <device> ...\n"));
21565cd9f28Seschrock 	case HELP_ONLINE:
216441d80aaSlling 		return (gettext("\tonline <pool> <device> ...\n"));
21765cd9f28Seschrock 	case HELP_REPLACE:
21865cd9f28Seschrock 		return (gettext("\treplace [-f] <pool> <device> "
219e45ce728Sahrens 		    "[new-device]\n"));
22099653d4eSeschrock 	case HELP_REMOVE:
221fa94a07fSbrendan 		return (gettext("\tremove <pool> <device> ...\n"));
22265cd9f28Seschrock 	case HELP_SCRUB:
22365cd9f28Seschrock 		return (gettext("\tscrub [-s] <pool> ...\n"));
22465cd9f28Seschrock 	case HELP_STATUS:
22565cd9f28Seschrock 		return (gettext("\tstatus [-vx] [pool] ...\n"));
226eaca9bbdSeschrock 	case HELP_UPGRADE:
227eaca9bbdSeschrock 		return (gettext("\tupgrade\n"
228eaca9bbdSeschrock 		    "\tupgrade -v\n"
229990b4856Slling 		    "\tupgrade [-V version] <-a | pool ...>\n"));
230b1b8ab34Slling 	case HELP_GET:
231e45ce728Sahrens 		return (gettext("\tget <\"all\" | property[,...]> "
232b1b8ab34Slling 		    "<pool> ...\n"));
233b1b8ab34Slling 	case HELP_SET:
234b1b8ab34Slling 		return (gettext("\tset <property=value> <pool> \n"));
23565cd9f28Seschrock 	}
23665cd9f28Seschrock 
23765cd9f28Seschrock 	abort();
23865cd9f28Seschrock 	/* NOTREACHED */
23965cd9f28Seschrock }
24065cd9f28Seschrock 
241fa9e4066Sahrens 
242fa9e4066Sahrens /*
243b1b8ab34Slling  * Callback routine that will print out a pool property value.
244b1b8ab34Slling  */
245990b4856Slling static int
246990b4856Slling print_prop_cb(int prop, void *cb)
247b1b8ab34Slling {
248b1b8ab34Slling 	FILE *fp = cb;
249b1b8ab34Slling 
250b1b8ab34Slling 	(void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
251b1b8ab34Slling 
252990b4856Slling 	if (zpool_prop_readonly(prop))
253990b4856Slling 		(void) fprintf(fp, "  NO   ");
254990b4856Slling 	else
255990b4856Slling 		(void) fprintf(fp, " YES    ");
256990b4856Slling 
257b1b8ab34Slling 	if (zpool_prop_values(prop) == NULL)
258b1b8ab34Slling 		(void) fprintf(fp, "-\n");
259b1b8ab34Slling 	else
260b1b8ab34Slling 		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
261b1b8ab34Slling 
262990b4856Slling 	return (ZPROP_CONT);
263b1b8ab34Slling }
264b1b8ab34Slling 
265b1b8ab34Slling /*
266fa9e4066Sahrens  * Display usage message.  If we're inside a command, display only the usage for
267fa9e4066Sahrens  * that command.  Otherwise, iterate over the entire command table and display
268fa9e4066Sahrens  * a complete usage message.
269fa9e4066Sahrens  */
270fa9e4066Sahrens void
27199653d4eSeschrock usage(boolean_t requested)
272fa9e4066Sahrens {
273fa9e4066Sahrens 	FILE *fp = requested ? stdout : stderr;
274fa9e4066Sahrens 
275fa9e4066Sahrens 	if (current_command == NULL) {
276fa9e4066Sahrens 		int i;
277fa9e4066Sahrens 
278fa9e4066Sahrens 		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
279fa9e4066Sahrens 		(void) fprintf(fp,
280fa9e4066Sahrens 		    gettext("where 'command' is one of the following:\n\n"));
281fa9e4066Sahrens 
282fa9e4066Sahrens 		for (i = 0; i < NCOMMAND; i++) {
283fa9e4066Sahrens 			if (command_table[i].name == NULL)
284fa9e4066Sahrens 				(void) fprintf(fp, "\n");
285fa9e4066Sahrens 			else
286fa9e4066Sahrens 				(void) fprintf(fp, "%s",
28765cd9f28Seschrock 				    get_usage(command_table[i].usage));
288fa9e4066Sahrens 		}
289fa9e4066Sahrens 	} else {
290fa9e4066Sahrens 		(void) fprintf(fp, gettext("usage:\n"));
29165cd9f28Seschrock 		(void) fprintf(fp, "%s", get_usage(current_command->usage));
292fa9e4066Sahrens 	}
293fa9e4066Sahrens 
294b1b8ab34Slling 	if (current_command != NULL &&
295b1b8ab34Slling 	    ((strcmp(current_command->name, "set") == 0) ||
296990b4856Slling 	    (strcmp(current_command->name, "get") == 0) ||
297990b4856Slling 	    (strcmp(current_command->name, "list") == 0))) {
298b1b8ab34Slling 
299b1b8ab34Slling 		(void) fprintf(fp,
300b1b8ab34Slling 		    gettext("\nthe following properties are supported:\n"));
301b1b8ab34Slling 
302990b4856Slling 		(void) fprintf(fp, "\n\t%-13s  %s  %s\n\n",
303990b4856Slling 		    "PROPERTY", "EDIT", "VALUES");
304b1b8ab34Slling 
305b1b8ab34Slling 		/* Iterate over all properties */
306990b4856Slling 		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
307990b4856Slling 		    ZFS_TYPE_POOL);
308b1b8ab34Slling 	}
309b1b8ab34Slling 
310e9dbad6fSeschrock 	/*
311e9dbad6fSeschrock 	 * See comments at end of main().
312e9dbad6fSeschrock 	 */
313e9dbad6fSeschrock 	if (getenv("ZFS_ABORT") != NULL) {
314e9dbad6fSeschrock 		(void) printf("dumping core by request\n");
315e9dbad6fSeschrock 		abort();
316e9dbad6fSeschrock 	}
317e9dbad6fSeschrock 
318fa9e4066Sahrens 	exit(requested ? 0 : 2);
319fa9e4066Sahrens }
320fa9e4066Sahrens 
321fa9e4066Sahrens void
3228654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
3238654d025Sperrin     boolean_t print_logs)
324fa9e4066Sahrens {
325fa9e4066Sahrens 	nvlist_t **child;
326fa9e4066Sahrens 	uint_t c, children;
327afefbcddSeschrock 	char *vname;
328fa9e4066Sahrens 
329fa9e4066Sahrens 	if (name != NULL)
330fa9e4066Sahrens 		(void) printf("\t%*s%s\n", indent, "", name);
331fa9e4066Sahrens 
332fa9e4066Sahrens 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
333fa9e4066Sahrens 	    &child, &children) != 0)
334fa9e4066Sahrens 		return;
335fa9e4066Sahrens 
336afefbcddSeschrock 	for (c = 0; c < children; c++) {
3378654d025Sperrin 		uint64_t is_log = B_FALSE;
3388654d025Sperrin 
3398654d025Sperrin 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3408654d025Sperrin 		    &is_log);
3418654d025Sperrin 		if ((is_log && !print_logs) || (!is_log && print_logs))
3428654d025Sperrin 			continue;
3438654d025Sperrin 
34499653d4eSeschrock 		vname = zpool_vdev_name(g_zfs, zhp, child[c]);
3458654d025Sperrin 		print_vdev_tree(zhp, vname, child[c], indent + 2,
3468654d025Sperrin 		    B_FALSE);
347afefbcddSeschrock 		free(vname);
348afefbcddSeschrock 	}
349fa9e4066Sahrens }
350fa9e4066Sahrens 
351fa9e4066Sahrens /*
352990b4856Slling  * Add a property pair (name, string-value) into a property nvlist.
353990b4856Slling  */
354990b4856Slling static int
355*0a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props,
356*0a48a24eStimh     boolean_t poolprop)
357990b4856Slling {
358*0a48a24eStimh 	zpool_prop_t prop = ZPROP_INVAL;
359*0a48a24eStimh 	zfs_prop_t fprop;
360990b4856Slling 	nvlist_t *proplist;
361*0a48a24eStimh 	const char *normnm;
362*0a48a24eStimh 	char *strval;
363990b4856Slling 
364990b4856Slling 	if (*props == NULL &&
365990b4856Slling 	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
366990b4856Slling 		(void) fprintf(stderr,
367990b4856Slling 		    gettext("internal error: out of memory\n"));
368990b4856Slling 		return (1);
369990b4856Slling 	}
370990b4856Slling 
371990b4856Slling 	proplist = *props;
372990b4856Slling 
373*0a48a24eStimh 	if (poolprop) {
374990b4856Slling 		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
375990b4856Slling 			(void) fprintf(stderr, gettext("property '%s' is "
376990b4856Slling 			    "not a valid pool property\n"), propname);
377990b4856Slling 			return (2);
378990b4856Slling 		}
379*0a48a24eStimh 		normnm = zpool_prop_to_name(prop);
380*0a48a24eStimh 	} else {
381*0a48a24eStimh 		if ((fprop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
382*0a48a24eStimh 			(void) fprintf(stderr, gettext("property '%s' is "
383*0a48a24eStimh 			    "not a valid file system property\n"), propname);
384*0a48a24eStimh 			return (2);
385*0a48a24eStimh 		}
386*0a48a24eStimh 		normnm = zfs_prop_to_name(fprop);
387*0a48a24eStimh 	}
388990b4856Slling 
389*0a48a24eStimh 	if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
390*0a48a24eStimh 	    prop != ZPOOL_PROP_CACHEFILE) {
391990b4856Slling 		(void) fprintf(stderr, gettext("property '%s' "
392990b4856Slling 		    "specified multiple times\n"), propname);
393990b4856Slling 		return (2);
394990b4856Slling 	}
395990b4856Slling 
396*0a48a24eStimh 	if (nvlist_add_string(proplist, normnm, propval) != 0) {
397990b4856Slling 		(void) fprintf(stderr, gettext("internal "
398990b4856Slling 		    "error: out of memory\n"));
399990b4856Slling 		return (1);
400990b4856Slling 	}
401990b4856Slling 
402990b4856Slling 	return (0);
403990b4856Slling }
404990b4856Slling 
405990b4856Slling /*
406fa9e4066Sahrens  * zpool add [-fn] <pool> <vdev> ...
407fa9e4066Sahrens  *
408fa9e4066Sahrens  *	-f	Force addition of devices, even if they appear in use
409fa9e4066Sahrens  *	-n	Do not add the devices, but display the resulting layout if
410fa9e4066Sahrens  *		they were to be added.
411fa9e4066Sahrens  *
412fa9e4066Sahrens  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
413fa9e4066Sahrens  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
414fa9e4066Sahrens  * libzfs.
415fa9e4066Sahrens  */
416fa9e4066Sahrens int
417fa9e4066Sahrens zpool_do_add(int argc, char **argv)
418fa9e4066Sahrens {
41999653d4eSeschrock 	boolean_t force = B_FALSE;
42099653d4eSeschrock 	boolean_t dryrun = B_FALSE;
421fa9e4066Sahrens 	int c;
422fa9e4066Sahrens 	nvlist_t *nvroot;
423fa9e4066Sahrens 	char *poolname;
424fa9e4066Sahrens 	int ret;
425fa9e4066Sahrens 	zpool_handle_t *zhp;
426fa9e4066Sahrens 	nvlist_t *config;
427fa9e4066Sahrens 
428fa9e4066Sahrens 	/* check options */
429fa9e4066Sahrens 	while ((c = getopt(argc, argv, "fn")) != -1) {
430fa9e4066Sahrens 		switch (c) {
431fa9e4066Sahrens 		case 'f':
43299653d4eSeschrock 			force = B_TRUE;
433fa9e4066Sahrens 			break;
434fa9e4066Sahrens 		case 'n':
43599653d4eSeschrock 			dryrun = B_TRUE;
436fa9e4066Sahrens 			break;
437fa9e4066Sahrens 		case '?':
438fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
439fa9e4066Sahrens 			    optopt);
44099653d4eSeschrock 			usage(B_FALSE);
441fa9e4066Sahrens 		}
442fa9e4066Sahrens 	}
443fa9e4066Sahrens 
444fa9e4066Sahrens 	argc -= optind;
445fa9e4066Sahrens 	argv += optind;
446fa9e4066Sahrens 
447fa9e4066Sahrens 	/* get pool name and check number of arguments */
448fa9e4066Sahrens 	if (argc < 1) {
449fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
45099653d4eSeschrock 		usage(B_FALSE);
451fa9e4066Sahrens 	}
452fa9e4066Sahrens 	if (argc < 2) {
453fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
45499653d4eSeschrock 		usage(B_FALSE);
455fa9e4066Sahrens 	}
456fa9e4066Sahrens 
457fa9e4066Sahrens 	poolname = argv[0];
458fa9e4066Sahrens 
459fa9e4066Sahrens 	argc--;
460fa9e4066Sahrens 	argv++;
461fa9e4066Sahrens 
46299653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
463fa9e4066Sahrens 		return (1);
464fa9e4066Sahrens 
465088e9d47Seschrock 	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
466fa9e4066Sahrens 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
467fa9e4066Sahrens 		    poolname);
468fa9e4066Sahrens 		zpool_close(zhp);
469fa9e4066Sahrens 		return (1);
470fa9e4066Sahrens 	}
471fa9e4066Sahrens 
472fa9e4066Sahrens 	/* pass off to get_vdev_spec for processing */
4738488aeb5Staylor 	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, argc, argv);
474fa9e4066Sahrens 	if (nvroot == NULL) {
475fa9e4066Sahrens 		zpool_close(zhp);
476fa9e4066Sahrens 		return (1);
477fa9e4066Sahrens 	}
478fa9e4066Sahrens 
479fa9e4066Sahrens 	if (dryrun) {
480fa9e4066Sahrens 		nvlist_t *poolnvroot;
481fa9e4066Sahrens 
482fa9e4066Sahrens 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
483fa9e4066Sahrens 		    &poolnvroot) == 0);
484fa9e4066Sahrens 
485fa9e4066Sahrens 		(void) printf(gettext("would update '%s' to the following "
486fa9e4066Sahrens 		    "configuration:\n"), zpool_get_name(zhp));
487fa9e4066Sahrens 
4888654d025Sperrin 		/* print original main pool and new tree */
4898654d025Sperrin 		print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
4908654d025Sperrin 		print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
4918654d025Sperrin 
4928654d025Sperrin 		/* Do the same for the logs */
4938654d025Sperrin 		if (num_logs(poolnvroot) > 0) {
4948654d025Sperrin 			print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
4958654d025Sperrin 			print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
4968654d025Sperrin 		} else if (num_logs(nvroot) > 0) {
4978654d025Sperrin 			print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
4988654d025Sperrin 		}
499fa9e4066Sahrens 
500fa9e4066Sahrens 		ret = 0;
501fa9e4066Sahrens 	} else {
502fa9e4066Sahrens 		ret = (zpool_add(zhp, nvroot) != 0);
503fa9e4066Sahrens 	}
504fa9e4066Sahrens 
50599653d4eSeschrock 	nvlist_free(nvroot);
50699653d4eSeschrock 	zpool_close(zhp);
50799653d4eSeschrock 
50899653d4eSeschrock 	return (ret);
50999653d4eSeschrock }
51099653d4eSeschrock 
51199653d4eSeschrock /*
512fa94a07fSbrendan  * zpool remove <pool> <vdev> ...
51399653d4eSeschrock  *
51499653d4eSeschrock  * Removes the given vdev from the pool.  Currently, this only supports removing
515fa94a07fSbrendan  * spares and cache devices from the pool.  Eventually, we'll want to support
516fa94a07fSbrendan  * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
51799653d4eSeschrock  */
51899653d4eSeschrock int
51999653d4eSeschrock zpool_do_remove(int argc, char **argv)
52099653d4eSeschrock {
52199653d4eSeschrock 	char *poolname;
522fa94a07fSbrendan 	int i, ret = 0;
52399653d4eSeschrock 	zpool_handle_t *zhp;
52499653d4eSeschrock 
52599653d4eSeschrock 	argc--;
52699653d4eSeschrock 	argv++;
52799653d4eSeschrock 
52899653d4eSeschrock 	/* get pool name and check number of arguments */
52999653d4eSeschrock 	if (argc < 1) {
53099653d4eSeschrock 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
53199653d4eSeschrock 		usage(B_FALSE);
53299653d4eSeschrock 	}
53399653d4eSeschrock 	if (argc < 2) {
53499653d4eSeschrock 		(void) fprintf(stderr, gettext("missing device\n"));
53599653d4eSeschrock 		usage(B_FALSE);
53699653d4eSeschrock 	}
53799653d4eSeschrock 
53899653d4eSeschrock 	poolname = argv[0];
53999653d4eSeschrock 
54099653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
54199653d4eSeschrock 		return (1);
54299653d4eSeschrock 
543fa94a07fSbrendan 	for (i = 1; i < argc; i++) {
544fa94a07fSbrendan 		if (zpool_vdev_remove(zhp, argv[i]) != 0)
545fa94a07fSbrendan 			ret = 1;
546fa94a07fSbrendan 	}
54799653d4eSeschrock 
548fa9e4066Sahrens 	return (ret);
549fa9e4066Sahrens }
550fa9e4066Sahrens 
551fa9e4066Sahrens /*
552*0a48a24eStimh  * zpool create [-fn] [-o property=value] ...
553*0a48a24eStimh  *		[-O file-system-property=value] ...
554*0a48a24eStimh  *		[-R root] [-m mountpoint] <pool> <dev> ...
555fa9e4066Sahrens  *
556fa9e4066Sahrens  *	-f	Force creation, even if devices appear in use
557fa9e4066Sahrens  *	-n	Do not create the pool, but display the resulting layout if it
558fa9e4066Sahrens  *		were to be created.
559fa9e4066Sahrens  *      -R	Create a pool under an alternate root
560fa9e4066Sahrens  *      -m	Set default mountpoint for the root dataset.  By default it's
561fa9e4066Sahrens  *      	'/<pool>'
562990b4856Slling  *	-o	Set property=value.
563*0a48a24eStimh  *	-O	Set fsproperty=value in the pool's root file system
564fa9e4066Sahrens  *
565b1b8ab34Slling  * Creates the named pool according to the given vdev specification.  The
566fa9e4066Sahrens  * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
567fa9e4066Sahrens  * we get the nvlist back from get_vdev_spec(), we either print out the contents
568fa9e4066Sahrens  * (if '-n' was specified), or pass it to libzfs to do the creation.
569fa9e4066Sahrens  */
570fa9e4066Sahrens int
571fa9e4066Sahrens zpool_do_create(int argc, char **argv)
572fa9e4066Sahrens {
57399653d4eSeschrock 	boolean_t force = B_FALSE;
57499653d4eSeschrock 	boolean_t dryrun = B_FALSE;
575fa9e4066Sahrens 	int c;
576990b4856Slling 	nvlist_t *nvroot = NULL;
577fa9e4066Sahrens 	char *poolname;
578990b4856Slling 	int ret = 1;
579fa9e4066Sahrens 	char *altroot = NULL;
580fa9e4066Sahrens 	char *mountpoint = NULL;
581*0a48a24eStimh 	nvlist_t *fsprops = NULL;
582990b4856Slling 	nvlist_t *props = NULL;
5832f8aaab3Seschrock 	char *propval;
584fa9e4066Sahrens 
585fa9e4066Sahrens 	/* check options */
586*0a48a24eStimh 	while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
587fa9e4066Sahrens 		switch (c) {
588fa9e4066Sahrens 		case 'f':
58999653d4eSeschrock 			force = B_TRUE;
590fa9e4066Sahrens 			break;
591fa9e4066Sahrens 		case 'n':
59299653d4eSeschrock 			dryrun = B_TRUE;
593fa9e4066Sahrens 			break;
594fa9e4066Sahrens 		case 'R':
595fa9e4066Sahrens 			altroot = optarg;
596990b4856Slling 			if (add_prop_list(zpool_prop_to_name(
597*0a48a24eStimh 			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
598990b4856Slling 				goto errout;
5992f8aaab3Seschrock 			if (nvlist_lookup_string(props,
6002f8aaab3Seschrock 			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
6012f8aaab3Seschrock 			    &propval) == 0)
6022f8aaab3Seschrock 				break;
603990b4856Slling 			if (add_prop_list(zpool_prop_to_name(
604*0a48a24eStimh 			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
605990b4856Slling 				goto errout;
606fa9e4066Sahrens 			break;
607fa9e4066Sahrens 		case 'm':
608fa9e4066Sahrens 			mountpoint = optarg;
609fa9e4066Sahrens 			break;
610990b4856Slling 		case 'o':
611990b4856Slling 			if ((propval = strchr(optarg, '=')) == NULL) {
612990b4856Slling 				(void) fprintf(stderr, gettext("missing "
613990b4856Slling 				    "'=' for -o option\n"));
614990b4856Slling 				goto errout;
615990b4856Slling 			}
616990b4856Slling 			*propval = '\0';
617990b4856Slling 			propval++;
618990b4856Slling 
619*0a48a24eStimh 			if (add_prop_list(optarg, propval, &props, B_TRUE))
620*0a48a24eStimh 				goto errout;
621*0a48a24eStimh 			break;
622*0a48a24eStimh 		case 'O':
623*0a48a24eStimh 			if ((propval = strchr(optarg, '=')) == NULL) {
624*0a48a24eStimh 				(void) fprintf(stderr, gettext("missing "
625*0a48a24eStimh 				    "'=' for -O option\n"));
626*0a48a24eStimh 				goto errout;
627*0a48a24eStimh 			}
628*0a48a24eStimh 			*propval = '\0';
629*0a48a24eStimh 			propval++;
630*0a48a24eStimh 
631*0a48a24eStimh 			if (add_prop_list(optarg, propval, &fsprops, B_FALSE))
632990b4856Slling 				goto errout;
633990b4856Slling 			break;
634fa9e4066Sahrens 		case ':':
635fa9e4066Sahrens 			(void) fprintf(stderr, gettext("missing argument for "
636fa9e4066Sahrens 			    "'%c' option\n"), optopt);
637990b4856Slling 			goto badusage;
638fa9e4066Sahrens 		case '?':
639fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
640fa9e4066Sahrens 			    optopt);
641990b4856Slling 			goto badusage;
642fa9e4066Sahrens 		}
643fa9e4066Sahrens 	}
644fa9e4066Sahrens 
645fa9e4066Sahrens 	argc -= optind;
646fa9e4066Sahrens 	argv += optind;
647fa9e4066Sahrens 
648fa9e4066Sahrens 	/* get pool name and check number of arguments */
649fa9e4066Sahrens 	if (argc < 1) {
650fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
651990b4856Slling 		goto badusage;
652fa9e4066Sahrens 	}
653fa9e4066Sahrens 	if (argc < 2) {
654fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing vdev specification\n"));
655990b4856Slling 		goto badusage;
656fa9e4066Sahrens 	}
657fa9e4066Sahrens 
658fa9e4066Sahrens 	poolname = argv[0];
659fa9e4066Sahrens 
660fa9e4066Sahrens 	/*
661fa9e4066Sahrens 	 * As a special case, check for use of '/' in the name, and direct the
662fa9e4066Sahrens 	 * user to use 'zfs create' instead.
663fa9e4066Sahrens 	 */
664fa9e4066Sahrens 	if (strchr(poolname, '/') != NULL) {
665fa9e4066Sahrens 		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
666fa9e4066Sahrens 		    "character '/' in pool name\n"), poolname);
667fa9e4066Sahrens 		(void) fprintf(stderr, gettext("use 'zfs create' to "
668fa9e4066Sahrens 		    "create a dataset\n"));
669990b4856Slling 		goto errout;
670fa9e4066Sahrens 	}
671fa9e4066Sahrens 
672fa9e4066Sahrens 	/* pass off to get_vdev_spec for bulk processing */
67399653d4eSeschrock 	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1,
67499653d4eSeschrock 	    argv + 1);
675fa9e4066Sahrens 	if (nvroot == NULL)
676*0a48a24eStimh 		goto errout;
677fa9e4066Sahrens 
67899653d4eSeschrock 	/* make_root_vdev() allows 0 toplevel children if there are spares */
679b7b97454Sperrin 	if (!zfs_allocatable_devs(nvroot)) {
68099653d4eSeschrock 		(void) fprintf(stderr, gettext("invalid vdev "
68199653d4eSeschrock 		    "specification: at least one toplevel vdev must be "
68299653d4eSeschrock 		    "specified\n"));
683990b4856Slling 		goto errout;
68499653d4eSeschrock 	}
68599653d4eSeschrock 
68699653d4eSeschrock 
687fa9e4066Sahrens 	if (altroot != NULL && altroot[0] != '/') {
688fa9e4066Sahrens 		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
689e9dbad6fSeschrock 		    "must be an absolute path\n"), altroot);
690990b4856Slling 		goto errout;
691fa9e4066Sahrens 	}
692fa9e4066Sahrens 
693fa9e4066Sahrens 	/*
694fa9e4066Sahrens 	 * Check the validity of the mountpoint and direct the user to use the
695fa9e4066Sahrens 	 * '-m' mountpoint option if it looks like its in use.
696fa9e4066Sahrens 	 */
697fa9e4066Sahrens 	if (mountpoint == NULL ||
698fa9e4066Sahrens 	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
699fa9e4066Sahrens 	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
700fa9e4066Sahrens 		char buf[MAXPATHLEN];
70111022c7cStimh 		DIR *dirp;
702fa9e4066Sahrens 
703fa9e4066Sahrens 		if (mountpoint && mountpoint[0] != '/') {
704fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid mountpoint "
705fa9e4066Sahrens 			    "'%s': must be an absolute path, 'legacy', or "
706fa9e4066Sahrens 			    "'none'\n"), mountpoint);
707990b4856Slling 			goto errout;
708fa9e4066Sahrens 		}
709fa9e4066Sahrens 
710fa9e4066Sahrens 		if (mountpoint == NULL) {
711fa9e4066Sahrens 			if (altroot != NULL)
712fa9e4066Sahrens 				(void) snprintf(buf, sizeof (buf), "%s/%s",
713fa9e4066Sahrens 				    altroot, poolname);
714fa9e4066Sahrens 			else
715fa9e4066Sahrens 				(void) snprintf(buf, sizeof (buf), "/%s",
716fa9e4066Sahrens 				    poolname);
717fa9e4066Sahrens 		} else {
718fa9e4066Sahrens 			if (altroot != NULL)
719fa9e4066Sahrens 				(void) snprintf(buf, sizeof (buf), "%s%s",
720fa9e4066Sahrens 				    altroot, mountpoint);
721fa9e4066Sahrens 			else
722fa9e4066Sahrens 				(void) snprintf(buf, sizeof (buf), "%s",
723fa9e4066Sahrens 				    mountpoint);
724fa9e4066Sahrens 		}
725fa9e4066Sahrens 
72611022c7cStimh 		if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
72711022c7cStimh 			(void) fprintf(stderr, gettext("mountpoint '%s' : "
72811022c7cStimh 			    "%s\n"), buf, strerror(errno));
729fa9e4066Sahrens 			(void) fprintf(stderr, gettext("use '-m' "
730fa9e4066Sahrens 			    "option to provide a different default\n"));
731990b4856Slling 			goto errout;
73211022c7cStimh 		} else if (dirp) {
73311022c7cStimh 			int count = 0;
73411022c7cStimh 
73511022c7cStimh 			while (count < 3 && readdir(dirp) != NULL)
73611022c7cStimh 				count++;
73711022c7cStimh 			(void) closedir(dirp);
73811022c7cStimh 
73911022c7cStimh 			if (count > 2) {
74011022c7cStimh 				(void) fprintf(stderr, gettext("mountpoint "
74111022c7cStimh 				    "'%s' exists and is not empty\n"), buf);
74211022c7cStimh 				(void) fprintf(stderr, gettext("use '-m' "
74311022c7cStimh 				    "option to provide a "
74411022c7cStimh 				    "different default\n"));
74511022c7cStimh 				goto errout;
74611022c7cStimh 			}
747fa9e4066Sahrens 		}
748fa9e4066Sahrens 	}
749fa9e4066Sahrens 
750fa9e4066Sahrens 	if (dryrun) {
751fa9e4066Sahrens 		/*
752fa9e4066Sahrens 		 * For a dry run invocation, print out a basic message and run
753fa9e4066Sahrens 		 * through all the vdevs in the list and print out in an
754fa9e4066Sahrens 		 * appropriate hierarchy.
755fa9e4066Sahrens 		 */
756fa9e4066Sahrens 		(void) printf(gettext("would create '%s' with the "
757fa9e4066Sahrens 		    "following layout:\n\n"), poolname);
758fa9e4066Sahrens 
7598654d025Sperrin 		print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
7608654d025Sperrin 		if (num_logs(nvroot) > 0)
7618654d025Sperrin 			print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
762fa9e4066Sahrens 
763fa9e4066Sahrens 		ret = 0;
764fa9e4066Sahrens 	} else {
765fa9e4066Sahrens 		/*
766fa9e4066Sahrens 		 * Hand off to libzfs.
767fa9e4066Sahrens 		 */
768*0a48a24eStimh 		if (zpool_create(g_zfs, poolname,
769*0a48a24eStimh 		    nvroot, props, fsprops) == 0) {
77099653d4eSeschrock 			zfs_handle_t *pool = zfs_open(g_zfs, poolname,
771fa9e4066Sahrens 			    ZFS_TYPE_FILESYSTEM);
772fa9e4066Sahrens 			if (pool != NULL) {
773fa9e4066Sahrens 				if (mountpoint != NULL)
774fa9e4066Sahrens 					verify(zfs_prop_set(pool,
775e9dbad6fSeschrock 					    zfs_prop_to_name(
776e9dbad6fSeschrock 					    ZFS_PROP_MOUNTPOINT),
777fa9e4066Sahrens 					    mountpoint) == 0);
778fa9e4066Sahrens 				if (zfs_mount(pool, NULL, 0) == 0)
779da6c28aaSamw 					ret = zfs_shareall(pool);
780fa9e4066Sahrens 				zfs_close(pool);
781fa9e4066Sahrens 			}
78299653d4eSeschrock 		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
78399653d4eSeschrock 			(void) fprintf(stderr, gettext("pool name may have "
78499653d4eSeschrock 			    "been omitted\n"));
785fa9e4066Sahrens 		}
786fa9e4066Sahrens 	}
787fa9e4066Sahrens 
788990b4856Slling errout:
789fa9e4066Sahrens 	nvlist_free(nvroot);
790*0a48a24eStimh 	nvlist_free(fsprops);
791990b4856Slling 	nvlist_free(props);
792fa9e4066Sahrens 	return (ret);
793990b4856Slling badusage:
794*0a48a24eStimh 	nvlist_free(fsprops);
795990b4856Slling 	nvlist_free(props);
796990b4856Slling 	usage(B_FALSE);
797990b4856Slling 	return (2);
798fa9e4066Sahrens }
799fa9e4066Sahrens 
800fa9e4066Sahrens /*
801fa9e4066Sahrens  * zpool destroy <pool>
802fa9e4066Sahrens  *
803fa9e4066Sahrens  * 	-f	Forcefully unmount any datasets
804fa9e4066Sahrens  *
805fa9e4066Sahrens  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
806fa9e4066Sahrens  */
807fa9e4066Sahrens int
808fa9e4066Sahrens zpool_do_destroy(int argc, char **argv)
809fa9e4066Sahrens {
81099653d4eSeschrock 	boolean_t force = B_FALSE;
811fa9e4066Sahrens 	int c;
812fa9e4066Sahrens 	char *pool;
813fa9e4066Sahrens 	zpool_handle_t *zhp;
814fa9e4066Sahrens 	int ret;
815fa9e4066Sahrens 
816fa9e4066Sahrens 	/* check options */
817fa9e4066Sahrens 	while ((c = getopt(argc, argv, "f")) != -1) {
818fa9e4066Sahrens 		switch (c) {
819fa9e4066Sahrens 		case 'f':
82099653d4eSeschrock 			force = B_TRUE;
821fa9e4066Sahrens 			break;
822fa9e4066Sahrens 		case '?':
823fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
824fa9e4066Sahrens 			    optopt);
82599653d4eSeschrock 			usage(B_FALSE);
826fa9e4066Sahrens 		}
827fa9e4066Sahrens 	}
828fa9e4066Sahrens 
829fa9e4066Sahrens 	argc -= optind;
830fa9e4066Sahrens 	argv += optind;
831fa9e4066Sahrens 
832fa9e4066Sahrens 	/* check arguments */
833fa9e4066Sahrens 	if (argc < 1) {
834fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool argument\n"));
83599653d4eSeschrock 		usage(B_FALSE);
836fa9e4066Sahrens 	}
837fa9e4066Sahrens 	if (argc > 1) {
838fa9e4066Sahrens 		(void) fprintf(stderr, gettext("too many arguments\n"));
83999653d4eSeschrock 		usage(B_FALSE);
840fa9e4066Sahrens 	}
841fa9e4066Sahrens 
842fa9e4066Sahrens 	pool = argv[0];
843fa9e4066Sahrens 
84499653d4eSeschrock 	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
845fa9e4066Sahrens 		/*
846fa9e4066Sahrens 		 * As a special case, check for use of '/' in the name, and
847fa9e4066Sahrens 		 * direct the user to use 'zfs destroy' instead.
848fa9e4066Sahrens 		 */
849fa9e4066Sahrens 		if (strchr(pool, '/') != NULL)
850fa9e4066Sahrens 			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
851fa9e4066Sahrens 			    "destroy a dataset\n"));
852fa9e4066Sahrens 		return (1);
853fa9e4066Sahrens 	}
854fa9e4066Sahrens 
855f3861e1aSahl 	if (zpool_disable_datasets(zhp, force) != 0) {
856fa9e4066Sahrens 		(void) fprintf(stderr, gettext("could not destroy '%s': "
857fa9e4066Sahrens 		    "could not unmount datasets\n"), zpool_get_name(zhp));
858fa9e4066Sahrens 		return (1);
859fa9e4066Sahrens 	}
860fa9e4066Sahrens 
861fa9e4066Sahrens 	ret = (zpool_destroy(zhp) != 0);
862fa9e4066Sahrens 
863fa9e4066Sahrens 	zpool_close(zhp);
864fa9e4066Sahrens 
865fa9e4066Sahrens 	return (ret);
866fa9e4066Sahrens }
867fa9e4066Sahrens 
868fa9e4066Sahrens /*
869fa9e4066Sahrens  * zpool export [-f] <pool> ...
870fa9e4066Sahrens  *
871fa9e4066Sahrens  *	-f	Forcefully unmount datasets
872fa9e4066Sahrens  *
873b1b8ab34Slling  * Export the given pools.  By default, the command will attempt to cleanly
874fa9e4066Sahrens  * unmount any active datasets within the pool.  If the '-f' flag is specified,
875fa9e4066Sahrens  * then the datasets will be forcefully unmounted.
876fa9e4066Sahrens  */
877fa9e4066Sahrens int
878fa9e4066Sahrens zpool_do_export(int argc, char **argv)
879fa9e4066Sahrens {
88099653d4eSeschrock 	boolean_t force = B_FALSE;
881fa9e4066Sahrens 	int c;
882fa9e4066Sahrens 	zpool_handle_t *zhp;
883fa9e4066Sahrens 	int ret;
884fa9e4066Sahrens 	int i;
885fa9e4066Sahrens 
886fa9e4066Sahrens 	/* check options */
887fa9e4066Sahrens 	while ((c = getopt(argc, argv, "f")) != -1) {
888fa9e4066Sahrens 		switch (c) {
889fa9e4066Sahrens 		case 'f':
89099653d4eSeschrock 			force = B_TRUE;
891fa9e4066Sahrens 			break;
892fa9e4066Sahrens 		case '?':
893fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
894fa9e4066Sahrens 			    optopt);
89599653d4eSeschrock 			usage(B_FALSE);
896fa9e4066Sahrens 		}
897fa9e4066Sahrens 	}
898fa9e4066Sahrens 
899fa9e4066Sahrens 	argc -= optind;
900fa9e4066Sahrens 	argv += optind;
901fa9e4066Sahrens 
902fa9e4066Sahrens 	/* check arguments */
903fa9e4066Sahrens 	if (argc < 1) {
904fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool argument\n"));
90599653d4eSeschrock 		usage(B_FALSE);
906fa9e4066Sahrens 	}
907fa9e4066Sahrens 
908fa9e4066Sahrens 	ret = 0;
909fa9e4066Sahrens 	for (i = 0; i < argc; i++) {
91099653d4eSeschrock 		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
911fa9e4066Sahrens 			ret = 1;
912fa9e4066Sahrens 			continue;
913fa9e4066Sahrens 		}
914fa9e4066Sahrens 
915f3861e1aSahl 		if (zpool_disable_datasets(zhp, force) != 0) {
916fa9e4066Sahrens 			ret = 1;
917fa9e4066Sahrens 			zpool_close(zhp);
918fa9e4066Sahrens 			continue;
919fa9e4066Sahrens 		}
920fa9e4066Sahrens 
921fa9e4066Sahrens 		if (zpool_export(zhp) != 0)
922fa9e4066Sahrens 			ret = 1;
923fa9e4066Sahrens 
924fa9e4066Sahrens 		zpool_close(zhp);
925fa9e4066Sahrens 	}
926fa9e4066Sahrens 
927fa9e4066Sahrens 	return (ret);
928fa9e4066Sahrens }
929fa9e4066Sahrens 
930fa9e4066Sahrens /*
931fa9e4066Sahrens  * Given a vdev configuration, determine the maximum width needed for the device
932fa9e4066Sahrens  * name column.
933fa9e4066Sahrens  */
934fa9e4066Sahrens static int
935c67d9675Seschrock max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
936fa9e4066Sahrens {
93799653d4eSeschrock 	char *name = zpool_vdev_name(g_zfs, zhp, nv);
938fa9e4066Sahrens 	nvlist_t **child;
939fa9e4066Sahrens 	uint_t c, children;
940fa9e4066Sahrens 	int ret;
941fa9e4066Sahrens 
942fa9e4066Sahrens 	if (strlen(name) + depth > max)
943fa9e4066Sahrens 		max = strlen(name) + depth;
944fa9e4066Sahrens 
945afefbcddSeschrock 	free(name);
946afefbcddSeschrock 
94799653d4eSeschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
94899653d4eSeschrock 	    &child, &children) == 0) {
949fa9e4066Sahrens 		for (c = 0; c < children; c++)
95099653d4eSeschrock 			if ((ret = max_width(zhp, child[c], depth + 2,
95199653d4eSeschrock 			    max)) > max)
952fa9e4066Sahrens 				max = ret;
95399653d4eSeschrock 	}
95499653d4eSeschrock 
955fa94a07fSbrendan 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
956fa94a07fSbrendan 	    &child, &children) == 0) {
957fa94a07fSbrendan 		for (c = 0; c < children; c++)
958fa94a07fSbrendan 			if ((ret = max_width(zhp, child[c], depth + 2,
959fa94a07fSbrendan 			    max)) > max)
960fa94a07fSbrendan 				max = ret;
961fa94a07fSbrendan 	}
962fa94a07fSbrendan 
96399653d4eSeschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
96499653d4eSeschrock 	    &child, &children) == 0) {
96599653d4eSeschrock 		for (c = 0; c < children; c++)
96699653d4eSeschrock 			if ((ret = max_width(zhp, child[c], depth + 2,
96799653d4eSeschrock 			    max)) > max)
96899653d4eSeschrock 				max = ret;
96999653d4eSeschrock 	}
97099653d4eSeschrock 
971fa9e4066Sahrens 
972fa9e4066Sahrens 	return (max);
973fa9e4066Sahrens }
974fa9e4066Sahrens 
975fa9e4066Sahrens 
976fa9e4066Sahrens /*
977fa9e4066Sahrens  * Print the configuration of an exported pool.  Iterate over all vdevs in the
978fa9e4066Sahrens  * pool, printing out the name and status for each one.
979fa9e4066Sahrens  */
980fa9e4066Sahrens void
9818654d025Sperrin print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
9828654d025Sperrin     boolean_t print_logs)
983fa9e4066Sahrens {
984fa9e4066Sahrens 	nvlist_t **child;
985fa9e4066Sahrens 	uint_t c, children;
986fa9e4066Sahrens 	vdev_stat_t *vs;
987afefbcddSeschrock 	char *type, *vname;
988fa9e4066Sahrens 
989fa9e4066Sahrens 	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
990fa9e4066Sahrens 	if (strcmp(type, VDEV_TYPE_MISSING) == 0)
991fa9e4066Sahrens 		return;
992fa9e4066Sahrens 
993fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
994fa9e4066Sahrens 	    (uint64_t **)&vs, &c) == 0);
995fa9e4066Sahrens 
996fa9e4066Sahrens 	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
997990b4856Slling 	(void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
998fa9e4066Sahrens 
999fa9e4066Sahrens 	if (vs->vs_aux != 0) {
10003d7072f8Seschrock 		(void) printf("  ");
1001fa9e4066Sahrens 
1002fa9e4066Sahrens 		switch (vs->vs_aux) {
1003fa9e4066Sahrens 		case VDEV_AUX_OPEN_FAILED:
1004fa9e4066Sahrens 			(void) printf(gettext("cannot open"));
1005fa9e4066Sahrens 			break;
1006fa9e4066Sahrens 
1007fa9e4066Sahrens 		case VDEV_AUX_BAD_GUID_SUM:
1008fa9e4066Sahrens 			(void) printf(gettext("missing device"));
1009fa9e4066Sahrens 			break;
1010fa9e4066Sahrens 
1011fa9e4066Sahrens 		case VDEV_AUX_NO_REPLICAS:
1012fa9e4066Sahrens 			(void) printf(gettext("insufficient replicas"));
1013fa9e4066Sahrens 			break;
1014fa9e4066Sahrens 
1015eaca9bbdSeschrock 		case VDEV_AUX_VERSION_NEWER:
1016eaca9bbdSeschrock 			(void) printf(gettext("newer version"));
1017eaca9bbdSeschrock 			break;
1018eaca9bbdSeschrock 
10193d7072f8Seschrock 		case VDEV_AUX_ERR_EXCEEDED:
10203d7072f8Seschrock 			(void) printf(gettext("too many errors"));
10213d7072f8Seschrock 			break;
10223d7072f8Seschrock 
1023fa9e4066Sahrens 		default:
1024fa9e4066Sahrens 			(void) printf(gettext("corrupted data"));
1025fa9e4066Sahrens 			break;
1026fa9e4066Sahrens 		}
1027fa9e4066Sahrens 	}
1028fa9e4066Sahrens 	(void) printf("\n");
1029fa9e4066Sahrens 
1030fa9e4066Sahrens 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1031fa9e4066Sahrens 	    &child, &children) != 0)
1032fa9e4066Sahrens 		return;
1033fa9e4066Sahrens 
1034afefbcddSeschrock 	for (c = 0; c < children; c++) {
10358654d025Sperrin 		uint64_t is_log = B_FALSE;
10368654d025Sperrin 
10378654d025Sperrin 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
10388654d025Sperrin 		    &is_log);
10398654d025Sperrin 		if ((is_log && !print_logs) || (!is_log && print_logs))
10408654d025Sperrin 			continue;
10418654d025Sperrin 
104299653d4eSeschrock 		vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1043afefbcddSeschrock 		print_import_config(vname, child[c],
10448654d025Sperrin 		    namewidth, depth + 2, B_FALSE);
1045afefbcddSeschrock 		free(vname);
1046afefbcddSeschrock 	}
104799653d4eSeschrock 
1048fa94a07fSbrendan 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1049fa94a07fSbrendan 	    &child, &children) == 0) {
1050fa94a07fSbrendan 		(void) printf(gettext("\tcache\n"));
1051fa94a07fSbrendan 		for (c = 0; c < children; c++) {
1052fa94a07fSbrendan 			vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1053fa94a07fSbrendan 			(void) printf("\t  %s\n", vname);
1054fa94a07fSbrendan 			free(vname);
1055fa94a07fSbrendan 		}
1056fa94a07fSbrendan 	}
105799653d4eSeschrock 
1058fa94a07fSbrendan 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1059fa94a07fSbrendan 	    &child, &children) == 0) {
106099653d4eSeschrock 		(void) printf(gettext("\tspares\n"));
106199653d4eSeschrock 		for (c = 0; c < children; c++) {
106299653d4eSeschrock 			vname = zpool_vdev_name(g_zfs, NULL, child[c]);
106399653d4eSeschrock 			(void) printf("\t  %s\n", vname);
106499653d4eSeschrock 			free(vname);
106599653d4eSeschrock 		}
1066fa9e4066Sahrens 	}
1067fa94a07fSbrendan }
1068fa9e4066Sahrens 
1069fa9e4066Sahrens /*
1070fa9e4066Sahrens  * Display the status for the given pool.
1071fa9e4066Sahrens  */
1072fa9e4066Sahrens static void
1073fa9e4066Sahrens show_import(nvlist_t *config)
1074fa9e4066Sahrens {
1075fa9e4066Sahrens 	uint64_t pool_state;
1076fa9e4066Sahrens 	vdev_stat_t *vs;
1077fa9e4066Sahrens 	char *name;
1078fa9e4066Sahrens 	uint64_t guid;
1079fa9e4066Sahrens 	char *msgid;
1080fa9e4066Sahrens 	nvlist_t *nvroot;
1081fa9e4066Sahrens 	int reason;
108246657f8dSmmusante 	const char *health;
1083fa9e4066Sahrens 	uint_t vsc;
1084fa9e4066Sahrens 	int namewidth;
1085fa9e4066Sahrens 
1086fa9e4066Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1087fa9e4066Sahrens 	    &name) == 0);
1088fa9e4066Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1089fa9e4066Sahrens 	    &guid) == 0);
1090fa9e4066Sahrens 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1091fa9e4066Sahrens 	    &pool_state) == 0);
1092fa9e4066Sahrens 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1093fa9e4066Sahrens 	    &nvroot) == 0);
1094fa9e4066Sahrens 
1095fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1096fa9e4066Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
1097990b4856Slling 	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1098fa9e4066Sahrens 
1099fa9e4066Sahrens 	reason = zpool_import_status(config, &msgid);
1100fa9e4066Sahrens 
110146657f8dSmmusante 	(void) printf(gettext("  pool: %s\n"), name);
110246657f8dSmmusante 	(void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
110346657f8dSmmusante 	(void) printf(gettext(" state: %s"), health);
11044c58d714Sdarrenm 	if (pool_state == POOL_STATE_DESTROYED)
110546657f8dSmmusante 		(void) printf(gettext(" (DESTROYED)"));
11064c58d714Sdarrenm 	(void) printf("\n");
1107fa9e4066Sahrens 
1108fa9e4066Sahrens 	switch (reason) {
1109fa9e4066Sahrens 	case ZPOOL_STATUS_MISSING_DEV_R:
1110fa9e4066Sahrens 	case ZPOOL_STATUS_MISSING_DEV_NR:
1111fa9e4066Sahrens 	case ZPOOL_STATUS_BAD_GUID_SUM:
1112fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices are missing "
1113fa9e4066Sahrens 		    "from the system.\n"));
1114fa9e4066Sahrens 		break;
1115fa9e4066Sahrens 
1116fa9e4066Sahrens 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
1117fa9e4066Sahrens 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1118fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices contains "
1119fa9e4066Sahrens 		    "corrupted data.\n"));
1120fa9e4066Sahrens 		break;
1121fa9e4066Sahrens 
1122fa9e4066Sahrens 	case ZPOOL_STATUS_CORRUPT_DATA:
1123fa9e4066Sahrens 		(void) printf(gettext("status: The pool data is corrupted.\n"));
1124fa9e4066Sahrens 		break;
1125fa9e4066Sahrens 
1126441d80aaSlling 	case ZPOOL_STATUS_OFFLINE_DEV:
1127441d80aaSlling 		(void) printf(gettext("status: One or more devices "
1128441d80aaSlling 		    "are offlined.\n"));
1129441d80aaSlling 		break;
1130441d80aaSlling 
1131ea8dc4b6Seschrock 	case ZPOOL_STATUS_CORRUPT_POOL:
1132ea8dc4b6Seschrock 		(void) printf(gettext("status: The pool metadata is "
1133ea8dc4b6Seschrock 		    "corrupted.\n"));
1134ea8dc4b6Seschrock 		break;
1135ea8dc4b6Seschrock 
1136eaca9bbdSeschrock 	case ZPOOL_STATUS_VERSION_OLDER:
1137eaca9bbdSeschrock 		(void) printf(gettext("status: The pool is formatted using an "
1138eaca9bbdSeschrock 		    "older on-disk version.\n"));
1139eaca9bbdSeschrock 		break;
1140eaca9bbdSeschrock 
1141eaca9bbdSeschrock 	case ZPOOL_STATUS_VERSION_NEWER:
1142eaca9bbdSeschrock 		(void) printf(gettext("status: The pool is formatted using an "
1143eaca9bbdSeschrock 		    "incompatible version.\n"));
1144eaca9bbdSeschrock 		break;
114595173954Sek110237 	case ZPOOL_STATUS_HOSTID_MISMATCH:
114695173954Sek110237 		(void) printf(gettext("status: The pool was last accessed by "
114795173954Sek110237 		    "another system.\n"));
114895173954Sek110237 		break;
11493d7072f8Seschrock 	case ZPOOL_STATUS_FAULTED_DEV_R:
11503d7072f8Seschrock 	case ZPOOL_STATUS_FAULTED_DEV_NR:
11513d7072f8Seschrock 		(void) printf(gettext("status: One or more devices are "
11523d7072f8Seschrock 		    "faulted.\n"));
11533d7072f8Seschrock 		break;
11543d7072f8Seschrock 
1155fa9e4066Sahrens 	default:
1156fa9e4066Sahrens 		/*
1157fa9e4066Sahrens 		 * No other status can be seen when importing pools.
1158fa9e4066Sahrens 		 */
1159fa9e4066Sahrens 		assert(reason == ZPOOL_STATUS_OK);
1160fa9e4066Sahrens 	}
1161fa9e4066Sahrens 
1162fa9e4066Sahrens 	/*
1163fa9e4066Sahrens 	 * Print out an action according to the overall state of the pool.
1164fa9e4066Sahrens 	 */
116546657f8dSmmusante 	if (vs->vs_state == VDEV_STATE_HEALTHY) {
1166eaca9bbdSeschrock 		if (reason == ZPOOL_STATUS_VERSION_OLDER)
1167eaca9bbdSeschrock 			(void) printf(gettext("action: The pool can be "
1168eaca9bbdSeschrock 			    "imported using its name or numeric identifier, "
1169eaca9bbdSeschrock 			    "though\n\tsome features will not be available "
1170eaca9bbdSeschrock 			    "without an explicit 'zpool upgrade'.\n"));
117195173954Sek110237 		else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
117295173954Sek110237 			(void) printf(gettext("action: The pool can be "
117395173954Sek110237 			    "imported using its name or numeric "
117495173954Sek110237 			    "identifier and\n\tthe '-f' flag.\n"));
1175fa9e4066Sahrens 		else
1176eaca9bbdSeschrock 			(void) printf(gettext("action: The pool can be "
1177eaca9bbdSeschrock 			    "imported using its name or numeric "
1178eaca9bbdSeschrock 			    "identifier.\n"));
117946657f8dSmmusante 	} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1180fa9e4066Sahrens 		(void) printf(gettext("action: The pool can be imported "
1181fa9e4066Sahrens 		    "despite missing or damaged devices.  The\n\tfault "
1182eaca9bbdSeschrock 		    "tolerance of the pool may be compromised if imported.\n"));
1183fa9e4066Sahrens 	} else {
1184eaca9bbdSeschrock 		switch (reason) {
1185eaca9bbdSeschrock 		case ZPOOL_STATUS_VERSION_NEWER:
1186eaca9bbdSeschrock 			(void) printf(gettext("action: The pool cannot be "
1187eaca9bbdSeschrock 			    "imported.  Access the pool on a system running "
1188eaca9bbdSeschrock 			    "newer\n\tsoftware, or recreate the pool from "
1189eaca9bbdSeschrock 			    "backup.\n"));
1190eaca9bbdSeschrock 			break;
1191eaca9bbdSeschrock 		case ZPOOL_STATUS_MISSING_DEV_R:
1192eaca9bbdSeschrock 		case ZPOOL_STATUS_MISSING_DEV_NR:
1193eaca9bbdSeschrock 		case ZPOOL_STATUS_BAD_GUID_SUM:
1194fa9e4066Sahrens 			(void) printf(gettext("action: The pool cannot be "
1195fa9e4066Sahrens 			    "imported. Attach the missing\n\tdevices and try "
1196fa9e4066Sahrens 			    "again.\n"));
1197eaca9bbdSeschrock 			break;
1198eaca9bbdSeschrock 		default:
1199fa9e4066Sahrens 			(void) printf(gettext("action: The pool cannot be "
1200fa9e4066Sahrens 			    "imported due to damaged devices or data.\n"));
1201fa9e4066Sahrens 		}
1202eaca9bbdSeschrock 	}
1203eaca9bbdSeschrock 
120446657f8dSmmusante 	/*
120546657f8dSmmusante 	 * If the state is "closed" or "can't open", and the aux state
120646657f8dSmmusante 	 * is "corrupt data":
120746657f8dSmmusante 	 */
120846657f8dSmmusante 	if (((vs->vs_state == VDEV_STATE_CLOSED) ||
120946657f8dSmmusante 	    (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
121046657f8dSmmusante 	    (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1211eaca9bbdSeschrock 		if (pool_state == POOL_STATE_DESTROYED)
1212eaca9bbdSeschrock 			(void) printf(gettext("\tThe pool was destroyed, "
1213eaca9bbdSeschrock 			    "but can be imported using the '-Df' flags.\n"));
1214eaca9bbdSeschrock 		else if (pool_state != POOL_STATE_EXPORTED)
1215eaca9bbdSeschrock 			(void) printf(gettext("\tThe pool may be active on "
121618ce54dfSek110237 			    "another system, but can be imported using\n\t"
1217eaca9bbdSeschrock 			    "the '-f' flag.\n"));
1218eaca9bbdSeschrock 	}
1219fa9e4066Sahrens 
1220fa9e4066Sahrens 	if (msgid != NULL)
1221fa9e4066Sahrens 		(void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
1222fa9e4066Sahrens 		    msgid);
1223fa9e4066Sahrens 
1224fa9e4066Sahrens 	(void) printf(gettext("config:\n\n"));
1225fa9e4066Sahrens 
1226c67d9675Seschrock 	namewidth = max_width(NULL, nvroot, 0, 0);
1227fa9e4066Sahrens 	if (namewidth < 10)
1228fa9e4066Sahrens 		namewidth = 10;
12298654d025Sperrin 
12308654d025Sperrin 	print_import_config(name, nvroot, namewidth, 0, B_FALSE);
12318654d025Sperrin 	if (num_logs(nvroot) > 0) {
12328654d025Sperrin 		(void) printf(gettext("\tlogs\n"));
12338654d025Sperrin 		print_import_config(name, nvroot, namewidth, 0, B_TRUE);
12348654d025Sperrin 	}
1235fa9e4066Sahrens 
1236fa9e4066Sahrens 	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
123746657f8dSmmusante 		(void) printf(gettext("\n\tAdditional devices are known to "
1238fa9e4066Sahrens 		    "be part of this pool, though their\n\texact "
123946657f8dSmmusante 		    "configuration cannot be determined.\n"));
1240fa9e4066Sahrens 	}
1241fa9e4066Sahrens }
1242fa9e4066Sahrens 
1243fa9e4066Sahrens /*
1244fa9e4066Sahrens  * Perform the import for the given configuration.  This passes the heavy
1245990b4856Slling  * lifting off to zpool_import_props(), and then mounts the datasets contained
1246990b4856Slling  * within the pool.
1247fa9e4066Sahrens  */
1248fa9e4066Sahrens static int
1249fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts,
1250c5904d13Seschrock     int force, nvlist_t *props, boolean_t allowfaulted)
1251fa9e4066Sahrens {
1252fa9e4066Sahrens 	zpool_handle_t *zhp;
1253fa9e4066Sahrens 	char *name;
1254fa9e4066Sahrens 	uint64_t state;
1255eaca9bbdSeschrock 	uint64_t version;
1256ecd6cf80Smarks 	int error = 0;
1257fa9e4066Sahrens 
1258fa9e4066Sahrens 	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1259fa9e4066Sahrens 	    &name) == 0);
1260fa9e4066Sahrens 
1261fa9e4066Sahrens 	verify(nvlist_lookup_uint64(config,
1262fa9e4066Sahrens 	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1263eaca9bbdSeschrock 	verify(nvlist_lookup_uint64(config,
1264eaca9bbdSeschrock 	    ZPOOL_CONFIG_VERSION, &version) == 0);
1265e7437265Sahrens 	if (version > SPA_VERSION) {
1266eaca9bbdSeschrock 		(void) fprintf(stderr, gettext("cannot import '%s': pool "
1267eaca9bbdSeschrock 		    "is formatted using a newer ZFS version\n"), name);
1268eaca9bbdSeschrock 		return (1);
1269eaca9bbdSeschrock 	} else if (state != POOL_STATE_EXPORTED && !force) {
127095173954Sek110237 		uint64_t hostid;
127195173954Sek110237 
127295173954Sek110237 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
127395173954Sek110237 		    &hostid) == 0) {
127495173954Sek110237 			if ((unsigned long)hostid != gethostid()) {
127595173954Sek110237 				char *hostname;
127695173954Sek110237 				uint64_t timestamp;
127795173954Sek110237 				time_t t;
127895173954Sek110237 
127995173954Sek110237 				verify(nvlist_lookup_string(config,
128095173954Sek110237 				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
128195173954Sek110237 				verify(nvlist_lookup_uint64(config,
128295173954Sek110237 				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
128395173954Sek110237 				t = timestamp;
128495173954Sek110237 				(void) fprintf(stderr, gettext("cannot import "
128595173954Sek110237 				    "'%s': pool may be in use from other "
128695173954Sek110237 				    "system, it was last accessed by %s "
128795173954Sek110237 				    "(hostid: 0x%lx) on %s"), name, hostname,
128895173954Sek110237 				    (unsigned long)hostid,
128995173954Sek110237 				    asctime(localtime(&t)));
129095173954Sek110237 				(void) fprintf(stderr, gettext("use '-f' to "
129195173954Sek110237 				    "import anyway\n"));
1292fa9e4066Sahrens 				return (1);
1293fa9e4066Sahrens 			}
129495173954Sek110237 		} else {
129595173954Sek110237 			(void) fprintf(stderr, gettext("cannot import '%s': "
129695173954Sek110237 			    "pool may be in use from other system\n"), name);
129795173954Sek110237 			(void) fprintf(stderr, gettext("use '-f' to import "
129895173954Sek110237 			    "anyway\n"));
129995173954Sek110237 			return (1);
130095173954Sek110237 		}
130195173954Sek110237 	}
1302fa9e4066Sahrens 
1303c5904d13Seschrock 	if (zpool_import_props(g_zfs, config, newname, props,
1304c5904d13Seschrock 	    allowfaulted) != 0)
1305fa9e4066Sahrens 		return (1);
1306fa9e4066Sahrens 
1307fa9e4066Sahrens 	if (newname != NULL)
1308fa9e4066Sahrens 		name = (char *)newname;
1309fa9e4066Sahrens 
1310c5904d13Seschrock 	verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1311fa9e4066Sahrens 
1312f3861e1aSahl 	if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1313fa9e4066Sahrens 		zpool_close(zhp);
1314fa9e4066Sahrens 		return (1);
1315fa9e4066Sahrens 	}
1316fa9e4066Sahrens 
1317fa9e4066Sahrens 	zpool_close(zhp);
1318ecd6cf80Smarks 	return (error);
1319fa9e4066Sahrens }
1320fa9e4066Sahrens 
1321fa9e4066Sahrens /*
13224c58d714Sdarrenm  * zpool import [-d dir] [-D]
13232f8aaab3Seschrock  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
13242f8aaab3Seschrock  *              [-d dir | -c cachefile] [-f] -a
13252f8aaab3Seschrock  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
13262f8aaab3Seschrock  *              [-d dir | -c cachefile] [-f] <pool | id> [newpool]
13272f8aaab3Seschrock  *
13282f8aaab3Seschrock  *	 -c	Read pool information from a cachefile instead of searching
13292f8aaab3Seschrock  *		devices.
1330fa9e4066Sahrens  *
1331fa9e4066Sahrens  *       -d	Scan in a specific directory, other than /dev/dsk.  More than
1332fa9e4066Sahrens  *		one directory can be specified using multiple '-d' options.
1333fa9e4066Sahrens  *
13344c58d714Sdarrenm  *       -D     Scan for previously destroyed pools or import all or only
13354c58d714Sdarrenm  *              specified destroyed pools.
13364c58d714Sdarrenm  *
1337fa9e4066Sahrens  *       -R	Temporarily import the pool, with all mountpoints relative to
1338fa9e4066Sahrens  *		the given root.  The pool will remain exported when the machine
1339fa9e4066Sahrens  *		is rebooted.
1340fa9e4066Sahrens  *
1341fa9e4066Sahrens  *       -f	Force import, even if it appears that the pool is active.
1342fa9e4066Sahrens  *
1343c5904d13Seschrock  *       -F	Import even in the presence of faulted vdevs.  This is an
1344c5904d13Seschrock  *       	intentionally undocumented option for testing purposes, and
1345c5904d13Seschrock  *       	treats the pool configuration as complete, leaving any bad
1346c5904d13Seschrock  *		vdevs in the FAULTED state.
1347c5904d13Seschrock  *
1348fa9e4066Sahrens  *       -a	Import all pools found.
1349fa9e4066Sahrens  *
1350990b4856Slling  *       -o	Set property=value and/or temporary mount options (without '=').
1351ecd6cf80Smarks  *
1352fa9e4066Sahrens  * The import command scans for pools to import, and import pools based on pool
1353fa9e4066Sahrens  * name and GUID.  The pool can also be renamed as part of the import process.
1354fa9e4066Sahrens  */
1355fa9e4066Sahrens int
1356fa9e4066Sahrens zpool_do_import(int argc, char **argv)
1357fa9e4066Sahrens {
1358fa9e4066Sahrens 	char **searchdirs = NULL;
1359fa9e4066Sahrens 	int nsearch = 0;
1360fa9e4066Sahrens 	int c;
1361fa9e4066Sahrens 	int err;
13622f8aaab3Seschrock 	nvlist_t *pools = NULL;
136399653d4eSeschrock 	boolean_t do_all = B_FALSE;
136499653d4eSeschrock 	boolean_t do_destroyed = B_FALSE;
1365fa9e4066Sahrens 	char *mntopts = NULL;
136699653d4eSeschrock 	boolean_t do_force = B_FALSE;
1367fa9e4066Sahrens 	nvpair_t *elem;
1368fa9e4066Sahrens 	nvlist_t *config;
136924e697d4Sck153898 	uint64_t searchguid = 0;
137024e697d4Sck153898 	char *searchname = NULL;
1371990b4856Slling 	char *propval;
1372fa9e4066Sahrens 	nvlist_t *found_config;
1373ecd6cf80Smarks 	nvlist_t *props = NULL;
137499653d4eSeschrock 	boolean_t first;
1375c5904d13Seschrock 	boolean_t allow_faulted = B_FALSE;
13764c58d714Sdarrenm 	uint64_t pool_state;
13772f8aaab3Seschrock 	char *cachefile = NULL;
1378fa9e4066Sahrens 
1379fa9e4066Sahrens 	/* check options */
1380c5904d13Seschrock 	while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) {
1381fa9e4066Sahrens 		switch (c) {
1382fa9e4066Sahrens 		case 'a':
138399653d4eSeschrock 			do_all = B_TRUE;
1384fa9e4066Sahrens 			break;
13852f8aaab3Seschrock 		case 'c':
13862f8aaab3Seschrock 			cachefile = optarg;
13872f8aaab3Seschrock 			break;
1388fa9e4066Sahrens 		case 'd':
1389fa9e4066Sahrens 			if (searchdirs == NULL) {
1390fa9e4066Sahrens 				searchdirs = safe_malloc(sizeof (char *));
1391fa9e4066Sahrens 			} else {
1392fa9e4066Sahrens 				char **tmp = safe_malloc((nsearch + 1) *
1393fa9e4066Sahrens 				    sizeof (char *));
1394fa9e4066Sahrens 				bcopy(searchdirs, tmp, nsearch *
1395fa9e4066Sahrens 				    sizeof (char *));
1396fa9e4066Sahrens 				free(searchdirs);
1397fa9e4066Sahrens 				searchdirs = tmp;
1398fa9e4066Sahrens 			}
1399fa9e4066Sahrens 			searchdirs[nsearch++] = optarg;
1400fa9e4066Sahrens 			break;
14014c58d714Sdarrenm 		case 'D':
140299653d4eSeschrock 			do_destroyed = B_TRUE;
14034c58d714Sdarrenm 			break;
1404fa9e4066Sahrens 		case 'f':
140599653d4eSeschrock 			do_force = B_TRUE;
1406fa9e4066Sahrens 			break;
1407c5904d13Seschrock 		case 'F':
1408c5904d13Seschrock 			allow_faulted = B_TRUE;
1409c5904d13Seschrock 			break;
1410fa9e4066Sahrens 		case 'o':
1411990b4856Slling 			if ((propval = strchr(optarg, '=')) != NULL) {
1412990b4856Slling 				*propval = '\0';
1413990b4856Slling 				propval++;
1414*0a48a24eStimh 				if (add_prop_list(optarg, propval,
1415*0a48a24eStimh 				    &props, B_TRUE))
1416990b4856Slling 					goto error;
1417990b4856Slling 			} else {
1418fa9e4066Sahrens 				mntopts = optarg;
1419990b4856Slling 			}
1420fa9e4066Sahrens 			break;
1421fa9e4066Sahrens 		case 'R':
1422990b4856Slling 			if (add_prop_list(zpool_prop_to_name(
1423*0a48a24eStimh 			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1424990b4856Slling 				goto error;
14252f8aaab3Seschrock 			if (nvlist_lookup_string(props,
14262f8aaab3Seschrock 			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
14272f8aaab3Seschrock 			    &propval) == 0)
14282f8aaab3Seschrock 				break;
1429990b4856Slling 			if (add_prop_list(zpool_prop_to_name(
1430*0a48a24eStimh 			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1431990b4856Slling 				goto error;
1432fa9e4066Sahrens 			break;
1433fa9e4066Sahrens 		case ':':
1434fa9e4066Sahrens 			(void) fprintf(stderr, gettext("missing argument for "
1435fa9e4066Sahrens 			    "'%c' option\n"), optopt);
143699653d4eSeschrock 			usage(B_FALSE);
1437fa9e4066Sahrens 			break;
1438fa9e4066Sahrens 		case '?':
1439fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1440fa9e4066Sahrens 			    optopt);
144199653d4eSeschrock 			usage(B_FALSE);
1442fa9e4066Sahrens 		}
1443fa9e4066Sahrens 	}
1444fa9e4066Sahrens 
1445fa9e4066Sahrens 	argc -= optind;
1446fa9e4066Sahrens 	argv += optind;
1447fa9e4066Sahrens 
14482f8aaab3Seschrock 	if (cachefile && nsearch != 0) {
14492f8aaab3Seschrock 		(void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
14502f8aaab3Seschrock 		usage(B_FALSE);
14512f8aaab3Seschrock 	}
14522f8aaab3Seschrock 
1453fa9e4066Sahrens 	if (searchdirs == NULL) {
1454fa9e4066Sahrens 		searchdirs = safe_malloc(sizeof (char *));
1455fa9e4066Sahrens 		searchdirs[0] = "/dev/dsk";
1456fa9e4066Sahrens 		nsearch = 1;
1457fa9e4066Sahrens 	}
1458fa9e4066Sahrens 
1459fa9e4066Sahrens 	/* check argument count */
1460fa9e4066Sahrens 	if (do_all) {
1461fa9e4066Sahrens 		if (argc != 0) {
1462fa9e4066Sahrens 			(void) fprintf(stderr, gettext("too many arguments\n"));
146399653d4eSeschrock 			usage(B_FALSE);
1464fa9e4066Sahrens 		}
1465fa9e4066Sahrens 	} else {
1466fa9e4066Sahrens 		if (argc > 2) {
1467fa9e4066Sahrens 			(void) fprintf(stderr, gettext("too many arguments\n"));
146899653d4eSeschrock 			usage(B_FALSE);
1469fa9e4066Sahrens 		}
1470fa9e4066Sahrens 
1471fa9e4066Sahrens 		/*
1472fa9e4066Sahrens 		 * Check for the SYS_CONFIG privilege.  We do this explicitly
1473fa9e4066Sahrens 		 * here because otherwise any attempt to discover pools will
1474fa9e4066Sahrens 		 * silently fail.
1475fa9e4066Sahrens 		 */
1476fa9e4066Sahrens 		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1477fa9e4066Sahrens 			(void) fprintf(stderr, gettext("cannot "
1478fa9e4066Sahrens 			    "discover pools: permission denied\n"));
147999653d4eSeschrock 			free(searchdirs);
1480fa9e4066Sahrens 			return (1);
1481fa9e4066Sahrens 		}
1482fa9e4066Sahrens 	}
1483fa9e4066Sahrens 
1484fa9e4066Sahrens 	/*
1485fa9e4066Sahrens 	 * Depending on the arguments given, we do one of the following:
1486fa9e4066Sahrens 	 *
1487fa9e4066Sahrens 	 *	<none>	Iterate through all pools and display information about
1488fa9e4066Sahrens 	 *		each one.
1489fa9e4066Sahrens 	 *
1490fa9e4066Sahrens 	 *	-a	Iterate through all pools and try to import each one.
1491fa9e4066Sahrens 	 *
1492fa9e4066Sahrens 	 *	<id>	Find the pool that corresponds to the given GUID/pool
1493fa9e4066Sahrens 	 *		name and import that one.
14944c58d714Sdarrenm 	 *
14954c58d714Sdarrenm 	 *	-D	Above options applies only to destroyed pools.
1496fa9e4066Sahrens 	 */
1497fa9e4066Sahrens 	if (argc != 0) {
1498fa9e4066Sahrens 		char *endptr;
1499fa9e4066Sahrens 
1500fa9e4066Sahrens 		errno = 0;
1501fa9e4066Sahrens 		searchguid = strtoull(argv[0], &endptr, 10);
1502fa9e4066Sahrens 		if (errno != 0 || *endptr != '\0')
1503fa9e4066Sahrens 			searchname = argv[0];
1504fa9e4066Sahrens 		found_config = NULL;
1505fa9e4066Sahrens 	}
1506fa9e4066Sahrens 
150724e697d4Sck153898 	if (cachefile) {
1508e829d913Sck153898 		pools = zpool_find_import_cached(g_zfs, cachefile, searchname,
1509e829d913Sck153898 		    searchguid);
151024e697d4Sck153898 	} else if (searchname != NULL) {
151124e697d4Sck153898 		pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs,
151224e697d4Sck153898 		    searchname);
151324e697d4Sck153898 	} else {
151424e697d4Sck153898 		/*
151524e697d4Sck153898 		 * It's OK to search by guid even if searchguid is 0.
151624e697d4Sck153898 		 */
151724e697d4Sck153898 		pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs,
151824e697d4Sck153898 		    searchguid);
151924e697d4Sck153898 	}
152024e697d4Sck153898 
152124e697d4Sck153898 	if (pools == NULL) {
152224e697d4Sck153898 		if (argc != 0) {
152324e697d4Sck153898 			(void) fprintf(stderr, gettext("cannot import '%s': "
152424e697d4Sck153898 			    "no such pool available\n"), argv[0]);
152524e697d4Sck153898 		}
152624e697d4Sck153898 		free(searchdirs);
152724e697d4Sck153898 		return (1);
152824e697d4Sck153898 	}
152924e697d4Sck153898 
153024e697d4Sck153898 	/*
153124e697d4Sck153898 	 * At this point we have a list of import candidate configs. Even if
153224e697d4Sck153898 	 * we were searching by pool name or guid, we still need to
153324e697d4Sck153898 	 * post-process the list to deal with pool state and possible
153424e697d4Sck153898 	 * duplicate names.
153524e697d4Sck153898 	 */
1536fa9e4066Sahrens 	err = 0;
1537fa9e4066Sahrens 	elem = NULL;
153899653d4eSeschrock 	first = B_TRUE;
1539fa9e4066Sahrens 	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1540fa9e4066Sahrens 
1541fa9e4066Sahrens 		verify(nvpair_value_nvlist(elem, &config) == 0);
1542fa9e4066Sahrens 
15434c58d714Sdarrenm 		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
15444c58d714Sdarrenm 		    &pool_state) == 0);
15454c58d714Sdarrenm 		if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
15464c58d714Sdarrenm 			continue;
15474c58d714Sdarrenm 		if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
15484c58d714Sdarrenm 			continue;
15494c58d714Sdarrenm 
1550fa9e4066Sahrens 		if (argc == 0) {
1551fa9e4066Sahrens 			if (first)
155299653d4eSeschrock 				first = B_FALSE;
15533bb79becSeschrock 			else if (!do_all)
1554fa9e4066Sahrens 				(void) printf("\n");
1555fa9e4066Sahrens 
1556fa9e4066Sahrens 			if (do_all)
1557fa9e4066Sahrens 				err |= do_import(config, NULL, mntopts,
1558c5904d13Seschrock 				    do_force, props, allow_faulted);
1559fa9e4066Sahrens 			else
1560fa9e4066Sahrens 				show_import(config);
1561fa9e4066Sahrens 		} else if (searchname != NULL) {
1562fa9e4066Sahrens 			char *name;
1563fa9e4066Sahrens 
1564fa9e4066Sahrens 			/*
1565fa9e4066Sahrens 			 * We are searching for a pool based on name.
1566fa9e4066Sahrens 			 */
1567fa9e4066Sahrens 			verify(nvlist_lookup_string(config,
1568fa9e4066Sahrens 			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1569fa9e4066Sahrens 
1570fa9e4066Sahrens 			if (strcmp(name, searchname) == 0) {
1571fa9e4066Sahrens 				if (found_config != NULL) {
1572fa9e4066Sahrens 					(void) fprintf(stderr, gettext(
1573fa9e4066Sahrens 					    "cannot import '%s': more than "
1574fa9e4066Sahrens 					    "one matching pool\n"), searchname);
1575fa9e4066Sahrens 					(void) fprintf(stderr, gettext(
1576fa9e4066Sahrens 					    "import by numeric ID instead\n"));
157799653d4eSeschrock 					err = B_TRUE;
1578fa9e4066Sahrens 				}
1579fa9e4066Sahrens 				found_config = config;
1580fa9e4066Sahrens 			}
1581fa9e4066Sahrens 		} else {
1582fa9e4066Sahrens 			uint64_t guid;
1583fa9e4066Sahrens 
1584fa9e4066Sahrens 			/*
1585fa9e4066Sahrens 			 * Search for a pool by guid.
1586fa9e4066Sahrens 			 */
1587fa9e4066Sahrens 			verify(nvlist_lookup_uint64(config,
1588fa9e4066Sahrens 			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1589fa9e4066Sahrens 
1590fa9e4066Sahrens 			if (guid == searchguid)
1591fa9e4066Sahrens 				found_config = config;
1592fa9e4066Sahrens 		}
1593fa9e4066Sahrens 	}
1594fa9e4066Sahrens 
1595fa9e4066Sahrens 	/*
1596fa9e4066Sahrens 	 * If we were searching for a specific pool, verify that we found a
1597fa9e4066Sahrens 	 * pool, and then do the import.
1598fa9e4066Sahrens 	 */
1599fa9e4066Sahrens 	if (argc != 0 && err == 0) {
1600fa9e4066Sahrens 		if (found_config == NULL) {
1601fa9e4066Sahrens 			(void) fprintf(stderr, gettext("cannot import '%s': "
1602fa9e4066Sahrens 			    "no such pool available\n"), argv[0]);
160399653d4eSeschrock 			err = B_TRUE;
1604fa9e4066Sahrens 		} else {
1605fa9e4066Sahrens 			err |= do_import(found_config, argc == 1 ? NULL :
1606c5904d13Seschrock 			    argv[1], mntopts, do_force, props, allow_faulted);
1607fa9e4066Sahrens 		}
1608fa9e4066Sahrens 	}
1609fa9e4066Sahrens 
1610fa9e4066Sahrens 	/*
1611fa9e4066Sahrens 	 * If we were just looking for pools, report an error if none were
1612fa9e4066Sahrens 	 * found.
1613fa9e4066Sahrens 	 */
1614fa9e4066Sahrens 	if (argc == 0 && first)
1615fa9e4066Sahrens 		(void) fprintf(stderr,
1616fa9e4066Sahrens 		    gettext("no pools available to import\n"));
1617fa9e4066Sahrens 
1618ecd6cf80Smarks error:
1619ecd6cf80Smarks 	nvlist_free(props);
1620fa9e4066Sahrens 	nvlist_free(pools);
162199653d4eSeschrock 	free(searchdirs);
1622fa9e4066Sahrens 
1623fa9e4066Sahrens 	return (err ? 1 : 0);
1624fa9e4066Sahrens }
1625fa9e4066Sahrens 
1626fa9e4066Sahrens typedef struct iostat_cbdata {
1627fa9e4066Sahrens 	zpool_list_t *cb_list;
1628fa9e4066Sahrens 	int cb_verbose;
1629fa9e4066Sahrens 	int cb_iteration;
1630fa9e4066Sahrens 	int cb_namewidth;
1631fa9e4066Sahrens } iostat_cbdata_t;
1632fa9e4066Sahrens 
1633fa9e4066Sahrens static void
1634fa9e4066Sahrens print_iostat_separator(iostat_cbdata_t *cb)
1635fa9e4066Sahrens {
1636fa9e4066Sahrens 	int i = 0;
1637fa9e4066Sahrens 
1638fa9e4066Sahrens 	for (i = 0; i < cb->cb_namewidth; i++)
1639fa9e4066Sahrens 		(void) printf("-");
1640fa9e4066Sahrens 	(void) printf("  -----  -----  -----  -----  -----  -----\n");
1641fa9e4066Sahrens }
1642fa9e4066Sahrens 
1643fa9e4066Sahrens static void
1644fa9e4066Sahrens print_iostat_header(iostat_cbdata_t *cb)
1645fa9e4066Sahrens {
1646fa9e4066Sahrens 	(void) printf("%*s     capacity     operations    bandwidth\n",
1647fa9e4066Sahrens 	    cb->cb_namewidth, "");
1648fa9e4066Sahrens 	(void) printf("%-*s   used  avail   read  write   read  write\n",
1649fa9e4066Sahrens 	    cb->cb_namewidth, "pool");
1650fa9e4066Sahrens 	print_iostat_separator(cb);
1651fa9e4066Sahrens }
1652fa9e4066Sahrens 
1653fa9e4066Sahrens /*
1654fa9e4066Sahrens  * Display a single statistic.
1655fa9e4066Sahrens  */
1656990b4856Slling static void
1657fa9e4066Sahrens print_one_stat(uint64_t value)
1658fa9e4066Sahrens {
1659fa9e4066Sahrens 	char buf[64];
1660fa9e4066Sahrens 
1661fa9e4066Sahrens 	zfs_nicenum(value, buf, sizeof (buf));
1662fa9e4066Sahrens 	(void) printf("  %5s", buf);
1663fa9e4066Sahrens }
1664fa9e4066Sahrens 
1665fa9e4066Sahrens /*
1666fa9e4066Sahrens  * Print out all the statistics for the given vdev.  This can either be the
1667fa9e4066Sahrens  * toplevel configuration, or called recursively.  If 'name' is NULL, then this
1668fa9e4066Sahrens  * is a verbose output, and we don't want to display the toplevel pool stats.
1669fa9e4066Sahrens  */
1670fa9e4066Sahrens void
1671c67d9675Seschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1672c67d9675Seschrock     nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1673fa9e4066Sahrens {
1674fa9e4066Sahrens 	nvlist_t **oldchild, **newchild;
1675fa9e4066Sahrens 	uint_t c, children;
1676fa9e4066Sahrens 	vdev_stat_t *oldvs, *newvs;
1677fa9e4066Sahrens 	vdev_stat_t zerovs = { 0 };
1678fa9e4066Sahrens 	uint64_t tdelta;
1679fa9e4066Sahrens 	double scale;
1680afefbcddSeschrock 	char *vname;
1681fa9e4066Sahrens 
1682fa9e4066Sahrens 	if (oldnv != NULL) {
1683fa9e4066Sahrens 		verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1684fa9e4066Sahrens 		    (uint64_t **)&oldvs, &c) == 0);
1685fa9e4066Sahrens 	} else {
1686fa9e4066Sahrens 		oldvs = &zerovs;
1687fa9e4066Sahrens 	}
1688fa9e4066Sahrens 
1689fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1690fa9e4066Sahrens 	    (uint64_t **)&newvs, &c) == 0);
1691fa9e4066Sahrens 
1692fa9e4066Sahrens 	if (strlen(name) + depth > cb->cb_namewidth)
1693fa9e4066Sahrens 		(void) printf("%*s%s", depth, "", name);
1694fa9e4066Sahrens 	else
1695fa9e4066Sahrens 		(void) printf("%*s%s%*s", depth, "", name,
1696fa9e4066Sahrens 		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
1697fa9e4066Sahrens 
1698fa9e4066Sahrens 	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1699fa9e4066Sahrens 
1700fa9e4066Sahrens 	if (tdelta == 0)
1701fa9e4066Sahrens 		scale = 1.0;
1702fa9e4066Sahrens 	else
1703fa9e4066Sahrens 		scale = (double)NANOSEC / tdelta;
1704fa9e4066Sahrens 
1705fa9e4066Sahrens 	/* only toplevel vdevs have capacity stats */
1706fa9e4066Sahrens 	if (newvs->vs_space == 0) {
1707fa9e4066Sahrens 		(void) printf("      -      -");
1708fa9e4066Sahrens 	} else {
1709fa9e4066Sahrens 		print_one_stat(newvs->vs_alloc);
1710fa9e4066Sahrens 		print_one_stat(newvs->vs_space - newvs->vs_alloc);
1711fa9e4066Sahrens 	}
1712fa9e4066Sahrens 
1713fa9e4066Sahrens 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1714fa9e4066Sahrens 	    oldvs->vs_ops[ZIO_TYPE_READ])));
1715fa9e4066Sahrens 
1716fa9e4066Sahrens 	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1717fa9e4066Sahrens 	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
1718fa9e4066Sahrens 
1719fa9e4066Sahrens 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1720fa9e4066Sahrens 	    oldvs->vs_bytes[ZIO_TYPE_READ])));
1721fa9e4066Sahrens 
1722fa9e4066Sahrens 	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1723fa9e4066Sahrens 	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1724fa9e4066Sahrens 
1725fa9e4066Sahrens 	(void) printf("\n");
1726fa9e4066Sahrens 
1727fa9e4066Sahrens 	if (!cb->cb_verbose)
1728fa9e4066Sahrens 		return;
1729fa9e4066Sahrens 
1730fa9e4066Sahrens 	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1731fa9e4066Sahrens 	    &newchild, &children) != 0)
1732fa9e4066Sahrens 		return;
1733fa9e4066Sahrens 
1734fa9e4066Sahrens 	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1735fa9e4066Sahrens 	    &oldchild, &c) != 0)
1736fa9e4066Sahrens 		return;
1737fa9e4066Sahrens 
1738afefbcddSeschrock 	for (c = 0; c < children; c++) {
173999653d4eSeschrock 		vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1740c67d9675Seschrock 		print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1741afefbcddSeschrock 		    newchild[c], cb, depth + 2);
1742afefbcddSeschrock 		free(vname);
1743afefbcddSeschrock 	}
1744fa94a07fSbrendan 
1745fa94a07fSbrendan 	/*
1746fa94a07fSbrendan 	 * Include level 2 ARC devices in iostat output
1747fa94a07fSbrendan 	 */
1748fa94a07fSbrendan 	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1749fa94a07fSbrendan 	    &newchild, &children) != 0)
1750fa94a07fSbrendan 		return;
1751fa94a07fSbrendan 
1752fa94a07fSbrendan 	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1753fa94a07fSbrendan 	    &oldchild, &c) != 0)
1754fa94a07fSbrendan 		return;
1755fa94a07fSbrendan 
1756fa94a07fSbrendan 	if (children > 0) {
1757fa94a07fSbrendan 		(void) printf("%-*s      -      -      -      -      -      "
1758fa94a07fSbrendan 		    "-\n", cb->cb_namewidth, "cache");
1759fa94a07fSbrendan 		for (c = 0; c < children; c++) {
1760fa94a07fSbrendan 			vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1761fa94a07fSbrendan 			print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1762fa94a07fSbrendan 			    newchild[c], cb, depth + 2);
1763fa94a07fSbrendan 			free(vname);
1764fa94a07fSbrendan 		}
1765fa94a07fSbrendan 	}
1766fa9e4066Sahrens }
1767fa9e4066Sahrens 
1768088e9d47Seschrock static int
1769088e9d47Seschrock refresh_iostat(zpool_handle_t *zhp, void *data)
1770088e9d47Seschrock {
1771088e9d47Seschrock 	iostat_cbdata_t *cb = data;
177294de1d4cSeschrock 	boolean_t missing;
1773088e9d47Seschrock 
1774088e9d47Seschrock 	/*
1775088e9d47Seschrock 	 * If the pool has disappeared, remove it from the list and continue.
1776088e9d47Seschrock 	 */
177794de1d4cSeschrock 	if (zpool_refresh_stats(zhp, &missing) != 0)
177894de1d4cSeschrock 		return (-1);
177994de1d4cSeschrock 
178094de1d4cSeschrock 	if (missing)
1781088e9d47Seschrock 		pool_list_remove(cb->cb_list, zhp);
1782088e9d47Seschrock 
1783088e9d47Seschrock 	return (0);
1784088e9d47Seschrock }
1785088e9d47Seschrock 
1786fa9e4066Sahrens /*
1787fa9e4066Sahrens  * Callback to print out the iostats for the given pool.
1788fa9e4066Sahrens  */
1789fa9e4066Sahrens int
1790fa9e4066Sahrens print_iostat(zpool_handle_t *zhp, void *data)
1791fa9e4066Sahrens {
1792fa9e4066Sahrens 	iostat_cbdata_t *cb = data;
1793fa9e4066Sahrens 	nvlist_t *oldconfig, *newconfig;
1794fa9e4066Sahrens 	nvlist_t *oldnvroot, *newnvroot;
1795fa9e4066Sahrens 
1796088e9d47Seschrock 	newconfig = zpool_get_config(zhp, &oldconfig);
1797fa9e4066Sahrens 
1798088e9d47Seschrock 	if (cb->cb_iteration == 1)
1799fa9e4066Sahrens 		oldconfig = NULL;
1800fa9e4066Sahrens 
1801fa9e4066Sahrens 	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1802fa9e4066Sahrens 	    &newnvroot) == 0);
1803fa9e4066Sahrens 
1804088e9d47Seschrock 	if (oldconfig == NULL)
1805fa9e4066Sahrens 		oldnvroot = NULL;
1806088e9d47Seschrock 	else
1807088e9d47Seschrock 		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1808088e9d47Seschrock 		    &oldnvroot) == 0);
1809fa9e4066Sahrens 
1810fa9e4066Sahrens 	/*
1811fa9e4066Sahrens 	 * Print out the statistics for the pool.
1812fa9e4066Sahrens 	 */
1813c67d9675Seschrock 	print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1814fa9e4066Sahrens 
1815fa9e4066Sahrens 	if (cb->cb_verbose)
1816fa9e4066Sahrens 		print_iostat_separator(cb);
1817fa9e4066Sahrens 
1818fa9e4066Sahrens 	return (0);
1819fa9e4066Sahrens }
1820fa9e4066Sahrens 
1821fa9e4066Sahrens int
1822fa9e4066Sahrens get_namewidth(zpool_handle_t *zhp, void *data)
1823fa9e4066Sahrens {
1824fa9e4066Sahrens 	iostat_cbdata_t *cb = data;
1825fa9e4066Sahrens 	nvlist_t *config, *nvroot;
1826fa9e4066Sahrens 
1827088e9d47Seschrock 	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1828fa9e4066Sahrens 		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1829fa9e4066Sahrens 		    &nvroot) == 0);
1830fa9e4066Sahrens 		if (!cb->cb_verbose)
1831fa9e4066Sahrens 			cb->cb_namewidth = strlen(zpool_get_name(zhp));
1832fa9e4066Sahrens 		else
1833c67d9675Seschrock 			cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1834fa9e4066Sahrens 	}
1835fa9e4066Sahrens 
1836fa9e4066Sahrens 	/*
1837fa9e4066Sahrens 	 * The width must fall into the range [10,38].  The upper limit is the
1838fa9e4066Sahrens 	 * maximum we can have and still fit in 80 columns.
1839fa9e4066Sahrens 	 */
1840fa9e4066Sahrens 	if (cb->cb_namewidth < 10)
1841fa9e4066Sahrens 		cb->cb_namewidth = 10;
1842fa9e4066Sahrens 	if (cb->cb_namewidth > 38)
1843fa9e4066Sahrens 		cb->cb_namewidth = 38;
1844fa9e4066Sahrens 
1845fa9e4066Sahrens 	return (0);
1846fa9e4066Sahrens }
1847fa9e4066Sahrens 
1848fa9e4066Sahrens /*
1849fa9e4066Sahrens  * zpool iostat [-v] [pool] ... [interval [count]]
1850fa9e4066Sahrens  *
1851fa9e4066Sahrens  *	-v	Display statistics for individual vdevs
1852fa9e4066Sahrens  *
1853fa9e4066Sahrens  * This command can be tricky because we want to be able to deal with pool
1854fa9e4066Sahrens  * creation/destruction as well as vdev configuration changes.  The bulk of this
1855fa9e4066Sahrens  * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
1856fa9e4066Sahrens  * on pool_list_update() to detect the addition of new pools.  Configuration
1857fa9e4066Sahrens  * changes are all handled within libzfs.
1858fa9e4066Sahrens  */
1859fa9e4066Sahrens int
1860fa9e4066Sahrens zpool_do_iostat(int argc, char **argv)
1861fa9e4066Sahrens {
1862fa9e4066Sahrens 	int c;
1863fa9e4066Sahrens 	int ret;
1864fa9e4066Sahrens 	int npools;
1865fa9e4066Sahrens 	unsigned long interval = 0, count = 0;
1866fa9e4066Sahrens 	zpool_list_t *list;
186799653d4eSeschrock 	boolean_t verbose = B_FALSE;
1868fa9e4066Sahrens 	iostat_cbdata_t cb;
1869fa9e4066Sahrens 
1870fa9e4066Sahrens 	/* check options */
1871fa9e4066Sahrens 	while ((c = getopt(argc, argv, "v")) != -1) {
1872fa9e4066Sahrens 		switch (c) {
1873fa9e4066Sahrens 		case 'v':
187499653d4eSeschrock 			verbose = B_TRUE;
1875fa9e4066Sahrens 			break;
1876fa9e4066Sahrens 		case '?':
1877fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1878fa9e4066Sahrens 			    optopt);
187999653d4eSeschrock 			usage(B_FALSE);
1880fa9e4066Sahrens 		}
1881fa9e4066Sahrens 	}
1882fa9e4066Sahrens 
1883fa9e4066Sahrens 	argc -= optind;
1884fa9e4066Sahrens 	argv += optind;
1885fa9e4066Sahrens 
1886fa9e4066Sahrens 	/*
1887fa9e4066Sahrens 	 * Determine if the last argument is an integer or a pool name
1888fa9e4066Sahrens 	 */
1889fa9e4066Sahrens 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
1890fa9e4066Sahrens 		char *end;
1891fa9e4066Sahrens 
1892fa9e4066Sahrens 		errno = 0;
1893fa9e4066Sahrens 		interval = strtoul(argv[argc - 1], &end, 10);
1894fa9e4066Sahrens 
1895fa9e4066Sahrens 		if (*end == '\0' && errno == 0) {
1896fa9e4066Sahrens 			if (interval == 0) {
1897fa9e4066Sahrens 				(void) fprintf(stderr, gettext("interval "
1898fa9e4066Sahrens 				    "cannot be zero\n"));
189999653d4eSeschrock 				usage(B_FALSE);
1900fa9e4066Sahrens 			}
1901fa9e4066Sahrens 
1902fa9e4066Sahrens 			/*
1903fa9e4066Sahrens 			 * Ignore the last parameter
1904fa9e4066Sahrens 			 */
1905fa9e4066Sahrens 			argc--;
1906fa9e4066Sahrens 		} else {
1907fa9e4066Sahrens 			/*
1908fa9e4066Sahrens 			 * If this is not a valid number, just plow on.  The
1909fa9e4066Sahrens 			 * user will get a more informative error message later
1910fa9e4066Sahrens 			 * on.
1911fa9e4066Sahrens 			 */
1912fa9e4066Sahrens 			interval = 0;
1913fa9e4066Sahrens 		}
1914fa9e4066Sahrens 	}
1915fa9e4066Sahrens 
1916fa9e4066Sahrens 	/*
1917fa9e4066Sahrens 	 * If the last argument is also an integer, then we have both a count
1918fa9e4066Sahrens 	 * and an integer.
1919fa9e4066Sahrens 	 */
1920fa9e4066Sahrens 	if (argc > 0 && isdigit(argv[argc - 1][0])) {
1921fa9e4066Sahrens 		char *end;
1922fa9e4066Sahrens 
1923fa9e4066Sahrens 		errno = 0;
1924fa9e4066Sahrens 		count = interval;
1925fa9e4066Sahrens 		interval = strtoul(argv[argc - 1], &end, 10);
1926fa9e4066Sahrens 
1927fa9e4066Sahrens 		if (*end == '\0' && errno == 0) {
1928fa9e4066Sahrens 			if (interval == 0) {
1929fa9e4066Sahrens 				(void) fprintf(stderr, gettext("interval "
1930fa9e4066Sahrens 				    "cannot be zero\n"));
193199653d4eSeschrock 				usage(B_FALSE);
1932fa9e4066Sahrens 			}
1933fa9e4066Sahrens 
1934fa9e4066Sahrens 			/*
1935fa9e4066Sahrens 			 * Ignore the last parameter
1936fa9e4066Sahrens 			 */
1937fa9e4066Sahrens 			argc--;
1938fa9e4066Sahrens 		} else {
1939fa9e4066Sahrens 			interval = 0;
1940fa9e4066Sahrens 		}
1941fa9e4066Sahrens 	}
1942fa9e4066Sahrens 
1943fa9e4066Sahrens 	/*
1944fa9e4066Sahrens 	 * Construct the list of all interesting pools.
1945fa9e4066Sahrens 	 */
1946fa9e4066Sahrens 	ret = 0;
1947b1b8ab34Slling 	if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1948fa9e4066Sahrens 		return (1);
1949fa9e4066Sahrens 
195099653d4eSeschrock 	if (pool_list_count(list) == 0 && argc != 0) {
195199653d4eSeschrock 		pool_list_free(list);
1952fa9e4066Sahrens 		return (1);
195399653d4eSeschrock 	}
1954fa9e4066Sahrens 
1955fa9e4066Sahrens 	if (pool_list_count(list) == 0 && interval == 0) {
195699653d4eSeschrock 		pool_list_free(list);
1957fa9e4066Sahrens 		(void) fprintf(stderr, gettext("no pools available\n"));
1958fa9e4066Sahrens 		return (1);
1959fa9e4066Sahrens 	}
1960fa9e4066Sahrens 
1961fa9e4066Sahrens 	/*
1962fa9e4066Sahrens 	 * Enter the main iostat loop.
1963fa9e4066Sahrens 	 */
1964fa9e4066Sahrens 	cb.cb_list = list;
1965fa9e4066Sahrens 	cb.cb_verbose = verbose;
1966fa9e4066Sahrens 	cb.cb_iteration = 0;
1967fa9e4066Sahrens 	cb.cb_namewidth = 0;
1968fa9e4066Sahrens 
1969fa9e4066Sahrens 	for (;;) {
1970fa9e4066Sahrens 		pool_list_update(list);
1971fa9e4066Sahrens 
1972fa9e4066Sahrens 		if ((npools = pool_list_count(list)) == 0)
1973fa9e4066Sahrens 			break;
1974fa9e4066Sahrens 
1975fa9e4066Sahrens 		/*
1976088e9d47Seschrock 		 * Refresh all statistics.  This is done as an explicit step
1977088e9d47Seschrock 		 * before calculating the maximum name width, so that any
1978088e9d47Seschrock 		 * configuration changes are properly accounted for.
1979088e9d47Seschrock 		 */
198099653d4eSeschrock 		(void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1981088e9d47Seschrock 
1982088e9d47Seschrock 		/*
1983fa9e4066Sahrens 		 * Iterate over all pools to determine the maximum width
1984fa9e4066Sahrens 		 * for the pool / device name column across all pools.
1985fa9e4066Sahrens 		 */
1986fa9e4066Sahrens 		cb.cb_namewidth = 0;
198799653d4eSeschrock 		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
1988fa9e4066Sahrens 
1989fa9e4066Sahrens 		/*
1990fa9e4066Sahrens 		 * If it's the first time, or verbose mode, print the header.
1991fa9e4066Sahrens 		 */
1992fa9e4066Sahrens 		if (++cb.cb_iteration == 1 || verbose)
1993fa9e4066Sahrens 			print_iostat_header(&cb);
1994fa9e4066Sahrens 
199599653d4eSeschrock 		(void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
1996fa9e4066Sahrens 
1997fa9e4066Sahrens 		/*
1998fa9e4066Sahrens 		 * If there's more than one pool, and we're not in verbose mode
1999fa9e4066Sahrens 		 * (which prints a separator for us), then print a separator.
2000fa9e4066Sahrens 		 */
2001fa9e4066Sahrens 		if (npools > 1 && !verbose)
2002fa9e4066Sahrens 			print_iostat_separator(&cb);
2003fa9e4066Sahrens 
2004fa9e4066Sahrens 		if (verbose)
2005fa9e4066Sahrens 			(void) printf("\n");
2006fa9e4066Sahrens 
200739c23413Seschrock 		/*
200839c23413Seschrock 		 * Flush the output so that redirection to a file isn't buffered
200939c23413Seschrock 		 * indefinitely.
201039c23413Seschrock 		 */
201139c23413Seschrock 		(void) fflush(stdout);
201239c23413Seschrock 
2013fa9e4066Sahrens 		if (interval == 0)
2014fa9e4066Sahrens 			break;
2015fa9e4066Sahrens 
2016fa9e4066Sahrens 		if (count != 0 && --count == 0)
2017fa9e4066Sahrens 			break;
2018fa9e4066Sahrens 
2019fa9e4066Sahrens 		(void) sleep(interval);
2020fa9e4066Sahrens 	}
2021fa9e4066Sahrens 
2022fa9e4066Sahrens 	pool_list_free(list);
2023fa9e4066Sahrens 
2024fa9e4066Sahrens 	return (ret);
2025fa9e4066Sahrens }
2026fa9e4066Sahrens 
2027fa9e4066Sahrens typedef struct list_cbdata {
202899653d4eSeschrock 	boolean_t	cb_scripted;
202999653d4eSeschrock 	boolean_t	cb_first;
2030990b4856Slling 	zprop_list_t	*cb_proplist;
2031fa9e4066Sahrens } list_cbdata_t;
2032fa9e4066Sahrens 
2033fa9e4066Sahrens /*
2034fa9e4066Sahrens  * Given a list of columns to display, output appropriate headers for each one.
2035fa9e4066Sahrens  */
2036990b4856Slling static void
2037990b4856Slling print_header(zprop_list_t *pl)
2038fa9e4066Sahrens {
2039990b4856Slling 	const char *header;
2040990b4856Slling 	boolean_t first = B_TRUE;
2041990b4856Slling 	boolean_t right_justify;
2042fa9e4066Sahrens 
2043990b4856Slling 	for (; pl != NULL; pl = pl->pl_next) {
2044990b4856Slling 		if (pl->pl_prop == ZPROP_INVAL)
2045990b4856Slling 			continue;
2046990b4856Slling 
2047990b4856Slling 		if (!first)
2048fa9e4066Sahrens 			(void) printf("  ");
2049fa9e4066Sahrens 		else
2050990b4856Slling 			first = B_FALSE;
2051fa9e4066Sahrens 
2052990b4856Slling 		header = zpool_prop_column_name(pl->pl_prop);
2053990b4856Slling 		right_justify = zpool_prop_align_right(pl->pl_prop);
2054990b4856Slling 
2055990b4856Slling 		if (pl->pl_next == NULL && !right_justify)
2056990b4856Slling 			(void) printf("%s", header);
2057990b4856Slling 		else if (right_justify)
2058990b4856Slling 			(void) printf("%*s", pl->pl_width, header);
2059990b4856Slling 		else
2060990b4856Slling 			(void) printf("%-*s", pl->pl_width, header);
2061fa9e4066Sahrens 	}
2062fa9e4066Sahrens 
2063fa9e4066Sahrens 	(void) printf("\n");
2064fa9e4066Sahrens }
2065fa9e4066Sahrens 
2066990b4856Slling /*
2067990b4856Slling  * Given a pool and a list of properties, print out all the properties according
2068990b4856Slling  * to the described layout.
2069990b4856Slling  */
2070990b4856Slling static void
2071990b4856Slling print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2072990b4856Slling {
2073990b4856Slling 	boolean_t first = B_TRUE;
2074990b4856Slling 	char property[ZPOOL_MAXPROPLEN];
2075990b4856Slling 	char *propstr;
2076990b4856Slling 	boolean_t right_justify;
2077990b4856Slling 	int width;
2078990b4856Slling 
2079990b4856Slling 	for (; pl != NULL; pl = pl->pl_next) {
2080990b4856Slling 		if (!first) {
2081990b4856Slling 			if (scripted)
2082990b4856Slling 				(void) printf("\t");
2083990b4856Slling 			else
2084990b4856Slling 				(void) printf("  ");
2085990b4856Slling 		} else {
2086990b4856Slling 			first = B_FALSE;
2087990b4856Slling 		}
2088990b4856Slling 
2089990b4856Slling 		right_justify = B_FALSE;
2090990b4856Slling 		if (pl->pl_prop != ZPROP_INVAL) {
2091990b4856Slling 			if (zpool_get_prop(zhp, pl->pl_prop, property,
2092990b4856Slling 			    sizeof (property), NULL) != 0)
2093990b4856Slling 				propstr = "-";
2094990b4856Slling 			else
2095990b4856Slling 				propstr = property;
2096990b4856Slling 
2097990b4856Slling 			right_justify = zpool_prop_align_right(pl->pl_prop);
2098990b4856Slling 		} else {
2099990b4856Slling 			propstr = "-";
2100990b4856Slling 		}
2101990b4856Slling 
2102990b4856Slling 		width = pl->pl_width;
2103990b4856Slling 
2104990b4856Slling 		/*
2105990b4856Slling 		 * If this is being called in scripted mode, or if this is the
2106990b4856Slling 		 * last column and it is left-justified, don't include a width
2107990b4856Slling 		 * format specifier.
2108990b4856Slling 		 */
2109990b4856Slling 		if (scripted || (pl->pl_next == NULL && !right_justify))
2110990b4856Slling 			(void) printf("%s", propstr);
2111990b4856Slling 		else if (right_justify)
2112990b4856Slling 			(void) printf("%*s", width, propstr);
2113990b4856Slling 		else
2114990b4856Slling 			(void) printf("%-*s", width, propstr);
2115990b4856Slling 	}
2116990b4856Slling 
2117990b4856Slling 	(void) printf("\n");
2118990b4856Slling }
2119990b4856Slling 
2120990b4856Slling /*
2121990b4856Slling  * Generic callback function to list a pool.
2122990b4856Slling  */
2123fa9e4066Sahrens int
2124fa9e4066Sahrens list_callback(zpool_handle_t *zhp, void *data)
2125fa9e4066Sahrens {
2126fa9e4066Sahrens 	list_cbdata_t *cbp = data;
2127fa9e4066Sahrens 
2128fa9e4066Sahrens 	if (cbp->cb_first) {
2129fa9e4066Sahrens 		if (!cbp->cb_scripted)
2130990b4856Slling 			print_header(cbp->cb_proplist);
213199653d4eSeschrock 		cbp->cb_first = B_FALSE;
2132fa9e4066Sahrens 	}
2133fa9e4066Sahrens 
2134990b4856Slling 	print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2135fa9e4066Sahrens 
2136fa9e4066Sahrens 	return (0);
2137fa9e4066Sahrens }
2138fa9e4066Sahrens 
2139fa9e4066Sahrens /*
2140990b4856Slling  * zpool list [-H] [-o prop[,prop]*] [pool] ...
2141fa9e4066Sahrens  *
2142990b4856Slling  *	-H	Scripted mode.  Don't display headers, and separate properties
2143990b4856Slling  *		by a single tab.
2144990b4856Slling  *	-o	List of properties to display.  Defaults to
2145990b4856Slling  *		"name,size,used,available,capacity,health,altroot"
2146fa9e4066Sahrens  *
2147fa9e4066Sahrens  * List all pools in the system, whether or not they're healthy.  Output space
2148fa9e4066Sahrens  * statistics for each one, as well as health status summary.
2149fa9e4066Sahrens  */
2150fa9e4066Sahrens int
2151fa9e4066Sahrens zpool_do_list(int argc, char **argv)
2152fa9e4066Sahrens {
2153fa9e4066Sahrens 	int c;
2154fa9e4066Sahrens 	int ret;
2155fa9e4066Sahrens 	list_cbdata_t cb = { 0 };
2156990b4856Slling 	static char default_props[] =
2157990b4856Slling 	    "name,size,used,available,capacity,health,altroot";
2158990b4856Slling 	char *props = default_props;
2159fa9e4066Sahrens 
2160fa9e4066Sahrens 	/* check options */
2161fa9e4066Sahrens 	while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2162fa9e4066Sahrens 		switch (c) {
2163fa9e4066Sahrens 		case 'H':
216499653d4eSeschrock 			cb.cb_scripted = B_TRUE;
2165fa9e4066Sahrens 			break;
2166fa9e4066Sahrens 		case 'o':
2167990b4856Slling 			props = optarg;
2168fa9e4066Sahrens 			break;
2169fa9e4066Sahrens 		case ':':
2170fa9e4066Sahrens 			(void) fprintf(stderr, gettext("missing argument for "
2171fa9e4066Sahrens 			    "'%c' option\n"), optopt);
217299653d4eSeschrock 			usage(B_FALSE);
2173fa9e4066Sahrens 			break;
2174fa9e4066Sahrens 		case '?':
2175fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2176fa9e4066Sahrens 			    optopt);
217799653d4eSeschrock 			usage(B_FALSE);
2178fa9e4066Sahrens 		}
2179fa9e4066Sahrens 	}
2180fa9e4066Sahrens 
2181fa9e4066Sahrens 	argc -= optind;
2182fa9e4066Sahrens 	argv += optind;
2183fa9e4066Sahrens 
2184990b4856Slling 	if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
218599653d4eSeschrock 		usage(B_FALSE);
2186fa9e4066Sahrens 
218799653d4eSeschrock 	cb.cb_first = B_TRUE;
2188fa9e4066Sahrens 
2189990b4856Slling 	ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2190990b4856Slling 	    list_callback, &cb);
2191990b4856Slling 
2192990b4856Slling 	zprop_free_list(cb.cb_proplist);
2193fa9e4066Sahrens 
2194fce7d82bSmmusante 	if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2195fa9e4066Sahrens 		(void) printf(gettext("no pools available\n"));
2196fa9e4066Sahrens 		return (0);
2197fa9e4066Sahrens 	}
2198fa9e4066Sahrens 
2199fa9e4066Sahrens 	return (ret);
2200fa9e4066Sahrens }
2201fa9e4066Sahrens 
2202fa9e4066Sahrens static nvlist_t *
2203fa9e4066Sahrens zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2204fa9e4066Sahrens {
2205fa9e4066Sahrens 	nvlist_t **child;
2206fa9e4066Sahrens 	uint_t c, children;
2207fa9e4066Sahrens 	nvlist_t *match;
2208fa9e4066Sahrens 	char *path;
2209fa9e4066Sahrens 
2210fa9e4066Sahrens 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2211fa9e4066Sahrens 	    &child, &children) != 0) {
2212fa9e4066Sahrens 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2213fa9e4066Sahrens 		if (strncmp(name, "/dev/dsk/", 9) == 0)
2214fa9e4066Sahrens 			name += 9;
2215fa9e4066Sahrens 		if (strncmp(path, "/dev/dsk/", 9) == 0)
2216fa9e4066Sahrens 			path += 9;
2217fa9e4066Sahrens 		if (strcmp(name, path) == 0)
2218fa9e4066Sahrens 			return (nv);
2219fa9e4066Sahrens 		return (NULL);
2220fa9e4066Sahrens 	}
2221fa9e4066Sahrens 
2222fa9e4066Sahrens 	for (c = 0; c < children; c++)
2223fa9e4066Sahrens 		if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2224fa9e4066Sahrens 			return (match);
2225fa9e4066Sahrens 
2226fa9e4066Sahrens 	return (NULL);
2227fa9e4066Sahrens }
2228fa9e4066Sahrens 
2229fa9e4066Sahrens static int
2230fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2231fa9e4066Sahrens {
223299653d4eSeschrock 	boolean_t force = B_FALSE;
2233fa9e4066Sahrens 	int c;
2234fa9e4066Sahrens 	nvlist_t *nvroot;
2235fa9e4066Sahrens 	char *poolname, *old_disk, *new_disk;
2236fa9e4066Sahrens 	zpool_handle_t *zhp;
223799653d4eSeschrock 	int ret;
2238fa9e4066Sahrens 
2239fa9e4066Sahrens 	/* check options */
2240fa9e4066Sahrens 	while ((c = getopt(argc, argv, "f")) != -1) {
2241fa9e4066Sahrens 		switch (c) {
2242fa9e4066Sahrens 		case 'f':
224399653d4eSeschrock 			force = B_TRUE;
2244fa9e4066Sahrens 			break;
2245fa9e4066Sahrens 		case '?':
2246fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2247fa9e4066Sahrens 			    optopt);
224899653d4eSeschrock 			usage(B_FALSE);
2249fa9e4066Sahrens 		}
2250fa9e4066Sahrens 	}
2251fa9e4066Sahrens 
2252fa9e4066Sahrens 	argc -= optind;
2253fa9e4066Sahrens 	argv += optind;
2254fa9e4066Sahrens 
2255fa9e4066Sahrens 	/* get pool name and check number of arguments */
2256fa9e4066Sahrens 	if (argc < 1) {
2257fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
225899653d4eSeschrock 		usage(B_FALSE);
2259fa9e4066Sahrens 	}
2260fa9e4066Sahrens 
2261fa9e4066Sahrens 	poolname = argv[0];
2262fa9e4066Sahrens 
2263fa9e4066Sahrens 	if (argc < 2) {
2264fa9e4066Sahrens 		(void) fprintf(stderr,
2265fa9e4066Sahrens 		    gettext("missing <device> specification\n"));
226699653d4eSeschrock 		usage(B_FALSE);
2267fa9e4066Sahrens 	}
2268fa9e4066Sahrens 
2269fa9e4066Sahrens 	old_disk = argv[1];
2270fa9e4066Sahrens 
2271fa9e4066Sahrens 	if (argc < 3) {
2272fa9e4066Sahrens 		if (!replacing) {
2273fa9e4066Sahrens 			(void) fprintf(stderr,
2274fa9e4066Sahrens 			    gettext("missing <new_device> specification\n"));
227599653d4eSeschrock 			usage(B_FALSE);
2276fa9e4066Sahrens 		}
2277fa9e4066Sahrens 		new_disk = old_disk;
2278fa9e4066Sahrens 		argc -= 1;
2279fa9e4066Sahrens 		argv += 1;
2280fa9e4066Sahrens 	} else {
2281fa9e4066Sahrens 		new_disk = argv[2];
2282fa9e4066Sahrens 		argc -= 2;
2283fa9e4066Sahrens 		argv += 2;
2284fa9e4066Sahrens 	}
2285fa9e4066Sahrens 
2286fa9e4066Sahrens 	if (argc > 1) {
2287fa9e4066Sahrens 		(void) fprintf(stderr, gettext("too many arguments\n"));
228899653d4eSeschrock 		usage(B_FALSE);
2289fa9e4066Sahrens 	}
2290fa9e4066Sahrens 
229199653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2292fa9e4066Sahrens 		return (1);
2293fa9e4066Sahrens 
22948488aeb5Staylor 	if (zpool_get_config(zhp, NULL) == NULL) {
2295fa9e4066Sahrens 		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2296fa9e4066Sahrens 		    poolname);
2297fa9e4066Sahrens 		zpool_close(zhp);
2298fa9e4066Sahrens 		return (1);
2299fa9e4066Sahrens 	}
2300fa9e4066Sahrens 
23018488aeb5Staylor 	nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, argc, argv);
2302fa9e4066Sahrens 	if (nvroot == NULL) {
2303fa9e4066Sahrens 		zpool_close(zhp);
2304fa9e4066Sahrens 		return (1);
2305fa9e4066Sahrens 	}
2306fa9e4066Sahrens 
230799653d4eSeschrock 	ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
230899653d4eSeschrock 
230999653d4eSeschrock 	nvlist_free(nvroot);
231099653d4eSeschrock 	zpool_close(zhp);
231199653d4eSeschrock 
231299653d4eSeschrock 	return (ret);
2313fa9e4066Sahrens }
2314fa9e4066Sahrens 
2315fa9e4066Sahrens /*
2316fa9e4066Sahrens  * zpool replace [-f] <pool> <device> <new_device>
2317fa9e4066Sahrens  *
2318fa9e4066Sahrens  *	-f	Force attach, even if <new_device> appears to be in use.
2319fa9e4066Sahrens  *
2320fa9e4066Sahrens  * Replace <device> with <new_device>.
2321fa9e4066Sahrens  */
2322fa9e4066Sahrens /* ARGSUSED */
2323fa9e4066Sahrens int
2324fa9e4066Sahrens zpool_do_replace(int argc, char **argv)
2325fa9e4066Sahrens {
2326fa9e4066Sahrens 	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2327fa9e4066Sahrens }
2328fa9e4066Sahrens 
2329fa9e4066Sahrens /*
2330fa9e4066Sahrens  * zpool attach [-f] <pool> <device> <new_device>
2331fa9e4066Sahrens  *
2332fa9e4066Sahrens  *	-f	Force attach, even if <new_device> appears to be in use.
2333fa9e4066Sahrens  *
2334fa9e4066Sahrens  * Attach <new_device> to the mirror containing <device>.  If <device> is not
2335fa9e4066Sahrens  * part of a mirror, then <device> will be transformed into a mirror of
2336fa9e4066Sahrens  * <device> and <new_device>.  In either case, <new_device> will begin life
2337fa9e4066Sahrens  * with a DTL of [0, now], and will immediately begin to resilver itself.
2338fa9e4066Sahrens  */
2339fa9e4066Sahrens int
2340fa9e4066Sahrens zpool_do_attach(int argc, char **argv)
2341fa9e4066Sahrens {
2342fa9e4066Sahrens 	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2343fa9e4066Sahrens }
2344fa9e4066Sahrens 
2345fa9e4066Sahrens /*
2346fa9e4066Sahrens  * zpool detach [-f] <pool> <device>
2347fa9e4066Sahrens  *
2348fa9e4066Sahrens  *	-f	Force detach of <device>, even if DTLs argue against it
2349fa9e4066Sahrens  *		(not supported yet)
2350fa9e4066Sahrens  *
2351fa9e4066Sahrens  * Detach a device from a mirror.  The operation will be refused if <device>
2352fa9e4066Sahrens  * is the last device in the mirror, or if the DTLs indicate that this device
2353fa9e4066Sahrens  * has the only valid copy of some data.
2354fa9e4066Sahrens  */
2355fa9e4066Sahrens /* ARGSUSED */
2356fa9e4066Sahrens int
2357fa9e4066Sahrens zpool_do_detach(int argc, char **argv)
2358fa9e4066Sahrens {
2359fa9e4066Sahrens 	int c;
2360fa9e4066Sahrens 	char *poolname, *path;
2361fa9e4066Sahrens 	zpool_handle_t *zhp;
236299653d4eSeschrock 	int ret;
2363fa9e4066Sahrens 
2364fa9e4066Sahrens 	/* check options */
2365fa9e4066Sahrens 	while ((c = getopt(argc, argv, "f")) != -1) {
2366fa9e4066Sahrens 		switch (c) {
2367fa9e4066Sahrens 		case 'f':
2368fa9e4066Sahrens 		case '?':
2369fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2370fa9e4066Sahrens 			    optopt);
237199653d4eSeschrock 			usage(B_FALSE);
2372fa9e4066Sahrens 		}
2373fa9e4066Sahrens 	}
2374fa9e4066Sahrens 
2375fa9e4066Sahrens 	argc -= optind;
2376fa9e4066Sahrens 	argv += optind;
2377fa9e4066Sahrens 
2378fa9e4066Sahrens 	/* get pool name and check number of arguments */
2379fa9e4066Sahrens 	if (argc < 1) {
2380fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
238199653d4eSeschrock 		usage(B_FALSE);
2382fa9e4066Sahrens 	}
2383fa9e4066Sahrens 
2384fa9e4066Sahrens 	if (argc < 2) {
2385fa9e4066Sahrens 		(void) fprintf(stderr,
2386fa9e4066Sahrens 		    gettext("missing <device> specification\n"));
238799653d4eSeschrock 		usage(B_FALSE);
2388fa9e4066Sahrens 	}
2389fa9e4066Sahrens 
2390fa9e4066Sahrens 	poolname = argv[0];
2391fa9e4066Sahrens 	path = argv[1];
2392fa9e4066Sahrens 
239399653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2394fa9e4066Sahrens 		return (1);
2395fa9e4066Sahrens 
239699653d4eSeschrock 	ret = zpool_vdev_detach(zhp, path);
239799653d4eSeschrock 
239899653d4eSeschrock 	zpool_close(zhp);
239999653d4eSeschrock 
240099653d4eSeschrock 	return (ret);
2401fa9e4066Sahrens }
2402fa9e4066Sahrens 
2403fa9e4066Sahrens /*
2404441d80aaSlling  * zpool online <pool> <device> ...
2405fa9e4066Sahrens  */
2406fa9e4066Sahrens int
2407fa9e4066Sahrens zpool_do_online(int argc, char **argv)
2408fa9e4066Sahrens {
2409fa9e4066Sahrens 	int c, i;
2410fa9e4066Sahrens 	char *poolname;
2411fa9e4066Sahrens 	zpool_handle_t *zhp;
2412fa9e4066Sahrens 	int ret = 0;
24133d7072f8Seschrock 	vdev_state_t newstate;
2414fa9e4066Sahrens 
2415fa9e4066Sahrens 	/* check options */
2416fa9e4066Sahrens 	while ((c = getopt(argc, argv, "t")) != -1) {
2417fa9e4066Sahrens 		switch (c) {
2418fa9e4066Sahrens 		case 't':
2419fa9e4066Sahrens 		case '?':
2420fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2421fa9e4066Sahrens 			    optopt);
242299653d4eSeschrock 			usage(B_FALSE);
2423fa9e4066Sahrens 		}
2424fa9e4066Sahrens 	}
2425fa9e4066Sahrens 
2426fa9e4066Sahrens 	argc -= optind;
2427fa9e4066Sahrens 	argv += optind;
2428fa9e4066Sahrens 
2429fa9e4066Sahrens 	/* get pool name and check number of arguments */
2430fa9e4066Sahrens 	if (argc < 1) {
2431fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name\n"));
243299653d4eSeschrock 		usage(B_FALSE);
2433fa9e4066Sahrens 	}
2434fa9e4066Sahrens 	if (argc < 2) {
2435fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing device name\n"));
243699653d4eSeschrock 		usage(B_FALSE);
2437fa9e4066Sahrens 	}
2438fa9e4066Sahrens 
2439fa9e4066Sahrens 	poolname = argv[0];
2440fa9e4066Sahrens 
244199653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2442fa9e4066Sahrens 		return (1);
2443fa9e4066Sahrens 
24443d7072f8Seschrock 	for (i = 1; i < argc; i++) {
24453d7072f8Seschrock 		if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
24463d7072f8Seschrock 			if (newstate != VDEV_STATE_HEALTHY) {
24473d7072f8Seschrock 				(void) printf(gettext("warning: device '%s' "
24483d7072f8Seschrock 				    "onlined, but remains in faulted state\n"),
2449fa9e4066Sahrens 				    argv[i]);
24503d7072f8Seschrock 				if (newstate == VDEV_STATE_FAULTED)
24513d7072f8Seschrock 					(void) printf(gettext("use 'zpool "
24523d7072f8Seschrock 					    "clear' to restore a faulted "
24533d7072f8Seschrock 					    "device\n"));
2454fa9e4066Sahrens 				else
24553d7072f8Seschrock 					(void) printf(gettext("use 'zpool "
24563d7072f8Seschrock 					    "replace' to replace devices "
24573d7072f8Seschrock 					    "that are no longer present\n"));
24583d7072f8Seschrock 			}
24593d7072f8Seschrock 		} else {
2460fa9e4066Sahrens 			ret = 1;
24613d7072f8Seschrock 		}
24623d7072f8Seschrock 	}
2463fa9e4066Sahrens 
246499653d4eSeschrock 	zpool_close(zhp);
246599653d4eSeschrock 
2466fa9e4066Sahrens 	return (ret);
2467fa9e4066Sahrens }
2468fa9e4066Sahrens 
2469fa9e4066Sahrens /*
2470441d80aaSlling  * zpool offline [-ft] <pool> <device> ...
2471fa9e4066Sahrens  *
2472fa9e4066Sahrens  *	-f	Force the device into the offline state, even if doing
2473fa9e4066Sahrens  *		so would appear to compromise pool availability.
2474fa9e4066Sahrens  *		(not supported yet)
2475fa9e4066Sahrens  *
2476fa9e4066Sahrens  *	-t	Only take the device off-line temporarily.  The offline
2477fa9e4066Sahrens  *		state will not be persistent across reboots.
2478fa9e4066Sahrens  */
2479fa9e4066Sahrens /* ARGSUSED */
2480fa9e4066Sahrens int
2481fa9e4066Sahrens zpool_do_offline(int argc, char **argv)
2482fa9e4066Sahrens {
2483fa9e4066Sahrens 	int c, i;
2484fa9e4066Sahrens 	char *poolname;
2485fa9e4066Sahrens 	zpool_handle_t *zhp;
248699653d4eSeschrock 	int ret = 0;
248799653d4eSeschrock 	boolean_t istmp = B_FALSE;
2488fa9e4066Sahrens 
2489fa9e4066Sahrens 	/* check options */
2490fa9e4066Sahrens 	while ((c = getopt(argc, argv, "ft")) != -1) {
2491fa9e4066Sahrens 		switch (c) {
2492fa9e4066Sahrens 		case 't':
249399653d4eSeschrock 			istmp = B_TRUE;
2494441d80aaSlling 			break;
2495441d80aaSlling 		case 'f':
2496fa9e4066Sahrens 		case '?':
2497fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2498fa9e4066Sahrens 			    optopt);
249999653d4eSeschrock 			usage(B_FALSE);
2500fa9e4066Sahrens 		}
2501fa9e4066Sahrens 	}
2502fa9e4066Sahrens 
2503fa9e4066Sahrens 	argc -= optind;
2504fa9e4066Sahrens 	argv += optind;
2505fa9e4066Sahrens 
2506fa9e4066Sahrens 	/* get pool name and check number of arguments */
2507fa9e4066Sahrens 	if (argc < 1) {
2508fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name\n"));
250999653d4eSeschrock 		usage(B_FALSE);
2510fa9e4066Sahrens 	}
2511fa9e4066Sahrens 	if (argc < 2) {
2512fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing device name\n"));
251399653d4eSeschrock 		usage(B_FALSE);
2514fa9e4066Sahrens 	}
2515fa9e4066Sahrens 
2516fa9e4066Sahrens 	poolname = argv[0];
2517fa9e4066Sahrens 
251899653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2519fa9e4066Sahrens 		return (1);
2520fa9e4066Sahrens 
25213d7072f8Seschrock 	for (i = 1; i < argc; i++) {
25223d7072f8Seschrock 		if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2523fa9e4066Sahrens 			ret = 1;
25243d7072f8Seschrock 	}
2525fa9e4066Sahrens 
252699653d4eSeschrock 	zpool_close(zhp);
252799653d4eSeschrock 
2528fa9e4066Sahrens 	return (ret);
2529fa9e4066Sahrens }
2530fa9e4066Sahrens 
2531ea8dc4b6Seschrock /*
2532ea8dc4b6Seschrock  * zpool clear <pool> [device]
2533ea8dc4b6Seschrock  *
2534ea8dc4b6Seschrock  * Clear all errors associated with a pool or a particular device.
2535ea8dc4b6Seschrock  */
2536ea8dc4b6Seschrock int
2537ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv)
2538ea8dc4b6Seschrock {
2539ea8dc4b6Seschrock 	int ret = 0;
2540ea8dc4b6Seschrock 	zpool_handle_t *zhp;
2541ea8dc4b6Seschrock 	char *pool, *device;
2542ea8dc4b6Seschrock 
2543ea8dc4b6Seschrock 	if (argc < 2) {
2544ea8dc4b6Seschrock 		(void) fprintf(stderr, gettext("missing pool name\n"));
254599653d4eSeschrock 		usage(B_FALSE);
2546ea8dc4b6Seschrock 	}
2547ea8dc4b6Seschrock 
2548ea8dc4b6Seschrock 	if (argc > 3) {
2549ea8dc4b6Seschrock 		(void) fprintf(stderr, gettext("too many arguments\n"));
255099653d4eSeschrock 		usage(B_FALSE);
2551ea8dc4b6Seschrock 	}
2552ea8dc4b6Seschrock 
2553ea8dc4b6Seschrock 	pool = argv[1];
2554ea8dc4b6Seschrock 	device = argc == 3 ? argv[2] : NULL;
2555ea8dc4b6Seschrock 
255699653d4eSeschrock 	if ((zhp = zpool_open(g_zfs, pool)) == NULL)
2557ea8dc4b6Seschrock 		return (1);
2558ea8dc4b6Seschrock 
2559ea8dc4b6Seschrock 	if (zpool_clear(zhp, device) != 0)
2560ea8dc4b6Seschrock 		ret = 1;
2561ea8dc4b6Seschrock 
2562ea8dc4b6Seschrock 	zpool_close(zhp);
2563ea8dc4b6Seschrock 
2564ea8dc4b6Seschrock 	return (ret);
2565ea8dc4b6Seschrock }
2566ea8dc4b6Seschrock 
2567fa9e4066Sahrens typedef struct scrub_cbdata {
2568fa9e4066Sahrens 	int	cb_type;
256906eeb2adSek110237 	int	cb_argc;
257006eeb2adSek110237 	char	**cb_argv;
2571fa9e4066Sahrens } scrub_cbdata_t;
2572fa9e4066Sahrens 
2573fa9e4066Sahrens int
2574fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data)
2575fa9e4066Sahrens {
2576fa9e4066Sahrens 	scrub_cbdata_t *cb = data;
257706eeb2adSek110237 	int err;
2578fa9e4066Sahrens 
2579ea8dc4b6Seschrock 	/*
2580ea8dc4b6Seschrock 	 * Ignore faulted pools.
2581ea8dc4b6Seschrock 	 */
2582ea8dc4b6Seschrock 	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2583ea8dc4b6Seschrock 		(void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2584ea8dc4b6Seschrock 		    "currently unavailable\n"), zpool_get_name(zhp));
2585ea8dc4b6Seschrock 		return (1);
2586ea8dc4b6Seschrock 	}
2587ea8dc4b6Seschrock 
258806eeb2adSek110237 	err = zpool_scrub(zhp, cb->cb_type);
258906eeb2adSek110237 
259006eeb2adSek110237 	return (err != 0);
2591fa9e4066Sahrens }
2592fa9e4066Sahrens 
2593fa9e4066Sahrens /*
2594fa9e4066Sahrens  * zpool scrub [-s] <pool> ...
2595fa9e4066Sahrens  *
2596fa9e4066Sahrens  *	-s	Stop.  Stops any in-progress scrub.
2597fa9e4066Sahrens  */
2598fa9e4066Sahrens int
2599fa9e4066Sahrens zpool_do_scrub(int argc, char **argv)
2600fa9e4066Sahrens {
2601fa9e4066Sahrens 	int c;
2602fa9e4066Sahrens 	scrub_cbdata_t cb;
2603fa9e4066Sahrens 
2604fa9e4066Sahrens 	cb.cb_type = POOL_SCRUB_EVERYTHING;
2605fa9e4066Sahrens 
2606fa9e4066Sahrens 	/* check options */
2607fa9e4066Sahrens 	while ((c = getopt(argc, argv, "s")) != -1) {
2608fa9e4066Sahrens 		switch (c) {
2609fa9e4066Sahrens 		case 's':
2610fa9e4066Sahrens 			cb.cb_type = POOL_SCRUB_NONE;
2611fa9e4066Sahrens 			break;
2612fa9e4066Sahrens 		case '?':
2613fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2614fa9e4066Sahrens 			    optopt);
261599653d4eSeschrock 			usage(B_FALSE);
2616fa9e4066Sahrens 		}
2617fa9e4066Sahrens 	}
2618fa9e4066Sahrens 
261906eeb2adSek110237 	cb.cb_argc = argc;
262006eeb2adSek110237 	cb.cb_argv = argv;
2621fa9e4066Sahrens 	argc -= optind;
2622fa9e4066Sahrens 	argv += optind;
2623fa9e4066Sahrens 
2624fa9e4066Sahrens 	if (argc < 1) {
2625fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing pool name argument\n"));
262699653d4eSeschrock 		usage(B_FALSE);
2627fa9e4066Sahrens 	}
2628fa9e4066Sahrens 
2629b1b8ab34Slling 	return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2630fa9e4066Sahrens }
2631fa9e4066Sahrens 
2632fa9e4066Sahrens typedef struct status_cbdata {
2633fa9e4066Sahrens 	int		cb_count;
2634e9dbad6fSeschrock 	boolean_t	cb_allpools;
263599653d4eSeschrock 	boolean_t	cb_verbose;
263699653d4eSeschrock 	boolean_t	cb_explain;
263799653d4eSeschrock 	boolean_t	cb_first;
2638fa9e4066Sahrens } status_cbdata_t;
2639fa9e4066Sahrens 
2640fa9e4066Sahrens /*
2641fa9e4066Sahrens  * Print out detailed scrub status.
2642fa9e4066Sahrens  */
2643fa9e4066Sahrens void
2644fa9e4066Sahrens print_scrub_status(nvlist_t *nvroot)
2645fa9e4066Sahrens {
2646fa9e4066Sahrens 	vdev_stat_t *vs;
2647fa9e4066Sahrens 	uint_t vsc;
2648fa9e4066Sahrens 	time_t start, end, now;
2649fa9e4066Sahrens 	double fraction_done;
265018ce54dfSek110237 	uint64_t examined, total, minutes_left, minutes_taken;
2651fa9e4066Sahrens 	char *scrub_type;
2652fa9e4066Sahrens 
2653fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2654fa9e4066Sahrens 	    (uint64_t **)&vs, &vsc) == 0);
2655fa9e4066Sahrens 
2656fa9e4066Sahrens 	/*
2657fa9e4066Sahrens 	 * If there's never been a scrub, there's not much to say.
2658fa9e4066Sahrens 	 */
2659fa9e4066Sahrens 	if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2660fa9e4066Sahrens 		(void) printf(gettext("none requested\n"));
2661fa9e4066Sahrens 		return;
2662fa9e4066Sahrens 	}
2663fa9e4066Sahrens 
2664fa9e4066Sahrens 	scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2665fa9e4066Sahrens 	    "resilver" : "scrub";
2666fa9e4066Sahrens 
2667fa9e4066Sahrens 	start = vs->vs_scrub_start;
2668fa9e4066Sahrens 	end = vs->vs_scrub_end;
2669fa9e4066Sahrens 	now = time(NULL);
2670fa9e4066Sahrens 	examined = vs->vs_scrub_examined;
2671fa9e4066Sahrens 	total = vs->vs_alloc;
2672fa9e4066Sahrens 
2673fa9e4066Sahrens 	if (end != 0) {
267418ce54dfSek110237 		minutes_taken = (uint64_t)((end - start) / 60);
267518ce54dfSek110237 
267618ce54dfSek110237 		(void) printf(gettext("%s %s after %lluh%um with %llu errors "
267718ce54dfSek110237 		    "on %s"),
2678fa9e4066Sahrens 		    scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
267918ce54dfSek110237 		    (u_longlong_t)(minutes_taken / 60),
268018ce54dfSek110237 		    (uint_t)(minutes_taken % 60),
2681fa9e4066Sahrens 		    (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2682fa9e4066Sahrens 		return;
2683fa9e4066Sahrens 	}
2684fa9e4066Sahrens 
2685fa9e4066Sahrens 	if (examined == 0)
2686fa9e4066Sahrens 		examined = 1;
2687fa9e4066Sahrens 	if (examined > total)
2688fa9e4066Sahrens 		total = examined;
2689fa9e4066Sahrens 
2690fa9e4066Sahrens 	fraction_done = (double)examined / total;
2691fa9e4066Sahrens 	minutes_left = (uint64_t)((now - start) *
2692fa9e4066Sahrens 	    (1 - fraction_done) / fraction_done / 60);
269318ce54dfSek110237 	minutes_taken = (uint64_t)((now - start) / 60);
2694fa9e4066Sahrens 
269518ce54dfSek110237 	(void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
269618ce54dfSek110237 	    "%lluh%um to go\n"),
269718ce54dfSek110237 	    scrub_type, (u_longlong_t)(minutes_taken / 60),
269818ce54dfSek110237 	    (uint_t)(minutes_taken % 60), 100 * fraction_done,
2699fa9e4066Sahrens 	    (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2700fa9e4066Sahrens }
2701fa9e4066Sahrens 
270299653d4eSeschrock typedef struct spare_cbdata {
270399653d4eSeschrock 	uint64_t	cb_guid;
270499653d4eSeschrock 	zpool_handle_t	*cb_zhp;
270599653d4eSeschrock } spare_cbdata_t;
270699653d4eSeschrock 
270799653d4eSeschrock static boolean_t
270899653d4eSeschrock find_vdev(nvlist_t *nv, uint64_t search)
270999653d4eSeschrock {
271099653d4eSeschrock 	uint64_t guid;
271199653d4eSeschrock 	nvlist_t **child;
271299653d4eSeschrock 	uint_t c, children;
271399653d4eSeschrock 
271499653d4eSeschrock 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
271599653d4eSeschrock 	    search == guid)
271699653d4eSeschrock 		return (B_TRUE);
271799653d4eSeschrock 
271899653d4eSeschrock 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
271999653d4eSeschrock 	    &child, &children) == 0) {
272099653d4eSeschrock 		for (c = 0; c < children; c++)
272199653d4eSeschrock 			if (find_vdev(child[c], search))
272299653d4eSeschrock 				return (B_TRUE);
272399653d4eSeschrock 	}
272499653d4eSeschrock 
272599653d4eSeschrock 	return (B_FALSE);
272699653d4eSeschrock }
272799653d4eSeschrock 
272899653d4eSeschrock static int
272999653d4eSeschrock find_spare(zpool_handle_t *zhp, void *data)
273099653d4eSeschrock {
273199653d4eSeschrock 	spare_cbdata_t *cbp = data;
273299653d4eSeschrock 	nvlist_t *config, *nvroot;
273399653d4eSeschrock 
273499653d4eSeschrock 	config = zpool_get_config(zhp, NULL);
273599653d4eSeschrock 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
273699653d4eSeschrock 	    &nvroot) == 0);
273799653d4eSeschrock 
273899653d4eSeschrock 	if (find_vdev(nvroot, cbp->cb_guid)) {
273999653d4eSeschrock 		cbp->cb_zhp = zhp;
274099653d4eSeschrock 		return (1);
274199653d4eSeschrock 	}
274299653d4eSeschrock 
274399653d4eSeschrock 	zpool_close(zhp);
274499653d4eSeschrock 	return (0);
274599653d4eSeschrock }
274699653d4eSeschrock 
2747fa9e4066Sahrens /*
2748fa9e4066Sahrens  * Print out configuration state as requested by status_callback.
2749fa9e4066Sahrens  */
2750fa9e4066Sahrens void
2751c67d9675Seschrock print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
27528654d025Sperrin     int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2753fa9e4066Sahrens {
2754fa9e4066Sahrens 	nvlist_t **child;
2755fa9e4066Sahrens 	uint_t c, children;
2756fa9e4066Sahrens 	vdev_stat_t *vs;
2757ea8dc4b6Seschrock 	char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2758afefbcddSeschrock 	char *vname;
2759ea8dc4b6Seschrock 	uint64_t notpresent;
276099653d4eSeschrock 	spare_cbdata_t cb;
2761990b4856Slling 	char *state;
2762fa9e4066Sahrens 
2763fa9e4066Sahrens 	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2764fa9e4066Sahrens 	    (uint64_t **)&vs, &c) == 0);
2765fa9e4066Sahrens 
2766fa9e4066Sahrens 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2767fa9e4066Sahrens 	    &child, &children) != 0)
2768fa9e4066Sahrens 		children = 0;
2769fa9e4066Sahrens 
2770990b4856Slling 	state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
277199653d4eSeschrock 	if (isspare) {
277299653d4eSeschrock 		/*
277399653d4eSeschrock 		 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
277499653d4eSeschrock 		 * online drives.
277599653d4eSeschrock 		 */
277699653d4eSeschrock 		if (vs->vs_aux == VDEV_AUX_SPARED)
277799653d4eSeschrock 			state = "INUSE";
277899653d4eSeschrock 		else if (vs->vs_state == VDEV_STATE_HEALTHY)
277999653d4eSeschrock 			state = "AVAIL";
278099653d4eSeschrock 	}
2781fa9e4066Sahrens 
278299653d4eSeschrock 	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
278399653d4eSeschrock 	    name, state);
278499653d4eSeschrock 
278599653d4eSeschrock 	if (!isspare) {
2786fa9e4066Sahrens 		zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2787fa9e4066Sahrens 		zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2788fa9e4066Sahrens 		zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2789fa9e4066Sahrens 		(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
279099653d4eSeschrock 	}
2791fa9e4066Sahrens 
2792ea8dc4b6Seschrock 	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2793ea8dc4b6Seschrock 	    &notpresent) == 0) {
2794ea8dc4b6Seschrock 		char *path;
2795ea8dc4b6Seschrock 		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
27960917b783Seschrock 		(void) printf("  was %s", path);
2797ea8dc4b6Seschrock 	} else if (vs->vs_aux != 0) {
2798fa9e4066Sahrens 		(void) printf("  ");
2799fa9e4066Sahrens 
2800fa9e4066Sahrens 		switch (vs->vs_aux) {
2801fa9e4066Sahrens 		case VDEV_AUX_OPEN_FAILED:
2802fa9e4066Sahrens 			(void) printf(gettext("cannot open"));
2803fa9e4066Sahrens 			break;
2804fa9e4066Sahrens 
2805fa9e4066Sahrens 		case VDEV_AUX_BAD_GUID_SUM:
2806fa9e4066Sahrens 			(void) printf(gettext("missing device"));
2807fa9e4066Sahrens 			break;
2808fa9e4066Sahrens 
2809fa9e4066Sahrens 		case VDEV_AUX_NO_REPLICAS:
2810fa9e4066Sahrens 			(void) printf(gettext("insufficient replicas"));
2811fa9e4066Sahrens 			break;
2812fa9e4066Sahrens 
2813eaca9bbdSeschrock 		case VDEV_AUX_VERSION_NEWER:
2814eaca9bbdSeschrock 			(void) printf(gettext("newer version"));
2815eaca9bbdSeschrock 			break;
2816eaca9bbdSeschrock 
281799653d4eSeschrock 		case VDEV_AUX_SPARED:
281899653d4eSeschrock 			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
281999653d4eSeschrock 			    &cb.cb_guid) == 0);
282099653d4eSeschrock 			if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
282199653d4eSeschrock 				if (strcmp(zpool_get_name(cb.cb_zhp),
282299653d4eSeschrock 				    zpool_get_name(zhp)) == 0)
282399653d4eSeschrock 					(void) printf(gettext("currently in "
282499653d4eSeschrock 					    "use"));
282599653d4eSeschrock 				else
282699653d4eSeschrock 					(void) printf(gettext("in use by "
282799653d4eSeschrock 					    "pool '%s'"),
282899653d4eSeschrock 					    zpool_get_name(cb.cb_zhp));
282999653d4eSeschrock 				zpool_close(cb.cb_zhp);
283099653d4eSeschrock 			} else {
283199653d4eSeschrock 				(void) printf(gettext("currently in use"));
283299653d4eSeschrock 			}
283399653d4eSeschrock 			break;
283499653d4eSeschrock 
28353d7072f8Seschrock 		case VDEV_AUX_ERR_EXCEEDED:
28363d7072f8Seschrock 			(void) printf(gettext("too many errors"));
28373d7072f8Seschrock 			break;
28383d7072f8Seschrock 
283932b87932Sek110237 		case VDEV_AUX_IO_FAILURE:
284032b87932Sek110237 			(void) printf(gettext("experienced I/O failures"));
284132b87932Sek110237 			break;
284232b87932Sek110237 
2843fa9e4066Sahrens 		default:
2844fa9e4066Sahrens 			(void) printf(gettext("corrupted data"));
2845fa9e4066Sahrens 			break;
2846fa9e4066Sahrens 		}
2847fa9e4066Sahrens 	} else if (vs->vs_scrub_repaired != 0 && children == 0) {
2848fa9e4066Sahrens 		/*
2849fa9e4066Sahrens 		 * Report bytes resilvered/repaired on leaf devices.
2850fa9e4066Sahrens 		 */
2851fa9e4066Sahrens 		zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2852fa9e4066Sahrens 		(void) printf(gettext("  %s %s"), repaired,
2853fa9e4066Sahrens 		    (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2854fa9e4066Sahrens 		    "resilvered" : "repaired");
2855fa9e4066Sahrens 	}
2856fa9e4066Sahrens 
2857fa9e4066Sahrens 	(void) printf("\n");
2858fa9e4066Sahrens 
2859afefbcddSeschrock 	for (c = 0; c < children; c++) {
28608654d025Sperrin 		uint64_t is_log = B_FALSE;
28618654d025Sperrin 
28628654d025Sperrin 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
28638654d025Sperrin 		    &is_log);
28648654d025Sperrin 		if ((is_log && !print_logs) || (!is_log && print_logs))
28658654d025Sperrin 			continue;
286699653d4eSeschrock 		vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2867c67d9675Seschrock 		print_status_config(zhp, vname, child[c],
28688654d025Sperrin 		    namewidth, depth + 2, isspare, B_FALSE);
2869afefbcddSeschrock 		free(vname);
2870afefbcddSeschrock 	}
2871fa9e4066Sahrens }
2872fa9e4066Sahrens 
2873ea8dc4b6Seschrock static void
2874ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp)
2875ea8dc4b6Seschrock {
287675519f38Sek110237 	nvlist_t *nverrlist = NULL;
287755434c77Sek110237 	nvpair_t *elem;
287855434c77Sek110237 	char *pathname;
287955434c77Sek110237 	size_t len = MAXPATHLEN * 2;
2880ea8dc4b6Seschrock 
288155434c77Sek110237 	if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2882ea8dc4b6Seschrock 		(void) printf("errors: List of errors unavailable "
2883ea8dc4b6Seschrock 		    "(insufficient privileges)\n");
2884ea8dc4b6Seschrock 		return;
2885ea8dc4b6Seschrock 	}
2886ea8dc4b6Seschrock 
288755434c77Sek110237 	(void) printf("errors: Permanent errors have been "
288855434c77Sek110237 	    "detected in the following files:\n\n");
2889ea8dc4b6Seschrock 
289055434c77Sek110237 	pathname = safe_malloc(len);
289155434c77Sek110237 	elem = NULL;
289255434c77Sek110237 	while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
289355434c77Sek110237 		nvlist_t *nv;
289455434c77Sek110237 		uint64_t dsobj, obj;
2895ea8dc4b6Seschrock 
289655434c77Sek110237 		verify(nvpair_value_nvlist(elem, &nv) == 0);
289755434c77Sek110237 		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
289855434c77Sek110237 		    &dsobj) == 0);
289955434c77Sek110237 		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
290055434c77Sek110237 		    &obj) == 0);
290155434c77Sek110237 		zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
290255434c77Sek110237 		(void) printf("%7s %s\n", "", pathname);
2903ea8dc4b6Seschrock 	}
290455434c77Sek110237 	free(pathname);
290555434c77Sek110237 	nvlist_free(nverrlist);
2906ea8dc4b6Seschrock }
2907ea8dc4b6Seschrock 
290899653d4eSeschrock static void
290999653d4eSeschrock print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
291099653d4eSeschrock     int namewidth)
291199653d4eSeschrock {
291299653d4eSeschrock 	uint_t i;
291399653d4eSeschrock 	char *name;
291499653d4eSeschrock 
291599653d4eSeschrock 	if (nspares == 0)
291699653d4eSeschrock 		return;
291799653d4eSeschrock 
291899653d4eSeschrock 	(void) printf(gettext("\tspares\n"));
291999653d4eSeschrock 
292099653d4eSeschrock 	for (i = 0; i < nspares; i++) {
292199653d4eSeschrock 		name = zpool_vdev_name(g_zfs, zhp, spares[i]);
292299653d4eSeschrock 		print_status_config(zhp, name, spares[i],
29238654d025Sperrin 		    namewidth, 2, B_TRUE, B_FALSE);
292499653d4eSeschrock 		free(name);
292599653d4eSeschrock 	}
292699653d4eSeschrock }
292799653d4eSeschrock 
2928fa94a07fSbrendan static void
2929fa94a07fSbrendan print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2930fa94a07fSbrendan     int namewidth)
2931fa94a07fSbrendan {
2932fa94a07fSbrendan 	uint_t i;
2933fa94a07fSbrendan 	char *name;
2934fa94a07fSbrendan 
2935fa94a07fSbrendan 	if (nl2cache == 0)
2936fa94a07fSbrendan 		return;
2937fa94a07fSbrendan 
2938fa94a07fSbrendan 	(void) printf(gettext("\tcache\n"));
2939fa94a07fSbrendan 
2940fa94a07fSbrendan 	for (i = 0; i < nl2cache; i++) {
2941fa94a07fSbrendan 		name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2942fa94a07fSbrendan 		print_status_config(zhp, name, l2cache[i],
2943fa94a07fSbrendan 		    namewidth, 2, B_FALSE, B_FALSE);
2944fa94a07fSbrendan 		free(name);
2945fa94a07fSbrendan 	}
2946fa94a07fSbrendan }
2947fa94a07fSbrendan 
2948fa9e4066Sahrens /*
2949fa9e4066Sahrens  * Display a summary of pool status.  Displays a summary such as:
2950fa9e4066Sahrens  *
2951fa9e4066Sahrens  *        pool: tank
2952fa9e4066Sahrens  *	status: DEGRADED
2953fa9e4066Sahrens  *	reason: One or more devices ...
2954fa9e4066Sahrens  *         see: http://www.sun.com/msg/ZFS-xxxx-01
2955fa9e4066Sahrens  *	config:
2956fa9e4066Sahrens  *		mirror		DEGRADED
2957fa9e4066Sahrens  *                c1t0d0	OK
2958ea8dc4b6Seschrock  *                c2t0d0	UNAVAIL
2959fa9e4066Sahrens  *
2960fa9e4066Sahrens  * When given the '-v' option, we print out the complete config.  If the '-e'
2961fa9e4066Sahrens  * option is specified, then we print out error rate information as well.
2962fa9e4066Sahrens  */
2963fa9e4066Sahrens int
2964fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data)
2965fa9e4066Sahrens {
2966fa9e4066Sahrens 	status_cbdata_t *cbp = data;
2967fa9e4066Sahrens 	nvlist_t *config, *nvroot;
2968fa9e4066Sahrens 	char *msgid;
2969fa9e4066Sahrens 	int reason;
297046657f8dSmmusante 	const char *health;
297146657f8dSmmusante 	uint_t c;
297246657f8dSmmusante 	vdev_stat_t *vs;
2973fa9e4066Sahrens 
2974088e9d47Seschrock 	config = zpool_get_config(zhp, NULL);
2975fa9e4066Sahrens 	reason = zpool_get_status(zhp, &msgid);
2976fa9e4066Sahrens 
2977fa9e4066Sahrens 	cbp->cb_count++;
2978fa9e4066Sahrens 
2979fa9e4066Sahrens 	/*
2980fa9e4066Sahrens 	 * If we were given 'zpool status -x', only report those pools with
2981fa9e4066Sahrens 	 * problems.
2982fa9e4066Sahrens 	 */
2983e9dbad6fSeschrock 	if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
2984e9dbad6fSeschrock 		if (!cbp->cb_allpools) {
2985e9dbad6fSeschrock 			(void) printf(gettext("pool '%s' is healthy\n"),
2986e9dbad6fSeschrock 			    zpool_get_name(zhp));
2987e9dbad6fSeschrock 			if (cbp->cb_first)
2988e9dbad6fSeschrock 				cbp->cb_first = B_FALSE;
2989e9dbad6fSeschrock 		}
2990fa9e4066Sahrens 		return (0);
2991e9dbad6fSeschrock 	}
2992fa9e4066Sahrens 
2993fa9e4066Sahrens 	if (cbp->cb_first)
299499653d4eSeschrock 		cbp->cb_first = B_FALSE;
2995fa9e4066Sahrens 	else
2996fa9e4066Sahrens 		(void) printf("\n");
2997fa9e4066Sahrens 
299846657f8dSmmusante 	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
299946657f8dSmmusante 	    &nvroot) == 0);
300046657f8dSmmusante 	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
300146657f8dSmmusante 	    (uint64_t **)&vs, &c) == 0);
3002990b4856Slling 	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3003fa9e4066Sahrens 
3004fa9e4066Sahrens 	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3005fa9e4066Sahrens 	(void) printf(gettext(" state: %s\n"), health);
3006fa9e4066Sahrens 
3007fa9e4066Sahrens 	switch (reason) {
3008fa9e4066Sahrens 	case ZPOOL_STATUS_MISSING_DEV_R:
3009fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices could not "
3010fa9e4066Sahrens 		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
3011fa9e4066Sahrens 		    "continue functioning in a degraded state.\n"));
3012fa9e4066Sahrens 		(void) printf(gettext("action: Attach the missing device and "
3013fa9e4066Sahrens 		    "online it using 'zpool online'.\n"));
3014fa9e4066Sahrens 		break;
3015fa9e4066Sahrens 
3016fa9e4066Sahrens 	case ZPOOL_STATUS_MISSING_DEV_NR:
3017fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices could not "
3018fa9e4066Sahrens 		    "be opened.  There are insufficient\n\treplicas for the "
3019fa9e4066Sahrens 		    "pool to continue functioning.\n"));
3020fa9e4066Sahrens 		(void) printf(gettext("action: Attach the missing device and "
3021fa9e4066Sahrens 		    "online it using 'zpool online'.\n"));
3022fa9e4066Sahrens 		break;
3023fa9e4066Sahrens 
3024fa9e4066Sahrens 	case ZPOOL_STATUS_CORRUPT_LABEL_R:
3025fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices could not "
3026fa9e4066Sahrens 		    "be used because the label is missing or\n\tinvalid.  "
3027fa9e4066Sahrens 		    "Sufficient replicas exist for the pool to continue\n\t"
3028fa9e4066Sahrens 		    "functioning in a degraded state.\n"));
3029fa9e4066Sahrens 		(void) printf(gettext("action: Replace the device using "
3030fa9e4066Sahrens 		    "'zpool replace'.\n"));
3031fa9e4066Sahrens 		break;
3032fa9e4066Sahrens 
3033fa9e4066Sahrens 	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3034fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices could not "
3035b1b8ab34Slling 		    "be used because the label is missing \n\tor invalid.  "
3036fa9e4066Sahrens 		    "There are insufficient replicas for the pool to "
3037fa9e4066Sahrens 		    "continue\n\tfunctioning.\n"));
3038fa9e4066Sahrens 		(void) printf(gettext("action: Destroy and re-create the pool "
3039fa9e4066Sahrens 		    "from a backup source.\n"));
3040fa9e4066Sahrens 		break;
3041fa9e4066Sahrens 
3042fa9e4066Sahrens 	case ZPOOL_STATUS_FAILING_DEV:
3043fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices has "
3044fa9e4066Sahrens 		    "experienced an unrecoverable error.  An\n\tattempt was "
3045fa9e4066Sahrens 		    "made to correct the error.  Applications are "
3046fa9e4066Sahrens 		    "unaffected.\n"));
3047fa9e4066Sahrens 		(void) printf(gettext("action: Determine if the device needs "
3048fa9e4066Sahrens 		    "to be replaced, and clear the errors\n\tusing "
3049ea8dc4b6Seschrock 		    "'zpool clear' or replace the device with 'zpool "
3050fa9e4066Sahrens 		    "replace'.\n"));
3051fa9e4066Sahrens 		break;
3052fa9e4066Sahrens 
3053fa9e4066Sahrens 	case ZPOOL_STATUS_OFFLINE_DEV:
3054fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices has "
3055d7d4af51Smmusante 		    "been taken offline by the administrator.\n\tSufficient "
3056fa9e4066Sahrens 		    "replicas exist for the pool to continue functioning in "
3057fa9e4066Sahrens 		    "a\n\tdegraded state.\n"));
3058fa9e4066Sahrens 		(void) printf(gettext("action: Online the device using "
3059fa9e4066Sahrens 		    "'zpool online' or replace the device with\n\t'zpool "
3060fa9e4066Sahrens 		    "replace'.\n"));
3061fa9e4066Sahrens 		break;
3062fa9e4066Sahrens 
3063fa9e4066Sahrens 	case ZPOOL_STATUS_RESILVERING:
3064fa9e4066Sahrens 		(void) printf(gettext("status: One or more devices is "
3065fa9e4066Sahrens 		    "currently being resilvered.  The pool will\n\tcontinue "
3066fa9e4066Sahrens 		    "to function, possibly in a degraded state.\n"));
3067fa9e4066Sahrens 		(void) printf(gettext("action: Wait for the resilver to "
3068fa9e4066Sahrens 		    "complete.\n"));
3069fa9e4066Sahrens 		break;
3070fa9e4066Sahrens 
3071ea8dc4b6Seschrock 	case ZPOOL_STATUS_CORRUPT_DATA:
3072ea8dc4b6Seschrock 		(void) printf(gettext("status: One or more devices has "
3073ea8dc4b6Seschrock 		    "experienced an error resulting in data\n\tcorruption.  "
3074ea8dc4b6Seschrock 		    "Applications may be affected.\n"));
3075ea8dc4b6Seschrock 		(void) printf(gettext("action: Restore the file in question "
3076ea8dc4b6Seschrock 		    "if possible.  Otherwise restore the\n\tentire pool from "
3077ea8dc4b6Seschrock 		    "backup.\n"));
3078ea8dc4b6Seschrock 		break;
3079ea8dc4b6Seschrock 
3080ea8dc4b6Seschrock 	case ZPOOL_STATUS_CORRUPT_POOL:
3081ea8dc4b6Seschrock 		(void) printf(gettext("status: The pool metadata is corrupted "
3082ea8dc4b6Seschrock 		    "and the pool cannot be opened.\n"));
3083ea8dc4b6Seschrock 		(void) printf(gettext("action: Destroy and re-create the pool "
3084ea8dc4b6Seschrock 		    "from a backup source.\n"));
3085ea8dc4b6Seschrock 		break;
3086ea8dc4b6Seschrock 
3087eaca9bbdSeschrock 	case ZPOOL_STATUS_VERSION_OLDER:
3088eaca9bbdSeschrock 		(void) printf(gettext("status: The pool is formatted using an "
3089eaca9bbdSeschrock 		    "older on-disk format.  The pool can\n\tstill be used, but "
3090eaca9bbdSeschrock 		    "some features are unavailable.\n"));
3091eaca9bbdSeschrock 		(void) printf(gettext("action: Upgrade the pool using 'zpool "
3092eaca9bbdSeschrock 		    "upgrade'.  Once this is done, the\n\tpool will no longer "
3093eaca9bbdSeschrock 		    "be accessible on older software versions.\n"));
3094eaca9bbdSeschrock 		break;
3095eaca9bbdSeschrock 
3096eaca9bbdSeschrock 	case ZPOOL_STATUS_VERSION_NEWER:
3097eaca9bbdSeschrock 		(void) printf(gettext("status: The pool has been upgraded to a "
3098eaca9bbdSeschrock 		    "newer, incompatible on-disk version.\n\tThe pool cannot "
3099eaca9bbdSeschrock 		    "be accessed on this system.\n"));
3100eaca9bbdSeschrock 		(void) printf(gettext("action: Access the pool from a system "
3101eaca9bbdSeschrock 		    "running more recent software, or\n\trestore the pool from "
3102eaca9bbdSeschrock 		    "backup.\n"));
3103eaca9bbdSeschrock 		break;
3104eaca9bbdSeschrock 
31053d7072f8Seschrock 	case ZPOOL_STATUS_FAULTED_DEV_R:
31063d7072f8Seschrock 		(void) printf(gettext("status: One or more devices are "
31073d7072f8Seschrock 		    "faulted in response to persistent errors.\n\tSufficient "
31083d7072f8Seschrock 		    "replicas exist for the pool to continue functioning "
31093d7072f8Seschrock 		    "in a\n\tdegraded state.\n"));
31103d7072f8Seschrock 		(void) printf(gettext("action: Replace the faulted device, "
31113d7072f8Seschrock 		    "or use 'zpool clear' to mark the device\n\trepaired.\n"));
31123d7072f8Seschrock 		break;
31133d7072f8Seschrock 
31143d7072f8Seschrock 	case ZPOOL_STATUS_FAULTED_DEV_NR:
31153d7072f8Seschrock 		(void) printf(gettext("status: One or more devices are "
31163d7072f8Seschrock 		    "faulted in response to persistent errors.  There are "
31173d7072f8Seschrock 		    "insufficient replicas for the pool to\n\tcontinue "
31183d7072f8Seschrock 		    "functioning.\n"));
31193d7072f8Seschrock 		(void) printf(gettext("action: Destroy and re-create the pool "
31203d7072f8Seschrock 		    "from a backup source.  Manually marking the device\n"
31213d7072f8Seschrock 		    "\trepaired using 'zpool clear' may allow some data "
31223d7072f8Seschrock 		    "to be recovered.\n"));
31233d7072f8Seschrock 		break;
31243d7072f8Seschrock 
312532b87932Sek110237 	case ZPOOL_STATUS_IO_FAILURE_WAIT:
312632b87932Sek110237 	case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
312732b87932Sek110237 		(void) printf(gettext("status: One or more devices are "
31288a79c1b5Sek110237 		    "faulted in response to IO failures.\n"));
312932b87932Sek110237 		(void) printf(gettext("action: Make sure the affected devices "
313032b87932Sek110237 		    "are connected, then run 'zpool clear'.\n"));
313132b87932Sek110237 		break;
313232b87932Sek110237 
3133fa9e4066Sahrens 	default:
3134fa9e4066Sahrens 		/*
3135fa9e4066Sahrens 		 * The remaining errors can't actually be generated, yet.
3136fa9e4066Sahrens 		 */
3137fa9e4066Sahrens 		assert(reason == ZPOOL_STATUS_OK);
3138fa9e4066Sahrens 	}
3139fa9e4066Sahrens 
3140fa9e4066Sahrens 	if (msgid != NULL)
3141fa9e4066Sahrens 		(void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
3142fa9e4066Sahrens 		    msgid);
3143fa9e4066Sahrens 
3144fa9e4066Sahrens 	if (config != NULL) {
3145fa9e4066Sahrens 		int namewidth;
3146ea8dc4b6Seschrock 		uint64_t nerr;
3147fa94a07fSbrendan 		nvlist_t **spares, **l2cache;
3148fa94a07fSbrendan 		uint_t nspares, nl2cache;
3149fa9e4066Sahrens 
3150fa9e4066Sahrens 
3151fa9e4066Sahrens 		(void) printf(gettext(" scrub: "));
3152fa9e4066Sahrens 		print_scrub_status(nvroot);
3153fa9e4066Sahrens 
3154c67d9675Seschrock 		namewidth = max_width(zhp, nvroot, 0, 0);
3155fa9e4066Sahrens 		if (namewidth < 10)
3156fa9e4066Sahrens 			namewidth = 10;
3157fa9e4066Sahrens 
3158fa9e4066Sahrens 		(void) printf(gettext("config:\n\n"));
3159fa9e4066Sahrens 		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
3160fa9e4066Sahrens 		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
3161c67d9675Seschrock 		print_status_config(zhp, zpool_get_name(zhp), nvroot,
31628654d025Sperrin 		    namewidth, 0, B_FALSE, B_FALSE);
31638654d025Sperrin 		if (num_logs(nvroot) > 0)
31648654d025Sperrin 			print_status_config(zhp, "logs", nvroot, namewidth, 0,
31658654d025Sperrin 			    B_FALSE, B_TRUE);
316699653d4eSeschrock 
3167fa94a07fSbrendan 		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3168fa94a07fSbrendan 		    &l2cache, &nl2cache) == 0)
3169fa94a07fSbrendan 			print_l2cache(zhp, l2cache, nl2cache, namewidth);
3170fa94a07fSbrendan 
317199653d4eSeschrock 		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
317299653d4eSeschrock 		    &spares, &nspares) == 0)
317399653d4eSeschrock 			print_spares(zhp, spares, nspares, namewidth);
3174ea8dc4b6Seschrock 
3175ea8dc4b6Seschrock 		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3176ea8dc4b6Seschrock 		    &nerr) == 0) {
317755434c77Sek110237 			nvlist_t *nverrlist = NULL;
317855434c77Sek110237 
3179ea8dc4b6Seschrock 			/*
3180ea8dc4b6Seschrock 			 * If the approximate error count is small, get a
3181ea8dc4b6Seschrock 			 * precise count by fetching the entire log and
3182ea8dc4b6Seschrock 			 * uniquifying the results.
3183ea8dc4b6Seschrock 			 */
318475519f38Sek110237 			if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
318555434c77Sek110237 			    zpool_get_errlog(zhp, &nverrlist) == 0) {
318655434c77Sek110237 				nvpair_t *elem;
318755434c77Sek110237 
318855434c77Sek110237 				elem = NULL;
318955434c77Sek110237 				nerr = 0;
319055434c77Sek110237 				while ((elem = nvlist_next_nvpair(nverrlist,
319155434c77Sek110237 				    elem)) != NULL) {
319255434c77Sek110237 					nerr++;
319355434c77Sek110237 				}
319455434c77Sek110237 			}
319555434c77Sek110237 			nvlist_free(nverrlist);
3196ea8dc4b6Seschrock 
3197ea8dc4b6Seschrock 			(void) printf("\n");
319899653d4eSeschrock 
3199ea8dc4b6Seschrock 			if (nerr == 0)
3200ea8dc4b6Seschrock 				(void) printf(gettext("errors: No known data "
3201ea8dc4b6Seschrock 				    "errors\n"));
3202ea8dc4b6Seschrock 			else if (!cbp->cb_verbose)
3203e9dbad6fSeschrock 				(void) printf(gettext("errors: %llu data "
32045ad82045Snd150628 				    "errors, use '-v' for a list\n"),
32055ad82045Snd150628 				    (u_longlong_t)nerr);
3206ea8dc4b6Seschrock 			else
3207ea8dc4b6Seschrock 				print_error_log(zhp);
3208ea8dc4b6Seschrock 		}
3209fa9e4066Sahrens 	} else {
3210fa9e4066Sahrens 		(void) printf(gettext("config: The configuration cannot be "
3211fa9e4066Sahrens 		    "determined.\n"));
3212fa9e4066Sahrens 	}
3213fa9e4066Sahrens 
3214fa9e4066Sahrens 	return (0);
3215fa9e4066Sahrens }
3216fa9e4066Sahrens 
3217fa9e4066Sahrens /*
3218fa9e4066Sahrens  * zpool status [-vx] [pool] ...
3219fa9e4066Sahrens  *
3220fa9e4066Sahrens  *	-v	Display complete error logs
3221fa9e4066Sahrens  *	-x	Display only pools with potential problems
3222fa9e4066Sahrens  *
3223fa9e4066Sahrens  * Describes the health status of all pools or some subset.
3224fa9e4066Sahrens  */
3225fa9e4066Sahrens int
3226fa9e4066Sahrens zpool_do_status(int argc, char **argv)
3227fa9e4066Sahrens {
3228fa9e4066Sahrens 	int c;
3229fa9e4066Sahrens 	int ret;
3230fa9e4066Sahrens 	status_cbdata_t cb = { 0 };
3231fa9e4066Sahrens 
3232fa9e4066Sahrens 	/* check options */
3233fa9e4066Sahrens 	while ((c = getopt(argc, argv, "vx")) != -1) {
3234fa9e4066Sahrens 		switch (c) {
3235fa9e4066Sahrens 		case 'v':
323699653d4eSeschrock 			cb.cb_verbose = B_TRUE;
3237fa9e4066Sahrens 			break;
3238fa9e4066Sahrens 		case 'x':
323999653d4eSeschrock 			cb.cb_explain = B_TRUE;
3240fa9e4066Sahrens 			break;
3241fa9e4066Sahrens 		case '?':
3242fa9e4066Sahrens 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3243fa9e4066Sahrens 			    optopt);
324499653d4eSeschrock 			usage(B_FALSE);
3245fa9e4066Sahrens 		}
3246fa9e4066Sahrens 	}
3247fa9e4066Sahrens 
3248fa9e4066Sahrens 	argc -= optind;
3249fa9e4066Sahrens 	argv += optind;
3250fa9e4066Sahrens 
325199653d4eSeschrock 	cb.cb_first = B_TRUE;
3252fa9e4066Sahrens 
3253e9dbad6fSeschrock 	if (argc == 0)
3254e9dbad6fSeschrock 		cb.cb_allpools = B_TRUE;
3255e9dbad6fSeschrock 
3256b1b8ab34Slling 	ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3257fa9e4066Sahrens 
3258fa9e4066Sahrens 	if (argc == 0 && cb.cb_count == 0)
3259fa9e4066Sahrens 		(void) printf(gettext("no pools available\n"));
3260e9dbad6fSeschrock 	else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3261fa9e4066Sahrens 		(void) printf(gettext("all pools are healthy\n"));
3262fa9e4066Sahrens 
3263fa9e4066Sahrens 	return (ret);
3264fa9e4066Sahrens }
3265fa9e4066Sahrens 
3266eaca9bbdSeschrock typedef struct upgrade_cbdata {
3267eaca9bbdSeschrock 	int	cb_all;
3268eaca9bbdSeschrock 	int	cb_first;
3269eaca9bbdSeschrock 	int	cb_newer;
327006eeb2adSek110237 	int	cb_argc;
3271990b4856Slling 	uint64_t cb_version;
327206eeb2adSek110237 	char	**cb_argv;
3273eaca9bbdSeschrock } upgrade_cbdata_t;
3274eaca9bbdSeschrock 
3275eaca9bbdSeschrock static int
3276eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg)
3277eaca9bbdSeschrock {
3278eaca9bbdSeschrock 	upgrade_cbdata_t *cbp = arg;
3279eaca9bbdSeschrock 	nvlist_t *config;
3280eaca9bbdSeschrock 	uint64_t version;
3281eaca9bbdSeschrock 	int ret = 0;
3282eaca9bbdSeschrock 
3283eaca9bbdSeschrock 	config = zpool_get_config(zhp, NULL);
3284eaca9bbdSeschrock 	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3285eaca9bbdSeschrock 	    &version) == 0);
3286eaca9bbdSeschrock 
3287e7437265Sahrens 	if (!cbp->cb_newer && version < SPA_VERSION) {
3288eaca9bbdSeschrock 		if (!cbp->cb_all) {
3289eaca9bbdSeschrock 			if (cbp->cb_first) {
3290eaca9bbdSeschrock 				(void) printf(gettext("The following pools are "
3291eaca9bbdSeschrock 				    "out of date, and can be upgraded.  After "
3292eaca9bbdSeschrock 				    "being\nupgraded, these pools will no "
3293eaca9bbdSeschrock 				    "longer be accessible by older software "
3294eaca9bbdSeschrock 				    "versions.\n\n"));
3295eaca9bbdSeschrock 				(void) printf(gettext("VER  POOL\n"));
3296eaca9bbdSeschrock 				(void) printf(gettext("---  ------------\n"));
329799653d4eSeschrock 				cbp->cb_first = B_FALSE;
3298eaca9bbdSeschrock 			}
3299eaca9bbdSeschrock 
33005ad82045Snd150628 			(void) printf("%2llu   %s\n", (u_longlong_t)version,
3301eaca9bbdSeschrock 			    zpool_get_name(zhp));
3302eaca9bbdSeschrock 		} else {
330399653d4eSeschrock 			cbp->cb_first = B_FALSE;
3304990b4856Slling 			ret = zpool_upgrade(zhp, cbp->cb_version);
330506eeb2adSek110237 			if (!ret) {
3306eaca9bbdSeschrock 				(void) printf(gettext("Successfully upgraded "
3307990b4856Slling 				    "'%s'\n\n"), zpool_get_name(zhp));
3308eaca9bbdSeschrock 			}
330906eeb2adSek110237 		}
3310e7437265Sahrens 	} else if (cbp->cb_newer && version > SPA_VERSION) {
3311eaca9bbdSeschrock 		assert(!cbp->cb_all);
3312eaca9bbdSeschrock 
3313eaca9bbdSeschrock 		if (cbp->cb_first) {
3314eaca9bbdSeschrock 			(void) printf(gettext("The following pools are "
3315eaca9bbdSeschrock 			    "formatted using a newer software version and\n"
3316eaca9bbdSeschrock 			    "cannot be accessed on the current system.\n\n"));
3317eaca9bbdSeschrock 			(void) printf(gettext("VER  POOL\n"));
3318eaca9bbdSeschrock 			(void) printf(gettext("---  ------------\n"));
331999653d4eSeschrock 			cbp->cb_first = B_FALSE;
3320eaca9bbdSeschrock 		}
3321eaca9bbdSeschrock 
33225ad82045Snd150628 		(void) printf("%2llu   %s\n", (u_longlong_t)version,
3323eaca9bbdSeschrock 		    zpool_get_name(zhp));
3324eaca9bbdSeschrock 	}
3325eaca9bbdSeschrock 
3326eaca9bbdSeschrock 	zpool_close(zhp);
3327eaca9bbdSeschrock 	return (ret);
3328eaca9bbdSeschrock }
3329eaca9bbdSeschrock 
3330eaca9bbdSeschrock /* ARGSUSED */
3331eaca9bbdSeschrock static int
333206eeb2adSek110237 upgrade_one(zpool_handle_t *zhp, void *data)
3333eaca9bbdSeschrock {
3334990b4856Slling 	upgrade_cbdata_t *cbp = data;
3335990b4856Slling 	uint64_t cur_version;
3336eaca9bbdSeschrock 	int ret;
3337eaca9bbdSeschrock 
33388654d025Sperrin 	if (strcmp("log", zpool_get_name(zhp)) == 0) {
33398654d025Sperrin 		(void) printf(gettext("'log' is now a reserved word\n"
33408654d025Sperrin 		    "Pool 'log' must be renamed using export and import"
33418654d025Sperrin 		    " to upgrade.\n"));
33428654d025Sperrin 		return (1);
33438654d025Sperrin 	}
3344990b4856Slling 
3345990b4856Slling 	cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3346e6c728e1Sbrendan 	if (cur_version > cbp->cb_version) {
3347eaca9bbdSeschrock 		(void) printf(gettext("Pool '%s' is already formatted "
3348e6c728e1Sbrendan 		    "using more current version '%llu'.\n"),
3349e6c728e1Sbrendan 		    zpool_get_name(zhp), cur_version);
3350e6c728e1Sbrendan 		return (0);
3351e6c728e1Sbrendan 	}
3352e6c728e1Sbrendan 	if (cur_version == cbp->cb_version) {
3353e6c728e1Sbrendan 		(void) printf(gettext("Pool '%s' is already formatted "
3354e6c728e1Sbrendan 		    "using the current version.\n"), zpool_get_name(zhp));
3355eaca9bbdSeschrock 		return (0);
3356eaca9bbdSeschrock 	}
3357eaca9bbdSeschrock 
3358990b4856Slling 	ret = zpool_upgrade(zhp, cbp->cb_version);
335906eeb2adSek110237 
336006eeb2adSek110237 	if (!ret) {
336144cd46caSbillm 		(void) printf(gettext("Successfully upgraded '%s' "
3362990b4856Slling 		    "from version %llu to version %llu\n\n"),
3363990b4856Slling 		    zpool_get_name(zhp), (u_longlong_t)cur_version,
3364990b4856Slling 		    (u_longlong_t)cbp->cb_version);
336506eeb2adSek110237 	}
3366eaca9bbdSeschrock 
3367eaca9bbdSeschrock 	return (ret != 0);
3368eaca9bbdSeschrock }
3369eaca9bbdSeschrock 
3370eaca9bbdSeschrock /*
3371eaca9bbdSeschrock  * zpool upgrade
3372eaca9bbdSeschrock  * zpool upgrade -v
3373990b4856Slling  * zpool upgrade [-V version] <-a | pool ...>
3374eaca9bbdSeschrock  *
3375eaca9bbdSeschrock  * With no arguments, display downrev'd ZFS pool available for upgrade.
3376eaca9bbdSeschrock  * Individual pools can be upgraded by specifying the pool, and '-a' will
3377eaca9bbdSeschrock  * upgrade all pools.
3378eaca9bbdSeschrock  */
3379eaca9bbdSeschrock int
3380eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv)
3381eaca9bbdSeschrock {
3382eaca9bbdSeschrock 	int c;
3383eaca9bbdSeschrock 	upgrade_cbdata_t cb = { 0 };
3384eaca9bbdSeschrock 	int ret = 0;
3385eaca9bbdSeschrock 	boolean_t showversions = B_FALSE;
3386990b4856Slling 	char *end;
3387990b4856Slling 
3388eaca9bbdSeschrock 
3389eaca9bbdSeschrock 	/* check options */
3390990b4856Slling 	while ((c = getopt(argc, argv, "avV:")) != -1) {
3391eaca9bbdSeschrock 		switch (c) {
3392eaca9bbdSeschrock 		case 'a':
339399653d4eSeschrock 			cb.cb_all = B_TRUE;
3394eaca9bbdSeschrock 			break;
3395eaca9bbdSeschrock 		case 'v':
3396eaca9bbdSeschrock 			showversions = B_TRUE;
3397eaca9bbdSeschrock 			break;
3398990b4856Slling 		case 'V':
3399990b4856Slling 			cb.cb_version = strtoll(optarg, &end, 10);
3400351420b3Slling 			if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3401351420b3Slling 			    cb.cb_version < SPA_VERSION_1) {
3402990b4856Slling 				(void) fprintf(stderr,
3403990b4856Slling 				    gettext("invalid version '%s'\n"), optarg);
3404990b4856Slling 				usage(B_FALSE);
3405990b4856Slling 			}
3406990b4856Slling 			break;
3407eaca9bbdSeschrock 		case '?':
3408eaca9bbdSeschrock 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3409eaca9bbdSeschrock 			    optopt);
341099653d4eSeschrock 			usage(B_FALSE);
3411eaca9bbdSeschrock 		}
3412eaca9bbdSeschrock 	}
3413eaca9bbdSeschrock 
341406eeb2adSek110237 	cb.cb_argc = argc;
341506eeb2adSek110237 	cb.cb_argv = argv;
3416eaca9bbdSeschrock 	argc -= optind;
3417eaca9bbdSeschrock 	argv += optind;
3418eaca9bbdSeschrock 
3419351420b3Slling 	if (cb.cb_version == 0) {
3420351420b3Slling 		cb.cb_version = SPA_VERSION;
3421351420b3Slling 	} else if (!cb.cb_all && argc == 0) {
3422351420b3Slling 		(void) fprintf(stderr, gettext("-V option is "
3423351420b3Slling 		    "incompatible with other arguments\n"));
3424351420b3Slling 		usage(B_FALSE);
3425351420b3Slling 	}
3426351420b3Slling 
3427eaca9bbdSeschrock 	if (showversions) {
3428eaca9bbdSeschrock 		if (cb.cb_all || argc != 0) {
3429eaca9bbdSeschrock 			(void) fprintf(stderr, gettext("-v option is "
3430eaca9bbdSeschrock 			    "incompatible with other arguments\n"));
343199653d4eSeschrock 			usage(B_FALSE);
3432eaca9bbdSeschrock 		}
3433eaca9bbdSeschrock 	} else if (cb.cb_all) {
3434eaca9bbdSeschrock 		if (argc != 0) {
3435351420b3Slling 			(void) fprintf(stderr, gettext("-a option should not "
3436351420b3Slling 			    "be used along with a pool name\n"));
343799653d4eSeschrock 			usage(B_FALSE);
3438eaca9bbdSeschrock 		}
3439eaca9bbdSeschrock 	}
3440eaca9bbdSeschrock 
3441e7437265Sahrens 	(void) printf(gettext("This system is currently running "
3442e7437265Sahrens 	    "ZFS pool version %llu.\n\n"), SPA_VERSION);
344399653d4eSeschrock 	cb.cb_first = B_TRUE;
3444eaca9bbdSeschrock 	if (showversions) {
3445eaca9bbdSeschrock 		(void) printf(gettext("The following versions are "
3446d7d4af51Smmusante 		    "supported:\n\n"));
3447eaca9bbdSeschrock 		(void) printf(gettext("VER  DESCRIPTION\n"));
3448eaca9bbdSeschrock 		(void) printf("---  -----------------------------------------"
3449eaca9bbdSeschrock 		    "---------------\n");
345099653d4eSeschrock 		(void) printf(gettext(" 1   Initial ZFS version\n"));
345144cd46caSbillm 		(void) printf(gettext(" 2   Ditto blocks "
345244cd46caSbillm 		    "(replicated metadata)\n"));
345399653d4eSeschrock 		(void) printf(gettext(" 3   Hot spares and double parity "
345499653d4eSeschrock 		    "RAID-Z\n"));
3455d7306b64Sek110237 		(void) printf(gettext(" 4   zpool history\n"));
3456c9431fa1Sahl 		(void) printf(gettext(" 5   Compression using the gzip "
3457c9431fa1Sahl 		    "algorithm\n"));
3458990b4856Slling 		(void) printf(gettext(" 6   bootfs pool property\n"));
34598654d025Sperrin 		(void) printf(gettext(" 7   Separate intent log devices\n"));
3460ecd6cf80Smarks 		(void) printf(gettext(" 8   Delegated administration\n"));
3461a9799022Sck153898 		(void) printf(gettext(" 9   refquota and refreservation "
3462a9799022Sck153898 		    "properties\n"));
3463fa94a07fSbrendan 		(void) printf(gettext(" 10  Cache devices\n"));
3464088f3894Sahrens 		(void) printf(gettext(" 11  Improved scrub performance\n"));
34658654d025Sperrin 		(void) printf(gettext("For more information on a particular "
3466eaca9bbdSeschrock 		    "version, including supported releases, see:\n\n"));
3467eaca9bbdSeschrock 		(void) printf("http://www.opensolaris.org/os/community/zfs/"
3468eaca9bbdSeschrock 		    "version/N\n\n");
3469eaca9bbdSeschrock 		(void) printf(gettext("Where 'N' is the version number.\n"));
3470eaca9bbdSeschrock 	} else if (argc == 0) {
3471eaca9bbdSeschrock 		int notfound;
3472eaca9bbdSeschrock 
347399653d4eSeschrock 		ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3474eaca9bbdSeschrock 		notfound = cb.cb_first;
3475eaca9bbdSeschrock 
3476eaca9bbdSeschrock 		if (!cb.cb_all && ret == 0) {
3477eaca9bbdSeschrock 			if (!cb.cb_first)
3478eaca9bbdSeschrock 				(void) printf("\n");
3479eaca9bbdSeschrock 			cb.cb_first = B_TRUE;
3480eaca9bbdSeschrock 			cb.cb_newer = B_TRUE;
348199653d4eSeschrock 			ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3482eaca9bbdSeschrock 			if (!cb.cb_first) {
3483eaca9bbdSeschrock 				notfound = B_FALSE;
3484eaca9bbdSeschrock 				(void) printf("\n");
3485eaca9bbdSeschrock 			}
3486eaca9bbdSeschrock 		}
3487eaca9bbdSeschrock 
3488eaca9bbdSeschrock 		if (ret == 0) {
3489eaca9bbdSeschrock 			if (notfound)
3490eaca9bbdSeschrock 				(void) printf(gettext("All pools are formatted "
3491eaca9bbdSeschrock 				    "using this version.\n"));
3492eaca9bbdSeschrock 			else if (!cb.cb_all)
3493eaca9bbdSeschrock 				(void) printf(gettext("Use 'zpool upgrade -v' "
3494eaca9bbdSeschrock 				    "for a list of available versions and "
3495eaca9bbdSeschrock 				    "their associated\nfeatures.\n"));
3496eaca9bbdSeschrock 		}
3497eaca9bbdSeschrock 	} else {
3498b1b8ab34Slling 		ret = for_each_pool(argc, argv, B_FALSE, NULL,
3499b1b8ab34Slling 		    upgrade_one, &cb);
350006eeb2adSek110237 	}
350106eeb2adSek110237 
350206eeb2adSek110237 	return (ret);
350306eeb2adSek110237 }
350406eeb2adSek110237 
3505ecd6cf80Smarks typedef struct hist_cbdata {
3506ecd6cf80Smarks 	boolean_t first;
3507ecd6cf80Smarks 	int longfmt;
3508ecd6cf80Smarks 	int internal;
3509ecd6cf80Smarks } hist_cbdata_t;
3510ecd6cf80Smarks 
3511ecd6cf80Smarks char *hist_event_table[LOG_END] = {
3512ecd6cf80Smarks 	"invalid event",
3513ecd6cf80Smarks 	"pool create",
3514ecd6cf80Smarks 	"vdev add",
3515ecd6cf80Smarks 	"pool remove",
3516ecd6cf80Smarks 	"pool destroy",
3517ecd6cf80Smarks 	"pool export",
3518ecd6cf80Smarks 	"pool import",
3519ecd6cf80Smarks 	"vdev attach",
3520ecd6cf80Smarks 	"vdev replace",
3521ecd6cf80Smarks 	"vdev detach",
3522ecd6cf80Smarks 	"vdev online",
3523ecd6cf80Smarks 	"vdev offline",
3524ecd6cf80Smarks 	"vdev upgrade",
3525ecd6cf80Smarks 	"pool clear",
3526ecd6cf80Smarks 	"pool scrub",
3527ecd6cf80Smarks 	"pool property set",
3528ecd6cf80Smarks 	"create",
3529ecd6cf80Smarks 	"clone",
3530ecd6cf80Smarks 	"destroy",
3531ecd6cf80Smarks 	"destroy_begin_sync",
3532ecd6cf80Smarks 	"inherit",
3533ecd6cf80Smarks 	"property set",
3534ecd6cf80Smarks 	"quota set",
3535ecd6cf80Smarks 	"permission update",
3536ecd6cf80Smarks 	"permission remove",
3537ecd6cf80Smarks 	"permission who remove",
3538ecd6cf80Smarks 	"promote",
3539ecd6cf80Smarks 	"receive",
3540ecd6cf80Smarks 	"rename",
3541ecd6cf80Smarks 	"reservation set",
3542ecd6cf80Smarks 	"replay_inc_sync",
3543ecd6cf80Smarks 	"replay_full_sync",
3544ecd6cf80Smarks 	"rollback",
3545ecd6cf80Smarks 	"snapshot",
3546e7437265Sahrens 	"filesystem version upgrade",
3547a9799022Sck153898 	"refquota set",
3548a9799022Sck153898 	"refreservation set",
3549088f3894Sahrens 	"pool scrub done",
3550ecd6cf80Smarks };
3551ecd6cf80Smarks 
355206eeb2adSek110237 /*
355306eeb2adSek110237  * Print out the command history for a specific pool.
355406eeb2adSek110237  */
355506eeb2adSek110237 static int
355606eeb2adSek110237 get_history_one(zpool_handle_t *zhp, void *data)
355706eeb2adSek110237 {
355806eeb2adSek110237 	nvlist_t *nvhis;
355906eeb2adSek110237 	nvlist_t **records;
356006eeb2adSek110237 	uint_t numrecords;
356106eeb2adSek110237 	char *cmdstr;
3562ecd6cf80Smarks 	char *pathstr;
356306eeb2adSek110237 	uint64_t dst_time;
356406eeb2adSek110237 	time_t tsec;
356506eeb2adSek110237 	struct tm t;
356606eeb2adSek110237 	char tbuf[30];
356706eeb2adSek110237 	int ret, i;
3568ecd6cf80Smarks 	uint64_t who;
3569ecd6cf80Smarks 	struct passwd *pwd;
3570ecd6cf80Smarks 	char *hostname;
3571ecd6cf80Smarks 	char *zonename;
3572ecd6cf80Smarks 	char internalstr[MAXPATHLEN];
3573ecd6cf80Smarks 	hist_cbdata_t *cb = (hist_cbdata_t *)data;
3574ecd6cf80Smarks 	uint64_t txg;
3575ecd6cf80Smarks 	uint64_t ievent;
357606eeb2adSek110237 
3577ecd6cf80Smarks 	cb->first = B_FALSE;
357806eeb2adSek110237 
357906eeb2adSek110237 	(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
358006eeb2adSek110237 
358106eeb2adSek110237 	if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
358206eeb2adSek110237 		return (ret);
358306eeb2adSek110237 
358406eeb2adSek110237 	verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
358506eeb2adSek110237 	    &records, &numrecords) == 0);
358606eeb2adSek110237 	for (i = 0; i < numrecords; i++) {
358706eeb2adSek110237 		if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3588ecd6cf80Smarks 		    &dst_time) != 0)
3589ecd6cf80Smarks 			continue;
3590ecd6cf80Smarks 
3591ecd6cf80Smarks 		/* is it an internal event or a standard event? */
3592ecd6cf80Smarks 		if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3593ecd6cf80Smarks 		    &cmdstr) != 0) {
3594ecd6cf80Smarks 			if (cb->internal == 0)
3595ecd6cf80Smarks 				continue;
3596ecd6cf80Smarks 
3597ecd6cf80Smarks 			if (nvlist_lookup_uint64(records[i],
3598ecd6cf80Smarks 			    ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3599ecd6cf80Smarks 				continue;
3600ecd6cf80Smarks 			verify(nvlist_lookup_uint64(records[i],
3601ecd6cf80Smarks 			    ZPOOL_HIST_TXG, &txg) == 0);
3602ecd6cf80Smarks 			verify(nvlist_lookup_string(records[i],
3603ecd6cf80Smarks 			    ZPOOL_HIST_INT_STR, &pathstr) == 0);
3604088f3894Sahrens 			if (ievent >= LOG_END)
3605ecd6cf80Smarks 				continue;
3606ecd6cf80Smarks 			(void) snprintf(internalstr,
3607ecd6cf80Smarks 			    sizeof (internalstr),
3608ecd6cf80Smarks 			    "[internal %s txg:%lld] %s",
3609ecd6cf80Smarks 			    hist_event_table[ievent], txg,
3610ecd6cf80Smarks 			    pathstr);
3611ecd6cf80Smarks 			cmdstr = internalstr;
3612ecd6cf80Smarks 		}
361306eeb2adSek110237 		tsec = dst_time;
361406eeb2adSek110237 		(void) localtime_r(&tsec, &t);
361506eeb2adSek110237 		(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3616ecd6cf80Smarks 		(void) printf("%s %s", tbuf, cmdstr);
3617ecd6cf80Smarks 
3618ecd6cf80Smarks 		if (!cb->longfmt) {
3619ecd6cf80Smarks 			(void) printf("\n");
3620ecd6cf80Smarks 			continue;
362106eeb2adSek110237 		}
3622ecd6cf80Smarks 		(void) printf(" [");
3623ecd6cf80Smarks 		if (nvlist_lookup_uint64(records[i],
3624ecd6cf80Smarks 		    ZPOOL_HIST_WHO, &who) == 0) {
3625ecd6cf80Smarks 			pwd = getpwuid((uid_t)who);
3626ecd6cf80Smarks 			if (pwd)
3627ecd6cf80Smarks 				(void) printf("user %s on",
3628ecd6cf80Smarks 				    pwd->pw_name);
3629ecd6cf80Smarks 			else
3630ecd6cf80Smarks 				(void) printf("user %d on",
3631ecd6cf80Smarks 				    (int)who);
3632ecd6cf80Smarks 		} else {
3633ecd6cf80Smarks 			(void) printf(gettext("no info]\n"));
3634ecd6cf80Smarks 			continue;
3635ecd6cf80Smarks 		}
3636ecd6cf80Smarks 		if (nvlist_lookup_string(records[i],
3637ecd6cf80Smarks 		    ZPOOL_HIST_HOST, &hostname) == 0) {
3638ecd6cf80Smarks 			(void) printf(" %s", hostname);
3639ecd6cf80Smarks 		}
3640ecd6cf80Smarks 		if (nvlist_lookup_string(records[i],
3641ecd6cf80Smarks 		    ZPOOL_HIST_ZONE, &zonename) == 0) {
3642ecd6cf80Smarks 			(void) printf(":%s", zonename);
3643ecd6cf80Smarks 		}
3644ecd6cf80Smarks 
3645ecd6cf80Smarks 		(void) printf("]");
3646ecd6cf80Smarks 		(void) printf("\n");
364706eeb2adSek110237 	}
364806eeb2adSek110237 	(void) printf("\n");
364906eeb2adSek110237 	nvlist_free(nvhis);
365006eeb2adSek110237 
365106eeb2adSek110237 	return (ret);
365206eeb2adSek110237 }
365306eeb2adSek110237 
365406eeb2adSek110237 /*
365506eeb2adSek110237  * zpool history <pool>
365606eeb2adSek110237  *
365706eeb2adSek110237  * Displays the history of commands that modified pools.
365806eeb2adSek110237  */
3659ecd6cf80Smarks 
3660ecd6cf80Smarks 
366106eeb2adSek110237 int
366206eeb2adSek110237 zpool_do_history(int argc, char **argv)
366306eeb2adSek110237 {
3664ecd6cf80Smarks 	hist_cbdata_t cbdata = { 0 };
366506eeb2adSek110237 	int ret;
3666ecd6cf80Smarks 	int c;
366706eeb2adSek110237 
3668ecd6cf80Smarks 	cbdata.first = B_TRUE;
3669ecd6cf80Smarks 	/* check options */
3670ecd6cf80Smarks 	while ((c = getopt(argc, argv, "li")) != -1) {
3671ecd6cf80Smarks 		switch (c) {
3672ecd6cf80Smarks 		case 'l':
3673ecd6cf80Smarks 			cbdata.longfmt = 1;
3674ecd6cf80Smarks 			break;
3675ecd6cf80Smarks 		case 'i':
3676ecd6cf80Smarks 			cbdata.internal = 1;
3677ecd6cf80Smarks 			break;
3678ecd6cf80Smarks 		case '?':
3679ecd6cf80Smarks 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3680ecd6cf80Smarks 			    optopt);
3681ecd6cf80Smarks 			usage(B_FALSE);
3682ecd6cf80Smarks 		}
3683ecd6cf80Smarks 	}
368406eeb2adSek110237 	argc -= optind;
368506eeb2adSek110237 	argv += optind;
368606eeb2adSek110237 
3687b1b8ab34Slling 	ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
3688ecd6cf80Smarks 	    &cbdata);
368906eeb2adSek110237 
3690ecd6cf80Smarks 	if (argc == 0 && cbdata.first == B_TRUE) {
369106eeb2adSek110237 		(void) printf(gettext("no pools available\n"));
369206eeb2adSek110237 		return (0);
3693eaca9bbdSeschrock 	}
3694eaca9bbdSeschrock 
3695eaca9bbdSeschrock 	return (ret);
3696eaca9bbdSeschrock }
3697eaca9bbdSeschrock 
3698b1b8ab34Slling static int
3699b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data)
3700b1b8ab34Slling {
3701990b4856Slling 	zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3702b1b8ab34Slling 	char value[MAXNAMELEN];
3703990b4856Slling 	zprop_source_t srctype;
3704990b4856Slling 	zprop_list_t *pl;
3705b1b8ab34Slling 
3706b1b8ab34Slling 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3707b1b8ab34Slling 
3708b1b8ab34Slling 		/*
3709990b4856Slling 		 * Skip the special fake placeholder. This will also skip
3710990b4856Slling 		 * over the name property when 'all' is specified.
3711b1b8ab34Slling 		 */
3712990b4856Slling 		if (pl->pl_prop == ZPOOL_PROP_NAME &&
3713b1b8ab34Slling 		    pl == cbp->cb_proplist)
3714b1b8ab34Slling 			continue;
3715b1b8ab34Slling 
3716b1b8ab34Slling 		if (zpool_get_prop(zhp, pl->pl_prop,
3717b1b8ab34Slling 		    value, sizeof (value), &srctype) != 0)
3718b1b8ab34Slling 			continue;
3719b1b8ab34Slling 
3720990b4856Slling 		zprop_print_one_property(zpool_get_name(zhp), cbp,
3721b1b8ab34Slling 		    zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3722b1b8ab34Slling 	}
3723b1b8ab34Slling 	return (0);
3724b1b8ab34Slling }
3725b1b8ab34Slling 
3726b1b8ab34Slling int
3727b1b8ab34Slling zpool_do_get(int argc, char **argv)
3728b1b8ab34Slling {
3729990b4856Slling 	zprop_get_cbdata_t cb = { 0 };
3730990b4856Slling 	zprop_list_t fake_name = { 0 };
3731b1b8ab34Slling 	int ret;
3732b1b8ab34Slling 
3733b1b8ab34Slling 	if (argc < 3)
3734b1b8ab34Slling 		usage(B_FALSE);
3735b1b8ab34Slling 
3736b1b8ab34Slling 	cb.cb_first = B_TRUE;
3737990b4856Slling 	cb.cb_sources = ZPROP_SRC_ALL;
3738b1b8ab34Slling 	cb.cb_columns[0] = GET_COL_NAME;
3739b1b8ab34Slling 	cb.cb_columns[1] = GET_COL_PROPERTY;
3740b1b8ab34Slling 	cb.cb_columns[2] = GET_COL_VALUE;
3741b1b8ab34Slling 	cb.cb_columns[3] = GET_COL_SOURCE;
3742990b4856Slling 	cb.cb_type = ZFS_TYPE_POOL;
3743b1b8ab34Slling 
3744990b4856Slling 	if (zprop_get_list(g_zfs, argv[1],  &cb.cb_proplist,
3745990b4856Slling 	    ZFS_TYPE_POOL) != 0)
3746b1b8ab34Slling 		usage(B_FALSE);
3747b1b8ab34Slling 
3748b1b8ab34Slling 	if (cb.cb_proplist != NULL) {
3749990b4856Slling 		fake_name.pl_prop = ZPOOL_PROP_NAME;
3750b1b8ab34Slling 		fake_name.pl_width = strlen(gettext("NAME"));
3751b1b8ab34Slling 		fake_name.pl_next = cb.cb_proplist;
3752b1b8ab34Slling 		cb.cb_proplist = &fake_name;
3753b1b8ab34Slling 	}
3754b1b8ab34Slling 
3755b1b8ab34Slling 	ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3756b1b8ab34Slling 	    get_callback, &cb);
3757b1b8ab34Slling 
3758b1b8ab34Slling 	if (cb.cb_proplist == &fake_name)
3759990b4856Slling 		zprop_free_list(fake_name.pl_next);
3760b1b8ab34Slling 	else
3761990b4856Slling 		zprop_free_list(cb.cb_proplist);
3762b1b8ab34Slling 
3763b1b8ab34Slling 	return (ret);
3764b1b8ab34Slling }
3765b1b8ab34Slling 
3766b1b8ab34Slling typedef struct set_cbdata {
3767b1b8ab34Slling 	char *cb_propname;
3768b1b8ab34Slling 	char *cb_value;
3769b1b8ab34Slling 	boolean_t cb_any_successful;
3770b1b8ab34Slling } set_cbdata_t;
3771b1b8ab34Slling 
3772b1b8ab34Slling int
3773b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data)
3774b1b8ab34Slling {
3775b1b8ab34Slling 	int error;
3776b1b8ab34Slling 	set_cbdata_t *cb = (set_cbdata_t *)data;
3777b1b8ab34Slling 
3778b1b8ab34Slling 	error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3779b1b8ab34Slling 
3780b1b8ab34Slling 	if (!error)
3781b1b8ab34Slling 		cb->cb_any_successful = B_TRUE;
3782b1b8ab34Slling 
3783b1b8ab34Slling 	return (error);
3784b1b8ab34Slling }
3785b1b8ab34Slling 
3786b1b8ab34Slling int
3787b1b8ab34Slling zpool_do_set(int argc, char **argv)
3788b1b8ab34Slling {
3789b1b8ab34Slling 	set_cbdata_t cb = { 0 };
3790b1b8ab34Slling 	int error;
3791b1b8ab34Slling 
3792b1b8ab34Slling 	if (argc > 1 && argv[1][0] == '-') {
3793b1b8ab34Slling 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3794b1b8ab34Slling 		    argv[1][1]);
3795b1b8ab34Slling 		usage(B_FALSE);
3796b1b8ab34Slling 	}
3797b1b8ab34Slling 
3798b1b8ab34Slling 	if (argc < 2) {
3799b1b8ab34Slling 		(void) fprintf(stderr, gettext("missing property=value "
3800b1b8ab34Slling 		    "argument\n"));
3801b1b8ab34Slling 		usage(B_FALSE);
3802b1b8ab34Slling 	}
3803b1b8ab34Slling 
3804b1b8ab34Slling 	if (argc < 3) {
3805b1b8ab34Slling 		(void) fprintf(stderr, gettext("missing pool name\n"));
3806b1b8ab34Slling 		usage(B_FALSE);
3807b1b8ab34Slling 	}
3808b1b8ab34Slling 
3809b1b8ab34Slling 	if (argc > 3) {
3810b1b8ab34Slling 		(void) fprintf(stderr, gettext("too many pool names\n"));
3811b1b8ab34Slling 		usage(B_FALSE);
3812b1b8ab34Slling 	}
3813b1b8ab34Slling 
3814b1b8ab34Slling 	cb.cb_propname = argv[1];
3815b1b8ab34Slling 	cb.cb_value = strchr(cb.cb_propname, '=');
3816b1b8ab34Slling 	if (cb.cb_value == NULL) {
3817b1b8ab34Slling 		(void) fprintf(stderr, gettext("missing value in "
3818b1b8ab34Slling 		    "property=value argument\n"));
3819b1b8ab34Slling 		usage(B_FALSE);
3820b1b8ab34Slling 	}
3821b1b8ab34Slling 
3822b1b8ab34Slling 	*(cb.cb_value) = '\0';
3823b1b8ab34Slling 	cb.cb_value++;
3824b1b8ab34Slling 
3825b1b8ab34Slling 	error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3826b1b8ab34Slling 	    set_callback, &cb);
3827b1b8ab34Slling 
3828b1b8ab34Slling 	return (error);
3829b1b8ab34Slling }
3830b1b8ab34Slling 
3831b1b8ab34Slling static int
3832b1b8ab34Slling find_command_idx(char *command, int *idx)
3833b1b8ab34Slling {
3834b1b8ab34Slling 	int i;
3835b1b8ab34Slling 
3836b1b8ab34Slling 	for (i = 0; i < NCOMMAND; i++) {
3837b1b8ab34Slling 		if (command_table[i].name == NULL)
3838b1b8ab34Slling 			continue;
3839b1b8ab34Slling 
3840b1b8ab34Slling 		if (strcmp(command, command_table[i].name) == 0) {
3841b1b8ab34Slling 			*idx = i;
3842b1b8ab34Slling 			return (0);
3843b1b8ab34Slling 		}
3844b1b8ab34Slling 	}
3845b1b8ab34Slling 	return (1);
3846b1b8ab34Slling }
3847b1b8ab34Slling 
3848fa9e4066Sahrens int
3849fa9e4066Sahrens main(int argc, char **argv)
3850fa9e4066Sahrens {
3851fa9e4066Sahrens 	int ret;
3852fa9e4066Sahrens 	int i;
3853fa9e4066Sahrens 	char *cmdname;
3854fa9e4066Sahrens 
3855fa9e4066Sahrens 	(void) setlocale(LC_ALL, "");
3856fa9e4066Sahrens 	(void) textdomain(TEXT_DOMAIN);
3857fa9e4066Sahrens 
385899653d4eSeschrock 	if ((g_zfs = libzfs_init()) == NULL) {
385999653d4eSeschrock 		(void) fprintf(stderr, gettext("internal error: failed to "
3860203a47d8Snd150628 		    "initialize ZFS library\n"));
386199653d4eSeschrock 		return (1);
386299653d4eSeschrock 	}
386399653d4eSeschrock 
386499653d4eSeschrock 	libzfs_print_on_error(g_zfs, B_TRUE);
386599653d4eSeschrock 
3866fa9e4066Sahrens 	opterr = 0;
3867fa9e4066Sahrens 
3868fa9e4066Sahrens 	/*
3869fa9e4066Sahrens 	 * Make sure the user has specified some command.
3870fa9e4066Sahrens 	 */
3871fa9e4066Sahrens 	if (argc < 2) {
3872fa9e4066Sahrens 		(void) fprintf(stderr, gettext("missing command\n"));
387399653d4eSeschrock 		usage(B_FALSE);
3874fa9e4066Sahrens 	}
3875fa9e4066Sahrens 
3876fa9e4066Sahrens 	cmdname = argv[1];
3877fa9e4066Sahrens 
3878fa9e4066Sahrens 	/*
3879fa9e4066Sahrens 	 * Special case '-?'
3880fa9e4066Sahrens 	 */
3881fa9e4066Sahrens 	if (strcmp(cmdname, "-?") == 0)
388299653d4eSeschrock 		usage(B_TRUE);
3883fa9e4066Sahrens 
38842a6b87f0Sek110237 	zpool_set_history_str("zpool", argc, argv, history_str);
38852a6b87f0Sek110237 	verify(zpool_stage_history(g_zfs, history_str) == 0);
38862a6b87f0Sek110237 
3887fa9e4066Sahrens 	/*
3888fa9e4066Sahrens 	 * Run the appropriate command.
3889fa9e4066Sahrens 	 */
3890b1b8ab34Slling 	if (find_command_idx(cmdname, &i) == 0) {
3891fa9e4066Sahrens 		current_command = &command_table[i];
3892fa9e4066Sahrens 		ret = command_table[i].func(argc - 1, argv + 1);
389391ebeef5Sahrens 	} else if (strchr(cmdname, '=')) {
389491ebeef5Sahrens 		verify(find_command_idx("set", &i) == 0);
389591ebeef5Sahrens 		current_command = &command_table[i];
389691ebeef5Sahrens 		ret = command_table[i].func(argc, argv);
389791ebeef5Sahrens 	} else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3898fa9e4066Sahrens 		/*
389991ebeef5Sahrens 		 * 'freeze' is a vile debugging abomination, so we treat
390091ebeef5Sahrens 		 * it as such.
3901fa9e4066Sahrens 		 */
3902ea8dc4b6Seschrock 		char buf[16384];
3903ea8dc4b6Seschrock 		int fd = open(ZFS_DEV, O_RDWR);
3904fa9e4066Sahrens 		(void) strcpy((void *)buf, argv[2]);
3905fa9e4066Sahrens 		return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
390691ebeef5Sahrens 	} else {
3907fa9e4066Sahrens 		(void) fprintf(stderr, gettext("unrecognized "
3908fa9e4066Sahrens 		    "command '%s'\n"), cmdname);
390999653d4eSeschrock 		usage(B_FALSE);
3910fa9e4066Sahrens 	}
3911fa9e4066Sahrens 
391299653d4eSeschrock 	libzfs_fini(g_zfs);
391399653d4eSeschrock 
3914fa9e4066Sahrens 	/*
3915fa9e4066Sahrens 	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3916fa9e4066Sahrens 	 * for the purposes of running ::findleaks.
3917fa9e4066Sahrens 	 */
3918fa9e4066Sahrens 	if (getenv("ZFS_ABORT") != NULL) {
3919fa9e4066Sahrens 		(void) printf("dumping core by request\n");
3920fa9e4066Sahrens 		abort();
3921fa9e4066Sahrens 	}
3922fa9e4066Sahrens 
3923fa9e4066Sahrens 	return (ret);
3924fa9e4066Sahrens }
3925