zpool_main.c revision 332542
1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License (the "License").
6168404Spjd * You may not use this file except in compliance with the License.
7168404Spjd *
8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168404Spjd * or http://www.opensolaris.org/os/licensing.
10168404Spjd * See the License for the specific language governing permissions
11168404Spjd * and limitations under the License.
12168404Spjd *
13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168404Spjd * If applicable, add the following below this CDDL HEADER, with the
16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168404Spjd *
19168404Spjd * CDDL HEADER END
20168404Spjd */
21168404Spjd
22219089Spjd/*
23285202Savg * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24288549Smav * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25297112Smav * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26168404Spjd * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
27168404Spjd * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28168404Spjd * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
29168404Spjd * Copyright 2016 Nexenta Systems, Inc.
30168404Spjd * Copyright (c) 2017 Datto Inc.
31168404Spjd */
32168404Spjd
33168404Spjd#include <solaris.h>
34168404Spjd#include <assert.h>
35168404Spjd#include <ctype.h>
36168404Spjd#include <dirent.h>
37168404Spjd#include <errno.h>
38168404Spjd#include <fcntl.h>
39168404Spjd#include <libgen.h>
40265740Sdelphij#include <libintl.h>
41168404Spjd#include <libuutil.h>
42168404Spjd#include <locale.h>
43219089Spjd#include <stdio.h>
44219089Spjd#include <stdlib.h>
45219089Spjd#include <string.h>
46219089Spjd#include <strings.h>
47219089Spjd#include <unistd.h>
48219089Spjd#include <priv.h>
49219089Spjd#include <pwd.h>
50168404Spjd#include <zone.h>
51219089Spjd#include <sys/time.h>
52219089Spjd#include <zfs_prop.h>
53219089Spjd#include <sys/fs/zfs.h>
54219089Spjd#include <sys/stat.h>
55219089Spjd
56219089Spjd#include <libzfs.h>
57168404Spjd
58168404Spjd#include "zpool_util.h"
59168404Spjd#include "zfs_comutil.h"
60168404Spjd#include "zfeature_common.h"
61168404Spjd
62297077Smav#include "statcommon.h"
63219089Spjd
64219089Spjdstatic int zpool_do_create(int, char **);
65219089Spjdstatic int zpool_do_destroy(int, char **);
66269845Sdelphij
67269845Sdelphijstatic int zpool_do_add(int, char **);
68269845Sdelphijstatic int zpool_do_remove(int, char **);
69269845Sdelphijstatic int zpool_do_labelclear(int, char **);
70269845Sdelphij
71269845Sdelphijstatic int zpool_do_list(int, char **);
72269845Sdelphijstatic int zpool_do_iostat(int, char **);
73269845Sdelphijstatic int zpool_do_status(int, char **);
74270809Sdelphij
75270809Sdelphijstatic int zpool_do_online(int, char **);
76269845Sdelphijstatic int zpool_do_offline(int, char **);
77269845Sdelphijstatic int zpool_do_clear(int, char **);
78269845Sdelphijstatic int zpool_do_reopen(int, char **);
79269845Sdelphij
80269845Sdelphijstatic int zpool_do_reguid(int, char **);
81270809Sdelphij
82270809Sdelphijstatic int zpool_do_attach(int, char **);
83269845Sdelphijstatic int zpool_do_detach(int, char **);
84269845Sdelphijstatic int zpool_do_replace(int, char **);
85269845Sdelphijstatic int zpool_do_split(int, char **);
86277588Sdelphij
87277588Sdelphijstatic int zpool_do_scrub(int, char **);
88269845Sdelphij
89277588Sdelphijstatic int zpool_do_import(int, char **);
90277588Sdelphijstatic int zpool_do_export(int, char **);
91269845Sdelphij
92269845Sdelphijstatic int zpool_do_upgrade(int, char **);
93270809Sdelphij
94270809Sdelphijstatic int zpool_do_history(int, char **);
95270809Sdelphij
96270809Sdelphijstatic int zpool_do_get(int, char **);
97270809Sdelphijstatic int zpool_do_set(int, char **);
98270809Sdelphij
99270809Sdelphij/*
100270809Sdelphij * These libumem hooks provide a reasonable set of defaults for the allocator's
101269845Sdelphij * debugging facilities.
102269845Sdelphij */
103168404Spjd
104168404Spjd#ifdef DEBUG
105168404Spjdconst char *
106168404Spjd_umem_debug_init(void)
107219089Spjd{
108168404Spjd	return ("default,verbose"); /* $UMEM_DEBUG setting */
109168404Spjd}
110168404Spjd
111168404Spjdconst char *
112168404Spjd_umem_logging_init(void)
113208372Smm{
114208372Smm	return ("fail,contents"); /* $UMEM_LOGGING setting */
115248571Smm}
116248571Smm#endif
117248571Smm
118248571Smmtypedef enum {
119248571Smm	HELP_ADD,
120168404Spjd	HELP_ATTACH,
121219089Spjd	HELP_CLEAR,
122168404Spjd	HELP_CREATE,
123219089Spjd	HELP_DESTROY,
124219089Spjd	HELP_DETACH,
125219089Spjd	HELP_EXPORT,
126219089Spjd	HELP_HISTORY,
127219089Spjd	HELP_IMPORT,
128219089Spjd	HELP_IOSTAT,
129219089Spjd	HELP_LABELCLEAR,
130219089Spjd	HELP_LIST,
131168404Spjd	HELP_OFFLINE,
132219089Spjd	HELP_ONLINE,
133265740Sdelphij	HELP_REPLACE,
134168404Spjd	HELP_REMOVE,
135168404Spjd	HELP_SCRUB,
136168404Spjd	HELP_STATUS,
137168404Spjd	HELP_UPGRADE,
138168404Spjd	HELP_GET,
139219089Spjd	HELP_SET,
140219089Spjd	HELP_SPLIT,
141219089Spjd	HELP_REGUID,
142219089Spjd	HELP_REOPEN
143219089Spjd} zpool_help_t;
144219089Spjd
145219089Spjd
146219089Spjdtypedef struct zpool_command {
147219089Spjd	const char	*name;
148219089Spjd	int		(*func)(int, char **);
149219089Spjd	zpool_help_t	usage;
150219089Spjd} zpool_command_t;
151219089Spjd
152219089Spjd/*
153219089Spjd * Master command table.  Each ZFS command has a name, associated function, and
154219089Spjd * usage message.  The usage messages need to be internationalized, so we have
155219089Spjd * to have a function to return the usage message based on a command index.
156254753Sdelphij *
157269845Sdelphij * These commands are organized according to how they are displayed in the usage
158168404Spjd * message.  An empty command (one with a NULL name) indicates an empty line in
159168404Spjd * the generic usage message.
160219089Spjd */
161219089Spjdstatic zpool_command_t command_table[] = {
162168404Spjd	{ "create",	zpool_do_create,	HELP_CREATE		},
163168404Spjd	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
164168404Spjd	{ NULL },
165168404Spjd	{ "add",	zpool_do_add,		HELP_ADD		},
166168404Spjd	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
167168404Spjd	{ NULL },
168168404Spjd	{ "labelclear",	zpool_do_labelclear,	HELP_LABELCLEAR		},
169168404Spjd	{ NULL },
170168404Spjd	{ "list",	zpool_do_list,		HELP_LIST		},
171168404Spjd	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
172168404Spjd	{ "status",	zpool_do_status,	HELP_STATUS		},
173168404Spjd	{ NULL },
174168404Spjd	{ "online",	zpool_do_online,	HELP_ONLINE		},
175208372Smm	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
176168404Spjd	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
177168404Spjd	{ "reopen",	zpool_do_reopen,	HELP_REOPEN		},
178219089Spjd	{ NULL },
179168404Spjd	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
180168404Spjd	{ "detach",	zpool_do_detach,	HELP_DETACH		},
181219089Spjd	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
182265740Sdelphij	{ "split",	zpool_do_split,		HELP_SPLIT		},
183168404Spjd	{ NULL },
184240415Smm	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
185240415Smm	{ NULL },
186240415Smm	{ "import",	zpool_do_import,	HELP_IMPORT		},
187240415Smm	{ "export",	zpool_do_export,	HELP_EXPORT		},
188240415Smm	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
189240415Smm	{ "reguid",	zpool_do_reguid,	HELP_REGUID		},
190240415Smm	{ NULL },
191168404Spjd	{ "history",	zpool_do_history,	HELP_HISTORY		},
192168404Spjd	{ "get",	zpool_do_get,		HELP_GET		},
193240415Smm	{ "set",	zpool_do_set,		HELP_SET		},
194240415Smm};
195240415Smm
196240415Smm#define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
197219089Spjd
198219089Spjdstatic zpool_command_t *current_command;
199219089Spjdstatic char history_str[HIS_MAX_RECORD_LEN];
200219089Spjdstatic boolean_t log_history = B_TRUE;
201240415Smmstatic uint_t timestamp_fmt = NODATE;
202240415Smm
203240415Smmstatic const char *
204240415Smmget_usage(zpool_help_t idx)
205240415Smm{
206240415Smm	switch (idx) {
207240415Smm	case HELP_ADD:
208219089Spjd		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
209240415Smm	case HELP_ATTACH:
210254753Sdelphij		return (gettext("\tattach [-f] <pool> <device> "
211269845Sdelphij		    "<new-device>\n"));
212168404Spjd	case HELP_CLEAR:
213168404Spjd		return (gettext("\tclear [-nF] <pool> [device]\n"));
214168404Spjd	case HELP_CREATE:
215168404Spjd		return (gettext("\tcreate [-fnd] [-B] "
216168404Spjd		    "[-o property=value] ... \n"
217219089Spjd		    "\t    [-O file-system-property=value] ... \n"
218168404Spjd		    "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
219168404Spjd	case HELP_DESTROY:
220168404Spjd		return (gettext("\tdestroy [-f] <pool>\n"));
221219089Spjd	case HELP_DETACH:
222168404Spjd		return (gettext("\tdetach <pool> <device>\n"));
223168404Spjd	case HELP_EXPORT:
224168404Spjd		return (gettext("\texport [-f] <pool> ...\n"));
225168404Spjd	case HELP_HISTORY:
226168404Spjd		return (gettext("\thistory [-il] [<pool>] ...\n"));
227168404Spjd	case HELP_IMPORT:
228219089Spjd		return (gettext("\timport [-d dir] [-D]\n"
229168404Spjd		    "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
230168404Spjd		    "\timport [-o mntopts] [-o property=value] ... \n"
231168404Spjd		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
232168404Spjd		    "[-R root] [-F [-n]] -a\n"
233168404Spjd		    "\timport [-o mntopts] [-o property=value] ... \n"
234168404Spjd		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
235168404Spjd		    "[-R root] [-F [-n]]\n"
236168404Spjd		    "\t    <pool | id> [newpool]\n"));
237168404Spjd	case HELP_IOSTAT:
238168404Spjd		return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
239168404Spjd		    "[count]]\n"));
240219089Spjd	case HELP_LABELCLEAR:
241168404Spjd		return (gettext("\tlabelclear [-f] <vdev>\n"));
242236884Smm	case HELP_LIST:
243168404Spjd		return (gettext("\tlist [-Hpv] [-o property[,...]] "
244168404Spjd		    "[-T d|u] [pool] ... [interval [count]]\n"));
245168404Spjd	case HELP_OFFLINE:
246168404Spjd		return (gettext("\toffline [-t] <pool> <device> ...\n"));
247168404Spjd	case HELP_ONLINE:
248168404Spjd		return (gettext("\tonline [-e] <pool> <device> ...\n"));
249168404Spjd	case HELP_REPLACE:
250168404Spjd		return (gettext("\treplace [-f] <pool> <device> "
251168404Spjd		    "[new-device]\n"));
252168404Spjd	case HELP_REMOVE:
253168404Spjd		return (gettext("\tremove [-nps] <pool> <device> ...\n"));
254168404Spjd	case HELP_REOPEN:
255168404Spjd		return (gettext("\treopen <pool>\n"));
256168404Spjd	case HELP_SCRUB:
257168404Spjd		return (gettext("\tscrub [-s | -p] <pool> ...\n"));
258168404Spjd	case HELP_STATUS:
259168404Spjd		return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
260168404Spjd		    "[count]]\n"));
261236884Smm	case HELP_UPGRADE:
262168404Spjd		return (gettext("\tupgrade [-v]\n"
263168404Spjd		    "\tupgrade [-V version] <-a | pool ...>\n"));
264168404Spjd	case HELP_GET:
265168404Spjd		return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
266168404Spjd		    "<\"all\" | property[,...]> <pool> ...\n"));
267168404Spjd	case HELP_SET:
268168404Spjd		return (gettext("\tset <property=value> <pool> \n"));
269168404Spjd	case HELP_SPLIT:
270168404Spjd		return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
271168404Spjd		    "\t    [-o property=value] <pool> <newpool> "
272168404Spjd		    "[<device> ...]\n"));
273168404Spjd	case HELP_REGUID:
274168404Spjd		return (gettext("\treguid <pool>\n"));
275168404Spjd	}
276209962Smm
277168404Spjd	abort();
278168404Spjd	/* NOTREACHED */
279168404Spjd}
280168404Spjd
281168404Spjd
282168404Spjd/*
283168404Spjd * Callback routine that will print out a pool property value.
284168404Spjd */
285168404Spjdstatic int
286168404Spjdprint_prop_cb(int prop, void *cb)
287168404Spjd{
288168404Spjd	FILE *fp = cb;
289168404Spjd
290168404Spjd	(void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
291168404Spjd
292168404Spjd	if (zpool_prop_readonly(prop))
293168404Spjd		(void) fprintf(fp, "  NO   ");
294168404Spjd	else
295168404Spjd		(void) fprintf(fp, " YES   ");
296168404Spjd
297168404Spjd	if (zpool_prop_values(prop) == NULL)
298168404Spjd		(void) fprintf(fp, "-\n");
299168404Spjd	else
300168404Spjd		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
301168404Spjd
302168404Spjd	return (ZPROP_CONT);
303168404Spjd}
304168404Spjd
305168404Spjd/*
306168404Spjd * Display usage message.  If we're inside a command, display only the usage for
307168404Spjd * that command.  Otherwise, iterate over the entire command table and display
308168404Spjd * a complete usage message.
309168404Spjd */
310168404Spjdvoid
311168404Spjdusage(boolean_t requested)
312168404Spjd{
313168404Spjd	FILE *fp = requested ? stdout : stderr;
314168404Spjd
315168404Spjd	if (current_command == NULL) {
316168404Spjd		int i;
317168404Spjd
318168404Spjd		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
319168404Spjd		(void) fprintf(fp,
320168404Spjd		    gettext("where 'command' is one of the following:\n\n"));
321168404Spjd
322168404Spjd		for (i = 0; i < NCOMMAND; i++) {
323168404Spjd			if (command_table[i].name == NULL)
324168404Spjd				(void) fprintf(fp, "\n");
325168404Spjd			else
326168404Spjd				(void) fprintf(fp, "%s",
327236884Smm				    get_usage(command_table[i].usage));
328236884Smm		}
329236884Smm	} else {
330236884Smm		(void) fprintf(fp, gettext("usage:\n"));
331168404Spjd		(void) fprintf(fp, "%s", get_usage(current_command->usage));
332219089Spjd	}
333219089Spjd
334219089Spjd	if (current_command != NULL &&
335219089Spjd	    ((strcmp(current_command->name, "set") == 0) ||
336219089Spjd	    (strcmp(current_command->name, "get") == 0) ||
337168404Spjd	    (strcmp(current_command->name, "list") == 0))) {
338168404Spjd
339168404Spjd		(void) fprintf(fp,
340168404Spjd		    gettext("\nthe following properties are supported:\n"));
341168404Spjd
342168404Spjd		(void) fprintf(fp, "\n\t%-15s  %s   %s\n\n",
343168404Spjd		    "PROPERTY", "EDIT", "VALUES");
344168404Spjd
345168404Spjd		/* Iterate over all properties */
346168404Spjd		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
347168404Spjd		    ZFS_TYPE_POOL);
348168404Spjd
349168404Spjd		(void) fprintf(fp, "\t%-15s   ", "feature@...");
350168404Spjd		(void) fprintf(fp, "YES   disabled | enabled | active\n");
351168404Spjd
352168404Spjd		(void) fprintf(fp, gettext("\nThe feature@ properties must be "
353168404Spjd		    "appended with a feature name.\nSee zpool-features(7).\n"));
354168404Spjd	}
355185029Spjd
356185029Spjd	/*
357185029Spjd	 * See comments at end of main().
358185029Spjd	 */
359185029Spjd	if (getenv("ZFS_ABORT") != NULL) {
360185029Spjd		(void) printf("dumping core by request\n");
361185029Spjd		abort();
362185029Spjd	}
363185029Spjd
364185029Spjd	exit(requested ? 0 : 2);
365185029Spjd}
366185029Spjd
367185029Spjdvoid
368185029Spjdprint_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
369185029Spjd    boolean_t print_logs)
370185029Spjd{
371185029Spjd	nvlist_t **child;
372219089Spjd	uint_t c, children;
373219089Spjd	char *vname;
374219089Spjd
375219089Spjd	if (name != NULL)
376219089Spjd		(void) printf("\t%*s%s\n", indent, "", name);
377219089Spjd
378219089Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
379219089Spjd	    &child, &children) != 0)
380219089Spjd		return;
381219089Spjd
382219089Spjd	for (c = 0; c < children; c++) {
383219089Spjd		uint64_t is_log = B_FALSE;
384219089Spjd
385219089Spjd		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
386219089Spjd		    &is_log);
387219089Spjd		if ((is_log && !print_logs) || (!is_log && print_logs))
388219089Spjd			continue;
389219089Spjd
390219089Spjd		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
391219089Spjd		print_vdev_tree(zhp, vname, child[c], indent + 2,
392219089Spjd		    B_FALSE);
393168404Spjd		free(vname);
394168404Spjd	}
395168404Spjd}
396240415Smm
397168404Spjdstatic boolean_t
398168404Spjdprop_list_contains_feature(nvlist_t *proplist)
399168404Spjd{
400168404Spjd	nvpair_t *nvp;
401168404Spjd	for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
402168404Spjd	    nvp = nvlist_next_nvpair(proplist, nvp)) {
403265740Sdelphij		if (zpool_prop_feature(nvpair_name(nvp)))
404168404Spjd			return (B_TRUE);
405168404Spjd	}
406168404Spjd	return (B_FALSE);
407219089Spjd}
408219089Spjd
409168404Spjd/*
410288549Smav * Add a property pair (name, string-value) into a property nvlist.
411168404Spjd */
412288549Smavstatic int
413219089Spjdadd_prop_list(const char *propname, char *propval, nvlist_t **props,
414219089Spjd    boolean_t poolprop)
415219089Spjd{
416219089Spjd	zpool_prop_t prop = ZPROP_INVAL;
417219089Spjd	zfs_prop_t fprop;
418219089Spjd	nvlist_t *proplist;
419219089Spjd	const char *normnm;
420168404Spjd	char *strval;
421168404Spjd
422219089Spjd	if (*props == NULL &&
423168404Spjd	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
424168404Spjd		(void) fprintf(stderr,
425219089Spjd		    gettext("internal error: out of memory\n"));
426168404Spjd		return (1);
427219089Spjd	}
428219089Spjd
429219089Spjd	proplist = *props;
430219089Spjd
431219089Spjd	if (poolprop) {
432168404Spjd		const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
433168404Spjd
434168404Spjd		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
435168404Spjd		    !zpool_prop_feature(propname)) {
436168404Spjd			(void) fprintf(stderr, gettext("property '%s' is "
437168404Spjd			    "not a valid pool property\n"), propname);
438168404Spjd			return (2);
439168404Spjd		}
440168404Spjd
441219089Spjd		/*
442219089Spjd		 * feature@ properties and version should not be specified
443168404Spjd		 * at the same time.
444168404Spjd		 */
445168404Spjd		if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
446236884Smm		    nvlist_exists(proplist, vname)) ||
447219089Spjd		    (prop == ZPOOL_PROP_VERSION &&
448168404Spjd		    prop_list_contains_feature(proplist))) {
449288549Smav			(void) fprintf(stderr, gettext("'feature@' and "
450288549Smav			    "'version' properties cannot be specified "
451288549Smav			    "together\n"));
452288549Smav			return (2);
453288549Smav		}
454288549Smav
455288549Smav
456288549Smav		if (zpool_prop_feature(propname))
457288549Smav			normnm = propname;
458288549Smav		else
459288549Smav			normnm = zpool_prop_to_name(prop);
460288549Smav	} else {
461288549Smav		if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
462288549Smav			normnm = zfs_prop_to_name(fprop);
463288549Smav		} else {
464288549Smav			normnm = propname;
465219089Spjd		}
466288549Smav	}
467219089Spjd
468288549Smav	if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
469288549Smav	    prop != ZPOOL_PROP_CACHEFILE) {
470219089Spjd		(void) fprintf(stderr, gettext("property '%s' "
471219089Spjd		    "specified multiple times\n"), propname);
472288549Smav		return (2);
473288549Smav	}
474168404Spjd
475168404Spjd	if (nvlist_add_string(proplist, normnm, propval) != 0) {
476208373Smm		(void) fprintf(stderr, gettext("internal "
477168404Spjd		    "error: out of memory\n"));
478168404Spjd		return (1);
479168404Spjd	}
480219089Spjd
481219089Spjd	return (0);
482219089Spjd}
483168404Spjd
484168404Spjd/*
485168404Spjd * zpool add [-fn] <pool> <vdev> ...
486219089Spjd *
487288549Smav *	-f	Force addition of devices, even if they appear in use
488168404Spjd *	-n	Do not add the devices, but display the resulting layout if
489219089Spjd *		they were to be added.
490168404Spjd *
491168404Spjd * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
492219089Spjd * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
493288549Smav * libzfs.
494288549Smav */
495288549Smavint
496288549Smavzpool_do_add(int argc, char **argv)
497288549Smav{
498288549Smav	boolean_t force = B_FALSE;
499168404Spjd	boolean_t dryrun = B_FALSE;
500168404Spjd	int c;
501219089Spjd	nvlist_t *nvroot;
502219089Spjd	char *poolname;
503219089Spjd	zpool_boot_label_t boot_type;
504219089Spjd	uint64_t boot_size;
505219089Spjd	int ret;
506219089Spjd	zpool_handle_t *zhp;
507219089Spjd	nvlist_t *config;
508219089Spjd
509219089Spjd	/* check options */
510168404Spjd	while ((c = getopt(argc, argv, "fn")) != -1) {
511168404Spjd		switch (c) {
512168404Spjd		case 'f':
513219089Spjd			force = B_TRUE;
514168404Spjd			break;
515307266Smav		case 'n':
516168404Spjd			dryrun = B_TRUE;
517168404Spjd			break;
518219089Spjd		case '?':
519219089Spjd			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
520219089Spjd			    optopt);
521219089Spjd			usage(B_FALSE);
522219089Spjd		}
523219089Spjd	}
524219089Spjd
525219089Spjd	argc -= optind;
526219089Spjd	argv += optind;
527219089Spjd
528254753Sdelphij	/* get pool name and check number of arguments */
529219089Spjd	if (argc < 1) {
530288594Smav		(void) fprintf(stderr, gettext("missing pool name argument\n"));
531168404Spjd		usage(B_FALSE);
532208373Smm	}
533288549Smav	if (argc < 2) {
534288549Smav		(void) fprintf(stderr, gettext("missing vdev specification\n"));
535288549Smav		usage(B_FALSE);
536168404Spjd	}
537168404Spjd
538168404Spjd	poolname = argv[0];
539168404Spjd
540168404Spjd	argc--;
541168404Spjd	argv++;
542168404Spjd
543168404Spjd	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
544276081Sdelphij		return (1);
545276081Sdelphij
546168404Spjd	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
547168404Spjd		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
548168404Spjd		    poolname);
549168404Spjd		zpool_close(zhp);
550168404Spjd		return (1);
551168404Spjd	}
552168404Spjd
553168404Spjd	if (zpool_is_bootable(zhp))
554168404Spjd		boot_type = ZPOOL_COPY_BOOT_LABEL;
555168404Spjd	else
556168404Spjd		boot_type = ZPOOL_NO_BOOT_LABEL;
557168404Spjd
558168404Spjd	/* pass off to get_vdev_spec for processing */
559168404Spjd	boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
560168404Spjd	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
561168404Spjd	    boot_type, boot_size, argc, argv);
562168404Spjd	if (nvroot == NULL) {
563236884Smm		zpool_close(zhp);
564168404Spjd		return (1);
565219089Spjd	}
566168404Spjd
567236884Smm	if (dryrun) {
568168404Spjd		nvlist_t *poolnvroot;
569168404Spjd
570240415Smm		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
571240415Smm		    &poolnvroot) == 0);
572240415Smm
573168404Spjd		(void) printf(gettext("would update '%s' to the following "
574168404Spjd		    "configuration:\n"), zpool_get_name(zhp));
575269845Sdelphij
576168404Spjd		/* print original main pool and new tree */
577168404Spjd		print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
578240415Smm		print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
579240415Smm
580240415Smm		/* Do the same for the logs */
581240415Smm		if (num_logs(poolnvroot) > 0) {
582240415Smm			print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
583240415Smm			print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
584240415Smm		} else if (num_logs(nvroot) > 0) {
585168404Spjd			print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
586168404Spjd		}
587265740Sdelphij
588168404Spjd		ret = 0;
589168404Spjd	} else {
590168404Spjd		ret = (zpool_add(zhp, nvroot) != 0);
591168404Spjd	}
592168404Spjd
593168404Spjd	nvlist_free(nvroot);
594219089Spjd	zpool_close(zhp);
595219089Spjd
596219089Spjd	return (ret);
597219089Spjd}
598219089Spjd
599168404Spjd/*
600168404Spjd * zpool remove  <pool> <vdev> ...
601168404Spjd *
602168404Spjd * Removes the given vdev from the pool.
603168404Spjd */
604168404Spjdint
605168404Spjdzpool_do_remove(int argc, char **argv)
606168404Spjd{
607168404Spjd	char *poolname;
608168404Spjd	int i, ret = 0;
609168404Spjd	zpool_handle_t *zhp;
610168404Spjd	boolean_t stop = B_FALSE;
611168404Spjd	boolean_t noop = B_FALSE;
612219089Spjd	boolean_t parsable = B_FALSE;
613168404Spjd	char c;
614168404Spjd
615168404Spjd	/* check options */
616185029Spjd	while ((c = getopt(argc, argv, "nps")) != -1) {
617219089Spjd		switch (c) {
618168404Spjd		case 'n':
619168404Spjd			noop = B_TRUE;
620168404Spjd			break;
621168404Spjd		case 'p':
622168404Spjd			parsable = B_TRUE;
623168404Spjd			break;
624168404Spjd		case 's':
625200726Sdelphij			stop = B_TRUE;
626168404Spjd			break;
627168404Spjd		case '?':
628276081Sdelphij			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
629276081Sdelphij			    optopt);
630240415Smm			usage(B_FALSE);
631168404Spjd		}
632168404Spjd	}
633168404Spjd
634219089Spjd	argc -= optind;
635219089Spjd	argv += optind;
636236884Smm
637168404Spjd	/* get pool name and check number of arguments */
638168404Spjd	if (argc < 1) {
639168404Spjd		(void) fprintf(stderr, gettext("missing pool name argument\n"));
640185029Spjd		usage(B_FALSE);
641168404Spjd	}
642219089Spjd
643219089Spjd	poolname = argv[0];
644200726Sdelphij
645200726Sdelphij	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
646200726Sdelphij		return (1);
647200726Sdelphij
648200726Sdelphij	if (stop && noop) {
649200726Sdelphij		(void) fprintf(stderr, gettext("stop request ignored\n"));
650200726Sdelphij		return (0);
651200726Sdelphij	}
652200726Sdelphij
653168404Spjd	if (stop) {
654200726Sdelphij		if (argc > 1) {
655200726Sdelphij			(void) fprintf(stderr, gettext("too many arguments\n"));
656219089Spjd			usage(B_FALSE);
657219089Spjd		}
658219089Spjd		if (zpool_vdev_remove_cancel(zhp) != 0)
659219089Spjd			ret = 1;
660219089Spjd	} else {
661219089Spjd		if (argc < 2) {
662219089Spjd			(void) fprintf(stderr, gettext("missing device\n"));
663196703Spjd			usage(B_FALSE);
664196703Spjd		}
665219089Spjd
666219089Spjd		for (i = 1; i < argc; i++) {
667219089Spjd			if (noop) {
668219089Spjd				uint64_t size;
669168404Spjd
670168404Spjd				if (zpool_vdev_indirect_size(zhp, argv[i],
671168404Spjd				    &size) != 0) {
672168404Spjd					ret = 1;
673168404Spjd					break;
674168404Spjd				}
675168404Spjd				if (parsable) {
676168404Spjd					(void) printf("%s %llu\n",
677168404Spjd					    argv[i], size);
678196703Spjd				} else {
679168404Spjd					char valstr[32];
680168404Spjd					zfs_nicenum(size, valstr,
681168404Spjd					    sizeof (valstr));
682168404Spjd					(void) printf("Memory that will be "
683196703Spjd					    "used after removing %s: %s\n",
684196703Spjd					    argv[i], valstr);
685185029Spjd				}
686185029Spjd			} else {
687185029Spjd				if (zpool_vdev_remove(zhp, argv[i]) != 0)
688185029Spjd					ret = 1;
689185029Spjd			}
690168404Spjd		}
691168404Spjd	}
692168404Spjd
693168404Spjd	return (ret);
694219089Spjd}
695219089Spjd
696219089Spjd/*
697219089Spjd * zpool labelclear [-f] <vdev>
698219089Spjd *
699219089Spjd *	-f	Force clearing the label for the vdevs which are members of
700219089Spjd *		the exported or foreign pools.
701219089Spjd *
702219089Spjd * Verifies that the vdev is not active and zeros out the label information
703219089Spjd * on the device.
704219089Spjd */
705219089Spjdint
706219089Spjdzpool_do_labelclear(int argc, char **argv)
707219089Spjd{
708219089Spjd	char vdev[MAXPATHLEN];
709219089Spjd	char *name = NULL;
710219089Spjd	struct stat st;
711219089Spjd	int c, fd, ret = 0;
712219089Spjd	nvlist_t *config;
713219089Spjd	pool_state_t state;
714219089Spjd	boolean_t inuse = B_FALSE;
715219089Spjd	boolean_t force = B_FALSE;
716219089Spjd
717219089Spjd	/* check options */
718219089Spjd	while ((c = getopt(argc, argv, "f")) != -1) {
719219089Spjd		switch (c) {
720219089Spjd		case 'f':
721219089Spjd			force = B_TRUE;
722219089Spjd			break;
723219089Spjd		default:
724219089Spjd			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
725219089Spjd			    optopt);
726219089Spjd			usage(B_FALSE);
727219089Spjd		}
728219089Spjd	}
729219089Spjd
730219089Spjd	argc -= optind;
731219089Spjd	argv += optind;
732219089Spjd
733219089Spjd	/* get vdev name */
734219089Spjd	if (argc < 1) {
735219089Spjd		(void) fprintf(stderr, gettext("missing vdev name\n"));
736219089Spjd		usage(B_FALSE);
737219089Spjd	}
738219089Spjd	if (argc > 1) {
739219089Spjd		(void) fprintf(stderr, gettext("too many arguments\n"));
740219089Spjd		usage(B_FALSE);
741219089Spjd	}
742219089Spjd
743219089Spjd	/*
744219089Spjd	 * Check if we were given absolute path and use it as is.
745219089Spjd	 * Otherwise if the provided vdev name doesn't point to a file,
746219089Spjd	 * try prepending dsk path and appending s0.
747219089Spjd	 */
748219089Spjd	(void) strlcpy(vdev, argv[0], sizeof (vdev));
749219089Spjd	if (vdev[0] != '/' && stat(vdev, &st) != 0) {
750219089Spjd		char *s;
751219089Spjd
752265740Sdelphij		(void) snprintf(vdev, sizeof (vdev), "%s/%s",
753265740Sdelphij#ifdef illumos
754219089Spjd		    ZFS_DISK_ROOT, argv[0]);
755219089Spjd		if ((s = strrchr(argv[0], 's')) == NULL ||
756219089Spjd		    !isdigit(*(s + 1)))
757219089Spjd			(void) strlcat(vdev, "s0", sizeof (vdev));
758219089Spjd#else
759219089Spjd		    "/dev", argv[0]);
760219089Spjd#endif
761269845Sdelphij		if (stat(vdev, &st) != 0) {
762269845Sdelphij			(void) fprintf(stderr, gettext(
763219089Spjd			    "failed to find device %s, try specifying absolute "
764254753Sdelphij			    "path instead\n"), argv[0]);
765219089Spjd			return (1);
766219089Spjd		}
767219089Spjd	}
768219089Spjd
769219089Spjd	if ((fd = open(vdev, O_RDWR)) < 0) {
770219089Spjd		(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
771219089Spjd		    vdev, strerror(errno));
772219089Spjd		return (1);
773219089Spjd	}
774219089Spjd
775219089Spjd	if (zpool_read_label(fd, &config) != 0) {
776219089Spjd		(void) fprintf(stderr,
777219089Spjd		    gettext("failed to read label from %s\n"), vdev);
778219089Spjd		return (1);
779219089Spjd	}
780219089Spjd	nvlist_free(config);
781219089Spjd
782219089Spjd	ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
783219089Spjd	if (ret != 0) {
784219089Spjd		(void) fprintf(stderr,
785219089Spjd		    gettext("failed to check state for %s\n"), vdev);
786219089Spjd		return (1);
787219089Spjd	}
788219089Spjd
789219089Spjd	if (!inuse)
790219089Spjd		goto wipe_label;
791219089Spjd
792219089Spjd	switch (state) {
793219089Spjd	default:
794269845Sdelphij	case POOL_STATE_ACTIVE:
795219089Spjd	case POOL_STATE_SPARE:
796219089Spjd	case POOL_STATE_L2CACHE:
797254753Sdelphij		(void) fprintf(stderr, gettext(
798219089Spjd		    "%s is a member (%s) of pool \"%s\"\n"),
799219089Spjd		    vdev, zpool_pool_state_to_name(state), name);
800219089Spjd		ret = 1;
801219089Spjd		goto errout;
802219089Spjd
803219089Spjd	case POOL_STATE_EXPORTED:
804219089Spjd		if (force)
805219089Spjd			break;
806219089Spjd		(void) fprintf(stderr, gettext(
807219089Spjd		    "use '-f' to override the following error:\n"
808219089Spjd		    "%s is a member of exported pool \"%s\"\n"),
809219089Spjd		    vdev, name);
810219089Spjd		ret = 1;
811219089Spjd		goto errout;
812219089Spjd
813219089Spjd	case POOL_STATE_POTENTIALLY_ACTIVE:
814265740Sdelphij		if (force)
815219089Spjd			break;
816219089Spjd		(void) fprintf(stderr, gettext(
817219089Spjd		    "use '-f' to override the following error:\n"
818219089Spjd		    "%s is a member of potentially active pool \"%s\"\n"),
819219089Spjd		    vdev, name);
820219089Spjd		ret = 1;
821219089Spjd		goto errout;
822219089Spjd
823219089Spjd	case POOL_STATE_DESTROYED:
824219089Spjd		/* inuse should never be set for a destroyed pool */
825219089Spjd		assert(0);
826219089Spjd		break;
827219089Spjd	}
828219089Spjd
829219089Spjdwipe_label:
830219089Spjd	ret = zpool_clear_label(fd);
831219089Spjd	if (ret != 0) {
832219089Spjd		(void) fprintf(stderr,
833219089Spjd		    gettext("failed to clear label for %s\n"), vdev);
834219089Spjd	}
835219089Spjd
836219089Spjderrout:
837219089Spjd	free(name);
838219089Spjd	(void) close(fd);
839219089Spjd
840219089Spjd	return (ret);
841219089Spjd}
842219089Spjd
843219089Spjd/*
844297077Smav * zpool create [-fnd] [-B] [-o property=value] ...
845219089Spjd *		[-O file-system-property=value] ...
846219089Spjd *		[-R root] [-m mountpoint] <pool> <dev> ...
847219089Spjd *
848219089Spjd *	-B	Create boot partition.
849219089Spjd *	-f	Force creation, even if devices appear in use
850219089Spjd *	-n	Do not create the pool, but display the resulting layout if it
851219089Spjd *		were to be created.
852219089Spjd *      -R	Create a pool under an alternate root
853219089Spjd *      -m	Set default mountpoint for the root dataset.  By default it's
854219089Spjd *		'/<pool>'
855219089Spjd *	-o	Set property=value.
856219089Spjd *	-d	Don't automatically enable all supported pool features
857219089Spjd *		(individual features can be enabled with -o).
858219089Spjd *	-O	Set fsproperty=value in the pool's root file system
859219089Spjd *
860219089Spjd * Creates the named pool according to the given vdev specification.  The
861219089Spjd * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
862219089Spjd * we get the nvlist back from get_vdev_spec(), we either print out the contents
863219089Spjd * (if '-n' was specified), or pass it to libzfs to do the creation.
864219089Spjd */
865219089Spjd
866219089Spjd#define	SYSTEM256	(256 * 1024 * 1024)
867219089Spjdint
868219089Spjdzpool_do_create(int argc, char **argv)
869219089Spjd{
870219089Spjd	boolean_t force = B_FALSE;
871219089Spjd	boolean_t dryrun = B_FALSE;
872219089Spjd	boolean_t enable_all_pool_feat = B_TRUE;
873219089Spjd	zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
874219089Spjd	uint64_t boot_size = 0;
875219089Spjd	int c;
876219089Spjd	nvlist_t *nvroot = NULL;
877219089Spjd	char *poolname;
878219089Spjd	int ret = 1;
879219089Spjd	char *altroot = NULL;
880219089Spjd	char *mountpoint = NULL;
881219089Spjd	nvlist_t *fsprops = NULL;
882219089Spjd	nvlist_t *props = NULL;
883219089Spjd	char *propval;
884219089Spjd
885219089Spjd	/* check options */
886219089Spjd	while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) {
887219089Spjd		switch (c) {
888219089Spjd		case 'f':
889219089Spjd			force = B_TRUE;
890219089Spjd			break;
891219089Spjd		case 'n':
892219089Spjd			dryrun = B_TRUE;
893219089Spjd			break;
894219089Spjd		case 'd':
895219089Spjd			enable_all_pool_feat = B_FALSE;
896219089Spjd			break;
897219089Spjd		case 'B':
898219089Spjd#ifdef illumos
899219089Spjd			/*
900219089Spjd			 * We should create the system partition.
901219089Spjd			 * Also make sure the size is set.
902219089Spjd			 */
903219089Spjd			boot_type = ZPOOL_CREATE_BOOT_LABEL;
904219089Spjd			if (boot_size == 0)
905219089Spjd				boot_size = SYSTEM256;
906219089Spjd			break;
907219089Spjd#else
908219089Spjd			(void) fprintf(stderr,
909219089Spjd			    gettext("option '%c' is not supported\n"),
910219089Spjd			    optopt);
911219089Spjd			goto badusage;
912219089Spjd#endif
913219089Spjd		case 'R':
914219089Spjd			altroot = optarg;
915219089Spjd			if (add_prop_list(zpool_prop_to_name(
916219089Spjd			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
917219089Spjd				goto errout;
918219089Spjd			if (nvlist_lookup_string(props,
919219089Spjd			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
920219089Spjd			    &propval) == 0)
921219089Spjd				break;
922219089Spjd			if (add_prop_list(zpool_prop_to_name(
923219089Spjd			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
924219089Spjd				goto errout;
925219089Spjd			break;
926219089Spjd		case 'm':
927219089Spjd			/* Equivalent to -O mountpoint=optarg */
928219089Spjd			mountpoint = optarg;
929219089Spjd			break;
930219089Spjd		case 'o':
931219089Spjd			if ((propval = strchr(optarg, '=')) == NULL) {
932219089Spjd				(void) fprintf(stderr, gettext("missing "
933219089Spjd				    "'=' for -o option\n"));
934219089Spjd				goto errout;
935219089Spjd			}
936219089Spjd			*propval = '\0';
937219089Spjd			propval++;
938219089Spjd
939219089Spjd			if (add_prop_list(optarg, propval, &props, B_TRUE))
940219089Spjd				goto errout;
941219089Spjd
942219089Spjd			/*
943219089Spjd			 * Get bootsize value for make_root_vdev().
944219089Spjd			 */
945219089Spjd			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
946219089Spjd				if (zfs_nicestrtonum(g_zfs, propval,
947219089Spjd				    &boot_size) < 0 || boot_size == 0) {
948219089Spjd					(void) fprintf(stderr,
949219089Spjd					    gettext("bad boot partition size "
950219089Spjd					    "'%s': %s\n"),  propval,
951219089Spjd					    libzfs_error_description(g_zfs));
952219089Spjd					goto errout;
953219089Spjd				}
954219089Spjd			}
955219089Spjd
956219089Spjd			/*
957219089Spjd			 * If the user is creating a pool that doesn't support
958219089Spjd			 * feature flags, don't enable any features.
959219089Spjd			 */
960219089Spjd			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
961219089Spjd				char *end;
962219089Spjd				u_longlong_t ver;
963219089Spjd
964219089Spjd				ver = strtoull(propval, &end, 10);
965219089Spjd				if (*end == '\0' &&
966219089Spjd				    ver < SPA_VERSION_FEATURES) {
967219089Spjd					enable_all_pool_feat = B_FALSE;
968219089Spjd				}
969219089Spjd			}
970219089Spjd			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
971219089Spjd				altroot = propval;
972219089Spjd			break;
973219089Spjd		case 'O':
974219089Spjd			if ((propval = strchr(optarg, '=')) == NULL) {
975219089Spjd				(void) fprintf(stderr, gettext("missing "
976219089Spjd				    "'=' for -O option\n"));
977219089Spjd				goto errout;
978219089Spjd			}
979219089Spjd			*propval = '\0';
980219089Spjd			propval++;
981219089Spjd
982219089Spjd			/*
983219089Spjd			 * Mountpoints are checked and then added later.
984219089Spjd			 * Uniquely among properties, they can be specified
985219089Spjd			 * more than once, to avoid conflict with -m.
986219089Spjd			 */
987297077Smav			if (0 == strcmp(optarg,
988219089Spjd			    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
989168404Spjd				mountpoint = propval;
990219089Spjd			} else if (add_prop_list(optarg, propval, &fsprops,
991168404Spjd			    B_FALSE)) {
992219089Spjd				goto errout;
993219089Spjd			}
994168404Spjd			break;
995168404Spjd		case ':':
996168404Spjd			(void) fprintf(stderr, gettext("missing argument for "
997168404Spjd			    "'%c' option\n"), optopt);
998168404Spjd			goto badusage;
999168404Spjd		case '?':
1000168404Spjd			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1001168404Spjd			    optopt);
1002288549Smav			goto badusage;
1003288549Smav		}
1004219089Spjd	}
1005219089Spjd
1006219089Spjd	argc -= optind;
1007219089Spjd	argv += optind;
1008168404Spjd
1009168404Spjd	/* get pool name and check number of arguments */
1010288549Smav	if (argc < 1) {
1011219089Spjd		(void) fprintf(stderr, gettext("missing pool name argument\n"));
1012219089Spjd		goto badusage;
1013168404Spjd	}
1014288549Smav	if (argc < 2) {
1015288549Smav		(void) fprintf(stderr, gettext("missing vdev specification\n"));
1016288549Smav		goto badusage;
1017219089Spjd	}
1018168404Spjd
1019168404Spjd	poolname = argv[0];
1020168404Spjd
1021168404Spjd	/*
1022288549Smav	 * As a special case, check for use of '/' in the name, and direct the
1023168404Spjd	 * user to use 'zfs create' instead.
1024288549Smav	 */
1025168404Spjd	if (strchr(poolname, '/') != NULL) {
1026168404Spjd		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
1027288549Smav		    "character '/' in pool name\n"), poolname);
1028219089Spjd		(void) fprintf(stderr, gettext("use 'zfs create' to "
1029219089Spjd		    "create a dataset\n"));
1030168404Spjd		goto errout;
1031219089Spjd	}
1032219089Spjd
1033219089Spjd	/*
1034219089Spjd	 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1035219089Spjd	 * and not set otherwise.
1036219089Spjd	 */
1037219089Spjd	if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1038168404Spjd		const char *propname;
1039219089Spjd		char *strptr, *buf = NULL;
1040219089Spjd		int rv;
1041219089Spjd
1042219089Spjd		propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1043168404Spjd		if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1044168404Spjd			(void) asprintf(&buf, "%" PRIu64, boot_size);
1045168404Spjd			if (buf == NULL) {
1046219089Spjd				(void) fprintf(stderr,
1047168404Spjd				    gettext("internal error: out of memory\n"));
1048168404Spjd				goto errout;
1049168404Spjd			}
1050168404Spjd			rv = add_prop_list(propname, buf, &props, B_TRUE);
1051168404Spjd			free(buf);
1052219089Spjd			if (rv != 0)
1053219089Spjd				goto errout;
1054219089Spjd		}
1055168404Spjd	} else {
1056219089Spjd		const char *propname;
1057288549Smav		char *strptr;
1058168404Spjd
1059168404Spjd		propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1060168404Spjd		if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1061168404Spjd			(void) fprintf(stderr, gettext("error: setting boot "
1062168404Spjd			    "partition size requires option '-B'\n"));
1063168404Spjd			goto errout;
1064168404Spjd		}
1065168404Spjd	}
1066168404Spjd
1067219089Spjd	/* pass off to get_vdev_spec for bulk processing */
1068168404Spjd	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1069168404Spjd	    boot_type, boot_size, argc - 1, argv + 1);
1070168404Spjd	if (nvroot == NULL)
1071168404Spjd		goto errout;
1072168404Spjd
1073168404Spjd	/* make_root_vdev() allows 0 toplevel children if there are spares */
1074168404Spjd	if (!zfs_allocatable_devs(nvroot)) {
1075168404Spjd		(void) fprintf(stderr, gettext("invalid vdev "
1076219089Spjd		    "specification: at least one toplevel vdev must be "
1077219089Spjd		    "specified\n"));
1078168404Spjd		goto errout;
1079185029Spjd	}
1080185029Spjd
1081219089Spjd	if (altroot != NULL && altroot[0] != '/') {
1082219089Spjd		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
1083219089Spjd		    "must be an absolute path\n"), altroot);
1084185029Spjd		goto errout;
1085219089Spjd	}
1086219089Spjd
1087219089Spjd	/*
1088185029Spjd	 * Check the validity of the mountpoint and direct the user to use the
1089209962Smm	 * '-m' mountpoint option if it looks like its in use.
1090209962Smm	 * Ignore the checks if the '-f' option is given.
1091219089Spjd	 */
1092209962Smm	if (!force && (mountpoint == NULL ||
1093249195Smm	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1094209962Smm	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) {
1095209962Smm		char buf[MAXPATHLEN];
1096249195Smm		DIR *dirp;
1097209962Smm
1098249195Smm		if (mountpoint && mountpoint[0] != '/') {
1099209962Smm			(void) fprintf(stderr, gettext("invalid mountpoint "
1100209962Smm			    "'%s': must be an absolute path, 'legacy', or "
1101209962Smm			    "'none'\n"), mountpoint);
1102209962Smm			goto errout;
1103209962Smm		}
1104209962Smm
1105168404Spjd		if (mountpoint == NULL) {
1106249195Smm			if (altroot != NULL)
1107168404Spjd				(void) snprintf(buf, sizeof (buf), "%s/%s",
1108219089Spjd				    altroot, poolname);
1109219089Spjd			else
1110168404Spjd				(void) snprintf(buf, sizeof (buf), "/%s",
1111168404Spjd				    poolname);
1112168404Spjd		} else {
1113168404Spjd			if (altroot != NULL)
1114168404Spjd				(void) snprintf(buf, sizeof (buf), "%s%s",
1115168404Spjd				    altroot, mountpoint);
1116168404Spjd			else
1117168404Spjd				(void) snprintf(buf, sizeof (buf), "%s",
1118288571Smav				    mountpoint);
1119168404Spjd		}
1120168404Spjd
1121168404Spjd		if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1122168404Spjd			(void) fprintf(stderr, gettext("mountpoint '%s' : "
1123168404Spjd			    "%s\n"), buf, strerror(errno));
1124249195Smm			(void) fprintf(stderr, gettext("use '-m' "
1125168404Spjd			    "option to provide a different default\n"));
1126168404Spjd			goto errout;
1127168404Spjd		} else if (dirp) {
1128168404Spjd			int count = 0;
1129168404Spjd
1130168404Spjd			while (count < 3 && readdir(dirp) != NULL)
1131168404Spjd				count++;
1132168404Spjd			(void) closedir(dirp);
1133168404Spjd
1134168404Spjd			if (count > 2) {
1135168404Spjd				(void) fprintf(stderr, gettext("mountpoint "
1136219089Spjd				    "'%s' exists and is not empty\n"), buf);
1137168404Spjd				(void) fprintf(stderr, gettext("use '-m' "
1138168404Spjd				    "option to provide a "
1139219089Spjd				    "different default\n"));
1140219089Spjd				goto errout;
1141230256Spluknet			}
1142270127Sdelphij		}
1143219089Spjd	}
1144219089Spjd
1145219089Spjd	/*
1146219089Spjd	 * Now that the mountpoint's validity has been checked, ensure that
1147219089Spjd	 * the property is set appropriately prior to creating the pool.
1148288549Smav	 */
1149288549Smav	if (mountpoint != NULL) {
1150288549Smav		ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1151288549Smav		    mountpoint, &fsprops, B_FALSE);
1152269218Sdelphij		if (ret != 0)
1153269218Sdelphij			goto errout;
1154269218Sdelphij	}
1155269218Sdelphij
1156269218Sdelphij	ret = 1;
1157219089Spjd	if (dryrun) {
1158270127Sdelphij		/*
1159168404Spjd		 * For a dry run invocation, print out a basic message and run
1160168404Spjd		 * through all the vdevs in the list and print out in an
1161168404Spjd		 * appropriate hierarchy.
1162219089Spjd		 */
1163168404Spjd		(void) printf(gettext("would create '%s' with the "
1164219089Spjd		    "following layout:\n\n"), poolname);
1165219089Spjd
1166288549Smav		print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1167288549Smav		if (num_logs(nvroot) > 0)
1168219089Spjd			print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1169185029Spjd
1170219089Spjd		ret = 0;
1171168404Spjd	} else {
1172168404Spjd		/*
1173168404Spjd		 * Hand off to libzfs.
1174168404Spjd		 */
1175168404Spjd		if (enable_all_pool_feat) {
1176168404Spjd			spa_feature_t i;
1177209962Smm			for (i = 0; i < SPA_FEATURES; i++) {
1178219089Spjd				char propname[MAXPATHLEN];
1179168404Spjd				zfeature_info_t *feat = &spa_feature_table[i];
1180219089Spjd
1181168404Spjd				(void) snprintf(propname, sizeof (propname),
1182168404Spjd				    "feature@%s", feat->fi_uname);
1183168404Spjd
1184288549Smav				/*
1185288549Smav				 * Skip feature if user specified it manually
1186168404Spjd				 * on the command line.
1187168404Spjd				 */
1188219089Spjd				if (nvlist_exists(props, propname))
1189219089Spjd					continue;
1190168404Spjd
1191168404Spjd				ret = add_prop_list(propname,
1192168404Spjd				    ZFS_FEATURE_ENABLED, &props, B_TRUE);
1193168404Spjd				if (ret != 0)
1194168404Spjd					goto errout;
1195168404Spjd			}
1196168404Spjd		}
1197168404Spjd
1198168404Spjd		ret = 1;
1199168404Spjd		if (zpool_create(g_zfs, poolname,
1200168404Spjd		    nvroot, props, fsprops) == 0) {
1201168404Spjd			zfs_handle_t *pool = zfs_open(g_zfs, poolname,
1202168404Spjd			    ZFS_TYPE_FILESYSTEM);
1203168404Spjd			if (pool != NULL) {
1204219089Spjd				if (zfs_mount(pool, NULL, 0) == 0)
1205168404Spjd					ret = zfs_shareall(pool);
1206168404Spjd				zfs_close(pool);
1207168404Spjd			}
1208168404Spjd		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1209185029Spjd			(void) fprintf(stderr, gettext("pool name may have "
1210185029Spjd			    "been omitted\n"));
1211185029Spjd		}
1212185029Spjd	}
1213185029Spjd
1214185029Spjderrout:
1215168404Spjd	nvlist_free(nvroot);
1216168404Spjd	nvlist_free(fsprops);
1217185029Spjd	nvlist_free(props);
1218185029Spjd	return (ret);
1219185029Spjdbadusage:
1220185029Spjd	nvlist_free(fsprops);
1221185029Spjd	nvlist_free(props);
1222185029Spjd	usage(B_FALSE);
1223185029Spjd	return (2);
1224185029Spjd}
1225168404Spjd
1226168404Spjd/*
1227168404Spjd * zpool destroy <pool>
1228168404Spjd *
1229168404Spjd * 	-f	Forcefully unmount any datasets
1230288541Smav *
1231288541Smav * Destroy the given pool.  Automatically unmounts any datasets in the pool.
1232288541Smav */
1233288541Smavint
1234288541Smavzpool_do_destroy(int argc, char **argv)
1235288541Smav{
1236288541Smav	boolean_t force = B_FALSE;
1237168404Spjd	int c;
1238219089Spjd	char *pool;
1239219089Spjd	zpool_handle_t *zhp;
1240219089Spjd	int ret;
1241168404Spjd
1242168404Spjd	/* check options */
1243185029Spjd	while ((c = getopt(argc, argv, "f")) != -1) {
1244219089Spjd		switch (c) {
1245219089Spjd		case 'f':
1246219089Spjd			force = B_TRUE;
1247219089Spjd			break;
1248219089Spjd		case '?':
1249219089Spjd			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1250219089Spjd			    optopt);
1251219089Spjd			usage(B_FALSE);
1252219089Spjd		}
1253219089Spjd	}
1254219089Spjd
1255219089Spjd	argc -= optind;
1256168404Spjd	argv += optind;
1257219089Spjd
1258219089Spjd	/* check arguments */
1259219089Spjd	if (argc < 1) {
1260219089Spjd		(void) fprintf(stderr, gettext("missing pool argument\n"));
1261219089Spjd		usage(B_FALSE);
1262219089Spjd	}
1263219089Spjd	if (argc > 1) {
1264219089Spjd		(void) fprintf(stderr, gettext("too many arguments\n"));
1265219089Spjd		usage(B_FALSE);
1266219089Spjd	}
1267219089Spjd
1268168404Spjd	pool = argv[0];
1269168404Spjd
1270168404Spjd	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1271168404Spjd		/*
1272168404Spjd		 * As a special case, check for use of '/' in the name, and
1273219089Spjd		 * direct the user to use 'zfs destroy' instead.
1274168404Spjd		 */
1275168404Spjd		if (strchr(pool, '/') != NULL)
1276209962Smm			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
1277209962Smm			    "destroy a dataset\n"));
1278168404Spjd		return (1);
1279209962Smm	}
1280168404Spjd
1281168404Spjd	if (zpool_disable_datasets(zhp, force) != 0) {
1282168404Spjd		(void) fprintf(stderr, gettext("could not destroy '%s': "
1283168404Spjd		    "could not unmount datasets\n"), zpool_get_name(zhp));
1284168404Spjd		return (1);
1285168404Spjd	}
1286219089Spjd
1287168404Spjd	/* The history must be logged as part of the export */
1288168404Spjd	log_history = B_FALSE;
1289168404Spjd
1290219089Spjd	ret = (zpool_destroy(zhp, history_str) != 0);
1291219089Spjd
1292219089Spjd	zpool_close(zhp);
1293219089Spjd
1294219089Spjd	return (ret);
1295168404Spjd}
1296168404Spjd
1297168404Spjd/*
1298168404Spjd * zpool export [-f] <pool> ...
1299168404Spjd *
1300168404Spjd *	-f	Forcefully unmount datasets
1301168404Spjd *
1302168404Spjd * Export the given pools.  By default, the command will attempt to cleanly
1303168404Spjd * unmount any active datasets within the pool.  If the '-f' flag is specified,
1304168404Spjd * then the datasets will be forcefully unmounted.
1305269845Sdelphij */
1306269845Sdelphijint
1307168404Spjdzpool_do_export(int argc, char **argv)
1308240415Smm{
1309240415Smm	boolean_t force = B_FALSE;
1310240415Smm	boolean_t hardforce = B_FALSE;
1311168404Spjd	int c;
1312168404Spjd	zpool_handle_t *zhp;
1313168404Spjd	int ret;
1314168404Spjd	int i;
1315168404Spjd
1316168404Spjd	/* check options */
1317168404Spjd	while ((c = getopt(argc, argv, "fF")) != -1) {
1318168404Spjd		switch (c) {
1319168404Spjd		case 'f':
1320168404Spjd			force = B_TRUE;
1321168404Spjd			break;
1322168404Spjd		case 'F':
1323168404Spjd			hardforce = B_TRUE;
1324168404Spjd			break;
1325168404Spjd		case '?':
1326219089Spjd			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1327168404Spjd			    optopt);
1328168404Spjd			usage(B_FALSE);
1329168404Spjd		}
1330168404Spjd	}
1331168404Spjd
1332185029Spjd	argc -= optind;
1333168404Spjd	argv += optind;
1334168404Spjd
1335168404Spjd	/* check arguments */
1336168404Spjd	if (argc < 1) {
1337168404Spjd		(void) fprintf(stderr, gettext("missing pool argument\n"));
1338168404Spjd		usage(B_FALSE);
1339168404Spjd	}
1340168404Spjd
1341168404Spjd	ret = 0;
1342168404Spjd	for (i = 0; i < argc; i++) {
1343168404Spjd		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1344168404Spjd			ret = 1;
1345168404Spjd			continue;
1346168404Spjd		}
1347168404Spjd
1348168404Spjd		if (zpool_disable_datasets(zhp, force) != 0) {
1349168404Spjd			ret = 1;
1350168404Spjd			zpool_close(zhp);
1351168404Spjd			continue;
1352168404Spjd		}
1353168404Spjd
1354168404Spjd		/* The history must be logged as part of the export */
1355168404Spjd		log_history = B_FALSE;
1356168404Spjd
1357168404Spjd		if (hardforce) {
1358168404Spjd			if (zpool_export_force(zhp, history_str) != 0)
1359168404Spjd				ret = 1;
1360168404Spjd		} else if (zpool_export(zhp, force, history_str) != 0) {
1361168404Spjd			ret = 1;
1362168404Spjd		}
1363168404Spjd
1364168404Spjd		zpool_close(zhp);
1365168404Spjd	}
1366168404Spjd
1367168404Spjd	return (ret);
1368168404Spjd}
1369168404Spjd
1370168404Spjd/*
1371168404Spjd * Given a vdev configuration, determine the maximum width needed for the device
1372168404Spjd * name column.
1373168404Spjd */
1374168404Spjdstatic int
1375168404Spjdmax_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1376168404Spjd{
1377168404Spjd	char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1378168404Spjd	nvlist_t **child;
1379269845Sdelphij	uint_t c, children;
1380185029Spjd	int ret;
1381168404Spjd
1382276081Sdelphij	if (strlen(name) + depth > max)
1383168404Spjd		max = strlen(name) + depth;
1384168404Spjd
1385168404Spjd	free(name);
1386168404Spjd
1387168404Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1388168404Spjd	    &child, &children) == 0) {
1389168404Spjd		for (c = 0; c < children; c++)
1390168404Spjd			if ((ret = max_width(zhp, child[c], depth + 2,
1391168404Spjd			    max)) > max)
1392168404Spjd				max = ret;
1393168404Spjd	}
1394168404Spjd
1395168404Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1396168404Spjd	    &child, &children) == 0) {
1397262093Savg		for (c = 0; c < children; c++)
1398168404Spjd			if ((ret = max_width(zhp, child[c], depth + 2,
1399168404Spjd			    max)) > max)
1400168404Spjd				max = ret;
1401269845Sdelphij	}
1402269845Sdelphij
1403219089Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1404219089Spjd	    &child, &children) == 0) {
1405168404Spjd		for (c = 0; c < children; c++)
1406168404Spjd			if ((ret = max_width(zhp, child[c], depth + 2,
1407168404Spjd			    max)) > max)
1408168404Spjd				max = ret;
1409168404Spjd	}
1410168404Spjd
1411168404Spjd
1412168404Spjd	return (max);
1413168404Spjd}
1414185029Spjd
1415288571Smavtypedef struct spare_cbdata {
1416185029Spjd	uint64_t	cb_guid;
1417168404Spjd	zpool_handle_t	*cb_zhp;
1418185029Spjd} spare_cbdata_t;
1419185029Spjd
1420168404Spjdstatic boolean_t
1421168404Spjdfind_vdev(nvlist_t *nv, uint64_t search)
1422168404Spjd{
1423168404Spjd	uint64_t guid;
1424168404Spjd	nvlist_t **child;
1425168404Spjd	uint_t c, children;
1426168404Spjd
1427168404Spjd	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1428185029Spjd	    search == guid)
1429168404Spjd		return (B_TRUE);
1430168404Spjd
1431168404Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1432168404Spjd	    &child, &children) == 0) {
1433168404Spjd		for (c = 0; c < children; c++)
1434168404Spjd			if (find_vdev(child[c], search))
1435168404Spjd				return (B_TRUE);
1436168404Spjd	}
1437249195Smm
1438168404Spjd	return (B_FALSE);
1439168404Spjd}
1440185029Spjd
1441168404Spjdstatic int
1442185029Spjdfind_spare(zpool_handle_t *zhp, void *data)
1443168404Spjd{
1444168404Spjd	spare_cbdata_t *cbp = data;
1445168404Spjd	nvlist_t *config, *nvroot;
1446168404Spjd
1447168404Spjd	config = zpool_get_config(zhp, NULL);
1448219089Spjd	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1449168404Spjd	    &nvroot) == 0);
1450185029Spjd
1451185029Spjd	if (find_vdev(nvroot, cbp->cb_guid)) {
1452185029Spjd		cbp->cb_zhp = zhp;
1453185029Spjd		return (1);
1454185029Spjd	}
1455185029Spjd
1456185029Spjd	zpool_close(zhp);
1457185029Spjd	return (0);
1458185029Spjd}
1459185029Spjd
1460185029Spjd/*
1461185029Spjd * Print out configuration state as requested by status_callback.
1462185029Spjd */
1463185029Spjdvoid
1464185029Spjdprint_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1465185029Spjd    int namewidth, int depth, boolean_t isspare)
1466168404Spjd{
1467168404Spjd	nvlist_t **child;
1468168404Spjd	uint_t c, vsc, children;
1469168404Spjd	pool_scan_stat_t *ps = NULL;
1470168404Spjd	vdev_stat_t *vs;
1471168404Spjd	char rbuf[6], wbuf[6], cbuf[6];
1472168404Spjd	char *vname;
1473168404Spjd	uint64_t notpresent;
1474168404Spjd	uint64_t ashift;
1475168404Spjd	spare_cbdata_t cb;
1476168404Spjd	const char *state;
1477168404Spjd	char *type;
1478168404Spjd
1479168404Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1480168404Spjd	    &child, &children) != 0)
1481168404Spjd		children = 0;
1482168404Spjd
1483168404Spjd	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1484168404Spjd	    (uint64_t **)&vs, &vsc) == 0);
1485168404Spjd
1486168404Spjd	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1487168404Spjd
1488168404Spjd	if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1489168404Spjd		return;
1490168404Spjd
1491168404Spjd	state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1492168404Spjd	if (isspare) {
1493168404Spjd		/*
1494168404Spjd		 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1495219089Spjd		 * online drives.
1496168404Spjd		 */
1497168404Spjd		if (vs->vs_aux == VDEV_AUX_SPARED)
1498168404Spjd			state = "INUSE";
1499168404Spjd		else if (vs->vs_state == VDEV_STATE_HEALTHY)
1500168404Spjd			state = "AVAIL";
1501168404Spjd	}
1502168404Spjd
1503168404Spjd	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1504168404Spjd	    name, state);
1505168404Spjd
1506219089Spjd	if (!isspare) {
1507219089Spjd		zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1508168404Spjd		zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1509168404Spjd		zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1510168404Spjd		(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1511168404Spjd	}
1512168404Spjd
1513168404Spjd	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1514168404Spjd	    &notpresent) == 0 ||
1515168404Spjd	    vs->vs_state <= VDEV_STATE_CANT_OPEN) {
1516168404Spjd		char *path;
1517168404Spjd		if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0)
1518168404Spjd			(void) printf("  was %s", path);
1519185029Spjd	} else if (vs->vs_aux != 0) {
1520185029Spjd		(void) printf("  ");
1521168404Spjd
1522168404Spjd		switch (vs->vs_aux) {
1523285202Savg		case VDEV_AUX_OPEN_FAILED:
1524285202Savg			(void) printf(gettext("cannot open"));
1525285202Savg			break;
1526285202Savg
1527285202Savg		case VDEV_AUX_BAD_GUID_SUM:
1528285202Savg			(void) printf(gettext("missing device"));
1529285202Savg			break;
1530285202Savg
1531285202Savg		case VDEV_AUX_NO_REPLICAS:
1532285202Savg			(void) printf(gettext("insufficient replicas"));
1533168404Spjd			break;
1534168404Spjd
1535168404Spjd		case VDEV_AUX_VERSION_NEWER:
1536168404Spjd			(void) printf(gettext("newer version"));
1537168404Spjd			break;
1538185029Spjd
1539168404Spjd		case VDEV_AUX_UNSUP_FEAT:
1540185029Spjd			(void) printf(gettext("unsupported feature(s)"));
1541168404Spjd			break;
1542168404Spjd
1543168404Spjd		case VDEV_AUX_ASHIFT_TOO_BIG:
1544185029Spjd			(void) printf(gettext("unsupported minimum blocksize"));
1545185029Spjd			break;
1546168404Spjd
1547254753Sdelphij		case VDEV_AUX_SPARED:
1548168404Spjd			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1549168404Spjd			    &cb.cb_guid) == 0);
1550168404Spjd			if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1551168404Spjd				if (strcmp(zpool_get_name(cb.cb_zhp),
1552168404Spjd				    zpool_get_name(zhp)) == 0)
1553168404Spjd					(void) printf(gettext("currently in "
1554168404Spjd					    "use"));
1555168404Spjd				else
1556168404Spjd					(void) printf(gettext("in use by "
1557168404Spjd					    "pool '%s'"),
1558185029Spjd					    zpool_get_name(cb.cb_zhp));
1559185029Spjd				zpool_close(cb.cb_zhp);
1560168404Spjd			} else {
1561168404Spjd				(void) printf(gettext("currently in use"));
1562168404Spjd			}
1563263397Sdelphij			break;
1564263397Sdelphij
1565263397Sdelphij		case VDEV_AUX_ERR_EXCEEDED:
1566263397Sdelphij			(void) printf(gettext("too many errors"));
1567263397Sdelphij			break;
1568263397Sdelphij
1569263397Sdelphij		case VDEV_AUX_IO_FAILURE:
1570185029Spjd			(void) printf(gettext("experienced I/O failures"));
1571185029Spjd			break;
1572185029Spjd
1573185029Spjd		case VDEV_AUX_BAD_LOG:
1574185029Spjd			(void) printf(gettext("bad intent log"));
1575185029Spjd			break;
1576168404Spjd
1577168404Spjd		case VDEV_AUX_EXTERNAL:
1578168404Spjd			(void) printf(gettext("external device fault"));
1579168404Spjd			break;
1580168404Spjd
1581168404Spjd		case VDEV_AUX_SPLIT_POOL:
1582168404Spjd			(void) printf(gettext("split into new pool"));
1583168404Spjd			break;
1584168404Spjd
1585168404Spjd		case VDEV_AUX_CHILDREN_OFFLINE:
1586168404Spjd			(void) printf(gettext("all children offline"));
1587168404Spjd			break;
1588288571Smav
1589288571Smav		default:
1590168404Spjd			(void) printf(gettext("corrupted data"));
1591168404Spjd			break;
1592168404Spjd		}
1593168404Spjd	} else if (children == 0 && !isspare &&
1594168404Spjd	    VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
1595168404Spjd	    vs->vs_configured_ashift < vs->vs_physical_ashift) {
1596263397Sdelphij		(void) printf(
1597168404Spjd		    gettext("  block size: %dB configured, %dB native"),
1598168404Spjd		    1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
1599168404Spjd	}
1600168404Spjd
1601168404Spjd	(void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1602168404Spjd	    (uint64_t **)&ps, &c);
1603168404Spjd
1604168404Spjd	if (ps && ps->pss_state == DSS_SCANNING &&
1605168404Spjd	    vs->vs_scan_processed != 0 && children == 0) {
1606168404Spjd		(void) printf(gettext("  (%s)"),
1607168404Spjd		    (ps->pss_func == POOL_SCAN_RESILVER) ?
1608185029Spjd		    "resilvering" : "repairing");
1609168404Spjd	}
1610168404Spjd
1611185029Spjd	(void) printf("\n");
1612185029Spjd
1613185029Spjd	for (c = 0; c < children; c++) {
1614168404Spjd		uint64_t islog = B_FALSE, ishole = B_FALSE;
1615185029Spjd
1616185029Spjd		/* Don't print logs or holes here */
1617185029Spjd		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1618185029Spjd		    &islog);
1619185029Spjd		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1620168404Spjd		    &ishole);
1621240415Smm		if (islog || ishole)
1622185029Spjd			continue;
1623185029Spjd		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1624185029Spjd		print_status_config(zhp, vname, child[c],
1625185029Spjd		    namewidth, depth + 2, isspare);
1626288571Smav		free(vname);
1627288571Smav	}
1628185029Spjd}
1629185029Spjd
1630185029Spjd
1631185029Spjd/*
1632263397Sdelphij * Print the configuration of an exported pool.  Iterate over all vdevs in the
1633185029Spjd * pool, printing out the name and status for each one.
1634185029Spjd */
1635168404Spjdvoid
1636185029Spjdprint_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1637168404Spjd{
1638185029Spjd	nvlist_t **child;
1639185029Spjd	uint_t c, children;
1640168404Spjd	vdev_stat_t *vs;
1641185029Spjd	char *type, *vname;
1642185029Spjd
1643185029Spjd	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1644185029Spjd	if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1645185029Spjd	    strcmp(type, VDEV_TYPE_HOLE) == 0)
1646185029Spjd		return;
1647185029Spjd
1648185029Spjd	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1649185029Spjd	    (uint64_t **)&vs, &c) == 0);
1650185029Spjd
1651185029Spjd	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1652185029Spjd	(void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1653285202Savg
1654285202Savg	if (vs->vs_aux != 0) {
1655285202Savg		(void) printf("  ");
1656285202Savg
1657285202Savg		switch (vs->vs_aux) {
1658285202Savg		case VDEV_AUX_OPEN_FAILED:
1659285202Savg			(void) printf(gettext("cannot open"));
1660285202Savg			break;
1661285202Savg
1662285202Savg		case VDEV_AUX_BAD_GUID_SUM:
1663285202Savg			(void) printf(gettext("missing device"));
1664285202Savg			break;
1665285202Savg
1666285202Savg		case VDEV_AUX_NO_REPLICAS:
1667285202Savg			(void) printf(gettext("insufficient replicas"));
1668285202Savg			break;
1669285202Savg
1670285202Savg		case VDEV_AUX_VERSION_NEWER:
1671185029Spjd			(void) printf(gettext("newer version"));
1672185029Spjd			break;
1673263397Sdelphij
1674185029Spjd		case VDEV_AUX_UNSUP_FEAT:
1675185029Spjd			(void) printf(gettext("unsupported feature(s)"));
1676285202Savg			break;
1677185029Spjd
1678185029Spjd		case VDEV_AUX_ERR_EXCEEDED:
1679185029Spjd			(void) printf(gettext("too many errors"));
1680185029Spjd			break;
1681285202Savg
1682285202Savg		case VDEV_AUX_CHILDREN_OFFLINE:
1683285202Savg			(void) printf(gettext("all children offline"));
1684285202Savg			break;
1685285202Savg
1686285202Savg		default:
1687285202Savg			(void) printf(gettext("corrupted data"));
1688285202Savg			break;
1689285202Savg		}
1690285202Savg	}
1691285202Savg	(void) printf("\n");
1692285202Savg
1693285202Savg	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1694285202Savg	    &child, &children) != 0)
1695285202Savg		return;
1696285202Savg
1697285202Savg	for (c = 0; c < children; c++) {
1698285202Savg		uint64_t is_log = B_FALSE;
1699285202Savg
1700285202Savg		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1701285202Savg		    &is_log);
1702285202Savg		if (is_log)
1703285202Savg			continue;
1704285202Savg
1705285202Savg		vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1706285202Savg		print_import_config(vname, child[c], namewidth, depth + 2);
1707285202Savg		free(vname);
1708285202Savg	}
1709285202Savg
1710285202Savg	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1711285202Savg	    &child, &children) == 0) {
1712285202Savg		(void) printf(gettext("\tcache\n"));
1713285202Savg		for (c = 0; c < children; c++) {
1714168404Spjd			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1715263397Sdelphij			(void) printf("\t  %s\n", vname);
1716168404Spjd			free(vname);
1717185029Spjd		}
1718185029Spjd	}
1719185029Spjd
1720185029Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1721185029Spjd	    &child, &children) == 0) {
1722168404Spjd		(void) printf(gettext("\tspares\n"));
1723265740Sdelphij		for (c = 0; c < children; c++) {
1724265740Sdelphij			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1725265740Sdelphij			(void) printf("\t  %s\n", vname);
1726265740Sdelphij			free(vname);
1727168404Spjd		}
1728265740Sdelphij	}
1729265740Sdelphij}
1730265740Sdelphij
1731265740Sdelphij/*
1732168404Spjd * Print log vdevs.
1733168404Spjd * Logs are recorded as top level vdevs in the main pool child array
1734185029Spjd * but with "is_log" set to 1. We use either print_status_config() or
1735168404Spjd * print_import_config() to print the top level logs then any log
1736168404Spjd * children (eg mirrored slogs) are printed recursively - which
1737185029Spjd * works because only the top level vdev is marked "is_log"
1738168404Spjd */
1739168404Spjdstatic void
1740168404Spjdprint_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1741219089Spjd{
1742219089Spjd	uint_t c, children;
1743219089Spjd	nvlist_t **child;
1744219089Spjd
1745219089Spjd	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1746219089Spjd	    &children) != 0)
1747219089Spjd		return;
1748219089Spjd
1749219089Spjd	(void) printf(gettext("\tlogs\n"));
1750219089Spjd
1751219089Spjd	for (c = 0; c < children; c++) {
1752219089Spjd		uint64_t is_log = B_FALSE;
1753219089Spjd		char *name;
1754219089Spjd
1755168404Spjd		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1756168404Spjd		    &is_log);
1757168404Spjd		if (!is_log)
1758168404Spjd			continue;
1759168404Spjd		name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1760168404Spjd		if (verbose)
1761168404Spjd			print_status_config(zhp, name, child[c], namewidth,
1762219089Spjd			    2, B_FALSE);
1763168404Spjd		else
1764168404Spjd			print_import_config(name, child[c], namewidth, 2);
1765168404Spjd		free(name);
1766168404Spjd	}
1767168404Spjd}
1768168404Spjd
1769168404Spjd/*
1770168404Spjd * Display the status for the given pool.
1771168404Spjd */
1772168404Spjdstatic void
1773168404Spjdshow_import(nvlist_t *config)
1774168404Spjd{
1775219089Spjd	uint64_t pool_state;
1776219089Spjd	vdev_stat_t *vs;
1777219089Spjd	char *name;
1778168404Spjd	uint64_t guid;
1779168404Spjd	char *msgid;
1780265740Sdelphij	nvlist_t *nvroot;
1781265740Sdelphij	int reason;
1782168404Spjd	const char *health;
1783168404Spjd	uint_t vsc;
1784168404Spjd	int namewidth;
1785168404Spjd	char *comment;
1786168404Spjd
1787168404Spjd	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1788168404Spjd	    &name) == 0);
1789168404Spjd	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1790168404Spjd	    &guid) == 0);
1791168404Spjd	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1792168404Spjd	    &pool_state) == 0);
1793168404Spjd	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1794168404Spjd	    &nvroot) == 0);
1795168404Spjd
1796168404Spjd	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1797168404Spjd	    (uint64_t **)&vs, &vsc) == 0);
1798168404Spjd	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1799168404Spjd
1800168404Spjd	reason = zpool_import_status(config, &msgid);
1801168404Spjd
1802168404Spjd	(void) printf(gettext("   pool: %s\n"), name);
1803168404Spjd	(void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
1804168404Spjd	(void) printf(gettext("  state: %s"), health);
1805168404Spjd	if (pool_state == POOL_STATE_DESTROYED)
1806185029Spjd		(void) printf(gettext(" (DESTROYED)"));
1807168404Spjd	(void) printf("\n");
1808240415Smm
1809168404Spjd	switch (reason) {
1810168404Spjd	case ZPOOL_STATUS_MISSING_DEV_R:
1811168404Spjd	case ZPOOL_STATUS_MISSING_DEV_NR:
1812168404Spjd	case ZPOOL_STATUS_BAD_GUID_SUM:
1813168404Spjd		(void) printf(gettext(" status: One or more devices are "
1814168404Spjd		    "missing from the system.\n"));
1815168404Spjd		break;
1816168404Spjd
1817168404Spjd	case ZPOOL_STATUS_CORRUPT_LABEL_R:
1818260763Savg	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1819260763Savg		(void) printf(gettext(" status: One or more devices contains "
1820168404Spjd		    "corrupted data.\n"));
1821168404Spjd		break;
1822168404Spjd
1823168404Spjd	case ZPOOL_STATUS_CORRUPT_DATA:
1824219089Spjd		(void) printf(
1825168404Spjd		    gettext(" status: The pool data is corrupted.\n"));
1826260763Savg		break;
1827168404Spjd
1828260763Savg	case ZPOOL_STATUS_OFFLINE_DEV:
1829260763Savg		(void) printf(gettext(" status: One or more devices "
1830260763Savg		    "are offlined.\n"));
1831260763Savg		break;
1832168404Spjd
1833260763Savg	case ZPOOL_STATUS_CORRUPT_POOL:
1834168404Spjd		(void) printf(gettext(" status: The pool metadata is "
1835168404Spjd		    "corrupted.\n"));
1836208775Smm		break;
1837251631Sdelphij
1838251631Sdelphij	case ZPOOL_STATUS_VERSION_OLDER:
1839208775Smm		(void) printf(gettext(" status: The pool is formatted using a "
1840251631Sdelphij		    "legacy on-disk version.\n"));
1841251631Sdelphij		break;
1842251631Sdelphij
1843251631Sdelphij	case ZPOOL_STATUS_VERSION_NEWER:
1844251631Sdelphij		(void) printf(gettext(" status: The pool is formatted using an "
1845251631Sdelphij		    "incompatible version.\n"));
1846251631Sdelphij		break;
1847251631Sdelphij
1848208775Smm	case ZPOOL_STATUS_FEAT_DISABLED:
1849208775Smm		(void) printf(gettext(" status: Some supported features are "
1850208775Smm		    "not enabled on the pool.\n"));
1851208775Smm		break;
1852208775Smm
1853208775Smm	case ZPOOL_STATUS_UNSUP_FEAT_READ:
1854168404Spjd		(void) printf(gettext("status: The pool uses the following "
1855185029Spjd		    "feature(s) not supported on this system:\n"));
1856288571Smav		zpool_print_unsup_feat(config);
1857168404Spjd		break;
1858168404Spjd
1859168404Spjd	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1860168404Spjd		(void) printf(gettext("status: The pool can only be accessed "
1861168404Spjd		    "in read-only mode on this system. It\n\tcannot be "
1862168404Spjd		    "accessed in read-write mode because it uses the "
1863185029Spjd		    "following\n\tfeature(s) not supported on this system:\n"));
1864185029Spjd		zpool_print_unsup_feat(config);
1865168404Spjd		break;
1866168404Spjd
1867168404Spjd	case ZPOOL_STATUS_HOSTID_MISMATCH:
1868168404Spjd		(void) printf(gettext(" status: The pool was last accessed by "
1869209962Smm		    "another system.\n"));
1870185029Spjd		break;
1871185029Spjd
1872185029Spjd	case ZPOOL_STATUS_FAULTED_DEV_R:
1873168404Spjd	case ZPOOL_STATUS_FAULTED_DEV_NR:
1874168404Spjd		(void) printf(gettext(" status: One or more devices are "
1875168404Spjd		    "faulted.\n"));
1876168404Spjd		break;
1877168404Spjd
1878288571Smav	case ZPOOL_STATUS_BAD_LOG:
1879288571Smav		(void) printf(gettext(" status: An intent log record cannot be "
1880168404Spjd		    "read.\n"));
1881185029Spjd		break;
1882185029Spjd
1883185029Spjd	case ZPOOL_STATUS_RESILVERING:
1884185029Spjd		(void) printf(gettext(" status: One or more devices were being "
1885185029Spjd		    "resilvered.\n"));
1886185029Spjd		break;
1887185029Spjd
1888185029Spjd	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
1889185029Spjd		(void) printf(gettext("status: One or more devices were "
1890185029Spjd		    "configured to use a non-native block size.\n"
1891185029Spjd		    "\tExpect reduced performance.\n"));
1892249195Smm		break;
1893168404Spjd
1894168404Spjd	default:
1895168404Spjd		/*
1896168404Spjd		 * No other status can be seen when importing pools.
1897168404Spjd		 */
1898168404Spjd		assert(reason == ZPOOL_STATUS_OK);
1899168404Spjd	}
1900168404Spjd
1901168404Spjd	/*
1902263397Sdelphij	 * Print out an action according to the overall state of the pool.
1903263397Sdelphij	 */
1904263397Sdelphij	if (vs->vs_state == VDEV_STATE_HEALTHY) {
1905263397Sdelphij		if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1906185029Spjd		    reason == ZPOOL_STATUS_FEAT_DISABLED) {
1907185029Spjd			(void) printf(gettext(" action: The pool can be "
1908185029Spjd			    "imported using its name or numeric identifier, "
1909185029Spjd			    "though\n\tsome features will not be available "
1910249195Smm			    "without an explicit 'zpool upgrade'.\n"));
1911168404Spjd		} else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1912168404Spjd			(void) printf(gettext(" action: The pool can be "
1913168404Spjd			    "imported using its name or numeric "
1914168404Spjd			    "identifier and\n\tthe '-f' flag.\n"));
1915168404Spjd		} else {
1916185029Spjd			(void) printf(gettext(" action: The pool can be "
1917185029Spjd			    "imported using its name or numeric "
1918209094Smm			    "identifier.\n"));
1919168404Spjd		}
1920185029Spjd	} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1921168404Spjd		(void) printf(gettext(" action: The pool can be imported "
1922185029Spjd		    "despite missing or damaged devices.  The\n\tfault "
1923249195Smm		    "tolerance of the pool may be compromised if imported.\n"));
1924168404Spjd	} else {
1925168404Spjd		switch (reason) {
1926208775Smm		case ZPOOL_STATUS_VERSION_NEWER:
1927168404Spjd			(void) printf(gettext(" action: The pool cannot be "
1928168404Spjd			    "imported.  Access the pool on a system running "
1929168404Spjd			    "newer\n\tsoftware, or recreate the pool from "
1930168404Spjd			    "backup.\n"));
1931168404Spjd			break;
1932168404Spjd		case ZPOOL_STATUS_UNSUP_FEAT_READ:
1933168404Spjd			(void) printf(gettext("action: The pool cannot be "
1934168404Spjd			    "imported. Access the pool on a system that "
1935168404Spjd			    "supports\n\tthe required feature(s), or recreate "
1936208775Smm			    "the pool from backup.\n"));
1937208775Smm			break;
1938185029Spjd		case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1939268649Sdelphij			(void) printf(gettext("action: The pool cannot be "
1940268649Sdelphij			    "imported in read-write mode. Import the pool "
1941185029Spjd			    "with\n"
1942168404Spjd			    "\t\"-o readonly=on\", access the pool on a system "
1943208775Smm			    "that supports the\n\trequired feature(s), or "
1944208775Smm			    "recreate the pool from backup.\n"));
1945168404Spjd			break;
1946208775Smm		case ZPOOL_STATUS_MISSING_DEV_R:
1947208775Smm		case ZPOOL_STATUS_MISSING_DEV_NR:
1948208775Smm		case ZPOOL_STATUS_BAD_GUID_SUM:
1949208775Smm			(void) printf(gettext(" action: The pool cannot be "
1950208775Smm			    "imported. Attach the missing\n\tdevices and try "
1951208775Smm			    "again.\n"));
1952208775Smm			break;
1953208775Smm		default:
1954208775Smm			(void) printf(gettext(" action: The pool cannot be "
1955249195Smm			    "imported due to damaged devices or data.\n"));
1956168404Spjd		}
1957168404Spjd	}
1958168404Spjd
1959168404Spjd	/* Print the comment attached to the pool. */
1960168404Spjd	if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1961168404Spjd		(void) printf(gettext("comment: %s\n"), comment);
1962168404Spjd
1963168404Spjd	/*
1964168404Spjd	 * If the state is "closed" or "can't open", and the aux state
1965168404Spjd	 * is "corrupt data":
1966168404Spjd	 */
1967168404Spjd	if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1968168404Spjd	    (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1969168404Spjd	    (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1970168404Spjd		if (pool_state == POOL_STATE_DESTROYED)
1971168404Spjd			(void) printf(gettext("\tThe pool was destroyed, "
1972168404Spjd			    "but can be imported using the '-Df' flags.\n"));
1973185029Spjd		else if (pool_state != POOL_STATE_EXPORTED)
1974185029Spjd			(void) printf(gettext("\tThe pool may be active on "
1975168404Spjd			    "another system, but can be imported using\n\t"
1976168404Spjd			    "the '-f' flag.\n"));
1977185029Spjd	}
1978168404Spjd
1979168404Spjd	if (msgid != NULL)
1980168404Spjd		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
1981168404Spjd		    msgid);
1982168404Spjd
1983185029Spjd	(void) printf(gettext(" config:\n\n"));
1984168404Spjd
1985168404Spjd	namewidth = max_width(NULL, nvroot, 0, 0);
1986168404Spjd	if (namewidth < 10)
1987168404Spjd		namewidth = 10;
1988185029Spjd
1989168404Spjd	print_import_config(name, nvroot, namewidth, 0);
1990168404Spjd	if (num_logs(nvroot) > 0)
1991185029Spjd		print_logs(NULL, nvroot, namewidth, B_FALSE);
1992168404Spjd
1993168404Spjd	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1994168404Spjd		(void) printf(gettext("\n\tAdditional devices are known to "
1995185029Spjd		    "be part of this pool, though their\n\texact "
1996185029Spjd		    "configuration cannot be determined.\n"));
1997168404Spjd	}
1998168404Spjd}
1999249195Smm
2000185029Spjd/*
2001168404Spjd * Perform the import for the given configuration.  This passes the heavy
2002168404Spjd * lifting off to zpool_import_props(), and then mounts the datasets contained
2003168404Spjd * within the pool.
2004168404Spjd */
2005185029Spjdstatic int
2006168404Spjddo_import(nvlist_t *config, const char *newname, const char *mntopts,
2007168404Spjd    nvlist_t *props, int flags)
2008249195Smm{
2009168404Spjd	zpool_handle_t *zhp;
2010185029Spjd	char *name;
2011168404Spjd	uint64_t state;
2012168404Spjd	uint64_t version;
2013168404Spjd
2014168404Spjd	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2015168404Spjd	    &name) == 0);
2016168404Spjd
2017185029Spjd	verify(nvlist_lookup_uint64(config,
2018168404Spjd	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2019168404Spjd	verify(nvlist_lookup_uint64(config,
2020168404Spjd	    ZPOOL_CONFIG_VERSION, &version) == 0);
2021168404Spjd	if (!SPA_VERSION_IS_SUPPORTED(version)) {
2022185029Spjd		(void) fprintf(stderr, gettext("cannot import '%s': pool "
2023168404Spjd		    "is formatted using an unsupported ZFS version\n"), name);
2024185029Spjd		return (1);
2025168404Spjd	} else if (state != POOL_STATE_EXPORTED &&
2026168404Spjd	    !(flags & ZFS_IMPORT_ANY_HOST)) {
2027272134Sdelphij		uint64_t hostid;
2028272134Sdelphij
2029272134Sdelphij		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
2030272134Sdelphij		    &hostid) == 0) {
2031272134Sdelphij			if ((unsigned long)hostid != gethostid()) {
2032272134Sdelphij				char *hostname;
2033272134Sdelphij				uint64_t timestamp;
2034272134Sdelphij				time_t t;
2035272134Sdelphij
2036185029Spjd				verify(nvlist_lookup_string(config,
2037185029Spjd				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2038249195Smm				verify(nvlist_lookup_uint64(config,
2039185029Spjd				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
2040185029Spjd				t = timestamp;
2041185029Spjd				(void) fprintf(stderr, gettext("cannot import "
2042168404Spjd				    "'%s': pool may be in use from other "
2043168404Spjd				    "system, it was last accessed by %s "
2044168404Spjd				    "(hostid: 0x%lx) on %s"), name, hostname,
2045				    (unsigned long)hostid,
2046				    asctime(localtime(&t)));
2047				(void) fprintf(stderr, gettext("use '-f' to "
2048				    "import anyway\n"));
2049				return (1);
2050			}
2051		} else {
2052			(void) fprintf(stderr, gettext("cannot import '%s': "
2053			    "pool may be in use from other system\n"), name);
2054			(void) fprintf(stderr, gettext("use '-f' to import "
2055			    "anyway\n"));
2056			return (1);
2057		}
2058	}
2059
2060	if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2061		return (1);
2062
2063	if (newname != NULL)
2064		name = (char *)newname;
2065
2066	if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2067		return (1);
2068
2069	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2070	    !(flags & ZFS_IMPORT_ONLY) &&
2071	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2072		zpool_close(zhp);
2073		return (1);
2074	}
2075
2076	zpool_close(zhp);
2077	return (0);
2078}
2079
2080/*
2081 * zpool import [-d dir] [-D]
2082 *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2083 *              [-d dir | -c cachefile] [-f] -a
2084 *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2085 *              [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2086 *
2087 *	 -c	Read pool information from a cachefile instead of searching
2088 *		devices.
2089 *
2090 *       -d	Scan in a specific directory, other than /dev/dsk.  More than
2091 *		one directory can be specified using multiple '-d' options.
2092 *
2093 *       -D     Scan for previously destroyed pools or import all or only
2094 *              specified destroyed pools.
2095 *
2096 *       -R	Temporarily import the pool, with all mountpoints relative to
2097 *		the given root.  The pool will remain exported when the machine
2098 *		is rebooted.
2099 *
2100 *       -V	Import even in the presence of faulted vdevs.  This is an
2101 *       	intentionally undocumented option for testing purposes, and
2102 *       	treats the pool configuration as complete, leaving any bad
2103 *		vdevs in the FAULTED state. In other words, it does verbatim
2104 *		import.
2105 *
2106 *       -f	Force import, even if it appears that the pool is active.
2107 *
2108 *       -F     Attempt rewind if necessary.
2109 *
2110 *       -n     See if rewind would work, but don't actually rewind.
2111 *
2112 *       -N     Import the pool but don't mount datasets.
2113 *
2114 *       -T     Specify a starting txg to use for import. This option is
2115 *       	intentionally undocumented option for testing purposes.
2116 *
2117 *       -a	Import all pools found.
2118 *
2119 *       -o	Set property=value and/or temporary mount options (without '=').
2120 *
2121 * The import command scans for pools to import, and import pools based on pool
2122 * name and GUID.  The pool can also be renamed as part of the import process.
2123 */
2124int
2125zpool_do_import(int argc, char **argv)
2126{
2127	char **searchdirs = NULL;
2128	int nsearch = 0;
2129	int c;
2130	int err = 0;
2131	nvlist_t *pools = NULL;
2132	boolean_t do_all = B_FALSE;
2133	boolean_t do_destroyed = B_FALSE;
2134	char *mntopts = NULL;
2135	nvpair_t *elem;
2136	nvlist_t *config;
2137	uint64_t searchguid = 0;
2138	char *searchname = NULL;
2139	char *propval;
2140	nvlist_t *found_config;
2141	nvlist_t *policy = NULL;
2142	nvlist_t *props = NULL;
2143	boolean_t first;
2144	int flags = ZFS_IMPORT_NORMAL;
2145	uint32_t rewind_policy = ZPOOL_NO_REWIND;
2146	boolean_t dryrun = B_FALSE;
2147	boolean_t do_rewind = B_FALSE;
2148	boolean_t xtreme_rewind = B_FALSE;
2149	uint64_t pool_state, txg = -1ULL;
2150	char *cachefile = NULL;
2151	importargs_t idata = { 0 };
2152	char *endptr;
2153
2154	/* check options */
2155	while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:R:T:VX")) != -1) {
2156		switch (c) {
2157		case 'a':
2158			do_all = B_TRUE;
2159			break;
2160		case 'c':
2161			cachefile = optarg;
2162			break;
2163		case 'd':
2164			if (searchdirs == NULL) {
2165				searchdirs = safe_malloc(sizeof (char *));
2166			} else {
2167				char **tmp = safe_malloc((nsearch + 1) *
2168				    sizeof (char *));
2169				bcopy(searchdirs, tmp, nsearch *
2170				    sizeof (char *));
2171				free(searchdirs);
2172				searchdirs = tmp;
2173			}
2174			searchdirs[nsearch++] = optarg;
2175			break;
2176		case 'D':
2177			do_destroyed = B_TRUE;
2178			break;
2179		case 'f':
2180			flags |= ZFS_IMPORT_ANY_HOST;
2181			break;
2182		case 'F':
2183			do_rewind = B_TRUE;
2184			break;
2185		case 'm':
2186			flags |= ZFS_IMPORT_MISSING_LOG;
2187			break;
2188		case 'n':
2189			dryrun = B_TRUE;
2190			break;
2191		case 'N':
2192			flags |= ZFS_IMPORT_ONLY;
2193			break;
2194		case 'o':
2195			if ((propval = strchr(optarg, '=')) != NULL) {
2196				*propval = '\0';
2197				propval++;
2198				if (add_prop_list(optarg, propval,
2199				    &props, B_TRUE))
2200					goto error;
2201			} else {
2202				mntopts = optarg;
2203			}
2204			break;
2205		case 'R':
2206			if (add_prop_list(zpool_prop_to_name(
2207			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2208				goto error;
2209			if (nvlist_lookup_string(props,
2210			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2211			    &propval) == 0)
2212				break;
2213			if (add_prop_list(zpool_prop_to_name(
2214			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2215				goto error;
2216			break;
2217		case 'T':
2218			errno = 0;
2219			txg = strtoull(optarg, &endptr, 0);
2220			if (errno != 0 || *endptr != '\0') {
2221				(void) fprintf(stderr,
2222				    gettext("invalid txg value\n"));
2223				usage(B_FALSE);
2224			}
2225			rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2226			break;
2227		case 'V':
2228			flags |= ZFS_IMPORT_VERBATIM;
2229			break;
2230		case 'X':
2231			xtreme_rewind = B_TRUE;
2232			break;
2233		case ':':
2234			(void) fprintf(stderr, gettext("missing argument for "
2235			    "'%c' option\n"), optopt);
2236			usage(B_FALSE);
2237			break;
2238		case '?':
2239			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2240			    optopt);
2241			usage(B_FALSE);
2242		}
2243	}
2244
2245	argc -= optind;
2246	argv += optind;
2247
2248	if (cachefile && nsearch != 0) {
2249		(void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2250		usage(B_FALSE);
2251	}
2252
2253	if ((dryrun || xtreme_rewind) && !do_rewind) {
2254		(void) fprintf(stderr,
2255		    gettext("-n or -X only meaningful with -F\n"));
2256		usage(B_FALSE);
2257	}
2258	if (dryrun)
2259		rewind_policy = ZPOOL_TRY_REWIND;
2260	else if (do_rewind)
2261		rewind_policy = ZPOOL_DO_REWIND;
2262	if (xtreme_rewind)
2263		rewind_policy |= ZPOOL_EXTREME_REWIND;
2264
2265	/* In the future, we can capture further policy and include it here */
2266	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2267	    nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
2268	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2269		goto error;
2270
2271	if (searchdirs == NULL) {
2272		searchdirs = safe_malloc(sizeof (char *));
2273		searchdirs[0] = "/dev";
2274		nsearch = 1;
2275	}
2276
2277	/* check argument count */
2278	if (do_all) {
2279		if (argc != 0) {
2280			(void) fprintf(stderr, gettext("too many arguments\n"));
2281			usage(B_FALSE);
2282		}
2283	} else {
2284		if (argc > 2) {
2285			(void) fprintf(stderr, gettext("too many arguments\n"));
2286			usage(B_FALSE);
2287		}
2288
2289		/*
2290		 * Check for the SYS_CONFIG privilege.  We do this explicitly
2291		 * here because otherwise any attempt to discover pools will
2292		 * silently fail.
2293		 */
2294		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2295			(void) fprintf(stderr, gettext("cannot "
2296			    "discover pools: permission denied\n"));
2297			free(searchdirs);
2298			nvlist_free(policy);
2299			return (1);
2300		}
2301	}
2302
2303	/*
2304	 * Depending on the arguments given, we do one of the following:
2305	 *
2306	 *	<none>	Iterate through all pools and display information about
2307	 *		each one.
2308	 *
2309	 *	-a	Iterate through all pools and try to import each one.
2310	 *
2311	 *	<id>	Find the pool that corresponds to the given GUID/pool
2312	 *		name and import that one.
2313	 *
2314	 *	-D	Above options applies only to destroyed pools.
2315	 */
2316	if (argc != 0) {
2317		char *endptr;
2318
2319		errno = 0;
2320		searchguid = strtoull(argv[0], &endptr, 10);
2321		if (errno != 0 || *endptr != '\0') {
2322			searchname = argv[0];
2323			searchguid = 0;
2324		}
2325		found_config = NULL;
2326
2327		/*
2328		 * User specified a name or guid.  Ensure it's unique.
2329		 */
2330		idata.unique = B_TRUE;
2331	}
2332
2333
2334	idata.path = searchdirs;
2335	idata.paths = nsearch;
2336	idata.poolname = searchname;
2337	idata.guid = searchguid;
2338	idata.cachefile = cachefile;
2339	idata.policy = policy;
2340
2341	pools = zpool_search_import(g_zfs, &idata);
2342
2343	if (pools != NULL && idata.exists &&
2344	    (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2345		(void) fprintf(stderr, gettext("cannot import '%s': "
2346		    "a pool with that name already exists\n"),
2347		    argv[0]);
2348		(void) fprintf(stderr, gettext("use the form '%s "
2349		    "<pool | id> <newpool>' to give it a new name\n"),
2350		    "zpool import");
2351		err = 1;
2352	} else if (pools == NULL && idata.exists) {
2353		(void) fprintf(stderr, gettext("cannot import '%s': "
2354		    "a pool with that name is already created/imported,\n"),
2355		    argv[0]);
2356		(void) fprintf(stderr, gettext("and no additional pools "
2357		    "with that name were found\n"));
2358		err = 1;
2359	} else if (pools == NULL) {
2360		if (argc != 0) {
2361			(void) fprintf(stderr, gettext("cannot import '%s': "
2362			    "no such pool available\n"), argv[0]);
2363		}
2364		err = 1;
2365	}
2366
2367	if (err == 1) {
2368		free(searchdirs);
2369		nvlist_free(policy);
2370		return (1);
2371	}
2372
2373	/*
2374	 * At this point we have a list of import candidate configs. Even if
2375	 * we were searching by pool name or guid, we still need to
2376	 * post-process the list to deal with pool state and possible
2377	 * duplicate names.
2378	 */
2379	err = 0;
2380	elem = NULL;
2381	first = B_TRUE;
2382	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2383
2384		verify(nvpair_value_nvlist(elem, &config) == 0);
2385
2386		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2387		    &pool_state) == 0);
2388		if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2389			continue;
2390		if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2391			continue;
2392
2393		verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2394		    policy) == 0);
2395
2396		if (argc == 0) {
2397			if (first)
2398				first = B_FALSE;
2399			else if (!do_all)
2400				(void) printf("\n");
2401
2402			if (do_all) {
2403				err |= do_import(config, NULL, mntopts,
2404				    props, flags);
2405			} else {
2406				show_import(config);
2407			}
2408		} else if (searchname != NULL) {
2409			char *name;
2410
2411			/*
2412			 * We are searching for a pool based on name.
2413			 */
2414			verify(nvlist_lookup_string(config,
2415			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2416
2417			if (strcmp(name, searchname) == 0) {
2418				if (found_config != NULL) {
2419					(void) fprintf(stderr, gettext(
2420					    "cannot import '%s': more than "
2421					    "one matching pool\n"), searchname);
2422					(void) fprintf(stderr, gettext(
2423					    "import by numeric ID instead\n"));
2424					err = B_TRUE;
2425				}
2426				found_config = config;
2427			}
2428		} else {
2429			uint64_t guid;
2430
2431			/*
2432			 * Search for a pool by guid.
2433			 */
2434			verify(nvlist_lookup_uint64(config,
2435			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2436
2437			if (guid == searchguid)
2438				found_config = config;
2439		}
2440	}
2441
2442	/*
2443	 * If we were searching for a specific pool, verify that we found a
2444	 * pool, and then do the import.
2445	 */
2446	if (argc != 0 && err == 0) {
2447		if (found_config == NULL) {
2448			(void) fprintf(stderr, gettext("cannot import '%s': "
2449			    "no such pool available\n"), argv[0]);
2450			err = B_TRUE;
2451		} else {
2452			err |= do_import(found_config, argc == 1 ? NULL :
2453			    argv[1], mntopts, props, flags);
2454		}
2455	}
2456
2457	/*
2458	 * If we were just looking for pools, report an error if none were
2459	 * found.
2460	 */
2461	if (argc == 0 && first)
2462		(void) fprintf(stderr,
2463		    gettext("no pools available to import\n"));
2464
2465error:
2466	nvlist_free(props);
2467	nvlist_free(pools);
2468	nvlist_free(policy);
2469	free(searchdirs);
2470
2471	return (err ? 1 : 0);
2472}
2473
2474typedef struct iostat_cbdata {
2475	boolean_t cb_verbose;
2476	int cb_namewidth;
2477	int cb_iteration;
2478	zpool_list_t *cb_list;
2479} iostat_cbdata_t;
2480
2481static void
2482print_iostat_separator(iostat_cbdata_t *cb)
2483{
2484	int i = 0;
2485
2486	for (i = 0; i < cb->cb_namewidth; i++)
2487		(void) printf("-");
2488	(void) printf("  -----  -----  -----  -----  -----  -----\n");
2489}
2490
2491static void
2492print_iostat_header(iostat_cbdata_t *cb)
2493{
2494	(void) printf("%*s     capacity     operations    bandwidth\n",
2495	    cb->cb_namewidth, "");
2496	(void) printf("%-*s  alloc   free   read  write   read  write\n",
2497	    cb->cb_namewidth, "pool");
2498	print_iostat_separator(cb);
2499}
2500
2501/*
2502 * Display a single statistic.
2503 */
2504static void
2505print_one_stat(uint64_t value)
2506{
2507	char buf[64];
2508
2509	zfs_nicenum(value, buf, sizeof (buf));
2510	(void) printf("  %5s", buf);
2511}
2512
2513/*
2514 * Print out all the statistics for the given vdev.  This can either be the
2515 * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2516 * is a verbose output, and we don't want to display the toplevel pool stats.
2517 */
2518void
2519print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2520    nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2521{
2522	nvlist_t **oldchild, **newchild;
2523	uint_t c, children;
2524	vdev_stat_t *oldvs, *newvs;
2525	vdev_stat_t zerovs = { 0 };
2526	uint64_t tdelta;
2527	double scale;
2528	char *vname;
2529
2530	if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2531		return;
2532
2533	if (oldnv != NULL) {
2534		verify(nvlist_lookup_uint64_array(oldnv,
2535		    ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2536	} else {
2537		oldvs = &zerovs;
2538	}
2539
2540	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2541	    (uint64_t **)&newvs, &c) == 0);
2542
2543	if (strlen(name) + depth > cb->cb_namewidth)
2544		(void) printf("%*s%s", depth, "", name);
2545	else
2546		(void) printf("%*s%s%*s", depth, "", name,
2547		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
2548
2549	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2550
2551	if (tdelta == 0)
2552		scale = 1.0;
2553	else
2554		scale = (double)NANOSEC / tdelta;
2555
2556	/* only toplevel vdevs have capacity stats */
2557	if (newvs->vs_space == 0) {
2558		(void) printf("      -      -");
2559	} else {
2560		print_one_stat(newvs->vs_alloc);
2561		print_one_stat(newvs->vs_space - newvs->vs_alloc);
2562	}
2563
2564	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2565	    oldvs->vs_ops[ZIO_TYPE_READ])));
2566
2567	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2568	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
2569
2570	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2571	    oldvs->vs_bytes[ZIO_TYPE_READ])));
2572
2573	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2574	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2575
2576	(void) printf("\n");
2577
2578	if (!cb->cb_verbose)
2579		return;
2580
2581	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2582	    &newchild, &children) != 0)
2583		return;
2584
2585	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2586	    &oldchild, &c) != 0)
2587		return;
2588
2589	for (c = 0; c < children; c++) {
2590		uint64_t ishole = B_FALSE, islog = B_FALSE;
2591
2592		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2593		    &ishole);
2594
2595		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2596		    &islog);
2597
2598		if (ishole || islog)
2599			continue;
2600
2601		vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2602		print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2603		    newchild[c], cb, depth + 2);
2604		free(vname);
2605	}
2606
2607	/*
2608	 * Log device section
2609	 */
2610
2611	if (num_logs(newnv) > 0) {
2612		(void) printf("%-*s      -      -      -      -      -      "
2613		    "-\n", cb->cb_namewidth, "logs");
2614
2615		for (c = 0; c < children; c++) {
2616			uint64_t islog = B_FALSE;
2617			(void) nvlist_lookup_uint64(newchild[c],
2618			    ZPOOL_CONFIG_IS_LOG, &islog);
2619
2620			if (islog) {
2621				vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2622				    B_FALSE);
2623				print_vdev_stats(zhp, vname, oldnv ?
2624				    oldchild[c] : NULL, newchild[c],
2625				    cb, depth + 2);
2626				free(vname);
2627			}
2628		}
2629
2630	}
2631
2632	/*
2633	 * Include level 2 ARC devices in iostat output
2634	 */
2635	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2636	    &newchild, &children) != 0)
2637		return;
2638
2639	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2640	    &oldchild, &c) != 0)
2641		return;
2642
2643	if (children > 0) {
2644		(void) printf("%-*s      -      -      -      -      -      "
2645		    "-\n", cb->cb_namewidth, "cache");
2646		for (c = 0; c < children; c++) {
2647			vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2648			    B_FALSE);
2649			print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2650			    newchild[c], cb, depth + 2);
2651			free(vname);
2652		}
2653	}
2654}
2655
2656static int
2657refresh_iostat(zpool_handle_t *zhp, void *data)
2658{
2659	iostat_cbdata_t *cb = data;
2660	boolean_t missing;
2661
2662	/*
2663	 * If the pool has disappeared, remove it from the list and continue.
2664	 */
2665	if (zpool_refresh_stats(zhp, &missing) != 0)
2666		return (-1);
2667
2668	if (missing)
2669		pool_list_remove(cb->cb_list, zhp);
2670
2671	return (0);
2672}
2673
2674/*
2675 * Callback to print out the iostats for the given pool.
2676 */
2677int
2678print_iostat(zpool_handle_t *zhp, void *data)
2679{
2680	iostat_cbdata_t *cb = data;
2681	nvlist_t *oldconfig, *newconfig;
2682	nvlist_t *oldnvroot, *newnvroot;
2683
2684	newconfig = zpool_get_config(zhp, &oldconfig);
2685
2686	if (cb->cb_iteration == 1)
2687		oldconfig = NULL;
2688
2689	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2690	    &newnvroot) == 0);
2691
2692	if (oldconfig == NULL)
2693		oldnvroot = NULL;
2694	else
2695		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2696		    &oldnvroot) == 0);
2697
2698	/*
2699	 * Print out the statistics for the pool.
2700	 */
2701	print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2702
2703	if (cb->cb_verbose)
2704		print_iostat_separator(cb);
2705
2706	return (0);
2707}
2708
2709int
2710get_namewidth(zpool_handle_t *zhp, void *data)
2711{
2712	iostat_cbdata_t *cb = data;
2713	nvlist_t *config, *nvroot;
2714
2715	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2716		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2717		    &nvroot) == 0);
2718		if (!cb->cb_verbose)
2719			cb->cb_namewidth = strlen(zpool_get_name(zhp));
2720		else
2721			cb->cb_namewidth = max_width(zhp, nvroot, 0,
2722			    cb->cb_namewidth);
2723	}
2724
2725	/*
2726	 * The width must fall into the range [10,38].  The upper limit is the
2727	 * maximum we can have and still fit in 80 columns.
2728	 */
2729	if (cb->cb_namewidth < 10)
2730		cb->cb_namewidth = 10;
2731	if (cb->cb_namewidth > 38)
2732		cb->cb_namewidth = 38;
2733
2734	return (0);
2735}
2736
2737/*
2738 * Parse the input string, get the 'interval' and 'count' value if there is one.
2739 */
2740static void
2741get_interval_count(int *argcp, char **argv, unsigned long *iv,
2742    unsigned long *cnt)
2743{
2744	unsigned long interval = 0, count = 0;
2745	int argc = *argcp, errno;
2746
2747	/*
2748	 * Determine if the last argument is an integer or a pool name
2749	 */
2750	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2751		char *end;
2752
2753		errno = 0;
2754		interval = strtoul(argv[argc - 1], &end, 10);
2755
2756		if (*end == '\0' && errno == 0) {
2757			if (interval == 0) {
2758				(void) fprintf(stderr, gettext("interval "
2759				    "cannot be zero\n"));
2760				usage(B_FALSE);
2761			}
2762			/*
2763			 * Ignore the last parameter
2764			 */
2765			argc--;
2766		} else {
2767			/*
2768			 * If this is not a valid number, just plow on.  The
2769			 * user will get a more informative error message later
2770			 * on.
2771			 */
2772			interval = 0;
2773		}
2774	}
2775
2776	/*
2777	 * If the last argument is also an integer, then we have both a count
2778	 * and an interval.
2779	 */
2780	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2781		char *end;
2782
2783		errno = 0;
2784		count = interval;
2785		interval = strtoul(argv[argc - 1], &end, 10);
2786
2787		if (*end == '\0' && errno == 0) {
2788			if (interval == 0) {
2789				(void) fprintf(stderr, gettext("interval "
2790				    "cannot be zero\n"));
2791				usage(B_FALSE);
2792			}
2793
2794			/*
2795			 * Ignore the last parameter
2796			 */
2797			argc--;
2798		} else {
2799			interval = 0;
2800		}
2801	}
2802
2803	*iv = interval;
2804	*cnt = count;
2805	*argcp = argc;
2806}
2807
2808static void
2809get_timestamp_arg(char c)
2810{
2811	if (c == 'u')
2812		timestamp_fmt = UDATE;
2813	else if (c == 'd')
2814		timestamp_fmt = DDATE;
2815	else
2816		usage(B_FALSE);
2817}
2818
2819/*
2820 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2821 *
2822 *	-v	Display statistics for individual vdevs
2823 *	-T	Display a timestamp in date(1) or Unix format
2824 *
2825 * This command can be tricky because we want to be able to deal with pool
2826 * creation/destruction as well as vdev configuration changes.  The bulk of this
2827 * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
2828 * on pool_list_update() to detect the addition of new pools.  Configuration
2829 * changes are all handled within libzfs.
2830 */
2831int
2832zpool_do_iostat(int argc, char **argv)
2833{
2834	int c;
2835	int ret;
2836	int npools;
2837	unsigned long interval = 0, count = 0;
2838	zpool_list_t *list;
2839	boolean_t verbose = B_FALSE;
2840	iostat_cbdata_t cb;
2841
2842	/* check options */
2843	while ((c = getopt(argc, argv, "T:v")) != -1) {
2844		switch (c) {
2845		case 'T':
2846			get_timestamp_arg(*optarg);
2847			break;
2848		case 'v':
2849			verbose = B_TRUE;
2850			break;
2851		case '?':
2852			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2853			    optopt);
2854			usage(B_FALSE);
2855		}
2856	}
2857
2858	argc -= optind;
2859	argv += optind;
2860
2861	get_interval_count(&argc, argv, &interval, &count);
2862
2863	/*
2864	 * Construct the list of all interesting pools.
2865	 */
2866	ret = 0;
2867	if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2868		return (1);
2869
2870	if (pool_list_count(list) == 0 && argc != 0) {
2871		pool_list_free(list);
2872		return (1);
2873	}
2874
2875	if (pool_list_count(list) == 0 && interval == 0) {
2876		pool_list_free(list);
2877		(void) fprintf(stderr, gettext("no pools available\n"));
2878		return (1);
2879	}
2880
2881	/*
2882	 * Enter the main iostat loop.
2883	 */
2884	cb.cb_list = list;
2885	cb.cb_verbose = verbose;
2886	cb.cb_iteration = 0;
2887	cb.cb_namewidth = 0;
2888
2889	for (;;) {
2890		pool_list_update(list);
2891
2892		if ((npools = pool_list_count(list)) == 0)
2893			break;
2894
2895		/*
2896		 * Refresh all statistics.  This is done as an explicit step
2897		 * before calculating the maximum name width, so that any
2898		 * configuration changes are properly accounted for.
2899		 */
2900		(void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2901
2902		/*
2903		 * Iterate over all pools to determine the maximum width
2904		 * for the pool / device name column across all pools.
2905		 */
2906		cb.cb_namewidth = 0;
2907		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2908
2909		if (timestamp_fmt != NODATE)
2910			print_timestamp(timestamp_fmt);
2911
2912		/*
2913		 * If it's the first time, or verbose mode, print the header.
2914		 */
2915		if (++cb.cb_iteration == 1 || verbose)
2916			print_iostat_header(&cb);
2917
2918		(void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2919
2920		/*
2921		 * If there's more than one pool, and we're not in verbose mode
2922		 * (which prints a separator for us), then print a separator.
2923		 */
2924		if (npools > 1 && !verbose)
2925			print_iostat_separator(&cb);
2926
2927		if (verbose)
2928			(void) printf("\n");
2929
2930		/*
2931		 * Flush the output so that redirection to a file isn't buffered
2932		 * indefinitely.
2933		 */
2934		(void) fflush(stdout);
2935
2936		if (interval == 0)
2937			break;
2938
2939		if (count != 0 && --count == 0)
2940			break;
2941
2942		(void) sleep(interval);
2943	}
2944
2945	pool_list_free(list);
2946
2947	return (ret);
2948}
2949
2950typedef struct list_cbdata {
2951	boolean_t	cb_verbose;
2952	int		cb_namewidth;
2953	boolean_t	cb_scripted;
2954	zprop_list_t	*cb_proplist;
2955	boolean_t	cb_literal;
2956} list_cbdata_t;
2957
2958/*
2959 * Given a list of columns to display, output appropriate headers for each one.
2960 */
2961static void
2962print_header(list_cbdata_t *cb)
2963{
2964	zprop_list_t *pl = cb->cb_proplist;
2965	char headerbuf[ZPOOL_MAXPROPLEN];
2966	const char *header;
2967	boolean_t first = B_TRUE;
2968	boolean_t right_justify;
2969	size_t width = 0;
2970
2971	for (; pl != NULL; pl = pl->pl_next) {
2972		width = pl->pl_width;
2973		if (first && cb->cb_verbose) {
2974			/*
2975			 * Reset the width to accommodate the verbose listing
2976			 * of devices.
2977			 */
2978			width = cb->cb_namewidth;
2979		}
2980
2981		if (!first)
2982			(void) printf("  ");
2983		else
2984			first = B_FALSE;
2985
2986		right_justify = B_FALSE;
2987		if (pl->pl_prop != ZPROP_INVAL) {
2988			header = zpool_prop_column_name(pl->pl_prop);
2989			right_justify = zpool_prop_align_right(pl->pl_prop);
2990		} else {
2991			int i;
2992
2993			for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
2994				headerbuf[i] = toupper(pl->pl_user_prop[i]);
2995			headerbuf[i] = '\0';
2996			header = headerbuf;
2997		}
2998
2999		if (pl->pl_next == NULL && !right_justify)
3000			(void) printf("%s", header);
3001		else if (right_justify)
3002			(void) printf("%*s", width, header);
3003		else
3004			(void) printf("%-*s", width, header);
3005
3006	}
3007
3008	(void) printf("\n");
3009}
3010
3011/*
3012 * Given a pool and a list of properties, print out all the properties according
3013 * to the described layout.
3014 */
3015static void
3016print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3017{
3018	zprop_list_t *pl = cb->cb_proplist;
3019	boolean_t first = B_TRUE;
3020	char property[ZPOOL_MAXPROPLEN];
3021	char *propstr;
3022	boolean_t right_justify;
3023	size_t width;
3024
3025	for (; pl != NULL; pl = pl->pl_next) {
3026
3027		width = pl->pl_width;
3028		if (first && cb->cb_verbose) {
3029			/*
3030			 * Reset the width to accommodate the verbose listing
3031			 * of devices.
3032			 */
3033			width = cb->cb_namewidth;
3034		}
3035
3036		if (!first) {
3037			if (cb->cb_scripted)
3038				(void) printf("\t");
3039			else
3040				(void) printf("  ");
3041		} else {
3042			first = B_FALSE;
3043		}
3044
3045		right_justify = B_FALSE;
3046		if (pl->pl_prop != ZPROP_INVAL) {
3047			if (zpool_get_prop(zhp, pl->pl_prop, property,
3048			    sizeof (property), NULL, cb->cb_literal) != 0)
3049				propstr = "-";
3050			else
3051				propstr = property;
3052
3053			right_justify = zpool_prop_align_right(pl->pl_prop);
3054		} else if ((zpool_prop_feature(pl->pl_user_prop) ||
3055		    zpool_prop_unsupported(pl->pl_user_prop)) &&
3056		    zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3057		    sizeof (property)) == 0) {
3058			propstr = property;
3059		} else {
3060			propstr = "-";
3061		}
3062
3063
3064		/*
3065		 * If this is being called in scripted mode, or if this is the
3066		 * last column and it is left-justified, don't include a width
3067		 * format specifier.
3068		 */
3069		if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3070			(void) printf("%s", propstr);
3071		else if (right_justify)
3072			(void) printf("%*s", width, propstr);
3073		else
3074			(void) printf("%-*s", width, propstr);
3075	}
3076
3077	(void) printf("\n");
3078}
3079
3080static void
3081print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3082    boolean_t valid)
3083{
3084	char propval[64];
3085	boolean_t fixed;
3086	size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3087
3088	switch (prop) {
3089	case ZPOOL_PROP_EXPANDSZ:
3090		if (value == 0)
3091			(void) strlcpy(propval, "-", sizeof (propval));
3092		else
3093			zfs_nicenum(value, propval, sizeof (propval));
3094		break;
3095	case ZPOOL_PROP_FRAGMENTATION:
3096		if (value == ZFS_FRAG_INVALID) {
3097			(void) strlcpy(propval, "-", sizeof (propval));
3098		} else {
3099			(void) snprintf(propval, sizeof (propval), "%llu%%",
3100			    value);
3101		}
3102		break;
3103	case ZPOOL_PROP_CAPACITY:
3104		(void) snprintf(propval, sizeof (propval), "%llu%%", value);
3105		break;
3106	default:
3107		zfs_nicenum(value, propval, sizeof (propval));
3108	}
3109
3110	if (!valid)
3111		(void) strlcpy(propval, "-", sizeof (propval));
3112
3113	if (scripted)
3114		(void) printf("\t%s", propval);
3115	else
3116		(void) printf("  %*s", width, propval);
3117}
3118
3119void
3120print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3121    list_cbdata_t *cb, int depth)
3122{
3123	nvlist_t **child;
3124	vdev_stat_t *vs;
3125	uint_t c, children;
3126	char *vname;
3127	boolean_t scripted = cb->cb_scripted;
3128	uint64_t islog = B_FALSE;
3129	boolean_t haslog = B_FALSE;
3130	char *dashes = "%-*s      -      -      -         -      -      -\n";
3131
3132	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3133	    (uint64_t **)&vs, &c) == 0);
3134
3135	if (name != NULL) {
3136		boolean_t toplevel = (vs->vs_space != 0);
3137		uint64_t cap;
3138
3139		if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3140			return;
3141
3142		if (scripted)
3143			(void) printf("\t%s", name);
3144		else if (strlen(name) + depth > cb->cb_namewidth)
3145			(void) printf("%*s%s", depth, "", name);
3146		else
3147			(void) printf("%*s%s%*s", depth, "", name,
3148			    (int)(cb->cb_namewidth - strlen(name) - depth), "");
3149
3150		/*
3151		 * Print the properties for the individual vdevs. Some
3152		 * properties are only applicable to toplevel vdevs. The
3153		 * 'toplevel' boolean value is passed to the print_one_column()
3154		 * to indicate that the value is valid.
3155		 */
3156		print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3157		    toplevel);
3158		print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3159		    toplevel);
3160		print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3161		    scripted, toplevel);
3162		print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3163		    B_TRUE);
3164		print_one_column(ZPOOL_PROP_FRAGMENTATION,
3165		    vs->vs_fragmentation, scripted,
3166		    (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3167		cap = (vs->vs_space == 0) ? 0 :
3168		    (vs->vs_alloc * 100 / vs->vs_space);
3169		print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3170		(void) printf("\n");
3171	}
3172
3173	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3174	    &child, &children) != 0)
3175		return;
3176
3177	for (c = 0; c < children; c++) {
3178		uint64_t ishole = B_FALSE;
3179
3180		if (nvlist_lookup_uint64(child[c],
3181		    ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3182			continue;
3183
3184		if (nvlist_lookup_uint64(child[c],
3185		    ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3186			haslog = B_TRUE;
3187			continue;
3188		}
3189
3190		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3191		print_list_stats(zhp, vname, child[c], cb, depth + 2);
3192		free(vname);
3193	}
3194
3195	if (haslog == B_TRUE) {
3196		/* LINTED E_SEC_PRINTF_VAR_FMT */
3197		(void) printf(dashes, cb->cb_namewidth, "log");
3198		for (c = 0; c < children; c++) {
3199			if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3200			    &islog) != 0 || !islog)
3201				continue;
3202			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3203			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3204			free(vname);
3205		}
3206	}
3207
3208	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3209	    &child, &children) == 0 && children > 0) {
3210		/* LINTED E_SEC_PRINTF_VAR_FMT */
3211		(void) printf(dashes, cb->cb_namewidth, "cache");
3212		for (c = 0; c < children; c++) {
3213			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3214			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3215			free(vname);
3216		}
3217	}
3218
3219	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3220	    &children) == 0 && children > 0) {
3221		/* LINTED E_SEC_PRINTF_VAR_FMT */
3222		(void) printf(dashes, cb->cb_namewidth, "spare");
3223		for (c = 0; c < children; c++) {
3224			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3225			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3226			free(vname);
3227		}
3228	}
3229}
3230
3231
3232/*
3233 * Generic callback function to list a pool.
3234 */
3235int
3236list_callback(zpool_handle_t *zhp, void *data)
3237{
3238	list_cbdata_t *cbp = data;
3239	nvlist_t *config;
3240	nvlist_t *nvroot;
3241
3242	config = zpool_get_config(zhp, NULL);
3243
3244	print_pool(zhp, cbp);
3245	if (!cbp->cb_verbose)
3246		return (0);
3247
3248	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3249	    &nvroot) == 0);
3250	print_list_stats(zhp, NULL, nvroot, cbp, 0);
3251
3252	return (0);
3253}
3254
3255/*
3256 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3257 *
3258 *	-H	Scripted mode.  Don't display headers, and separate properties
3259 *		by a single tab.
3260 *	-o	List of properties to display.  Defaults to
3261 *		"name,size,allocated,free,expandsize,fragmentation,capacity,"
3262 *		"dedupratio,health,altroot"
3263 * 	-p	Diplay values in parsable (exact) format.
3264 *	-T	Display a timestamp in date(1) or Unix format
3265 *
3266 * List all pools in the system, whether or not they're healthy.  Output space
3267 * statistics for each one, as well as health status summary.
3268 */
3269int
3270zpool_do_list(int argc, char **argv)
3271{
3272	int c;
3273	int ret;
3274	list_cbdata_t cb = { 0 };
3275	static char default_props[] =
3276	    "name,size,allocated,free,expandsize,fragmentation,capacity,"
3277	    "dedupratio,health,altroot";
3278	char *props = default_props;
3279	unsigned long interval = 0, count = 0;
3280	zpool_list_t *list;
3281	boolean_t first = B_TRUE;
3282
3283	/* check options */
3284	while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3285		switch (c) {
3286		case 'H':
3287			cb.cb_scripted = B_TRUE;
3288			break;
3289		case 'o':
3290			props = optarg;
3291			break;
3292		case 'p':
3293			cb.cb_literal = B_TRUE;
3294			break;
3295		case 'T':
3296			get_timestamp_arg(*optarg);
3297			break;
3298		case 'v':
3299			cb.cb_verbose = B_TRUE;
3300			break;
3301		case ':':
3302			(void) fprintf(stderr, gettext("missing argument for "
3303			    "'%c' option\n"), optopt);
3304			usage(B_FALSE);
3305			break;
3306		case '?':
3307			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3308			    optopt);
3309			usage(B_FALSE);
3310		}
3311	}
3312
3313	argc -= optind;
3314	argv += optind;
3315
3316	get_interval_count(&argc, argv, &interval, &count);
3317
3318	if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3319		usage(B_FALSE);
3320
3321	for (;;) {
3322		if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3323		    &ret)) == NULL)
3324			return (1);
3325
3326		if (pool_list_count(list) == 0)
3327			break;
3328
3329		cb.cb_namewidth = 0;
3330		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3331
3332		if (timestamp_fmt != NODATE)
3333			print_timestamp(timestamp_fmt);
3334
3335		if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3336			print_header(&cb);
3337			first = B_FALSE;
3338		}
3339		ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3340
3341		if (interval == 0)
3342			break;
3343
3344		if (count != 0 && --count == 0)
3345			break;
3346
3347		pool_list_free(list);
3348		(void) sleep(interval);
3349	}
3350
3351	if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3352		(void) printf(gettext("no pools available\n"));
3353		ret = 0;
3354	}
3355
3356	pool_list_free(list);
3357	zprop_free_list(cb.cb_proplist);
3358	return (ret);
3359}
3360
3361static int
3362zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3363{
3364	boolean_t force = B_FALSE;
3365	int c;
3366	nvlist_t *nvroot;
3367	char *poolname, *old_disk, *new_disk;
3368	zpool_handle_t *zhp;
3369	zpool_boot_label_t boot_type;
3370	uint64_t boot_size;
3371	int ret;
3372
3373	/* check options */
3374	while ((c = getopt(argc, argv, "f")) != -1) {
3375		switch (c) {
3376		case 'f':
3377			force = B_TRUE;
3378			break;
3379		case '?':
3380			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3381			    optopt);
3382			usage(B_FALSE);
3383		}
3384	}
3385
3386	argc -= optind;
3387	argv += optind;
3388
3389	/* get pool name and check number of arguments */
3390	if (argc < 1) {
3391		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3392		usage(B_FALSE);
3393	}
3394
3395	poolname = argv[0];
3396
3397	if (argc < 2) {
3398		(void) fprintf(stderr,
3399		    gettext("missing <device> specification\n"));
3400		usage(B_FALSE);
3401	}
3402
3403	old_disk = argv[1];
3404
3405	if (argc < 3) {
3406		if (!replacing) {
3407			(void) fprintf(stderr,
3408			    gettext("missing <new_device> specification\n"));
3409			usage(B_FALSE);
3410		}
3411		new_disk = old_disk;
3412		argc -= 1;
3413		argv += 1;
3414	} else {
3415		new_disk = argv[2];
3416		argc -= 2;
3417		argv += 2;
3418	}
3419
3420	if (argc > 1) {
3421		(void) fprintf(stderr, gettext("too many arguments\n"));
3422		usage(B_FALSE);
3423	}
3424
3425	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3426		return (1);
3427
3428	if (zpool_get_config(zhp, NULL) == NULL) {
3429		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3430		    poolname);
3431		zpool_close(zhp);
3432		return (1);
3433	}
3434
3435	if (zpool_is_bootable(zhp))
3436		boot_type = ZPOOL_COPY_BOOT_LABEL;
3437	else
3438		boot_type = ZPOOL_NO_BOOT_LABEL;
3439
3440	boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3441	nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3442	    boot_type, boot_size, argc, argv);
3443	if (nvroot == NULL) {
3444		zpool_close(zhp);
3445		return (1);
3446	}
3447
3448	ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3449
3450	nvlist_free(nvroot);
3451	zpool_close(zhp);
3452
3453	return (ret);
3454}
3455
3456/*
3457 * zpool replace [-f] <pool> <device> <new_device>
3458 *
3459 *	-f	Force attach, even if <new_device> appears to be in use.
3460 *
3461 * Replace <device> with <new_device>.
3462 */
3463/* ARGSUSED */
3464int
3465zpool_do_replace(int argc, char **argv)
3466{
3467	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3468}
3469
3470/*
3471 * zpool attach [-f] <pool> <device> <new_device>
3472 *
3473 *	-f	Force attach, even if <new_device> appears to be in use.
3474 *
3475 * Attach <new_device> to the mirror containing <device>.  If <device> is not
3476 * part of a mirror, then <device> will be transformed into a mirror of
3477 * <device> and <new_device>.  In either case, <new_device> will begin life
3478 * with a DTL of [0, now], and will immediately begin to resilver itself.
3479 */
3480int
3481zpool_do_attach(int argc, char **argv)
3482{
3483	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3484}
3485
3486/*
3487 * zpool detach [-f] <pool> <device>
3488 *
3489 *	-f	Force detach of <device>, even if DTLs argue against it
3490 *		(not supported yet)
3491 *
3492 * Detach a device from a mirror.  The operation will be refused if <device>
3493 * is the last device in the mirror, or if the DTLs indicate that this device
3494 * has the only valid copy of some data.
3495 */
3496/* ARGSUSED */
3497int
3498zpool_do_detach(int argc, char **argv)
3499{
3500	int c;
3501	char *poolname, *path;
3502	zpool_handle_t *zhp;
3503	int ret;
3504
3505	/* check options */
3506	while ((c = getopt(argc, argv, "f")) != -1) {
3507		switch (c) {
3508		case 'f':
3509		case '?':
3510			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3511			    optopt);
3512			usage(B_FALSE);
3513		}
3514	}
3515
3516	argc -= optind;
3517	argv += optind;
3518
3519	/* get pool name and check number of arguments */
3520	if (argc < 1) {
3521		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3522		usage(B_FALSE);
3523	}
3524
3525	if (argc < 2) {
3526		(void) fprintf(stderr,
3527		    gettext("missing <device> specification\n"));
3528		usage(B_FALSE);
3529	}
3530
3531	poolname = argv[0];
3532	path = argv[1];
3533
3534	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3535		return (1);
3536
3537	ret = zpool_vdev_detach(zhp, path);
3538
3539	zpool_close(zhp);
3540
3541	return (ret);
3542}
3543
3544/*
3545 * zpool split [-n] [-o prop=val] ...
3546 *		[-o mntopt] ...
3547 *		[-R altroot] <pool> <newpool> [<device> ...]
3548 *
3549 *	-n	Do not split the pool, but display the resulting layout if
3550 *		it were to be split.
3551 *	-o	Set property=value, or set mount options.
3552 *	-R	Mount the split-off pool under an alternate root.
3553 *
3554 * Splits the named pool and gives it the new pool name.  Devices to be split
3555 * off may be listed, provided that no more than one device is specified
3556 * per top-level vdev mirror.  The newly split pool is left in an exported
3557 * state unless -R is specified.
3558 *
3559 * Restrictions: the top-level of the pool pool must only be made up of
3560 * mirrors; all devices in the pool must be healthy; no device may be
3561 * undergoing a resilvering operation.
3562 */
3563int
3564zpool_do_split(int argc, char **argv)
3565{
3566	char *srcpool, *newpool, *propval;
3567	char *mntopts = NULL;
3568	splitflags_t flags;
3569	int c, ret = 0;
3570	zpool_handle_t *zhp;
3571	nvlist_t *config, *props = NULL;
3572
3573	flags.dryrun = B_FALSE;
3574	flags.import = B_FALSE;
3575
3576	/* check options */
3577	while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3578		switch (c) {
3579		case 'R':
3580			flags.import = B_TRUE;
3581			if (add_prop_list(
3582			    zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3583			    &props, B_TRUE) != 0) {
3584				nvlist_free(props);
3585				usage(B_FALSE);
3586			}
3587			break;
3588		case 'n':
3589			flags.dryrun = B_TRUE;
3590			break;
3591		case 'o':
3592			if ((propval = strchr(optarg, '=')) != NULL) {
3593				*propval = '\0';
3594				propval++;
3595				if (add_prop_list(optarg, propval,
3596				    &props, B_TRUE) != 0) {
3597					nvlist_free(props);
3598					usage(B_FALSE);
3599				}
3600			} else {
3601				mntopts = optarg;
3602			}
3603			break;
3604		case ':':
3605			(void) fprintf(stderr, gettext("missing argument for "
3606			    "'%c' option\n"), optopt);
3607			usage(B_FALSE);
3608			break;
3609		case '?':
3610			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3611			    optopt);
3612			usage(B_FALSE);
3613			break;
3614		}
3615	}
3616
3617	if (!flags.import && mntopts != NULL) {
3618		(void) fprintf(stderr, gettext("setting mntopts is only "
3619		    "valid when importing the pool\n"));
3620		usage(B_FALSE);
3621	}
3622
3623	argc -= optind;
3624	argv += optind;
3625
3626	if (argc < 1) {
3627		(void) fprintf(stderr, gettext("Missing pool name\n"));
3628		usage(B_FALSE);
3629	}
3630	if (argc < 2) {
3631		(void) fprintf(stderr, gettext("Missing new pool name\n"));
3632		usage(B_FALSE);
3633	}
3634
3635	srcpool = argv[0];
3636	newpool = argv[1];
3637
3638	argc -= 2;
3639	argv += 2;
3640
3641	if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3642		return (1);
3643
3644	config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3645	if (config == NULL) {
3646		ret = 1;
3647	} else {
3648		if (flags.dryrun) {
3649			(void) printf(gettext("would create '%s' with the "
3650			    "following layout:\n\n"), newpool);
3651			print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3652		}
3653		nvlist_free(config);
3654	}
3655
3656	zpool_close(zhp);
3657
3658	if (ret != 0 || flags.dryrun || !flags.import)
3659		return (ret);
3660
3661	/*
3662	 * The split was successful. Now we need to open the new
3663	 * pool and import it.
3664	 */
3665	if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3666		return (1);
3667	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3668	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3669		ret = 1;
3670		(void) fprintf(stderr, gettext("Split was successful, but "
3671		    "the datasets could not all be mounted\n"));
3672		(void) fprintf(stderr, gettext("Try doing '%s' with a "
3673		    "different altroot\n"), "zpool import");
3674	}
3675	zpool_close(zhp);
3676
3677	return (ret);
3678}
3679
3680
3681
3682/*
3683 * zpool online <pool> <device> ...
3684 */
3685int
3686zpool_do_online(int argc, char **argv)
3687{
3688	int c, i;
3689	char *poolname;
3690	zpool_handle_t *zhp;
3691	int ret = 0;
3692	vdev_state_t newstate;
3693	int flags = 0;
3694
3695	/* check options */
3696	while ((c = getopt(argc, argv, "et")) != -1) {
3697		switch (c) {
3698		case 'e':
3699			flags |= ZFS_ONLINE_EXPAND;
3700			break;
3701		case 't':
3702		case '?':
3703			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3704			    optopt);
3705			usage(B_FALSE);
3706		}
3707	}
3708
3709	argc -= optind;
3710	argv += optind;
3711
3712	/* get pool name and check number of arguments */
3713	if (argc < 1) {
3714		(void) fprintf(stderr, gettext("missing pool name\n"));
3715		usage(B_FALSE);
3716	}
3717	if (argc < 2) {
3718		(void) fprintf(stderr, gettext("missing device name\n"));
3719		usage(B_FALSE);
3720	}
3721
3722	poolname = argv[0];
3723
3724	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3725		return (1);
3726
3727	for (i = 1; i < argc; i++) {
3728		if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3729			if (newstate != VDEV_STATE_HEALTHY) {
3730				(void) printf(gettext("warning: device '%s' "
3731				    "onlined, but remains in faulted state\n"),
3732				    argv[i]);
3733				if (newstate == VDEV_STATE_FAULTED)
3734					(void) printf(gettext("use 'zpool "
3735					    "clear' to restore a faulted "
3736					    "device\n"));
3737				else
3738					(void) printf(gettext("use 'zpool "
3739					    "replace' to replace devices "
3740					    "that are no longer present\n"));
3741			}
3742		} else {
3743			ret = 1;
3744		}
3745	}
3746
3747	zpool_close(zhp);
3748
3749	return (ret);
3750}
3751
3752/*
3753 * zpool offline [-ft] <pool> <device> ...
3754 *
3755 *	-f	Force the device into the offline state, even if doing
3756 *		so would appear to compromise pool availability.
3757 *		(not supported yet)
3758 *
3759 *	-t	Only take the device off-line temporarily.  The offline
3760 *		state will not be persistent across reboots.
3761 */
3762/* ARGSUSED */
3763int
3764zpool_do_offline(int argc, char **argv)
3765{
3766	int c, i;
3767	char *poolname;
3768	zpool_handle_t *zhp;
3769	int ret = 0;
3770	boolean_t istmp = B_FALSE;
3771
3772	/* check options */
3773	while ((c = getopt(argc, argv, "ft")) != -1) {
3774		switch (c) {
3775		case 't':
3776			istmp = B_TRUE;
3777			break;
3778		case 'f':
3779		case '?':
3780			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3781			    optopt);
3782			usage(B_FALSE);
3783		}
3784	}
3785
3786	argc -= optind;
3787	argv += optind;
3788
3789	/* get pool name and check number of arguments */
3790	if (argc < 1) {
3791		(void) fprintf(stderr, gettext("missing pool name\n"));
3792		usage(B_FALSE);
3793	}
3794	if (argc < 2) {
3795		(void) fprintf(stderr, gettext("missing device name\n"));
3796		usage(B_FALSE);
3797	}
3798
3799	poolname = argv[0];
3800
3801	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3802		return (1);
3803
3804	for (i = 1; i < argc; i++) {
3805		if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3806			ret = 1;
3807	}
3808
3809	zpool_close(zhp);
3810
3811	return (ret);
3812}
3813
3814/*
3815 * zpool clear <pool> [device]
3816 *
3817 * Clear all errors associated with a pool or a particular device.
3818 */
3819int
3820zpool_do_clear(int argc, char **argv)
3821{
3822	int c;
3823	int ret = 0;
3824	boolean_t dryrun = B_FALSE;
3825	boolean_t do_rewind = B_FALSE;
3826	boolean_t xtreme_rewind = B_FALSE;
3827	uint32_t rewind_policy = ZPOOL_NO_REWIND;
3828	nvlist_t *policy = NULL;
3829	zpool_handle_t *zhp;
3830	char *pool, *device;
3831
3832	/* check options */
3833	while ((c = getopt(argc, argv, "FnX")) != -1) {
3834		switch (c) {
3835		case 'F':
3836			do_rewind = B_TRUE;
3837			break;
3838		case 'n':
3839			dryrun = B_TRUE;
3840			break;
3841		case 'X':
3842			xtreme_rewind = B_TRUE;
3843			break;
3844		case '?':
3845			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3846			    optopt);
3847			usage(B_FALSE);
3848		}
3849	}
3850
3851	argc -= optind;
3852	argv += optind;
3853
3854	if (argc < 1) {
3855		(void) fprintf(stderr, gettext("missing pool name\n"));
3856		usage(B_FALSE);
3857	}
3858
3859	if (argc > 2) {
3860		(void) fprintf(stderr, gettext("too many arguments\n"));
3861		usage(B_FALSE);
3862	}
3863
3864	if ((dryrun || xtreme_rewind) && !do_rewind) {
3865		(void) fprintf(stderr,
3866		    gettext("-n or -X only meaningful with -F\n"));
3867		usage(B_FALSE);
3868	}
3869	if (dryrun)
3870		rewind_policy = ZPOOL_TRY_REWIND;
3871	else if (do_rewind)
3872		rewind_policy = ZPOOL_DO_REWIND;
3873	if (xtreme_rewind)
3874		rewind_policy |= ZPOOL_EXTREME_REWIND;
3875
3876	/* In future, further rewind policy choices can be passed along here */
3877	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3878	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3879		return (1);
3880
3881	pool = argv[0];
3882	device = argc == 2 ? argv[1] : NULL;
3883
3884	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3885		nvlist_free(policy);
3886		return (1);
3887	}
3888
3889	if (zpool_clear(zhp, device, policy) != 0)
3890		ret = 1;
3891
3892	zpool_close(zhp);
3893
3894	nvlist_free(policy);
3895
3896	return (ret);
3897}
3898
3899/*
3900 * zpool reguid <pool>
3901 */
3902int
3903zpool_do_reguid(int argc, char **argv)
3904{
3905	int c;
3906	char *poolname;
3907	zpool_handle_t *zhp;
3908	int ret = 0;
3909
3910	/* check options */
3911	while ((c = getopt(argc, argv, "")) != -1) {
3912		switch (c) {
3913		case '?':
3914			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3915			    optopt);
3916			usage(B_FALSE);
3917		}
3918	}
3919
3920	argc -= optind;
3921	argv += optind;
3922
3923	/* get pool name and check number of arguments */
3924	if (argc < 1) {
3925		(void) fprintf(stderr, gettext("missing pool name\n"));
3926		usage(B_FALSE);
3927	}
3928
3929	if (argc > 1) {
3930		(void) fprintf(stderr, gettext("too many arguments\n"));
3931		usage(B_FALSE);
3932	}
3933
3934	poolname = argv[0];
3935	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3936		return (1);
3937
3938	ret = zpool_reguid(zhp);
3939
3940	zpool_close(zhp);
3941	return (ret);
3942}
3943
3944
3945/*
3946 * zpool reopen <pool>
3947 *
3948 * Reopen the pool so that the kernel can update the sizes of all vdevs.
3949 */
3950int
3951zpool_do_reopen(int argc, char **argv)
3952{
3953	int c;
3954	int ret = 0;
3955	zpool_handle_t *zhp;
3956	char *pool;
3957
3958	/* check options */
3959	while ((c = getopt(argc, argv, "")) != -1) {
3960		switch (c) {
3961		case '?':
3962			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3963			    optopt);
3964			usage(B_FALSE);
3965		}
3966	}
3967
3968	argc--;
3969	argv++;
3970
3971	if (argc < 1) {
3972		(void) fprintf(stderr, gettext("missing pool name\n"));
3973		usage(B_FALSE);
3974	}
3975
3976	if (argc > 1) {
3977		(void) fprintf(stderr, gettext("too many arguments\n"));
3978		usage(B_FALSE);
3979	}
3980
3981	pool = argv[0];
3982	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
3983		return (1);
3984
3985	ret = zpool_reopen(zhp);
3986	zpool_close(zhp);
3987	return (ret);
3988}
3989
3990typedef struct scrub_cbdata {
3991	int	cb_type;
3992	int	cb_argc;
3993	char	**cb_argv;
3994	pool_scrub_cmd_t cb_scrub_cmd;
3995} scrub_cbdata_t;
3996
3997int
3998scrub_callback(zpool_handle_t *zhp, void *data)
3999{
4000	scrub_cbdata_t *cb = data;
4001	int err;
4002
4003	/*
4004	 * Ignore faulted pools.
4005	 */
4006	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4007		(void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4008		    "currently unavailable\n"), zpool_get_name(zhp));
4009		return (1);
4010	}
4011
4012	err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4013
4014	return (err != 0);
4015}
4016
4017/*
4018 * zpool scrub [-s | -p] <pool> ...
4019 *
4020 *	-s	Stop.  Stops any in-progress scrub.
4021 *	-p	Pause. Pause in-progress scrub.
4022 */
4023int
4024zpool_do_scrub(int argc, char **argv)
4025{
4026	int c;
4027	scrub_cbdata_t cb;
4028
4029	cb.cb_type = POOL_SCAN_SCRUB;
4030	cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4031
4032	/* check options */
4033	while ((c = getopt(argc, argv, "sp")) != -1) {
4034		switch (c) {
4035		case 's':
4036			cb.cb_type = POOL_SCAN_NONE;
4037			break;
4038		case 'p':
4039			cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4040			break;
4041		case '?':
4042			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4043			    optopt);
4044			usage(B_FALSE);
4045		}
4046	}
4047
4048	if (cb.cb_type == POOL_SCAN_NONE &&
4049	    cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4050		(void) fprintf(stderr, gettext("invalid option combination: "
4051		    "-s and -p are mutually exclusive\n"));
4052		usage(B_FALSE);
4053	}
4054
4055	cb.cb_argc = argc;
4056	cb.cb_argv = argv;
4057	argc -= optind;
4058	argv += optind;
4059
4060	if (argc < 1) {
4061		(void) fprintf(stderr, gettext("missing pool name argument\n"));
4062		usage(B_FALSE);
4063	}
4064
4065	return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4066}
4067
4068typedef struct status_cbdata {
4069	int		cb_count;
4070	boolean_t	cb_allpools;
4071	boolean_t	cb_verbose;
4072	boolean_t	cb_explain;
4073	boolean_t	cb_first;
4074	boolean_t	cb_dedup_stats;
4075} status_cbdata_t;
4076
4077/*
4078 * Print out detailed scrub status.
4079 */
4080static void
4081print_scan_status(pool_scan_stat_t *ps)
4082{
4083	time_t start, end, pause;
4084	uint64_t elapsed, mins_left, hours_left;
4085	uint64_t pass_exam, examined, total;
4086	uint_t rate;
4087	double fraction_done;
4088	char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4089
4090	(void) printf(gettext("  scan: "));
4091
4092	/* If there's never been a scan, there's not much to say. */
4093	if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4094	    ps->pss_func >= POOL_SCAN_FUNCS) {
4095		(void) printf(gettext("none requested\n"));
4096		return;
4097	}
4098
4099	start = ps->pss_start_time;
4100	end = ps->pss_end_time;
4101	pause = ps->pss_pass_scrub_pause;
4102	zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4103
4104	assert(ps->pss_func == POOL_SCAN_SCRUB ||
4105	    ps->pss_func == POOL_SCAN_RESILVER);
4106	/*
4107	 * Scan is finished or canceled.
4108	 */
4109	if (ps->pss_state == DSS_FINISHED) {
4110		uint64_t minutes_taken = (end - start) / 60;
4111		char *fmt = NULL;
4112
4113		if (ps->pss_func == POOL_SCAN_SCRUB) {
4114			fmt = gettext("scrub repaired %s in %lluh%um with "
4115			    "%llu errors on %s");
4116		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4117			fmt = gettext("resilvered %s in %lluh%um with "
4118			    "%llu errors on %s");
4119		}
4120		/* LINTED */
4121		(void) printf(fmt, processed_buf,
4122		    (u_longlong_t)(minutes_taken / 60),
4123		    (uint_t)(minutes_taken % 60),
4124		    (u_longlong_t)ps->pss_errors,
4125		    ctime((time_t *)&end));
4126		return;
4127	} else if (ps->pss_state == DSS_CANCELED) {
4128		if (ps->pss_func == POOL_SCAN_SCRUB) {
4129			(void) printf(gettext("scrub canceled on %s"),
4130			    ctime(&end));
4131		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4132			(void) printf(gettext("resilver canceled on %s"),
4133			    ctime(&end));
4134		}
4135		return;
4136	}
4137
4138	assert(ps->pss_state == DSS_SCANNING);
4139
4140	/*
4141	 * Scan is in progress.
4142	 */
4143	if (ps->pss_func == POOL_SCAN_SCRUB) {
4144		if (pause == 0) {
4145			(void) printf(gettext("scrub in progress since %s"),
4146			    ctime(&start));
4147		} else {
4148			char buf[32];
4149			struct tm *p = localtime(&pause);
4150			(void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4151			(void) printf(gettext("scrub paused since %s\n"), buf);
4152			(void) printf(gettext("\tscrub started on   %s"),
4153			    ctime(&start));
4154		}
4155	} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4156		(void) printf(gettext("resilver in progress since %s"),
4157		    ctime(&start));
4158	}
4159
4160	examined = ps->pss_examined ? ps->pss_examined : 1;
4161	total = ps->pss_to_examine;
4162	fraction_done = (double)examined / total;
4163
4164	/* elapsed time for this pass */
4165	elapsed = time(NULL) - ps->pss_pass_start;
4166	elapsed -= ps->pss_pass_scrub_spent_paused;
4167	elapsed = elapsed ? elapsed : 1;
4168	pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4169	rate = pass_exam / elapsed;
4170	rate = rate ? rate : 1;
4171	mins_left = ((total - examined) / rate) / 60;
4172	hours_left = mins_left / 60;
4173
4174	zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4175	zfs_nicenum(total, total_buf, sizeof (total_buf));
4176
4177	/*
4178	 * do not print estimated time if hours_left is more than 30 days
4179	 * or we have a paused scrub
4180	 */
4181	if (pause == 0) {
4182		zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4183		(void) printf(gettext("\t%s scanned out of %s at %s/s"),
4184		    examined_buf, total_buf, rate_buf);
4185		if (hours_left < (30 * 24)) {
4186			(void) printf(gettext(", %lluh%um to go\n"),
4187			    (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4188		} else {
4189			(void) printf(gettext(
4190			    ", (scan is slow, no estimated time)\n"));
4191		}
4192	} else {
4193		(void) printf(gettext("\t%s scanned out of %s\n"),
4194		    examined_buf, total_buf);
4195	}
4196
4197	if (ps->pss_func == POOL_SCAN_RESILVER) {
4198		(void) printf(gettext("        %s resilvered, %.2f%% done\n"),
4199		    processed_buf, 100 * fraction_done);
4200	} else if (ps->pss_func == POOL_SCAN_SCRUB) {
4201		(void) printf(gettext("        %s repaired, %.2f%% done\n"),
4202		    processed_buf, 100 * fraction_done);
4203	}
4204}
4205
4206/*
4207 * Print out detailed removal status.
4208 */
4209static void
4210print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4211{
4212	char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4213	time_t start, end;
4214	nvlist_t *config, *nvroot;
4215	nvlist_t **child;
4216	uint_t children;
4217	char *vdev_name;
4218
4219	if (prs == NULL || prs->prs_state == DSS_NONE)
4220		return;
4221
4222	/*
4223	 * Determine name of vdev.
4224	 */
4225	config = zpool_get_config(zhp, NULL);
4226	nvroot = fnvlist_lookup_nvlist(config,
4227	    ZPOOL_CONFIG_VDEV_TREE);
4228	verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4229	    &child, &children) == 0);
4230	assert(prs->prs_removing_vdev < children);
4231	vdev_name = zpool_vdev_name(g_zfs, zhp,
4232	    child[prs->prs_removing_vdev], B_TRUE);
4233
4234	(void) printf(gettext("remove: "));
4235
4236	start = prs->prs_start_time;
4237	end = prs->prs_end_time;
4238	zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4239
4240	/*
4241	 * Removal is finished or canceled.
4242	 */
4243	if (prs->prs_state == DSS_FINISHED) {
4244		uint64_t minutes_taken = (end - start) / 60;
4245
4246		(void) printf(gettext("Removal of vdev %llu copied %s "
4247		    "in %lluh%um, completed on %s"),
4248		    (longlong_t)prs->prs_removing_vdev,
4249		    copied_buf,
4250		    (u_longlong_t)(minutes_taken / 60),
4251		    (uint_t)(minutes_taken % 60),
4252		    ctime((time_t *)&end));
4253	} else if (prs->prs_state == DSS_CANCELED) {
4254		(void) printf(gettext("Removal of %s canceled on %s"),
4255		    vdev_name, ctime(&end));
4256	} else {
4257		uint64_t copied, total, elapsed, mins_left, hours_left;
4258		double fraction_done;
4259		uint_t rate;
4260
4261		assert(prs->prs_state == DSS_SCANNING);
4262
4263		/*
4264		 * Removal is in progress.
4265		 */
4266		(void) printf(gettext(
4267		    "Evacuation of %s in progress since %s"),
4268		    vdev_name, ctime(&start));
4269
4270		copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4271		total = prs->prs_to_copy;
4272		fraction_done = (double)copied / total;
4273
4274		/* elapsed time for this pass */
4275		elapsed = time(NULL) - prs->prs_start_time;
4276		elapsed = elapsed > 0 ? elapsed : 1;
4277		rate = copied / elapsed;
4278		rate = rate > 0 ? rate : 1;
4279		mins_left = ((total - copied) / rate) / 60;
4280		hours_left = mins_left / 60;
4281
4282		zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4283		zfs_nicenum(total, total_buf, sizeof (total_buf));
4284		zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4285
4286		/*
4287		 * do not print estimated time if hours_left is more than
4288		 * 30 days
4289		 */
4290		(void) printf(gettext("    %s copied out of %s at %s/s, "
4291		    "%.2f%% done"),
4292		    examined_buf, total_buf, rate_buf, 100 * fraction_done);
4293		if (hours_left < (30 * 24)) {
4294			(void) printf(gettext(", %lluh%um to go\n"),
4295			    (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4296		} else {
4297			(void) printf(gettext(
4298			    ", (copy is slow, no estimated time)\n"));
4299		}
4300	}
4301
4302	if (prs->prs_mapping_memory > 0) {
4303		char mem_buf[7];
4304		zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4305		(void) printf(gettext("    %s memory used for "
4306		    "removed device mappings\n"),
4307		    mem_buf);
4308	}
4309}
4310
4311static void
4312print_error_log(zpool_handle_t *zhp)
4313{
4314	nvlist_t *nverrlist = NULL;
4315	nvpair_t *elem;
4316	char *pathname;
4317	size_t len = MAXPATHLEN * 2;
4318
4319	if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4320		(void) printf("errors: List of errors unavailable "
4321		    "(insufficient privileges)\n");
4322		return;
4323	}
4324
4325	(void) printf("errors: Permanent errors have been "
4326	    "detected in the following files:\n\n");
4327
4328	pathname = safe_malloc(len);
4329	elem = NULL;
4330	while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4331		nvlist_t *nv;
4332		uint64_t dsobj, obj;
4333
4334		verify(nvpair_value_nvlist(elem, &nv) == 0);
4335		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4336		    &dsobj) == 0);
4337		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4338		    &obj) == 0);
4339		zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4340		(void) printf("%7s %s\n", "", pathname);
4341	}
4342	free(pathname);
4343	nvlist_free(nverrlist);
4344}
4345
4346static void
4347print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4348    int namewidth)
4349{
4350	uint_t i;
4351	char *name;
4352
4353	if (nspares == 0)
4354		return;
4355
4356	(void) printf(gettext("\tspares\n"));
4357
4358	for (i = 0; i < nspares; i++) {
4359		name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4360		print_status_config(zhp, name, spares[i],
4361		    namewidth, 2, B_TRUE);
4362		free(name);
4363	}
4364}
4365
4366static void
4367print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4368    int namewidth)
4369{
4370	uint_t i;
4371	char *name;
4372
4373	if (nl2cache == 0)
4374		return;
4375
4376	(void) printf(gettext("\tcache\n"));
4377
4378	for (i = 0; i < nl2cache; i++) {
4379		name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4380		print_status_config(zhp, name, l2cache[i],
4381		    namewidth, 2, B_FALSE);
4382		free(name);
4383	}
4384}
4385
4386static void
4387print_dedup_stats(nvlist_t *config)
4388{
4389	ddt_histogram_t *ddh;
4390	ddt_stat_t *dds;
4391	ddt_object_t *ddo;
4392	uint_t c;
4393
4394	/*
4395	 * If the pool was faulted then we may not have been able to
4396	 * obtain the config. Otherwise, if we have anything in the dedup
4397	 * table continue processing the stats.
4398	 */
4399	if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4400	    (uint64_t **)&ddo, &c) != 0)
4401		return;
4402
4403	(void) printf("\n");
4404	(void) printf(gettext(" dedup: "));
4405	if (ddo->ddo_count == 0) {
4406		(void) printf(gettext("no DDT entries\n"));
4407		return;
4408	}
4409
4410	(void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4411	    (u_longlong_t)ddo->ddo_count,
4412	    (u_longlong_t)ddo->ddo_dspace,
4413	    (u_longlong_t)ddo->ddo_mspace);
4414
4415	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4416	    (uint64_t **)&dds, &c) == 0);
4417	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4418	    (uint64_t **)&ddh, &c) == 0);
4419	zpool_dump_ddt(dds, ddh);
4420}
4421
4422/*
4423 * Display a summary of pool status.  Displays a summary such as:
4424 *
4425 *        pool: tank
4426 *	status: DEGRADED
4427 *	reason: One or more devices ...
4428 *         see: http://illumos.org/msg/ZFS-xxxx-01
4429 *	config:
4430 *		mirror		DEGRADED
4431 *                c1t0d0	OK
4432 *                c2t0d0	UNAVAIL
4433 *
4434 * When given the '-v' option, we print out the complete config.  If the '-e'
4435 * option is specified, then we print out error rate information as well.
4436 */
4437int
4438status_callback(zpool_handle_t *zhp, void *data)
4439{
4440	status_cbdata_t *cbp = data;
4441	nvlist_t *config, *nvroot;
4442	char *msgid;
4443	int reason;
4444	const char *health;
4445	uint_t c;
4446	vdev_stat_t *vs;
4447
4448	config = zpool_get_config(zhp, NULL);
4449	reason = zpool_get_status(zhp, &msgid);
4450
4451	cbp->cb_count++;
4452
4453	/*
4454	 * If we were given 'zpool status -x', only report those pools with
4455	 * problems.
4456	 */
4457	if (cbp->cb_explain &&
4458	    (reason == ZPOOL_STATUS_OK ||
4459	    reason == ZPOOL_STATUS_VERSION_OLDER ||
4460	    reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
4461	    reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4462		if (!cbp->cb_allpools) {
4463			(void) printf(gettext("pool '%s' is healthy\n"),
4464			    zpool_get_name(zhp));
4465			if (cbp->cb_first)
4466				cbp->cb_first = B_FALSE;
4467		}
4468		return (0);
4469	}
4470
4471	if (cbp->cb_first)
4472		cbp->cb_first = B_FALSE;
4473	else
4474		(void) printf("\n");
4475
4476	nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4477	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4478	    (uint64_t **)&vs, &c) == 0);
4479	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4480
4481	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4482	(void) printf(gettext(" state: %s\n"), health);
4483
4484	switch (reason) {
4485	case ZPOOL_STATUS_MISSING_DEV_R:
4486		(void) printf(gettext("status: One or more devices could not "
4487		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
4488		    "continue functioning in a degraded state.\n"));
4489		(void) printf(gettext("action: Attach the missing device and "
4490		    "online it using 'zpool online'.\n"));
4491		break;
4492
4493	case ZPOOL_STATUS_MISSING_DEV_NR:
4494		(void) printf(gettext("status: One or more devices could not "
4495		    "be opened.  There are insufficient\n\treplicas for the "
4496		    "pool to continue functioning.\n"));
4497		(void) printf(gettext("action: Attach the missing device and "
4498		    "online it using 'zpool online'.\n"));
4499		break;
4500
4501	case ZPOOL_STATUS_CORRUPT_LABEL_R:
4502		(void) printf(gettext("status: One or more devices could not "
4503		    "be used because the label is missing or\n\tinvalid.  "
4504		    "Sufficient replicas exist for the pool to continue\n\t"
4505		    "functioning in a degraded state.\n"));
4506		(void) printf(gettext("action: Replace the device using "
4507		    "'zpool replace'.\n"));
4508		break;
4509
4510	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4511		(void) printf(gettext("status: One or more devices could not "
4512		    "be used because the label is missing \n\tor invalid.  "
4513		    "There are insufficient replicas for the pool to "
4514		    "continue\n\tfunctioning.\n"));
4515		zpool_explain_recover(zpool_get_handle(zhp),
4516		    zpool_get_name(zhp), reason, config);
4517		break;
4518
4519	case ZPOOL_STATUS_FAILING_DEV:
4520		(void) printf(gettext("status: One or more devices has "
4521		    "experienced an unrecoverable error.  An\n\tattempt was "
4522		    "made to correct the error.  Applications are "
4523		    "unaffected.\n"));
4524		(void) printf(gettext("action: Determine if the device needs "
4525		    "to be replaced, and clear the errors\n\tusing "
4526		    "'zpool clear' or replace the device with 'zpool "
4527		    "replace'.\n"));
4528		break;
4529
4530	case ZPOOL_STATUS_OFFLINE_DEV:
4531		(void) printf(gettext("status: One or more devices has "
4532		    "been taken offline by the administrator.\n\tSufficient "
4533		    "replicas exist for the pool to continue functioning in "
4534		    "a\n\tdegraded state.\n"));
4535		(void) printf(gettext("action: Online the device using "
4536		    "'zpool online' or replace the device with\n\t'zpool "
4537		    "replace'.\n"));
4538		break;
4539
4540	case ZPOOL_STATUS_REMOVED_DEV:
4541		(void) printf(gettext("status: One or more devices has "
4542		    "been removed by the administrator.\n\tSufficient "
4543		    "replicas exist for the pool to continue functioning in "
4544		    "a\n\tdegraded state.\n"));
4545		(void) printf(gettext("action: Online the device using "
4546		    "'zpool online' or replace the device with\n\t'zpool "
4547		    "replace'.\n"));
4548		break;
4549
4550	case ZPOOL_STATUS_RESILVERING:
4551		(void) printf(gettext("status: One or more devices is "
4552		    "currently being resilvered.  The pool will\n\tcontinue "
4553		    "to function, possibly in a degraded state.\n"));
4554		(void) printf(gettext("action: Wait for the resilver to "
4555		    "complete.\n"));
4556		break;
4557
4558	case ZPOOL_STATUS_CORRUPT_DATA:
4559		(void) printf(gettext("status: One or more devices has "
4560		    "experienced an error resulting in data\n\tcorruption.  "
4561		    "Applications may be affected.\n"));
4562		(void) printf(gettext("action: Restore the file in question "
4563		    "if possible.  Otherwise restore the\n\tentire pool from "
4564		    "backup.\n"));
4565		break;
4566
4567	case ZPOOL_STATUS_CORRUPT_POOL:
4568		(void) printf(gettext("status: The pool metadata is corrupted "
4569		    "and the pool cannot be opened.\n"));
4570		zpool_explain_recover(zpool_get_handle(zhp),
4571		    zpool_get_name(zhp), reason, config);
4572		break;
4573
4574	case ZPOOL_STATUS_VERSION_OLDER:
4575		(void) printf(gettext("status: The pool is formatted using a "
4576		    "legacy on-disk format.  The pool can\n\tstill be used, "
4577		    "but some features are unavailable.\n"));
4578		(void) printf(gettext("action: Upgrade the pool using 'zpool "
4579		    "upgrade'.  Once this is done, the\n\tpool will no longer "
4580		    "be accessible on software that does not support feature\n"
4581		    "\tflags.\n"));
4582		break;
4583
4584	case ZPOOL_STATUS_VERSION_NEWER:
4585		(void) printf(gettext("status: The pool has been upgraded to a "
4586		    "newer, incompatible on-disk version.\n\tThe pool cannot "
4587		    "be accessed on this system.\n"));
4588		(void) printf(gettext("action: Access the pool from a system "
4589		    "running more recent software, or\n\trestore the pool from "
4590		    "backup.\n"));
4591		break;
4592
4593	case ZPOOL_STATUS_FEAT_DISABLED:
4594		(void) printf(gettext("status: Some supported features are not "
4595		    "enabled on the pool. The pool can\n\tstill be used, but "
4596		    "some features are unavailable.\n"));
4597		(void) printf(gettext("action: Enable all features using "
4598		    "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4599		    "longer be accessible by software that does not support\n\t"
4600		    "the features. See zpool-features(7) for details.\n"));
4601		break;
4602
4603	case ZPOOL_STATUS_UNSUP_FEAT_READ:
4604		(void) printf(gettext("status: The pool cannot be accessed on "
4605		    "this system because it uses the\n\tfollowing feature(s) "
4606		    "not supported on this system:\n"));
4607		zpool_print_unsup_feat(config);
4608		(void) printf("\n");
4609		(void) printf(gettext("action: Access the pool from a system "
4610		    "that supports the required feature(s),\n\tor restore the "
4611		    "pool from backup.\n"));
4612		break;
4613
4614	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4615		(void) printf(gettext("status: The pool can only be accessed "
4616		    "in read-only mode on this system. It\n\tcannot be "
4617		    "accessed in read-write mode because it uses the "
4618		    "following\n\tfeature(s) not supported on this system:\n"));
4619		zpool_print_unsup_feat(config);
4620		(void) printf("\n");
4621		(void) printf(gettext("action: The pool cannot be accessed in "
4622		    "read-write mode. Import the pool with\n"
4623		    "\t\"-o readonly=on\", access the pool from a system that "
4624		    "supports the\n\trequired feature(s), or restore the "
4625		    "pool from backup.\n"));
4626		break;
4627
4628	case ZPOOL_STATUS_FAULTED_DEV_R:
4629		(void) printf(gettext("status: One or more devices are "
4630		    "faulted in response to persistent errors.\n\tSufficient "
4631		    "replicas exist for the pool to continue functioning "
4632		    "in a\n\tdegraded state.\n"));
4633		(void) printf(gettext("action: Replace the faulted device, "
4634		    "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4635		break;
4636
4637	case ZPOOL_STATUS_FAULTED_DEV_NR:
4638		(void) printf(gettext("status: One or more devices are "
4639		    "faulted in response to persistent errors.  There are "
4640		    "insufficient replicas for the pool to\n\tcontinue "
4641		    "functioning.\n"));
4642		(void) printf(gettext("action: Destroy and re-create the pool "
4643		    "from a backup source.  Manually marking the device\n"
4644		    "\trepaired using 'zpool clear' may allow some data "
4645		    "to be recovered.\n"));
4646		break;
4647
4648	case ZPOOL_STATUS_IO_FAILURE_WAIT:
4649	case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4650		(void) printf(gettext("status: One or more devices are "
4651		    "faulted in response to IO failures.\n"));
4652		(void) printf(gettext("action: Make sure the affected devices "
4653		    "are connected, then run 'zpool clear'.\n"));
4654		break;
4655
4656	case ZPOOL_STATUS_BAD_LOG:
4657		(void) printf(gettext("status: An intent log record "
4658		    "could not be read.\n"
4659		    "\tWaiting for adminstrator intervention to fix the "
4660		    "faulted pool.\n"));
4661		(void) printf(gettext("action: Either restore the affected "
4662		    "device(s) and run 'zpool online',\n"
4663		    "\tor ignore the intent log records by running "
4664		    "'zpool clear'.\n"));
4665		break;
4666
4667	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
4668		(void) printf(gettext("status: One or more devices are "
4669		    "configured to use a non-native block size.\n"
4670		    "\tExpect reduced performance.\n"));
4671		(void) printf(gettext("action: Replace affected devices with "
4672		    "devices that support the\n\tconfigured block size, or "
4673		    "migrate data to a properly configured\n\tpool.\n"));
4674		break;
4675
4676	default:
4677		/*
4678		 * The remaining errors can't actually be generated, yet.
4679		 */
4680		assert(reason == ZPOOL_STATUS_OK);
4681	}
4682
4683	if (msgid != NULL)
4684		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4685		    msgid);
4686
4687	if (config != NULL) {
4688		int namewidth;
4689		uint64_t nerr;
4690		nvlist_t **spares, **l2cache;
4691		uint_t nspares, nl2cache;
4692		pool_scan_stat_t *ps = NULL;
4693		pool_removal_stat_t *prs = NULL;
4694
4695		(void) nvlist_lookup_uint64_array(nvroot,
4696		    ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4697		print_scan_status(ps);
4698
4699		(void) nvlist_lookup_uint64_array(nvroot,
4700		    ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4701		print_removal_status(zhp, prs);
4702
4703		namewidth = max_width(zhp, nvroot, 0, 0);
4704		if (namewidth < 10)
4705			namewidth = 10;
4706
4707		(void) printf(gettext("config:\n\n"));
4708		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4709		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
4710		print_status_config(zhp, zpool_get_name(zhp), nvroot,
4711		    namewidth, 0, B_FALSE);
4712
4713		if (num_logs(nvroot) > 0)
4714			print_logs(zhp, nvroot, namewidth, B_TRUE);
4715		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4716		    &l2cache, &nl2cache) == 0)
4717			print_l2cache(zhp, l2cache, nl2cache, namewidth);
4718
4719		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4720		    &spares, &nspares) == 0)
4721			print_spares(zhp, spares, nspares, namewidth);
4722
4723		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4724		    &nerr) == 0) {
4725			nvlist_t *nverrlist = NULL;
4726
4727			/*
4728			 * If the approximate error count is small, get a
4729			 * precise count by fetching the entire log and
4730			 * uniquifying the results.
4731			 */
4732			if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4733			    zpool_get_errlog(zhp, &nverrlist) == 0) {
4734				nvpair_t *elem;
4735
4736				elem = NULL;
4737				nerr = 0;
4738				while ((elem = nvlist_next_nvpair(nverrlist,
4739				    elem)) != NULL) {
4740					nerr++;
4741				}
4742			}
4743			nvlist_free(nverrlist);
4744
4745			(void) printf("\n");
4746
4747			if (nerr == 0)
4748				(void) printf(gettext("errors: No known data "
4749				    "errors\n"));
4750			else if (!cbp->cb_verbose)
4751				(void) printf(gettext("errors: %llu data "
4752				    "errors, use '-v' for a list\n"),
4753				    (u_longlong_t)nerr);
4754			else
4755				print_error_log(zhp);
4756		}
4757
4758		if (cbp->cb_dedup_stats)
4759			print_dedup_stats(config);
4760	} else {
4761		(void) printf(gettext("config: The configuration cannot be "
4762		    "determined.\n"));
4763	}
4764
4765	return (0);
4766}
4767
4768/*
4769 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4770 *
4771 *	-v	Display complete error logs
4772 *	-x	Display only pools with potential problems
4773 *	-D	Display dedup status (undocumented)
4774 *	-T	Display a timestamp in date(1) or Unix format
4775 *
4776 * Describes the health status of all pools or some subset.
4777 */
4778int
4779zpool_do_status(int argc, char **argv)
4780{
4781	int c;
4782	int ret;
4783	unsigned long interval = 0, count = 0;
4784	status_cbdata_t cb = { 0 };
4785
4786	/* check options */
4787	while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4788		switch (c) {
4789		case 'v':
4790			cb.cb_verbose = B_TRUE;
4791			break;
4792		case 'x':
4793			cb.cb_explain = B_TRUE;
4794			break;
4795		case 'D':
4796			cb.cb_dedup_stats = B_TRUE;
4797			break;
4798		case 'T':
4799			get_timestamp_arg(*optarg);
4800			break;
4801		case '?':
4802			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4803			    optopt);
4804			usage(B_FALSE);
4805		}
4806	}
4807
4808	argc -= optind;
4809	argv += optind;
4810
4811	get_interval_count(&argc, argv, &interval, &count);
4812
4813	if (argc == 0)
4814		cb.cb_allpools = B_TRUE;
4815
4816	cb.cb_first = B_TRUE;
4817
4818	for (;;) {
4819		if (timestamp_fmt != NODATE)
4820			print_timestamp(timestamp_fmt);
4821
4822		ret = for_each_pool(argc, argv, B_TRUE, NULL,
4823		    status_callback, &cb);
4824
4825		if (argc == 0 && cb.cb_count == 0)
4826			(void) printf(gettext("no pools available\n"));
4827		else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4828			(void) printf(gettext("all pools are healthy\n"));
4829
4830		if (ret != 0)
4831			return (ret);
4832
4833		if (interval == 0)
4834			break;
4835
4836		if (count != 0 && --count == 0)
4837			break;
4838
4839		(void) sleep(interval);
4840	}
4841
4842	return (0);
4843}
4844
4845typedef struct upgrade_cbdata {
4846	boolean_t	cb_first;
4847	boolean_t	cb_unavail;
4848	char		cb_poolname[ZFS_MAX_DATASET_NAME_LEN];
4849	int		cb_argc;
4850	uint64_t	cb_version;
4851	char		**cb_argv;
4852} upgrade_cbdata_t;
4853
4854#ifdef __FreeBSD__
4855static int
4856is_root_pool(zpool_handle_t *zhp)
4857{
4858	static struct statfs sfs;
4859	static char *poolname = NULL;
4860	static boolean_t stated = B_FALSE;
4861	char *slash;
4862
4863	if (!stated) {
4864		stated = B_TRUE;
4865		if (statfs("/", &sfs) == -1) {
4866			(void) fprintf(stderr,
4867			    "Unable to stat root file system: %s.\n",
4868			    strerror(errno));
4869			return (0);
4870		}
4871		if (strcmp(sfs.f_fstypename, "zfs") != 0)
4872			return (0);
4873		poolname = sfs.f_mntfromname;
4874		if ((slash = strchr(poolname, '/')) != NULL)
4875			*slash = '\0';
4876	}
4877	return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
4878}
4879
4880static void
4881root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
4882{
4883
4884	if (poolname[0] == '\0' && is_root_pool(zhp))
4885		(void) strlcpy(poolname, zpool_get_name(zhp), size);
4886}
4887#endif	/* FreeBSD */
4888
4889static int
4890upgrade_version(zpool_handle_t *zhp, uint64_t version)
4891{
4892	int ret;
4893	nvlist_t *config;
4894	uint64_t oldversion;
4895
4896	config = zpool_get_config(zhp, NULL);
4897	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4898	    &oldversion) == 0);
4899
4900	assert(SPA_VERSION_IS_SUPPORTED(oldversion));
4901	assert(oldversion < version);
4902
4903	ret = zpool_upgrade(zhp, version);
4904	if (ret != 0)
4905		return (ret);
4906
4907	if (version >= SPA_VERSION_FEATURES) {
4908		(void) printf(gettext("Successfully upgraded "
4909		    "'%s' from version %llu to feature flags.\n"),
4910		    zpool_get_name(zhp), oldversion);
4911	} else {
4912		(void) printf(gettext("Successfully upgraded "
4913		    "'%s' from version %llu to version %llu.\n"),
4914		    zpool_get_name(zhp), oldversion, version);
4915	}
4916
4917	return (0);
4918}
4919
4920static int
4921upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4922{
4923	int i, ret, count;
4924	boolean_t firstff = B_TRUE;
4925	nvlist_t *enabled = zpool_get_features(zhp);
4926
4927	count = 0;
4928	for (i = 0; i < SPA_FEATURES; i++) {
4929		const char *fname = spa_feature_table[i].fi_uname;
4930		const char *fguid = spa_feature_table[i].fi_guid;
4931		if (!nvlist_exists(enabled, fguid)) {
4932			char *propname;
4933			verify(-1 != asprintf(&propname, "feature@%s", fname));
4934			ret = zpool_set_prop(zhp, propname,
4935			    ZFS_FEATURE_ENABLED);
4936			if (ret != 0) {
4937				free(propname);
4938				return (ret);
4939			}
4940			count++;
4941
4942			if (firstff) {
4943				(void) printf(gettext("Enabled the "
4944				    "following features on '%s':\n"),
4945				    zpool_get_name(zhp));
4946				firstff = B_FALSE;
4947			}
4948			(void) printf(gettext("  %s\n"), fname);
4949			free(propname);
4950		}
4951	}
4952
4953	if (countp != NULL)
4954		*countp = count;
4955	return (0);
4956}
4957
4958static int
4959upgrade_cb(zpool_handle_t *zhp, void *arg)
4960{
4961	upgrade_cbdata_t *cbp = arg;
4962	nvlist_t *config;
4963	uint64_t version;
4964	boolean_t printnl = B_FALSE;
4965	int ret;
4966
4967	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4968		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
4969		    "currently unavailable.\n\n"), zpool_get_name(zhp));
4970		cbp->cb_unavail = B_TRUE;
4971		/* Allow iteration to continue. */
4972		return (0);
4973	}
4974
4975	config = zpool_get_config(zhp, NULL);
4976	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4977	    &version) == 0);
4978
4979	assert(SPA_VERSION_IS_SUPPORTED(version));
4980
4981	if (version < cbp->cb_version) {
4982		cbp->cb_first = B_FALSE;
4983		ret = upgrade_version(zhp, cbp->cb_version);
4984		if (ret != 0)
4985			return (ret);
4986#ifdef __FreeBSD__
4987		root_pool_upgrade_check(zhp, cbp->cb_poolname,
4988		    sizeof(cbp->cb_poolname));
4989#endif	/* __FreeBSD__ */
4990		printnl = B_TRUE;
4991
4992#ifdef illumos
4993		/*
4994		 * If they did "zpool upgrade -a", then we could
4995		 * be doing ioctls to different pools.  We need
4996		 * to log this history once to each pool, and bypass
4997		 * the normal history logging that happens in main().
4998		 */
4999		(void) zpool_log_history(g_zfs, history_str);
5000		log_history = B_FALSE;
5001#endif
5002	}
5003
5004	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5005		int count;
5006		ret = upgrade_enable_all(zhp, &count);
5007		if (ret != 0)
5008			return (ret);
5009
5010		if (count > 0) {
5011			cbp->cb_first = B_FALSE;
5012			printnl = B_TRUE;
5013#ifdef __FreeBSD__
5014			root_pool_upgrade_check(zhp, cbp->cb_poolname,
5015			    sizeof(cbp->cb_poolname));
5016#endif	/* __FreeBSD__ */
5017			/*
5018			 * If they did "zpool upgrade -a", then we could
5019			 * be doing ioctls to different pools.  We need
5020			 * to log this history once to each pool, and bypass
5021			 * the normal history logging that happens in main().
5022			 */
5023			(void) zpool_log_history(g_zfs, history_str);
5024			log_history = B_FALSE;
5025		}
5026	}
5027
5028	if (printnl) {
5029		(void) printf(gettext("\n"));
5030	}
5031
5032	return (0);
5033}
5034
5035static int
5036upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
5037{
5038	upgrade_cbdata_t *cbp = arg;
5039
5040	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5041		if (cbp->cb_first) {
5042			(void) fprintf(stderr, gettext("The following pools "
5043			    "are unavailable and cannot be upgraded as this "
5044			    "time.\n\n"));
5045			(void) fprintf(stderr, gettext("POOL\n"));
5046			(void) fprintf(stderr, gettext("------------\n"));
5047			cbp->cb_first = B_FALSE;
5048		}
5049		(void) printf(gettext("%s\n"), zpool_get_name(zhp));
5050		cbp->cb_unavail = B_TRUE;
5051	}
5052	return (0);
5053}
5054
5055static int
5056upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5057{
5058	upgrade_cbdata_t *cbp = arg;
5059	nvlist_t *config;
5060	uint64_t version;
5061
5062	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5063		/*
5064		 * This will have been reported by upgrade_list_unavail so
5065		 * just allow iteration to continue.
5066		 */
5067		cbp->cb_unavail = B_TRUE;
5068		return (0);
5069	}
5070
5071	config = zpool_get_config(zhp, NULL);
5072	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5073	    &version) == 0);
5074
5075	assert(SPA_VERSION_IS_SUPPORTED(version));
5076
5077	if (version < SPA_VERSION_FEATURES) {
5078		if (cbp->cb_first) {
5079			(void) printf(gettext("The following pools are "
5080			    "formatted with legacy version numbers and can\n"
5081			    "be upgraded to use feature flags.  After "
5082			    "being upgraded, these pools\nwill no "
5083			    "longer be accessible by software that does not "
5084			    "support feature\nflags.\n\n"));
5085			(void) printf(gettext("VER  POOL\n"));
5086			(void) printf(gettext("---  ------------\n"));
5087			cbp->cb_first = B_FALSE;
5088		}
5089
5090		(void) printf("%2llu   %s\n", (u_longlong_t)version,
5091		    zpool_get_name(zhp));
5092	}
5093
5094	return (0);
5095}
5096
5097static int
5098upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5099{
5100	upgrade_cbdata_t *cbp = arg;
5101	nvlist_t *config;
5102	uint64_t version;
5103
5104	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5105		/*
5106		 * This will have been reported by upgrade_list_unavail so
5107		 * just allow iteration to continue.
5108		 */
5109		cbp->cb_unavail = B_TRUE;
5110		return (0);
5111	}
5112
5113	config = zpool_get_config(zhp, NULL);
5114	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5115	    &version) == 0);
5116
5117	if (version >= SPA_VERSION_FEATURES) {
5118		int i;
5119		boolean_t poolfirst = B_TRUE;
5120		nvlist_t *enabled = zpool_get_features(zhp);
5121
5122		for (i = 0; i < SPA_FEATURES; i++) {
5123			const char *fguid = spa_feature_table[i].fi_guid;
5124			const char *fname = spa_feature_table[i].fi_uname;
5125			if (!nvlist_exists(enabled, fguid)) {
5126				if (cbp->cb_first) {
5127					(void) printf(gettext("\nSome "
5128					    "supported features are not "
5129					    "enabled on the following pools. "
5130					    "Once a\nfeature is enabled the "
5131					    "pool may become incompatible with "
5132					    "software\nthat does not support "
5133					    "the feature. See "
5134					    "zpool-features(7) for "
5135					    "details.\n\n"));
5136					(void) printf(gettext("POOL  "
5137					    "FEATURE\n"));
5138					(void) printf(gettext("------"
5139					    "---------\n"));
5140					cbp->cb_first = B_FALSE;
5141				}
5142
5143				if (poolfirst) {
5144					(void) printf(gettext("%s\n"),
5145					    zpool_get_name(zhp));
5146					poolfirst = B_FALSE;
5147				}
5148
5149				(void) printf(gettext("      %s\n"), fname);
5150			}
5151		}
5152	}
5153
5154	return (0);
5155}
5156
5157/* ARGSUSED */
5158static int
5159upgrade_one(zpool_handle_t *zhp, void *data)
5160{
5161	boolean_t printnl = B_FALSE;
5162	upgrade_cbdata_t *cbp = data;
5163	uint64_t cur_version;
5164	int ret;
5165
5166	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5167		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5168		    "is currently unavailable.\n\n"), zpool_get_name(zhp));
5169		cbp->cb_unavail = B_TRUE;
5170		return (1);
5171	}
5172
5173	if (strcmp("log", zpool_get_name(zhp)) == 0) {
5174		(void) printf(gettext("'log' is now a reserved word\n"
5175		    "Pool 'log' must be renamed using export and import"
5176		    " to upgrade.\n\n"));
5177		return (1);
5178	}
5179
5180	cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5181	if (cur_version > cbp->cb_version) {
5182		(void) printf(gettext("Pool '%s' is already formatted "
5183		    "using more current version '%llu'.\n\n"),
5184		    zpool_get_name(zhp), cur_version);
5185		return (0);
5186	}
5187
5188	if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5189		(void) printf(gettext("Pool '%s' is already formatted "
5190		    "using version %llu.\n\n"), zpool_get_name(zhp),
5191		    cbp->cb_version);
5192		return (0);
5193	}
5194
5195	if (cur_version != cbp->cb_version) {
5196		printnl = B_TRUE;
5197		ret = upgrade_version(zhp, cbp->cb_version);
5198		if (ret != 0)
5199			return (ret);
5200#ifdef __FreeBSD__
5201		root_pool_upgrade_check(zhp, cbp->cb_poolname,
5202		    sizeof(cbp->cb_poolname));
5203#endif	/* __FreeBSD__ */
5204	}
5205
5206	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5207		int count = 0;
5208		ret = upgrade_enable_all(zhp, &count);
5209		if (ret != 0)
5210			return (ret);
5211
5212		if (count != 0) {
5213			printnl = B_TRUE;
5214#ifdef __FreeBSD__
5215			root_pool_upgrade_check(zhp, cbp->cb_poolname,
5216			    sizeof(cbp->cb_poolname));
5217#endif	/* __FreeBSD __*/
5218		} else if (cur_version == SPA_VERSION) {
5219			(void) printf(gettext("Pool '%s' already has all "
5220			    "supported features enabled.\n\n"),
5221			    zpool_get_name(zhp));
5222		}
5223	}
5224
5225	if (printnl) {
5226		(void) printf(gettext("\n"));
5227	}
5228
5229	return (0);
5230}
5231
5232/*
5233 * zpool upgrade
5234 * zpool upgrade -v
5235 * zpool upgrade [-V version] <-a | pool ...>
5236 *
5237 * With no arguments, display downrev'd ZFS pool available for upgrade.
5238 * Individual pools can be upgraded by specifying the pool, and '-a' will
5239 * upgrade all pools.
5240 */
5241int
5242zpool_do_upgrade(int argc, char **argv)
5243{
5244	int c;
5245	upgrade_cbdata_t cb = { 0 };
5246	int ret = 0;
5247	boolean_t showversions = B_FALSE;
5248	boolean_t upgradeall = B_FALSE;
5249	char *end;
5250
5251
5252	/* check options */
5253	while ((c = getopt(argc, argv, ":avV:")) != -1) {
5254		switch (c) {
5255		case 'a':
5256			upgradeall = B_TRUE;
5257			break;
5258		case 'v':
5259			showversions = B_TRUE;
5260			break;
5261		case 'V':
5262			cb.cb_version = strtoll(optarg, &end, 10);
5263			if (*end != '\0' ||
5264			    !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5265				(void) fprintf(stderr,
5266				    gettext("invalid version '%s'\n"), optarg);
5267				usage(B_FALSE);
5268			}
5269			break;
5270		case ':':
5271			(void) fprintf(stderr, gettext("missing argument for "
5272			    "'%c' option\n"), optopt);
5273			usage(B_FALSE);
5274			break;
5275		case '?':
5276			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5277			    optopt);
5278			usage(B_FALSE);
5279		}
5280	}
5281
5282	cb.cb_argc = argc;
5283	cb.cb_argv = argv;
5284	argc -= optind;
5285	argv += optind;
5286
5287	if (cb.cb_version == 0) {
5288		cb.cb_version = SPA_VERSION;
5289	} else if (!upgradeall && argc == 0) {
5290		(void) fprintf(stderr, gettext("-V option is "
5291		    "incompatible with other arguments\n"));
5292		usage(B_FALSE);
5293	}
5294
5295	if (showversions) {
5296		if (upgradeall || argc != 0) {
5297			(void) fprintf(stderr, gettext("-v option is "
5298			    "incompatible with other arguments\n"));
5299			usage(B_FALSE);
5300		}
5301	} else if (upgradeall) {
5302		if (argc != 0) {
5303			(void) fprintf(stderr, gettext("-a option should not "
5304			    "be used along with a pool name\n"));
5305			usage(B_FALSE);
5306		}
5307	}
5308
5309	(void) printf(gettext("This system supports ZFS pool feature "
5310	    "flags.\n\n"));
5311	if (showversions) {
5312		int i;
5313
5314		(void) printf(gettext("The following features are "
5315		    "supported:\n\n"));
5316		(void) printf(gettext("FEAT DESCRIPTION\n"));
5317		(void) printf("----------------------------------------------"
5318		    "---------------\n");
5319		for (i = 0; i < SPA_FEATURES; i++) {
5320			zfeature_info_t *fi = &spa_feature_table[i];
5321			const char *ro =
5322			    (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5323			    " (read-only compatible)" : "";
5324
5325			(void) printf("%-37s%s\n", fi->fi_uname, ro);
5326			(void) printf("     %s\n", fi->fi_desc);
5327		}
5328		(void) printf("\n");
5329
5330		(void) printf(gettext("The following legacy versions are also "
5331		    "supported:\n\n"));
5332		(void) printf(gettext("VER  DESCRIPTION\n"));
5333		(void) printf("---  -----------------------------------------"
5334		    "---------------\n");
5335		(void) printf(gettext(" 1   Initial ZFS version\n"));
5336		(void) printf(gettext(" 2   Ditto blocks "
5337		    "(replicated metadata)\n"));
5338		(void) printf(gettext(" 3   Hot spares and double parity "
5339		    "RAID-Z\n"));
5340		(void) printf(gettext(" 4   zpool history\n"));
5341		(void) printf(gettext(" 5   Compression using the gzip "
5342		    "algorithm\n"));
5343		(void) printf(gettext(" 6   bootfs pool property\n"));
5344		(void) printf(gettext(" 7   Separate intent log devices\n"));
5345		(void) printf(gettext(" 8   Delegated administration\n"));
5346		(void) printf(gettext(" 9   refquota and refreservation "
5347		    "properties\n"));
5348		(void) printf(gettext(" 10  Cache devices\n"));
5349		(void) printf(gettext(" 11  Improved scrub performance\n"));
5350		(void) printf(gettext(" 12  Snapshot properties\n"));
5351		(void) printf(gettext(" 13  snapused property\n"));
5352		(void) printf(gettext(" 14  passthrough-x aclinherit\n"));
5353		(void) printf(gettext(" 15  user/group space accounting\n"));
5354		(void) printf(gettext(" 16  stmf property support\n"));
5355		(void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
5356		(void) printf(gettext(" 18  Snapshot user holds\n"));
5357		(void) printf(gettext(" 19  Log device removal\n"));
5358		(void) printf(gettext(" 20  Compression using zle "
5359		    "(zero-length encoding)\n"));
5360		(void) printf(gettext(" 21  Deduplication\n"));
5361		(void) printf(gettext(" 22  Received properties\n"));
5362		(void) printf(gettext(" 23  Slim ZIL\n"));
5363		(void) printf(gettext(" 24  System attributes\n"));
5364		(void) printf(gettext(" 25  Improved scrub stats\n"));
5365		(void) printf(gettext(" 26  Improved snapshot deletion "
5366		    "performance\n"));
5367		(void) printf(gettext(" 27  Improved snapshot creation "
5368		    "performance\n"));
5369		(void) printf(gettext(" 28  Multiple vdev replacements\n"));
5370		(void) printf(gettext("\nFor more information on a particular "
5371		    "version, including supported releases,\n"));
5372		(void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5373	} else if (argc == 0 && upgradeall) {
5374		cb.cb_first = B_TRUE;
5375		ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5376		if (ret == 0 && cb.cb_first) {
5377			if (cb.cb_version == SPA_VERSION) {
5378				(void) printf(gettext("All %spools are already "
5379				    "formatted using feature flags.\n\n"),
5380				    cb.cb_unavail ? gettext("available ") : "");
5381				(void) printf(gettext("Every %sfeature flags "
5382				    "pool already has all supported features "
5383				    "enabled.\n"),
5384				    cb.cb_unavail ? gettext("available ") : "");
5385			} else {
5386				(void) printf(gettext("All pools are already "
5387				    "formatted with version %llu or higher.\n"),
5388				    cb.cb_version);
5389			}
5390		}
5391	} else if (argc == 0) {
5392		cb.cb_first = B_TRUE;
5393		ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
5394		assert(ret == 0);
5395
5396		if (!cb.cb_first) {
5397			(void) fprintf(stderr, "\n");
5398		}
5399
5400		cb.cb_first = B_TRUE;
5401		ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5402		assert(ret == 0);
5403
5404		if (cb.cb_first) {
5405			(void) printf(gettext("All %spools are formatted using "
5406			    "feature flags.\n\n"), cb.cb_unavail ?
5407			    gettext("available ") : "");
5408		} else {
5409			(void) printf(gettext("\nUse 'zpool upgrade -v' "
5410			    "for a list of available legacy versions.\n"));
5411		}
5412
5413		cb.cb_first = B_TRUE;
5414		ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5415		assert(ret == 0);
5416
5417		if (cb.cb_first) {
5418			(void) printf(gettext("Every %sfeature flags pool has "
5419			    "all supported features enabled.\n"),
5420			    cb.cb_unavail ? gettext("available ") : "");
5421		} else {
5422			(void) printf(gettext("\n"));
5423		}
5424	} else {
5425		ret = for_each_pool(argc, argv, B_TRUE, NULL,
5426		    upgrade_one, &cb);
5427	}
5428
5429	if (cb.cb_poolname[0] != '\0') {
5430		(void) printf(
5431		    "If you boot from pool '%s', don't forget to update boot code.\n"
5432		    "Assuming you use GPT partitioning and da0 is your boot disk\n"
5433		    "the following command will do it:\n"
5434		    "\n"
5435		    "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
5436		    cb.cb_poolname);
5437	}
5438
5439	return (ret);
5440}
5441
5442typedef struct hist_cbdata {
5443	boolean_t first;
5444	boolean_t longfmt;
5445	boolean_t internal;
5446} hist_cbdata_t;
5447
5448/*
5449 * Print out the command history for a specific pool.
5450 */
5451static int
5452get_history_one(zpool_handle_t *zhp, void *data)
5453{
5454	nvlist_t *nvhis;
5455	nvlist_t **records;
5456	uint_t numrecords;
5457	int ret, i;
5458	hist_cbdata_t *cb = (hist_cbdata_t *)data;
5459
5460	cb->first = B_FALSE;
5461
5462	(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5463
5464	if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5465		return (ret);
5466
5467	verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5468	    &records, &numrecords) == 0);
5469	for (i = 0; i < numrecords; i++) {
5470		nvlist_t *rec = records[i];
5471		char tbuf[30] = "";
5472
5473		if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5474			time_t tsec;
5475			struct tm t;
5476
5477			tsec = fnvlist_lookup_uint64(records[i],
5478			    ZPOOL_HIST_TIME);
5479			(void) localtime_r(&tsec, &t);
5480			(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5481		}
5482
5483		if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5484			(void) printf("%s %s", tbuf,
5485			    fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5486		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5487			int ievent =
5488			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5489			if (!cb->internal)
5490				continue;
5491			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5492				(void) printf("%s unrecognized record:\n",
5493				    tbuf);
5494				dump_nvlist(rec, 4);
5495				continue;
5496			}
5497			(void) printf("%s [internal %s txg:%lld] %s", tbuf,
5498			    zfs_history_event_names[ievent],
5499			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5500			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5501		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5502			if (!cb->internal)
5503				continue;
5504			(void) printf("%s [txg:%lld] %s", tbuf,
5505			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5506			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5507			if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5508				(void) printf(" %s (%llu)",
5509				    fnvlist_lookup_string(rec,
5510				    ZPOOL_HIST_DSNAME),
5511				    fnvlist_lookup_uint64(rec,
5512				    ZPOOL_HIST_DSID));
5513			}
5514			(void) printf(" %s", fnvlist_lookup_string(rec,
5515			    ZPOOL_HIST_INT_STR));
5516		} else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5517			if (!cb->internal)
5518				continue;
5519			(void) printf("%s ioctl %s\n", tbuf,
5520			    fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5521			if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5522				(void) printf("    input:\n");
5523				dump_nvlist(fnvlist_lookup_nvlist(rec,
5524				    ZPOOL_HIST_INPUT_NVL), 8);
5525			}
5526			if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5527				(void) printf("    output:\n");
5528				dump_nvlist(fnvlist_lookup_nvlist(rec,
5529				    ZPOOL_HIST_OUTPUT_NVL), 8);
5530			}
5531			if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5532				(void) printf("    errno: %lld\n",
5533				    fnvlist_lookup_int64(rec,
5534				    ZPOOL_HIST_ERRNO));
5535			}
5536		} else {
5537			if (!cb->internal)
5538				continue;
5539			(void) printf("%s unrecognized record:\n", tbuf);
5540			dump_nvlist(rec, 4);
5541		}
5542
5543		if (!cb->longfmt) {
5544			(void) printf("\n");
5545			continue;
5546		}
5547		(void) printf(" [");
5548		if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5549			uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5550			struct passwd *pwd = getpwuid(who);
5551			(void) printf("user %d ", (int)who);
5552			if (pwd != NULL)
5553				(void) printf("(%s) ", pwd->pw_name);
5554		}
5555		if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5556			(void) printf("on %s",
5557			    fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5558		}
5559		if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5560			(void) printf(":%s",
5561			    fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5562		}
5563		(void) printf("]");
5564		(void) printf("\n");
5565	}
5566	(void) printf("\n");
5567	nvlist_free(nvhis);
5568
5569	return (ret);
5570}
5571
5572/*
5573 * zpool history <pool>
5574 *
5575 * Displays the history of commands that modified pools.
5576 */
5577int
5578zpool_do_history(int argc, char **argv)
5579{
5580	hist_cbdata_t cbdata = { 0 };
5581	int ret;
5582	int c;
5583
5584	cbdata.first = B_TRUE;
5585	/* check options */
5586	while ((c = getopt(argc, argv, "li")) != -1) {
5587		switch (c) {
5588		case 'l':
5589			cbdata.longfmt = B_TRUE;
5590			break;
5591		case 'i':
5592			cbdata.internal = B_TRUE;
5593			break;
5594		case '?':
5595			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5596			    optopt);
5597			usage(B_FALSE);
5598		}
5599	}
5600	argc -= optind;
5601	argv += optind;
5602
5603	ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
5604	    &cbdata);
5605
5606	if (argc == 0 && cbdata.first == B_TRUE) {
5607		(void) printf(gettext("no pools available\n"));
5608		return (0);
5609	}
5610
5611	return (ret);
5612}
5613
5614static int
5615get_callback(zpool_handle_t *zhp, void *data)
5616{
5617	zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5618	char value[MAXNAMELEN];
5619	zprop_source_t srctype;
5620	zprop_list_t *pl;
5621
5622	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5623
5624		/*
5625		 * Skip the special fake placeholder. This will also skip
5626		 * over the name property when 'all' is specified.
5627		 */
5628		if (pl->pl_prop == ZPOOL_PROP_NAME &&
5629		    pl == cbp->cb_proplist)
5630			continue;
5631
5632		if (pl->pl_prop == ZPROP_INVAL &&
5633		    (zpool_prop_feature(pl->pl_user_prop) ||
5634		    zpool_prop_unsupported(pl->pl_user_prop))) {
5635			srctype = ZPROP_SRC_LOCAL;
5636
5637			if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5638			    value, sizeof (value)) == 0) {
5639				zprop_print_one_property(zpool_get_name(zhp),
5640				    cbp, pl->pl_user_prop, value, srctype,
5641				    NULL, NULL);
5642			}
5643		} else {
5644			if (zpool_get_prop(zhp, pl->pl_prop, value,
5645			    sizeof (value), &srctype, cbp->cb_literal) != 0)
5646				continue;
5647
5648			zprop_print_one_property(zpool_get_name(zhp), cbp,
5649			    zpool_prop_to_name(pl->pl_prop), value, srctype,
5650			    NULL, NULL);
5651		}
5652	}
5653	return (0);
5654}
5655
5656/*
5657 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5658 *
5659 *	-H	Scripted mode.  Don't display headers, and separate properties
5660 *		by a single tab.
5661 *	-o	List of columns to display.  Defaults to
5662 *		"name,property,value,source".
5663 * 	-p	Diplay values in parsable (exact) format.
5664 *
5665 * Get properties of pools in the system. Output space statistics
5666 * for each one as well as other attributes.
5667 */
5668int
5669zpool_do_get(int argc, char **argv)
5670{
5671	zprop_get_cbdata_t cb = { 0 };
5672	zprop_list_t fake_name = { 0 };
5673	int ret;
5674	int c, i;
5675	char *value;
5676
5677	cb.cb_first = B_TRUE;
5678
5679	/*
5680	 * Set up default columns and sources.
5681	 */
5682	cb.cb_sources = ZPROP_SRC_ALL;
5683	cb.cb_columns[0] = GET_COL_NAME;
5684	cb.cb_columns[1] = GET_COL_PROPERTY;
5685	cb.cb_columns[2] = GET_COL_VALUE;
5686	cb.cb_columns[3] = GET_COL_SOURCE;
5687	cb.cb_type = ZFS_TYPE_POOL;
5688
5689	/* check options */
5690	while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5691		switch (c) {
5692		case 'p':
5693			cb.cb_literal = B_TRUE;
5694			break;
5695		case 'H':
5696			cb.cb_scripted = B_TRUE;
5697			break;
5698		case 'o':
5699			bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5700			i = 0;
5701			while (*optarg != '\0') {
5702				static char *col_subopts[] =
5703				{ "name", "property", "value", "source",
5704				"all", NULL };
5705
5706				if (i == ZFS_GET_NCOLS) {
5707					(void) fprintf(stderr, gettext("too "
5708					"many fields given to -o "
5709					"option\n"));
5710					usage(B_FALSE);
5711				}
5712
5713				switch (getsubopt(&optarg, col_subopts,
5714				    &value)) {
5715				case 0:
5716					cb.cb_columns[i++] = GET_COL_NAME;
5717					break;
5718				case 1:
5719					cb.cb_columns[i++] = GET_COL_PROPERTY;
5720					break;
5721				case 2:
5722					cb.cb_columns[i++] = GET_COL_VALUE;
5723					break;
5724				case 3:
5725					cb.cb_columns[i++] = GET_COL_SOURCE;
5726					break;
5727				case 4:
5728					if (i > 0) {
5729						(void) fprintf(stderr,
5730						    gettext("\"all\" conflicts "
5731						    "with specific fields "
5732						    "given to -o option\n"));
5733						usage(B_FALSE);
5734					}
5735					cb.cb_columns[0] = GET_COL_NAME;
5736					cb.cb_columns[1] = GET_COL_PROPERTY;
5737					cb.cb_columns[2] = GET_COL_VALUE;
5738					cb.cb_columns[3] = GET_COL_SOURCE;
5739					i = ZFS_GET_NCOLS;
5740					break;
5741				default:
5742					(void) fprintf(stderr,
5743					    gettext("invalid column name "
5744					    "'%s'\n"), suboptarg);
5745					usage(B_FALSE);
5746				}
5747			}
5748			break;
5749		case '?':
5750			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5751			    optopt);
5752			usage(B_FALSE);
5753		}
5754	}
5755
5756	argc -= optind;
5757	argv += optind;
5758
5759	if (argc < 1) {
5760		(void) fprintf(stderr, gettext("missing property "
5761		    "argument\n"));
5762		usage(B_FALSE);
5763	}
5764
5765	if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5766	    ZFS_TYPE_POOL) != 0)
5767		usage(B_FALSE);
5768
5769	argc--;
5770	argv++;
5771
5772	if (cb.cb_proplist != NULL) {
5773		fake_name.pl_prop = ZPOOL_PROP_NAME;
5774		fake_name.pl_width = strlen(gettext("NAME"));
5775		fake_name.pl_next = cb.cb_proplist;
5776		cb.cb_proplist = &fake_name;
5777	}
5778
5779	ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5780	    get_callback, &cb);
5781
5782	if (cb.cb_proplist == &fake_name)
5783		zprop_free_list(fake_name.pl_next);
5784	else
5785		zprop_free_list(cb.cb_proplist);
5786
5787	return (ret);
5788}
5789
5790typedef struct set_cbdata {
5791	char *cb_propname;
5792	char *cb_value;
5793	boolean_t cb_any_successful;
5794} set_cbdata_t;
5795
5796int
5797set_callback(zpool_handle_t *zhp, void *data)
5798{
5799	int error;
5800	set_cbdata_t *cb = (set_cbdata_t *)data;
5801
5802	error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5803
5804	if (!error)
5805		cb->cb_any_successful = B_TRUE;
5806
5807	return (error);
5808}
5809
5810int
5811zpool_do_set(int argc, char **argv)
5812{
5813	set_cbdata_t cb = { 0 };
5814	int error;
5815
5816	if (argc > 1 && argv[1][0] == '-') {
5817		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5818		    argv[1][1]);
5819		usage(B_FALSE);
5820	}
5821
5822	if (argc < 2) {
5823		(void) fprintf(stderr, gettext("missing property=value "
5824		    "argument\n"));
5825		usage(B_FALSE);
5826	}
5827
5828	if (argc < 3) {
5829		(void) fprintf(stderr, gettext("missing pool name\n"));
5830		usage(B_FALSE);
5831	}
5832
5833	if (argc > 3) {
5834		(void) fprintf(stderr, gettext("too many pool names\n"));
5835		usage(B_FALSE);
5836	}
5837
5838	cb.cb_propname = argv[1];
5839	cb.cb_value = strchr(cb.cb_propname, '=');
5840	if (cb.cb_value == NULL) {
5841		(void) fprintf(stderr, gettext("missing value in "
5842		    "property=value argument\n"));
5843		usage(B_FALSE);
5844	}
5845
5846	*(cb.cb_value) = '\0';
5847	cb.cb_value++;
5848
5849	error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5850	    set_callback, &cb);
5851
5852	return (error);
5853}
5854
5855static int
5856find_command_idx(char *command, int *idx)
5857{
5858	int i;
5859
5860	for (i = 0; i < NCOMMAND; i++) {
5861		if (command_table[i].name == NULL)
5862			continue;
5863
5864		if (strcmp(command, command_table[i].name) == 0) {
5865			*idx = i;
5866			return (0);
5867		}
5868	}
5869	return (1);
5870}
5871
5872int
5873main(int argc, char **argv)
5874{
5875	int ret = 0;
5876	int i;
5877	char *cmdname;
5878
5879	(void) setlocale(LC_ALL, "");
5880	(void) textdomain(TEXT_DOMAIN);
5881
5882	if ((g_zfs = libzfs_init()) == NULL) {
5883		(void) fprintf(stderr, gettext("internal error: failed to "
5884		    "initialize ZFS library\n"));
5885		return (1);
5886	}
5887
5888	libzfs_print_on_error(g_zfs, B_TRUE);
5889
5890	opterr = 0;
5891
5892	/*
5893	 * Make sure the user has specified some command.
5894	 */
5895	if (argc < 2) {
5896		(void) fprintf(stderr, gettext("missing command\n"));
5897		usage(B_FALSE);
5898	}
5899
5900	cmdname = argv[1];
5901
5902	/*
5903	 * Special case '-?'
5904	 */
5905	if (strcmp(cmdname, "-?") == 0)
5906		usage(B_TRUE);
5907
5908	zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5909
5910	/*
5911	 * Run the appropriate command.
5912	 */
5913	if (find_command_idx(cmdname, &i) == 0) {
5914		current_command = &command_table[i];
5915		ret = command_table[i].func(argc - 1, argv + 1);
5916	} else if (strchr(cmdname, '=')) {
5917		verify(find_command_idx("set", &i) == 0);
5918		current_command = &command_table[i];
5919		ret = command_table[i].func(argc, argv);
5920	} else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5921		/*
5922		 * 'freeze' is a vile debugging abomination, so we treat
5923		 * it as such.
5924		 */
5925		zfs_cmd_t zc = { 0 };
5926		(void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
5927		return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
5928	} else {
5929		(void) fprintf(stderr, gettext("unrecognized "
5930		    "command '%s'\n"), cmdname);
5931		usage(B_FALSE);
5932	}
5933
5934	if (ret == 0 && log_history)
5935		(void) zpool_log_history(g_zfs, history_str);
5936
5937	libzfs_fini(g_zfs);
5938
5939	/*
5940	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5941	 * for the purposes of running ::findleaks.
5942	 */
5943	if (getenv("ZFS_ABORT") != NULL) {
5944		(void) printf("dumping core by request\n");
5945		abort();
5946	}
5947
5948	return (ret);
5949}
5950