1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
29 * Copyright 2016 Nexenta Systems, Inc.
30 * Copyright (c) 2017 Datto Inc.
31 */
32
33#include <solaris.h>
34#include <assert.h>
35#include <ctype.h>
36#include <dirent.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <getopt.h>
40#include <libgen.h>
41#include <libintl.h>
42#include <libuutil.h>
43#include <locale.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <strings.h>
48#include <unistd.h>
49#include <priv.h>
50#include <pwd.h>
51#include <zone.h>
52#include <sys/time.h>
53#include <zfs_prop.h>
54#include <sys/fs/zfs.h>
55#include <sys/stat.h>
56
57#include <libzfs.h>
58
59#include "zpool_util.h"
60#include "zfs_comutil.h"
61#include "zfeature_common.h"
62
63#include "statcommon.h"
64
65libzfs_handle_t *g_zfs;
66
67static int zpool_do_create(int, char **);
68static int zpool_do_destroy(int, char **);
69
70static int zpool_do_add(int, char **);
71static int zpool_do_remove(int, char **);
72static int zpool_do_labelclear(int, char **);
73
74static int zpool_do_checkpoint(int, char **);
75
76static int zpool_do_list(int, char **);
77static int zpool_do_iostat(int, char **);
78static int zpool_do_status(int, char **);
79
80static int zpool_do_online(int, char **);
81static int zpool_do_offline(int, char **);
82static int zpool_do_clear(int, char **);
83static int zpool_do_reopen(int, char **);
84
85static int zpool_do_reguid(int, char **);
86
87static int zpool_do_attach(int, char **);
88static int zpool_do_detach(int, char **);
89static int zpool_do_replace(int, char **);
90static int zpool_do_split(int, char **);
91
92static int zpool_do_initialize(int, char **);
93static int zpool_do_scrub(int, char **);
94
95static int zpool_do_import(int, char **);
96static int zpool_do_export(int, char **);
97
98static int zpool_do_upgrade(int, char **);
99
100static int zpool_do_history(int, char **);
101
102static int zpool_do_get(int, char **);
103static int zpool_do_set(int, char **);
104
105/*
106 * These libumem hooks provide a reasonable set of defaults for the allocator's
107 * debugging facilities.
108 */
109
110#ifdef DEBUG
111const char *
112_umem_debug_init(void)
113{
114	return ("default,verbose"); /* $UMEM_DEBUG setting */
115}
116
117const char *
118_umem_logging_init(void)
119{
120	return ("fail,contents"); /* $UMEM_LOGGING setting */
121}
122#endif
123
124typedef enum {
125	HELP_ADD,
126	HELP_ATTACH,
127	HELP_CLEAR,
128	HELP_CREATE,
129	HELP_CHECKPOINT,
130	HELP_DESTROY,
131	HELP_DETACH,
132	HELP_EXPORT,
133	HELP_HISTORY,
134	HELP_IMPORT,
135	HELP_IOSTAT,
136	HELP_LABELCLEAR,
137	HELP_LIST,
138	HELP_OFFLINE,
139	HELP_ONLINE,
140	HELP_REPLACE,
141	HELP_REMOVE,
142	HELP_INITIALIZE,
143	HELP_SCRUB,
144	HELP_STATUS,
145	HELP_UPGRADE,
146	HELP_GET,
147	HELP_SET,
148	HELP_SPLIT,
149	HELP_REGUID,
150	HELP_REOPEN
151} zpool_help_t;
152
153
154typedef struct zpool_command {
155	const char	*name;
156	int		(*func)(int, char **);
157	zpool_help_t	usage;
158} zpool_command_t;
159
160/*
161 * Master command table.  Each ZFS command has a name, associated function, and
162 * usage message.  The usage messages need to be internationalized, so we have
163 * to have a function to return the usage message based on a command index.
164 *
165 * These commands are organized according to how they are displayed in the usage
166 * message.  An empty command (one with a NULL name) indicates an empty line in
167 * the generic usage message.
168 */
169static zpool_command_t command_table[] = {
170	{ "create",	zpool_do_create,	HELP_CREATE		},
171	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
172	{ NULL },
173	{ "add",	zpool_do_add,		HELP_ADD		},
174	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
175	{ NULL },
176	{ "labelclear",	zpool_do_labelclear,	HELP_LABELCLEAR		},
177	{ NULL },
178	{ "checkpoint",	zpool_do_checkpoint,	HELP_CHECKPOINT		},
179	{ NULL },
180	{ "list",	zpool_do_list,		HELP_LIST		},
181	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
182	{ "status",	zpool_do_status,	HELP_STATUS		},
183	{ NULL },
184	{ "online",	zpool_do_online,	HELP_ONLINE		},
185	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
186	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
187	{ "reopen",	zpool_do_reopen,	HELP_REOPEN		},
188	{ NULL },
189	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
190	{ "detach",	zpool_do_detach,	HELP_DETACH		},
191	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
192	{ "split",	zpool_do_split,		HELP_SPLIT		},
193	{ NULL },
194	{ "initialize",	zpool_do_initialize,	HELP_INITIALIZE		},
195	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
196	{ NULL },
197	{ "import",	zpool_do_import,	HELP_IMPORT		},
198	{ "export",	zpool_do_export,	HELP_EXPORT		},
199	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
200	{ "reguid",	zpool_do_reguid,	HELP_REGUID		},
201	{ NULL },
202	{ "history",	zpool_do_history,	HELP_HISTORY		},
203	{ "get",	zpool_do_get,		HELP_GET		},
204	{ "set",	zpool_do_set,		HELP_SET		},
205};
206
207#define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
208
209static zpool_command_t *current_command;
210static char history_str[HIS_MAX_RECORD_LEN];
211static boolean_t log_history = B_TRUE;
212static uint_t timestamp_fmt = NODATE;
213
214static const char *
215get_usage(zpool_help_t idx)
216{
217	switch (idx) {
218	case HELP_ADD:
219		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
220	case HELP_ATTACH:
221		return (gettext("\tattach [-f] <pool> <device> "
222		    "<new-device>\n"));
223	case HELP_CLEAR:
224		return (gettext("\tclear [-nF] <pool> [device]\n"));
225	case HELP_CREATE:
226		return (gettext("\tcreate [-fnd] [-B] "
227		    "[-o property=value] ... \n"
228		    "\t    [-O file-system-property=value] ...\n"
229		    "\t    [-m mountpoint] [-R root] [-t tempname] "
230		    "<pool> <vdev> ...\n"));
231	case HELP_CHECKPOINT:
232		return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
233	case HELP_DESTROY:
234		return (gettext("\tdestroy [-f] <pool>\n"));
235	case HELP_DETACH:
236		return (gettext("\tdetach <pool> <device>\n"));
237	case HELP_EXPORT:
238		return (gettext("\texport [-f] <pool> ...\n"));
239	case HELP_HISTORY:
240		return (gettext("\thistory [-il] [<pool>] ...\n"));
241	case HELP_IMPORT:
242		return (gettext("\timport [-d dir] [-D]\n"
243		    "\timport [-o mntopts] [-o property=value] ... \n"
244		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
245		    "[-R root] [-F [-n]] -a\n"
246		    "\timport [-o mntopts] [-o property=value] ... \n"
247		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
248		    "[-R root] [-F [-n]] [-t]\n"
249		    "\t    [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
250	case HELP_IOSTAT:
251		return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
252		    "[count]]\n"));
253	case HELP_LABELCLEAR:
254		return (gettext("\tlabelclear [-f] <vdev>\n"));
255	case HELP_LIST:
256		return (gettext("\tlist [-Hpv] [-o property[,...]] "
257		    "[-T d|u] [pool] ... [interval [count]]\n"));
258	case HELP_OFFLINE:
259		return (gettext("\toffline [-t] <pool> <device> ...\n"));
260	case HELP_ONLINE:
261		return (gettext("\tonline [-e] <pool> <device> ...\n"));
262	case HELP_REPLACE:
263		return (gettext("\treplace [-f] <pool> <device> "
264		    "[new-device]\n"));
265	case HELP_REMOVE:
266		return (gettext("\tremove [-nps] <pool> <device> ...\n"));
267	case HELP_REOPEN:
268		return (gettext("\treopen <pool>\n"));
269	case HELP_INITIALIZE:
270		return (gettext("\tinitialize [-cs] <pool> [<device> ...]\n"));
271	case HELP_SCRUB:
272		return (gettext("\tscrub [-s | -p] <pool> ...\n"));
273	case HELP_STATUS:
274		return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
275		    "[count]]\n"));
276	case HELP_UPGRADE:
277		return (gettext("\tupgrade [-v]\n"
278		    "\tupgrade [-V version] <-a | pool ...>\n"));
279	case HELP_GET:
280		return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
281		    "<\"all\" | property[,...]> <pool> ...\n"));
282	case HELP_SET:
283		return (gettext("\tset <property=value> <pool> \n"));
284	case HELP_SPLIT:
285		return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
286		    "\t    [-o property=value] <pool> <newpool> "
287		    "[<device> ...]\n"));
288	case HELP_REGUID:
289		return (gettext("\treguid <pool>\n"));
290	}
291
292	abort();
293	/* NOTREACHED */
294}
295
296
297/*
298 * Callback routine that will print out a pool property value.
299 */
300static int
301print_prop_cb(int prop, void *cb)
302{
303	FILE *fp = cb;
304
305	(void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
306
307	if (zpool_prop_readonly(prop))
308		(void) fprintf(fp, "  NO   ");
309	else
310		(void) fprintf(fp, " YES   ");
311
312	if (zpool_prop_values(prop) == NULL)
313		(void) fprintf(fp, "-\n");
314	else
315		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
316
317	return (ZPROP_CONT);
318}
319
320/*
321 * Display usage message.  If we're inside a command, display only the usage for
322 * that command.  Otherwise, iterate over the entire command table and display
323 * a complete usage message.
324 */
325void
326usage(boolean_t requested)
327{
328	FILE *fp = requested ? stdout : stderr;
329
330	if (current_command == NULL) {
331		int i;
332
333		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
334		(void) fprintf(fp,
335		    gettext("where 'command' is one of the following:\n\n"));
336
337		for (i = 0; i < NCOMMAND; i++) {
338			if (command_table[i].name == NULL)
339				(void) fprintf(fp, "\n");
340			else
341				(void) fprintf(fp, "%s",
342				    get_usage(command_table[i].usage));
343		}
344	} else {
345		(void) fprintf(fp, gettext("usage:\n"));
346		(void) fprintf(fp, "%s", get_usage(current_command->usage));
347	}
348
349	if (current_command != NULL &&
350	    ((strcmp(current_command->name, "set") == 0) ||
351	    (strcmp(current_command->name, "get") == 0) ||
352	    (strcmp(current_command->name, "list") == 0))) {
353
354		(void) fprintf(fp,
355		    gettext("\nthe following properties are supported:\n"));
356
357		(void) fprintf(fp, "\n\t%-15s  %s   %s\n\n",
358		    "PROPERTY", "EDIT", "VALUES");
359
360		/* Iterate over all properties */
361		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
362		    ZFS_TYPE_POOL);
363
364		(void) fprintf(fp, "\t%-15s   ", "feature@...");
365		(void) fprintf(fp, "YES   disabled | enabled | active\n");
366
367		(void) fprintf(fp, gettext("\nThe feature@ properties must be "
368		    "appended with a feature name.\nSee zpool-features(7).\n"));
369	}
370
371	/*
372	 * See comments at end of main().
373	 */
374	if (getenv("ZFS_ABORT") != NULL) {
375		(void) printf("dumping core by request\n");
376		abort();
377	}
378
379	exit(requested ? 0 : 2);
380}
381
382void
383print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
384    boolean_t print_logs)
385{
386	nvlist_t **child;
387	uint_t c, children;
388	char *vname;
389
390	if (name != NULL)
391		(void) printf("\t%*s%s\n", indent, "", name);
392
393	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
394	    &child, &children) != 0)
395		return;
396
397	for (c = 0; c < children; c++) {
398		uint64_t is_log = B_FALSE;
399
400		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
401		    &is_log);
402		if ((is_log && !print_logs) || (!is_log && print_logs))
403			continue;
404
405		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
406		print_vdev_tree(zhp, vname, child[c], indent + 2,
407		    B_FALSE);
408		free(vname);
409	}
410}
411
412static boolean_t
413prop_list_contains_feature(nvlist_t *proplist)
414{
415	nvpair_t *nvp;
416	for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
417	    nvp = nvlist_next_nvpair(proplist, nvp)) {
418		if (zpool_prop_feature(nvpair_name(nvp)))
419			return (B_TRUE);
420	}
421	return (B_FALSE);
422}
423
424/*
425 * Add a property pair (name, string-value) into a property nvlist.
426 */
427static int
428add_prop_list(const char *propname, char *propval, nvlist_t **props,
429    boolean_t poolprop)
430{
431	zpool_prop_t prop = ZPROP_INVAL;
432	zfs_prop_t fprop;
433	nvlist_t *proplist;
434	const char *normnm;
435	char *strval;
436
437	if (*props == NULL &&
438	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
439		(void) fprintf(stderr,
440		    gettext("internal error: out of memory\n"));
441		return (1);
442	}
443
444	proplist = *props;
445
446	if (poolprop) {
447		const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
448
449		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
450		    !zpool_prop_feature(propname)) {
451			(void) fprintf(stderr, gettext("property '%s' is "
452			    "not a valid pool property\n"), propname);
453			return (2);
454		}
455
456		/*
457		 * feature@ properties and version should not be specified
458		 * at the same time.
459		 */
460		if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
461		    nvlist_exists(proplist, vname)) ||
462		    (prop == ZPOOL_PROP_VERSION &&
463		    prop_list_contains_feature(proplist))) {
464			(void) fprintf(stderr, gettext("'feature@' and "
465			    "'version' properties cannot be specified "
466			    "together\n"));
467			return (2);
468		}
469
470
471		if (zpool_prop_feature(propname))
472			normnm = propname;
473		else
474			normnm = zpool_prop_to_name(prop);
475	} else {
476		if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
477			normnm = zfs_prop_to_name(fprop);
478		} else {
479			normnm = propname;
480		}
481	}
482
483	if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
484	    prop != ZPOOL_PROP_CACHEFILE) {
485		(void) fprintf(stderr, gettext("property '%s' "
486		    "specified multiple times\n"), propname);
487		return (2);
488	}
489
490	if (nvlist_add_string(proplist, normnm, propval) != 0) {
491		(void) fprintf(stderr, gettext("internal "
492		    "error: out of memory\n"));
493		return (1);
494	}
495
496	return (0);
497}
498
499/*
500 * Set a default property pair (name, string-value) in a property nvlist
501 */
502static int
503add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
504    boolean_t poolprop)
505{
506	char *pval;
507
508	if (nvlist_lookup_string(*props, propname, &pval) == 0)
509		return (0);
510
511	return (add_prop_list(propname, propval, props, poolprop));
512}
513
514/*
515 * zpool add [-fn] <pool> <vdev> ...
516 *
517 *	-f	Force addition of devices, even if they appear in use
518 *	-n	Do not add the devices, but display the resulting layout if
519 *		they were to be added.
520 *
521 * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
522 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
523 * libzfs.
524 */
525int
526zpool_do_add(int argc, char **argv)
527{
528	boolean_t force = B_FALSE;
529	boolean_t dryrun = B_FALSE;
530	int c;
531	nvlist_t *nvroot;
532	char *poolname;
533	zpool_boot_label_t boot_type;
534	uint64_t boot_size;
535	int ret;
536	zpool_handle_t *zhp;
537	nvlist_t *config;
538
539	/* check options */
540	while ((c = getopt(argc, argv, "fn")) != -1) {
541		switch (c) {
542		case 'f':
543			force = B_TRUE;
544			break;
545		case 'n':
546			dryrun = B_TRUE;
547			break;
548		case '?':
549			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
550			    optopt);
551			usage(B_FALSE);
552		}
553	}
554
555	argc -= optind;
556	argv += optind;
557
558	/* get pool name and check number of arguments */
559	if (argc < 1) {
560		(void) fprintf(stderr, gettext("missing pool name argument\n"));
561		usage(B_FALSE);
562	}
563	if (argc < 2) {
564		(void) fprintf(stderr, gettext("missing vdev specification\n"));
565		usage(B_FALSE);
566	}
567
568	poolname = argv[0];
569
570	argc--;
571	argv++;
572
573	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
574		return (1);
575
576	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
577		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
578		    poolname);
579		zpool_close(zhp);
580		return (1);
581	}
582
583	if (zpool_is_bootable(zhp))
584		boot_type = ZPOOL_COPY_BOOT_LABEL;
585	else
586		boot_type = ZPOOL_NO_BOOT_LABEL;
587
588	/* pass off to get_vdev_spec for processing */
589	boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
590	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
591	    boot_type, boot_size, argc, argv);
592	if (nvroot == NULL) {
593		zpool_close(zhp);
594		return (1);
595	}
596
597	if (dryrun) {
598		nvlist_t *poolnvroot;
599
600		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
601		    &poolnvroot) == 0);
602
603		(void) printf(gettext("would update '%s' to the following "
604		    "configuration:\n"), zpool_get_name(zhp));
605
606		/* print original main pool and new tree */
607		print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
608		print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
609
610		/* Do the same for the logs */
611		if (num_logs(poolnvroot) > 0) {
612			print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
613			print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
614		} else if (num_logs(nvroot) > 0) {
615			print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
616		}
617
618		ret = 0;
619	} else {
620		ret = (zpool_add(zhp, nvroot) != 0);
621	}
622
623	nvlist_free(nvroot);
624	zpool_close(zhp);
625
626	return (ret);
627}
628
629/*
630 * zpool remove  <pool> <vdev> ...
631 *
632 * Removes the given vdev from the pool.
633 */
634int
635zpool_do_remove(int argc, char **argv)
636{
637	char *poolname;
638	int i, ret = 0;
639	zpool_handle_t *zhp;
640	boolean_t stop = B_FALSE;
641	boolean_t noop = B_FALSE;
642	boolean_t parsable = B_FALSE;
643	char c;
644
645	/* check options */
646	while ((c = getopt(argc, argv, "nps")) != -1) {
647		switch (c) {
648		case 'n':
649			noop = B_TRUE;
650			break;
651		case 'p':
652			parsable = B_TRUE;
653			break;
654		case 's':
655			stop = B_TRUE;
656			break;
657		case '?':
658			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
659			    optopt);
660			usage(B_FALSE);
661		}
662	}
663
664	argc -= optind;
665	argv += optind;
666
667	/* get pool name and check number of arguments */
668	if (argc < 1) {
669		(void) fprintf(stderr, gettext("missing pool name argument\n"));
670		usage(B_FALSE);
671	}
672
673	poolname = argv[0];
674
675	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
676		return (1);
677
678	if (stop && noop) {
679		(void) fprintf(stderr, gettext("stop request ignored\n"));
680		return (0);
681	}
682
683	if (stop) {
684		if (argc > 1) {
685			(void) fprintf(stderr, gettext("too many arguments\n"));
686			usage(B_FALSE);
687		}
688		if (zpool_vdev_remove_cancel(zhp) != 0)
689			ret = 1;
690	} else {
691		if (argc < 2) {
692			(void) fprintf(stderr, gettext("missing device\n"));
693			usage(B_FALSE);
694		}
695
696		for (i = 1; i < argc; i++) {
697			if (noop) {
698				uint64_t size;
699
700				if (zpool_vdev_indirect_size(zhp, argv[i],
701				    &size) != 0) {
702					ret = 1;
703					break;
704				}
705				if (parsable) {
706					(void) printf("%s %llu\n",
707					    argv[i], size);
708				} else {
709					char valstr[32];
710					zfs_nicenum(size, valstr,
711					    sizeof (valstr));
712					(void) printf("Memory that will be "
713					    "used after removing %s: %s\n",
714					    argv[i], valstr);
715				}
716			} else {
717				if (zpool_vdev_remove(zhp, argv[i]) != 0)
718					ret = 1;
719			}
720		}
721	}
722
723	return (ret);
724}
725
726/*
727 * zpool labelclear [-f] <vdev>
728 *
729 *	-f	Force clearing the label for the vdevs which are members of
730 *		the exported or foreign pools.
731 *
732 * Verifies that the vdev is not active and zeros out the label information
733 * on the device.
734 */
735int
736zpool_do_labelclear(int argc, char **argv)
737{
738	char vdev[MAXPATHLEN];
739	char *name = NULL;
740	struct stat st;
741	int c, fd, ret = 0;
742	nvlist_t *config;
743	pool_state_t state;
744	boolean_t inuse = B_FALSE;
745	boolean_t force = B_FALSE;
746
747	/* check options */
748	while ((c = getopt(argc, argv, "f")) != -1) {
749		switch (c) {
750		case 'f':
751			force = B_TRUE;
752			break;
753		default:
754			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
755			    optopt);
756			usage(B_FALSE);
757		}
758	}
759
760	argc -= optind;
761	argv += optind;
762
763	/* get vdev name */
764	if (argc < 1) {
765		(void) fprintf(stderr, gettext("missing vdev name\n"));
766		usage(B_FALSE);
767	}
768	if (argc > 1) {
769		(void) fprintf(stderr, gettext("too many arguments\n"));
770		usage(B_FALSE);
771	}
772
773	/*
774	 * Check if we were given absolute path and use it as is.
775	 * Otherwise if the provided vdev name doesn't point to a file,
776	 * try prepending dsk path and appending s0.
777	 */
778	(void) strlcpy(vdev, argv[0], sizeof (vdev));
779	if (vdev[0] != '/' && stat(vdev, &st) != 0) {
780		char *s;
781
782		(void) snprintf(vdev, sizeof (vdev), "%s/%s",
783#ifdef illumos
784		    ZFS_DISK_ROOT, argv[0]);
785		if ((s = strrchr(argv[0], 's')) == NULL ||
786		    !isdigit(*(s + 1)))
787			(void) strlcat(vdev, "s0", sizeof (vdev));
788#else
789		    "/dev", argv[0]);
790#endif
791		if (stat(vdev, &st) != 0) {
792			(void) fprintf(stderr, gettext(
793			    "failed to find device %s, try specifying absolute "
794			    "path instead\n"), argv[0]);
795			return (1);
796		}
797	}
798
799	if ((fd = open(vdev, O_RDWR)) < 0) {
800		(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
801		    vdev, strerror(errno));
802		return (1);
803	}
804
805	if (zpool_read_label(fd, &config) != 0) {
806		(void) fprintf(stderr,
807		    gettext("failed to read label from %s\n"), vdev);
808		return (1);
809	}
810	nvlist_free(config);
811
812	ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
813	if (ret != 0) {
814		(void) fprintf(stderr,
815		    gettext("failed to check state for %s\n"), vdev);
816		return (1);
817	}
818
819	if (!inuse)
820		goto wipe_label;
821
822	switch (state) {
823	default:
824	case POOL_STATE_ACTIVE:
825	case POOL_STATE_SPARE:
826	case POOL_STATE_L2CACHE:
827		(void) fprintf(stderr, gettext(
828		    "%s is a member (%s) of pool \"%s\"\n"),
829		    vdev, zpool_pool_state_to_name(state), name);
830		ret = 1;
831		goto errout;
832
833	case POOL_STATE_EXPORTED:
834		if (force)
835			break;
836		(void) fprintf(stderr, gettext(
837		    "use '-f' to override the following error:\n"
838		    "%s is a member of exported pool \"%s\"\n"),
839		    vdev, name);
840		ret = 1;
841		goto errout;
842
843	case POOL_STATE_POTENTIALLY_ACTIVE:
844		if (force)
845			break;
846		(void) fprintf(stderr, gettext(
847		    "use '-f' to override the following error:\n"
848		    "%s is a member of potentially active pool \"%s\"\n"),
849		    vdev, name);
850		ret = 1;
851		goto errout;
852
853	case POOL_STATE_DESTROYED:
854		/* inuse should never be set for a destroyed pool */
855		assert(0);
856		break;
857	}
858
859wipe_label:
860	ret = zpool_clear_label(fd);
861	if (ret != 0) {
862		(void) fprintf(stderr,
863		    gettext("failed to clear label for %s\n"), vdev);
864	}
865
866errout:
867	free(name);
868	(void) close(fd);
869
870	return (ret);
871}
872
873/*
874 * zpool create [-fnd] [-B] [-o property=value] ...
875 *		[-O file-system-property=value] ...
876 *		[-R root] [-m mountpoint] [-t tempname] <pool> <dev> ...
877 *
878 *	-B	Create boot partition.
879 *	-f	Force creation, even if devices appear in use
880 *	-n	Do not create the pool, but display the resulting layout if it
881 *		were to be created.
882 *	-R	Create a pool under an alternate root
883 *	-m	Set default mountpoint for the root dataset.  By default it's
884 *		'/<pool>'
885 *	-t	Use the temporary name until the pool is exported.
886 *	-o	Set property=value.
887 *	-d	Don't automatically enable all supported pool features
888 *		(individual features can be enabled with -o).
889 *	-O	Set fsproperty=value in the pool's root file system
890 *
891 * Creates the named pool according to the given vdev specification.  The
892 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
893 * we get the nvlist back from get_vdev_spec(), we either print out the contents
894 * (if '-n' was specified), or pass it to libzfs to do the creation.
895 */
896
897#define	SYSTEM256	(256 * 1024 * 1024)
898int
899zpool_do_create(int argc, char **argv)
900{
901	boolean_t force = B_FALSE;
902	boolean_t dryrun = B_FALSE;
903	boolean_t enable_all_pool_feat = B_TRUE;
904	zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
905	uint64_t boot_size = 0;
906	int c;
907	nvlist_t *nvroot = NULL;
908	char *poolname;
909	char *tname = NULL;
910	int ret = 1;
911	char *altroot = NULL;
912	char *mountpoint = NULL;
913	nvlist_t *fsprops = NULL;
914	nvlist_t *props = NULL;
915	char *propval;
916
917	/* check options */
918	while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) {
919		switch (c) {
920		case 'f':
921			force = B_TRUE;
922			break;
923		case 'n':
924			dryrun = B_TRUE;
925			break;
926		case 'd':
927			enable_all_pool_feat = B_FALSE;
928			break;
929		case 'B':
930#ifdef illumos
931			/*
932			 * We should create the system partition.
933			 * Also make sure the size is set.
934			 */
935			boot_type = ZPOOL_CREATE_BOOT_LABEL;
936			if (boot_size == 0)
937				boot_size = SYSTEM256;
938			break;
939#else
940			(void) fprintf(stderr,
941			    gettext("option '%c' is not supported\n"),
942			    optopt);
943			goto badusage;
944#endif
945		case 'R':
946			altroot = optarg;
947			if (add_prop_list(zpool_prop_to_name(
948			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
949				goto errout;
950			if (add_prop_list_default(zpool_prop_to_name(
951			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
952				goto errout;
953			break;
954		case 'm':
955			/* Equivalent to -O mountpoint=optarg */
956			mountpoint = optarg;
957			break;
958		case 'o':
959			if ((propval = strchr(optarg, '=')) == NULL) {
960				(void) fprintf(stderr, gettext("missing "
961				    "'=' for -o option\n"));
962				goto errout;
963			}
964			*propval = '\0';
965			propval++;
966
967			if (add_prop_list(optarg, propval, &props, B_TRUE))
968				goto errout;
969
970			/*
971			 * Get bootsize value for make_root_vdev().
972			 */
973			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
974				if (zfs_nicestrtonum(g_zfs, propval,
975				    &boot_size) < 0 || boot_size == 0) {
976					(void) fprintf(stderr,
977					    gettext("bad boot partition size "
978					    "'%s': %s\n"),  propval,
979					    libzfs_error_description(g_zfs));
980					goto errout;
981				}
982			}
983
984			/*
985			 * If the user is creating a pool that doesn't support
986			 * feature flags, don't enable any features.
987			 */
988			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
989				char *end;
990				u_longlong_t ver;
991
992				ver = strtoull(propval, &end, 10);
993				if (*end == '\0' &&
994				    ver < SPA_VERSION_FEATURES) {
995					enable_all_pool_feat = B_FALSE;
996				}
997			}
998			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
999				altroot = propval;
1000			break;
1001		case 'O':
1002			if ((propval = strchr(optarg, '=')) == NULL) {
1003				(void) fprintf(stderr, gettext("missing "
1004				    "'=' for -O option\n"));
1005				goto errout;
1006			}
1007			*propval = '\0';
1008			propval++;
1009
1010			/*
1011			 * Mountpoints are checked and then added later.
1012			 * Uniquely among properties, they can be specified
1013			 * more than once, to avoid conflict with -m.
1014			 */
1015			if (0 == strcmp(optarg,
1016			    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1017				mountpoint = propval;
1018			} else if (add_prop_list(optarg, propval, &fsprops,
1019			    B_FALSE)) {
1020				goto errout;
1021			}
1022			break;
1023		case 't':
1024			/*
1025			 * Sanity check temporary pool name.
1026			 */
1027			if (strchr(optarg, '/') != NULL) {
1028				(void) fprintf(stderr, gettext("cannot create "
1029				    "'%s': invalid character '/' in temporary "
1030				    "name\n"), optarg);
1031				(void) fprintf(stderr, gettext("use 'zfs "
1032				    "create' to create a dataset\n"));
1033				goto errout;
1034			}
1035
1036			if (add_prop_list(zpool_prop_to_name(
1037			    ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1038				goto errout;
1039			if (add_prop_list_default(zpool_prop_to_name(
1040			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1041				goto errout;
1042			tname = optarg;
1043			break;
1044		case ':':
1045			(void) fprintf(stderr, gettext("missing argument for "
1046			    "'%c' option\n"), optopt);
1047			goto badusage;
1048		case '?':
1049			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1050			    optopt);
1051			goto badusage;
1052		}
1053	}
1054
1055	argc -= optind;
1056	argv += optind;
1057
1058	/* get pool name and check number of arguments */
1059	if (argc < 1) {
1060		(void) fprintf(stderr, gettext("missing pool name argument\n"));
1061		goto badusage;
1062	}
1063	if (argc < 2) {
1064		(void) fprintf(stderr, gettext("missing vdev specification\n"));
1065		goto badusage;
1066	}
1067
1068	poolname = argv[0];
1069
1070	/*
1071	 * As a special case, check for use of '/' in the name, and direct the
1072	 * user to use 'zfs create' instead.
1073	 */
1074	if (strchr(poolname, '/') != NULL) {
1075		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
1076		    "character '/' in pool name\n"), poolname);
1077		(void) fprintf(stderr, gettext("use 'zfs create' to "
1078		    "create a dataset\n"));
1079		goto errout;
1080	}
1081
1082	/*
1083	 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1084	 * and not set otherwise.
1085	 */
1086	if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1087		const char *propname;
1088		char *strptr, *buf = NULL;
1089		int rv;
1090
1091		propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1092		if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1093			(void) asprintf(&buf, "%" PRIu64, boot_size);
1094			if (buf == NULL) {
1095				(void) fprintf(stderr,
1096				    gettext("internal error: out of memory\n"));
1097				goto errout;
1098			}
1099			rv = add_prop_list(propname, buf, &props, B_TRUE);
1100			free(buf);
1101			if (rv != 0)
1102				goto errout;
1103		}
1104	} else {
1105		const char *propname;
1106		char *strptr;
1107
1108		propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1109		if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1110			(void) fprintf(stderr, gettext("error: setting boot "
1111			    "partition size requires option '-B'\n"));
1112			goto errout;
1113		}
1114	}
1115
1116	/* pass off to get_vdev_spec for bulk processing */
1117	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1118	    boot_type, boot_size, argc - 1, argv + 1);
1119	if (nvroot == NULL)
1120		goto errout;
1121
1122	/* make_root_vdev() allows 0 toplevel children if there are spares */
1123	if (!zfs_allocatable_devs(nvroot)) {
1124		(void) fprintf(stderr, gettext("invalid vdev "
1125		    "specification: at least one toplevel vdev must be "
1126		    "specified\n"));
1127		goto errout;
1128	}
1129
1130	if (altroot != NULL && altroot[0] != '/') {
1131		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
1132		    "must be an absolute path\n"), altroot);
1133		goto errout;
1134	}
1135
1136	/*
1137	 * Check the validity of the mountpoint and direct the user to use the
1138	 * '-m' mountpoint option if it looks like its in use.
1139	 * Ignore the checks if the '-f' option is given.
1140	 */
1141	if (!force && (mountpoint == NULL ||
1142	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1143	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) {
1144		char buf[MAXPATHLEN];
1145		DIR *dirp;
1146
1147		if (mountpoint && mountpoint[0] != '/') {
1148			(void) fprintf(stderr, gettext("invalid mountpoint "
1149			    "'%s': must be an absolute path, 'legacy', or "
1150			    "'none'\n"), mountpoint);
1151			goto errout;
1152		}
1153
1154		if (mountpoint == NULL) {
1155			if (altroot != NULL)
1156				(void) snprintf(buf, sizeof (buf), "%s/%s",
1157				    altroot, poolname);
1158			else
1159				(void) snprintf(buf, sizeof (buf), "/%s",
1160				    poolname);
1161		} else {
1162			if (altroot != NULL)
1163				(void) snprintf(buf, sizeof (buf), "%s%s",
1164				    altroot, mountpoint);
1165			else
1166				(void) snprintf(buf, sizeof (buf), "%s",
1167				    mountpoint);
1168		}
1169
1170		if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1171			(void) fprintf(stderr, gettext("mountpoint '%s' : "
1172			    "%s\n"), buf, strerror(errno));
1173			(void) fprintf(stderr, gettext("use '-m' "
1174			    "option to provide a different default\n"));
1175			goto errout;
1176		} else if (dirp) {
1177			int count = 0;
1178
1179			while (count < 3 && readdir(dirp) != NULL)
1180				count++;
1181			(void) closedir(dirp);
1182
1183			if (count > 2) {
1184				(void) fprintf(stderr, gettext("mountpoint "
1185				    "'%s' exists and is not empty\n"), buf);
1186				(void) fprintf(stderr, gettext("use '-m' "
1187				    "option to provide a "
1188				    "different default\n"));
1189				goto errout;
1190			}
1191		}
1192	}
1193
1194	/*
1195	 * Now that the mountpoint's validity has been checked, ensure that
1196	 * the property is set appropriately prior to creating the pool.
1197	 */
1198	if (mountpoint != NULL) {
1199		ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1200		    mountpoint, &fsprops, B_FALSE);
1201		if (ret != 0)
1202			goto errout;
1203	}
1204
1205	ret = 1;
1206	if (dryrun) {
1207		/*
1208		 * For a dry run invocation, print out a basic message and run
1209		 * through all the vdevs in the list and print out in an
1210		 * appropriate hierarchy.
1211		 */
1212		(void) printf(gettext("would create '%s' with the "
1213		    "following layout:\n\n"), poolname);
1214
1215		print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1216		if (num_logs(nvroot) > 0)
1217			print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1218
1219		ret = 0;
1220	} else {
1221		/*
1222		 * Hand off to libzfs.
1223		 */
1224		if (enable_all_pool_feat) {
1225			spa_feature_t i;
1226			for (i = 0; i < SPA_FEATURES; i++) {
1227				char propname[MAXPATHLEN];
1228				zfeature_info_t *feat = &spa_feature_table[i];
1229
1230				(void) snprintf(propname, sizeof (propname),
1231				    "feature@%s", feat->fi_uname);
1232
1233				/*
1234				 * Skip feature if user specified it manually
1235				 * on the command line.
1236				 */
1237				if (nvlist_exists(props, propname))
1238					continue;
1239
1240				ret = add_prop_list(propname,
1241				    ZFS_FEATURE_ENABLED, &props, B_TRUE);
1242				if (ret != 0)
1243					goto errout;
1244			}
1245		}
1246
1247		ret = 1;
1248		if (zpool_create(g_zfs, poolname,
1249		    nvroot, props, fsprops) == 0) {
1250			zfs_handle_t *pool = zfs_open(g_zfs,
1251			    tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1252			if (pool != NULL) {
1253				if (zfs_mount(pool, NULL, 0) == 0)
1254					ret = zfs_shareall(pool);
1255				zfs_close(pool);
1256			}
1257		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1258			(void) fprintf(stderr, gettext("pool name may have "
1259			    "been omitted\n"));
1260		}
1261	}
1262
1263errout:
1264	nvlist_free(nvroot);
1265	nvlist_free(fsprops);
1266	nvlist_free(props);
1267	return (ret);
1268badusage:
1269	nvlist_free(fsprops);
1270	nvlist_free(props);
1271	usage(B_FALSE);
1272	return (2);
1273}
1274
1275/*
1276 * zpool destroy <pool>
1277 *
1278 *	-f	Forcefully unmount any datasets
1279 *
1280 * Destroy the given pool.  Automatically unmounts any datasets in the pool.
1281 */
1282int
1283zpool_do_destroy(int argc, char **argv)
1284{
1285	boolean_t force = B_FALSE;
1286	int c;
1287	char *pool;
1288	zpool_handle_t *zhp;
1289	int ret;
1290
1291	/* check options */
1292	while ((c = getopt(argc, argv, "f")) != -1) {
1293		switch (c) {
1294		case 'f':
1295			force = B_TRUE;
1296			break;
1297		case '?':
1298			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1299			    optopt);
1300			usage(B_FALSE);
1301		}
1302	}
1303
1304	argc -= optind;
1305	argv += optind;
1306
1307	/* check arguments */
1308	if (argc < 1) {
1309		(void) fprintf(stderr, gettext("missing pool argument\n"));
1310		usage(B_FALSE);
1311	}
1312	if (argc > 1) {
1313		(void) fprintf(stderr, gettext("too many arguments\n"));
1314		usage(B_FALSE);
1315	}
1316
1317	pool = argv[0];
1318
1319	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1320		/*
1321		 * As a special case, check for use of '/' in the name, and
1322		 * direct the user to use 'zfs destroy' instead.
1323		 */
1324		if (strchr(pool, '/') != NULL)
1325			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
1326			    "destroy a dataset\n"));
1327		return (1);
1328	}
1329
1330	if (zpool_disable_datasets(zhp, force) != 0) {
1331		(void) fprintf(stderr, gettext("could not destroy '%s': "
1332		    "could not unmount datasets\n"), zpool_get_name(zhp));
1333		return (1);
1334	}
1335
1336	/* The history must be logged as part of the export */
1337	log_history = B_FALSE;
1338
1339	ret = (zpool_destroy(zhp, history_str) != 0);
1340
1341	zpool_close(zhp);
1342
1343	return (ret);
1344}
1345
1346/*
1347 * zpool export [-f] <pool> ...
1348 *
1349 *	-f	Forcefully unmount datasets
1350 *
1351 * Export the given pools.  By default, the command will attempt to cleanly
1352 * unmount any active datasets within the pool.  If the '-f' flag is specified,
1353 * then the datasets will be forcefully unmounted.
1354 */
1355int
1356zpool_do_export(int argc, char **argv)
1357{
1358	boolean_t force = B_FALSE;
1359	boolean_t hardforce = B_FALSE;
1360	int c;
1361	zpool_handle_t *zhp;
1362	int ret;
1363	int i;
1364
1365	/* check options */
1366	while ((c = getopt(argc, argv, "fF")) != -1) {
1367		switch (c) {
1368		case 'f':
1369			force = B_TRUE;
1370			break;
1371		case 'F':
1372			hardforce = B_TRUE;
1373			break;
1374		case '?':
1375			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1376			    optopt);
1377			usage(B_FALSE);
1378		}
1379	}
1380
1381	argc -= optind;
1382	argv += optind;
1383
1384	/* check arguments */
1385	if (argc < 1) {
1386		(void) fprintf(stderr, gettext("missing pool argument\n"));
1387		usage(B_FALSE);
1388	}
1389
1390	ret = 0;
1391	for (i = 0; i < argc; i++) {
1392		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1393			ret = 1;
1394			continue;
1395		}
1396
1397		if (zpool_disable_datasets(zhp, force) != 0) {
1398			ret = 1;
1399			zpool_close(zhp);
1400			continue;
1401		}
1402
1403		/* The history must be logged as part of the export */
1404		log_history = B_FALSE;
1405
1406		if (hardforce) {
1407			if (zpool_export_force(zhp, history_str) != 0)
1408				ret = 1;
1409		} else if (zpool_export(zhp, force, history_str) != 0) {
1410			ret = 1;
1411		}
1412
1413		zpool_close(zhp);
1414	}
1415
1416	return (ret);
1417}
1418
1419/*
1420 * Given a vdev configuration, determine the maximum width needed for the device
1421 * name column.
1422 */
1423static int
1424max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1425{
1426	char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1427	nvlist_t **child;
1428	uint_t c, children;
1429	int ret;
1430
1431	if (strlen(name) + depth > max)
1432		max = strlen(name) + depth;
1433
1434	free(name);
1435
1436	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1437	    &child, &children) == 0) {
1438		for (c = 0; c < children; c++)
1439			if ((ret = max_width(zhp, child[c], depth + 2,
1440			    max)) > max)
1441				max = ret;
1442	}
1443
1444	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1445	    &child, &children) == 0) {
1446		for (c = 0; c < children; c++)
1447			if ((ret = max_width(zhp, child[c], depth + 2,
1448			    max)) > max)
1449				max = ret;
1450	}
1451
1452	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1453	    &child, &children) == 0) {
1454		for (c = 0; c < children; c++)
1455			if ((ret = max_width(zhp, child[c], depth + 2,
1456			    max)) > max)
1457				max = ret;
1458	}
1459
1460
1461	return (max);
1462}
1463
1464typedef struct spare_cbdata {
1465	uint64_t	cb_guid;
1466	zpool_handle_t	*cb_zhp;
1467} spare_cbdata_t;
1468
1469static boolean_t
1470find_vdev(nvlist_t *nv, uint64_t search)
1471{
1472	uint64_t guid;
1473	nvlist_t **child;
1474	uint_t c, children;
1475
1476	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1477	    search == guid)
1478		return (B_TRUE);
1479
1480	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1481	    &child, &children) == 0) {
1482		for (c = 0; c < children; c++)
1483			if (find_vdev(child[c], search))
1484				return (B_TRUE);
1485	}
1486
1487	return (B_FALSE);
1488}
1489
1490static int
1491find_spare(zpool_handle_t *zhp, void *data)
1492{
1493	spare_cbdata_t *cbp = data;
1494	nvlist_t *config, *nvroot;
1495
1496	config = zpool_get_config(zhp, NULL);
1497	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1498	    &nvroot) == 0);
1499
1500	if (find_vdev(nvroot, cbp->cb_guid)) {
1501		cbp->cb_zhp = zhp;
1502		return (1);
1503	}
1504
1505	zpool_close(zhp);
1506	return (0);
1507}
1508
1509/*
1510 * Print out configuration state as requested by status_callback.
1511 */
1512void
1513print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1514    int namewidth, int depth, boolean_t isspare)
1515{
1516	nvlist_t **child;
1517	uint_t c, vsc, children;
1518	pool_scan_stat_t *ps = NULL;
1519	vdev_stat_t *vs;
1520	char rbuf[6], wbuf[6], cbuf[6];
1521	char *vname;
1522	uint64_t notpresent;
1523	uint64_t ashift;
1524	spare_cbdata_t cb;
1525	const char *state;
1526	char *type;
1527
1528	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1529	    &child, &children) != 0)
1530		children = 0;
1531
1532	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1533	    (uint64_t **)&vs, &vsc) == 0);
1534
1535	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1536
1537	if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1538		return;
1539
1540	state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1541	if (isspare) {
1542		/*
1543		 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1544		 * online drives.
1545		 */
1546		if (vs->vs_aux == VDEV_AUX_SPARED)
1547			state = "INUSE";
1548		else if (vs->vs_state == VDEV_STATE_HEALTHY)
1549			state = "AVAIL";
1550	}
1551
1552	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
1553	    name, state);
1554
1555	if (!isspare) {
1556		zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1557		zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1558		zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1559		(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1560	}
1561
1562	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1563	    &notpresent) == 0 ||
1564	    vs->vs_state <= VDEV_STATE_CANT_OPEN) {
1565		char *path;
1566		if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0)
1567			(void) printf("  was %s", path);
1568	} else if (vs->vs_aux != 0) {
1569		(void) printf("  ");
1570
1571		switch (vs->vs_aux) {
1572		case VDEV_AUX_OPEN_FAILED:
1573			(void) printf(gettext("cannot open"));
1574			break;
1575
1576		case VDEV_AUX_BAD_GUID_SUM:
1577			(void) printf(gettext("missing device"));
1578			break;
1579
1580		case VDEV_AUX_NO_REPLICAS:
1581			(void) printf(gettext("insufficient replicas"));
1582			break;
1583
1584		case VDEV_AUX_VERSION_NEWER:
1585			(void) printf(gettext("newer version"));
1586			break;
1587
1588		case VDEV_AUX_UNSUP_FEAT:
1589			(void) printf(gettext("unsupported feature(s)"));
1590			break;
1591
1592		case VDEV_AUX_ASHIFT_TOO_BIG:
1593			(void) printf(gettext("unsupported minimum blocksize"));
1594			break;
1595
1596		case VDEV_AUX_SPARED:
1597			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1598			    &cb.cb_guid) == 0);
1599			if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1600				if (strcmp(zpool_get_name(cb.cb_zhp),
1601				    zpool_get_name(zhp)) == 0)
1602					(void) printf(gettext("currently in "
1603					    "use"));
1604				else
1605					(void) printf(gettext("in use by "
1606					    "pool '%s'"),
1607					    zpool_get_name(cb.cb_zhp));
1608				zpool_close(cb.cb_zhp);
1609			} else {
1610				(void) printf(gettext("currently in use"));
1611			}
1612			break;
1613
1614		case VDEV_AUX_ERR_EXCEEDED:
1615			(void) printf(gettext("too many errors"));
1616			break;
1617
1618		case VDEV_AUX_IO_FAILURE:
1619			(void) printf(gettext("experienced I/O failures"));
1620			break;
1621
1622		case VDEV_AUX_BAD_LOG:
1623			(void) printf(gettext("bad intent log"));
1624			break;
1625
1626		case VDEV_AUX_EXTERNAL:
1627			(void) printf(gettext("external device fault"));
1628			break;
1629
1630		case VDEV_AUX_SPLIT_POOL:
1631			(void) printf(gettext("split into new pool"));
1632			break;
1633
1634		case VDEV_AUX_CHILDREN_OFFLINE:
1635			(void) printf(gettext("all children offline"));
1636			break;
1637
1638		default:
1639			(void) printf(gettext("corrupted data"));
1640			break;
1641		}
1642	} else if (children == 0 && !isspare &&
1643	    VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
1644	    vs->vs_configured_ashift < vs->vs_physical_ashift) {
1645		(void) printf(
1646		    gettext("  block size: %dB configured, %dB native"),
1647		    1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
1648	}
1649
1650	(void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1651	    (uint64_t **)&ps, &c);
1652
1653	if (ps != NULL && ps->pss_state == DSS_SCANNING &&
1654	    vs->vs_scan_processed != 0 && children == 0) {
1655		(void) printf(gettext("  (%s)"),
1656		    (ps->pss_func == POOL_SCAN_RESILVER) ?
1657		    "resilvering" : "repairing");
1658	}
1659
1660	if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
1661	    vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
1662	    vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
1663	    !vs->vs_scan_removing) {
1664		char zbuf[1024];
1665		char tbuf[256];
1666		struct tm zaction_ts;
1667
1668		time_t t = vs->vs_initialize_action_time;
1669		int initialize_pct = 100;
1670		if (vs->vs_initialize_state != VDEV_INITIALIZE_COMPLETE) {
1671			initialize_pct = (vs->vs_initialize_bytes_done * 100 /
1672			    (vs->vs_initialize_bytes_est + 1));
1673		}
1674
1675		(void) localtime_r(&t, &zaction_ts);
1676		(void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1677
1678		switch (vs->vs_initialize_state) {
1679		case VDEV_INITIALIZE_SUSPENDED:
1680			(void) snprintf(zbuf, sizeof (zbuf),
1681			    ", suspended, started at %s", tbuf);
1682			break;
1683		case VDEV_INITIALIZE_ACTIVE:
1684			(void) snprintf(zbuf, sizeof (zbuf),
1685			    ", started at %s", tbuf);
1686			break;
1687		case VDEV_INITIALIZE_COMPLETE:
1688			(void) snprintf(zbuf, sizeof (zbuf),
1689			    ", completed at %s", tbuf);
1690			break;
1691		}
1692
1693		(void) printf(gettext("  (%d%% initialized%s)"),
1694		    initialize_pct, zbuf);
1695	}
1696
1697	(void) printf("\n");
1698
1699	for (c = 0; c < children; c++) {
1700		uint64_t islog = B_FALSE, ishole = B_FALSE;
1701
1702		/* Don't print logs or holes here */
1703		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1704		    &islog);
1705		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1706		    &ishole);
1707		if (islog || ishole)
1708			continue;
1709		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1710		print_status_config(zhp, vname, child[c],
1711		    namewidth, depth + 2, isspare);
1712		free(vname);
1713	}
1714}
1715
1716
1717/*
1718 * Print the configuration of an exported pool.  Iterate over all vdevs in the
1719 * pool, printing out the name and status for each one.
1720 */
1721void
1722print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1723{
1724	nvlist_t **child;
1725	uint_t c, children;
1726	vdev_stat_t *vs;
1727	char *type, *vname;
1728
1729	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1730	if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1731	    strcmp(type, VDEV_TYPE_HOLE) == 0)
1732		return;
1733
1734	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1735	    (uint64_t **)&vs, &c) == 0);
1736
1737	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1738	(void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1739
1740	if (vs->vs_aux != 0) {
1741		(void) printf("  ");
1742
1743		switch (vs->vs_aux) {
1744		case VDEV_AUX_OPEN_FAILED:
1745			(void) printf(gettext("cannot open"));
1746			break;
1747
1748		case VDEV_AUX_BAD_GUID_SUM:
1749			(void) printf(gettext("missing device"));
1750			break;
1751
1752		case VDEV_AUX_NO_REPLICAS:
1753			(void) printf(gettext("insufficient replicas"));
1754			break;
1755
1756		case VDEV_AUX_VERSION_NEWER:
1757			(void) printf(gettext("newer version"));
1758			break;
1759
1760		case VDEV_AUX_UNSUP_FEAT:
1761			(void) printf(gettext("unsupported feature(s)"));
1762			break;
1763
1764		case VDEV_AUX_ERR_EXCEEDED:
1765			(void) printf(gettext("too many errors"));
1766			break;
1767
1768		case VDEV_AUX_CHILDREN_OFFLINE:
1769			(void) printf(gettext("all children offline"));
1770			break;
1771
1772		default:
1773			(void) printf(gettext("corrupted data"));
1774			break;
1775		}
1776	}
1777	(void) printf("\n");
1778
1779	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1780	    &child, &children) != 0)
1781		return;
1782
1783	for (c = 0; c < children; c++) {
1784		uint64_t is_log = B_FALSE;
1785
1786		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1787		    &is_log);
1788		if (is_log)
1789			continue;
1790
1791		vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1792		print_import_config(vname, child[c], namewidth, depth + 2);
1793		free(vname);
1794	}
1795
1796	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1797	    &child, &children) == 0) {
1798		(void) printf(gettext("\tcache\n"));
1799		for (c = 0; c < children; c++) {
1800			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1801			(void) printf("\t  %s\n", vname);
1802			free(vname);
1803		}
1804	}
1805
1806	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1807	    &child, &children) == 0) {
1808		(void) printf(gettext("\tspares\n"));
1809		for (c = 0; c < children; c++) {
1810			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1811			(void) printf("\t  %s\n", vname);
1812			free(vname);
1813		}
1814	}
1815}
1816
1817/*
1818 * Print log vdevs.
1819 * Logs are recorded as top level vdevs in the main pool child array
1820 * but with "is_log" set to 1. We use either print_status_config() or
1821 * print_import_config() to print the top level logs then any log
1822 * children (eg mirrored slogs) are printed recursively - which
1823 * works because only the top level vdev is marked "is_log"
1824 */
1825static void
1826print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1827{
1828	uint_t c, children;
1829	nvlist_t **child;
1830
1831	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1832	    &children) != 0)
1833		return;
1834
1835	(void) printf(gettext("\tlogs\n"));
1836
1837	for (c = 0; c < children; c++) {
1838		uint64_t is_log = B_FALSE;
1839		char *name;
1840
1841		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1842		    &is_log);
1843		if (!is_log)
1844			continue;
1845		name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1846		if (verbose)
1847			print_status_config(zhp, name, child[c], namewidth,
1848			    2, B_FALSE);
1849		else
1850			print_import_config(name, child[c], namewidth, 2);
1851		free(name);
1852	}
1853}
1854
1855/*
1856 * Display the status for the given pool.
1857 */
1858static void
1859show_import(nvlist_t *config)
1860{
1861	uint64_t pool_state;
1862	vdev_stat_t *vs;
1863	char *name;
1864	uint64_t guid;
1865	char *msgid;
1866	nvlist_t *nvroot;
1867	int reason;
1868	const char *health;
1869	uint_t vsc;
1870	int namewidth;
1871	char *comment;
1872
1873	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1874	    &name) == 0);
1875	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1876	    &guid) == 0);
1877	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1878	    &pool_state) == 0);
1879	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1880	    &nvroot) == 0);
1881
1882	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1883	    (uint64_t **)&vs, &vsc) == 0);
1884	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1885
1886	reason = zpool_import_status(config, &msgid);
1887
1888	(void) printf(gettext("   pool: %s\n"), name);
1889	(void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
1890	(void) printf(gettext("  state: %s"), health);
1891	if (pool_state == POOL_STATE_DESTROYED)
1892		(void) printf(gettext(" (DESTROYED)"));
1893	(void) printf("\n");
1894
1895	switch (reason) {
1896	case ZPOOL_STATUS_MISSING_DEV_R:
1897	case ZPOOL_STATUS_MISSING_DEV_NR:
1898	case ZPOOL_STATUS_BAD_GUID_SUM:
1899		(void) printf(gettext(" status: One or more devices are "
1900		    "missing from the system.\n"));
1901		break;
1902
1903	case ZPOOL_STATUS_CORRUPT_LABEL_R:
1904	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1905		(void) printf(gettext(" status: One or more devices contains "
1906		    "corrupted data.\n"));
1907		break;
1908
1909	case ZPOOL_STATUS_CORRUPT_DATA:
1910		(void) printf(
1911		    gettext(" status: The pool data is corrupted.\n"));
1912		break;
1913
1914	case ZPOOL_STATUS_OFFLINE_DEV:
1915		(void) printf(gettext(" status: One or more devices "
1916		    "are offlined.\n"));
1917		break;
1918
1919	case ZPOOL_STATUS_CORRUPT_POOL:
1920		(void) printf(gettext(" status: The pool metadata is "
1921		    "corrupted.\n"));
1922		break;
1923
1924	case ZPOOL_STATUS_VERSION_OLDER:
1925		(void) printf(gettext(" status: The pool is formatted using a "
1926		    "legacy on-disk version.\n"));
1927		break;
1928
1929	case ZPOOL_STATUS_VERSION_NEWER:
1930		(void) printf(gettext(" status: The pool is formatted using an "
1931		    "incompatible version.\n"));
1932		break;
1933
1934	case ZPOOL_STATUS_FEAT_DISABLED:
1935		(void) printf(gettext(" status: Some supported features are "
1936		    "not enabled on the pool.\n"));
1937		break;
1938
1939	case ZPOOL_STATUS_UNSUP_FEAT_READ:
1940		(void) printf(gettext("status: The pool uses the following "
1941		    "feature(s) not supported on this system:\n"));
1942		zpool_print_unsup_feat(config);
1943		break;
1944
1945	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1946		(void) printf(gettext("status: The pool can only be accessed "
1947		    "in read-only mode on this system. It\n\tcannot be "
1948		    "accessed in read-write mode because it uses the "
1949		    "following\n\tfeature(s) not supported on this system:\n"));
1950		zpool_print_unsup_feat(config);
1951		break;
1952
1953	case ZPOOL_STATUS_HOSTID_MISMATCH:
1954		(void) printf(gettext(" status: The pool was last accessed by "
1955		    "another system.\n"));
1956		break;
1957
1958	case ZPOOL_STATUS_FAULTED_DEV_R:
1959	case ZPOOL_STATUS_FAULTED_DEV_NR:
1960		(void) printf(gettext(" status: One or more devices are "
1961		    "faulted.\n"));
1962		break;
1963
1964	case ZPOOL_STATUS_BAD_LOG:
1965		(void) printf(gettext(" status: An intent log record cannot be "
1966		    "read.\n"));
1967		break;
1968
1969	case ZPOOL_STATUS_RESILVERING:
1970		(void) printf(gettext(" status: One or more devices were being "
1971		    "resilvered.\n"));
1972		break;
1973
1974	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
1975		(void) printf(gettext("status: One or more devices were "
1976		    "configured to use a non-native block size.\n"
1977		    "\tExpect reduced performance.\n"));
1978		break;
1979
1980	default:
1981		/*
1982		 * No other status can be seen when importing pools.
1983		 */
1984		assert(reason == ZPOOL_STATUS_OK);
1985	}
1986
1987	/*
1988	 * Print out an action according to the overall state of the pool.
1989	 */
1990	if (vs->vs_state == VDEV_STATE_HEALTHY) {
1991		if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1992		    reason == ZPOOL_STATUS_FEAT_DISABLED) {
1993			(void) printf(gettext(" action: The pool can be "
1994			    "imported using its name or numeric identifier, "
1995			    "though\n\tsome features will not be available "
1996			    "without an explicit 'zpool upgrade'.\n"));
1997		} else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1998			(void) printf(gettext(" action: The pool can be "
1999			    "imported using its name or numeric "
2000			    "identifier and\n\tthe '-f' flag.\n"));
2001		} else {
2002			(void) printf(gettext(" action: The pool can be "
2003			    "imported using its name or numeric "
2004			    "identifier.\n"));
2005		}
2006	} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2007		(void) printf(gettext(" action: The pool can be imported "
2008		    "despite missing or damaged devices.  The\n\tfault "
2009		    "tolerance of the pool may be compromised if imported.\n"));
2010	} else {
2011		switch (reason) {
2012		case ZPOOL_STATUS_VERSION_NEWER:
2013			(void) printf(gettext(" action: The pool cannot be "
2014			    "imported.  Access the pool on a system running "
2015			    "newer\n\tsoftware, or recreate the pool from "
2016			    "backup.\n"));
2017			break;
2018		case ZPOOL_STATUS_UNSUP_FEAT_READ:
2019			(void) printf(gettext("action: The pool cannot be "
2020			    "imported. Access the pool on a system that "
2021			    "supports\n\tthe required feature(s), or recreate "
2022			    "the pool from backup.\n"));
2023			break;
2024		case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2025			(void) printf(gettext("action: The pool cannot be "
2026			    "imported in read-write mode. Import the pool "
2027			    "with\n"
2028			    "\t\"-o readonly=on\", access the pool on a system "
2029			    "that supports the\n\trequired feature(s), or "
2030			    "recreate the pool from backup.\n"));
2031			break;
2032		case ZPOOL_STATUS_MISSING_DEV_R:
2033		case ZPOOL_STATUS_MISSING_DEV_NR:
2034		case ZPOOL_STATUS_BAD_GUID_SUM:
2035			(void) printf(gettext(" action: The pool cannot be "
2036			    "imported. Attach the missing\n\tdevices and try "
2037			    "again.\n"));
2038			break;
2039		default:
2040			(void) printf(gettext(" action: The pool cannot be "
2041			    "imported due to damaged devices or data.\n"));
2042		}
2043	}
2044
2045	/* Print the comment attached to the pool. */
2046	if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2047		(void) printf(gettext("comment: %s\n"), comment);
2048
2049	/*
2050	 * If the state is "closed" or "can't open", and the aux state
2051	 * is "corrupt data":
2052	 */
2053	if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2054	    (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2055	    (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2056		if (pool_state == POOL_STATE_DESTROYED)
2057			(void) printf(gettext("\tThe pool was destroyed, "
2058			    "but can be imported using the '-Df' flags.\n"));
2059		else if (pool_state != POOL_STATE_EXPORTED)
2060			(void) printf(gettext("\tThe pool may be active on "
2061			    "another system, but can be imported using\n\t"
2062			    "the '-f' flag.\n"));
2063	}
2064
2065	if (msgid != NULL)
2066		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
2067		    msgid);
2068
2069	(void) printf(gettext(" config:\n\n"));
2070
2071	namewidth = max_width(NULL, nvroot, 0, 0);
2072	if (namewidth < 10)
2073		namewidth = 10;
2074
2075	print_import_config(name, nvroot, namewidth, 0);
2076	if (num_logs(nvroot) > 0)
2077		print_logs(NULL, nvroot, namewidth, B_FALSE);
2078
2079	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2080		(void) printf(gettext("\n\tAdditional devices are known to "
2081		    "be part of this pool, though their\n\texact "
2082		    "configuration cannot be determined.\n"));
2083	}
2084}
2085
2086/*
2087 * Perform the import for the given configuration.  This passes the heavy
2088 * lifting off to zpool_import_props(), and then mounts the datasets contained
2089 * within the pool.
2090 */
2091static int
2092do_import(nvlist_t *config, const char *newname, const char *mntopts,
2093    nvlist_t *props, int flags)
2094{
2095	zpool_handle_t *zhp;
2096	char *name;
2097	uint64_t state;
2098	uint64_t version;
2099
2100	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2101	    &name) == 0);
2102
2103	verify(nvlist_lookup_uint64(config,
2104	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2105	verify(nvlist_lookup_uint64(config,
2106	    ZPOOL_CONFIG_VERSION, &version) == 0);
2107	if (!SPA_VERSION_IS_SUPPORTED(version)) {
2108		(void) fprintf(stderr, gettext("cannot import '%s': pool "
2109		    "is formatted using an unsupported ZFS version\n"), name);
2110		return (1);
2111	} else if (state != POOL_STATE_EXPORTED &&
2112	    !(flags & ZFS_IMPORT_ANY_HOST)) {
2113		uint64_t hostid;
2114
2115		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
2116		    &hostid) == 0) {
2117			if ((unsigned long)hostid != gethostid()) {
2118				char *hostname;
2119				uint64_t timestamp;
2120				time_t t;
2121
2122				verify(nvlist_lookup_string(config,
2123				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2124				verify(nvlist_lookup_uint64(config,
2125				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
2126				t = timestamp;
2127				(void) fprintf(stderr, gettext("cannot import "
2128				    "'%s': pool may be in use from other "
2129				    "system, it was last accessed by %s "
2130				    "(hostid: 0x%lx) on %s"), name, hostname,
2131				    (unsigned long)hostid,
2132				    asctime(localtime(&t)));
2133				(void) fprintf(stderr, gettext("use '-f' to "
2134				    "import anyway\n"));
2135				return (1);
2136			}
2137		} else {
2138			(void) fprintf(stderr, gettext("cannot import '%s': "
2139			    "pool may be in use from other system\n"), name);
2140			(void) fprintf(stderr, gettext("use '-f' to import "
2141			    "anyway\n"));
2142			return (1);
2143		}
2144	}
2145
2146	if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2147		return (1);
2148
2149	if (newname != NULL)
2150		name = (char *)newname;
2151
2152	if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2153		return (1);
2154
2155	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2156	    !(flags & ZFS_IMPORT_ONLY) &&
2157	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2158		zpool_close(zhp);
2159		return (1);
2160	}
2161
2162	zpool_close(zhp);
2163	return (0);
2164}
2165
2166/*
2167 * zpool checkpoint <pool>
2168 *       checkpoint --discard <pool>
2169 *
2170 *	-d	Discard the checkpoint from a checkpointed
2171 *	--discard  pool.
2172 *
2173 * Checkpoints the specified pool, by taking a "snapshot" of its
2174 * current state. A pool can only have one checkpoint at a time.
2175 */
2176int
2177zpool_do_checkpoint(int argc, char **argv)
2178{
2179	boolean_t discard;
2180	char *pool;
2181	zpool_handle_t *zhp;
2182	int c, err;
2183
2184	struct option long_options[] = {
2185		{"discard", no_argument, NULL, 'd'},
2186		{0, 0, 0, 0}
2187	};
2188
2189	discard = B_FALSE;
2190	while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2191		switch (c) {
2192		case 'd':
2193			discard = B_TRUE;
2194			break;
2195		case '?':
2196			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2197			    optopt);
2198			usage(B_FALSE);
2199		}
2200	}
2201
2202	argc -= optind;
2203	argv += optind;
2204
2205	if (argc < 1) {
2206		(void) fprintf(stderr, gettext("missing pool argument\n"));
2207		usage(B_FALSE);
2208	}
2209
2210	if (argc > 1) {
2211		(void) fprintf(stderr, gettext("too many arguments\n"));
2212		usage(B_FALSE);
2213	}
2214
2215	pool = argv[0];
2216
2217	if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2218		/* As a special case, check for use of '/' in the name */
2219		if (strchr(pool, '/') != NULL)
2220			(void) fprintf(stderr, gettext("'zpool checkpoint' "
2221			    "doesn't work on datasets. To save the state "
2222			    "of a dataset from a specific point in time "
2223			    "please use 'zfs snapshot'\n"));
2224		return (1);
2225	}
2226
2227	if (discard)
2228		err = (zpool_discard_checkpoint(zhp) != 0);
2229	else
2230		err = (zpool_checkpoint(zhp) != 0);
2231
2232	zpool_close(zhp);
2233
2234	return (err);
2235}
2236
2237#define	CHECKPOINT_OPT	1024
2238
2239/*
2240 * zpool import [-d dir] [-D]
2241 *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2242 *              [-d dir | -c cachefile] [-f] -a
2243 *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2244 *              [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
2245 *              <pool | id> [newpool]
2246 *
2247 *	-c	Read pool information from a cachefile instead of searching
2248 *		devices.
2249 *
2250 *	-d	Scan in a specific directory, other than /dev/dsk.  More than
2251 *		one directory can be specified using multiple '-d' options.
2252 *
2253 *	-D	Scan for previously destroyed pools or import all or only
2254 *		specified destroyed pools.
2255 *
2256 *	-R	Temporarily import the pool, with all mountpoints relative to
2257 *		the given root.  The pool will remain exported when the machine
2258 *		is rebooted.
2259 *
2260 *	-V	Import even in the presence of faulted vdevs.  This is an
2261 *		intentionally undocumented option for testing purposes, and
2262 *		treats the pool configuration as complete, leaving any bad
2263 *		vdevs in the FAULTED state. In other words, it does verbatim
2264 *		import.
2265 *
2266 *	-f	Force import, even if it appears that the pool is active.
2267 *
2268 *	-F	Attempt rewind if necessary.
2269 *
2270 *	-n	See if rewind would work, but don't actually rewind.
2271 *
2272 *	-N	Import the pool but don't mount datasets.
2273 *
2274 *	-t	Use newpool as a temporary pool name instead of renaming
2275 *		the pool.
2276 *
2277 *	-T	Specify a starting txg to use for import. This option is
2278 *		intentionally undocumented option for testing purposes.
2279 *
2280 *	-a	Import all pools found.
2281 *
2282 *	-o	Set property=value and/or temporary mount options (without '=').
2283 *
2284 *	--rewind-to-checkpoint
2285 *		Import the pool and revert back to the checkpoint.
2286 *
2287 * The import command scans for pools to import, and import pools based on pool
2288 * name and GUID.  The pool can also be renamed as part of the import process.
2289 */
2290int
2291zpool_do_import(int argc, char **argv)
2292{
2293	char **searchdirs = NULL;
2294	int nsearch = 0;
2295	int c;
2296	int err = 0;
2297	nvlist_t *pools = NULL;
2298	boolean_t do_all = B_FALSE;
2299	boolean_t do_destroyed = B_FALSE;
2300	char *mntopts = NULL;
2301	nvpair_t *elem;
2302	nvlist_t *config;
2303	uint64_t searchguid = 0;
2304	char *searchname = NULL;
2305	char *propval;
2306	nvlist_t *found_config;
2307	nvlist_t *policy = NULL;
2308	nvlist_t *props = NULL;
2309	boolean_t first;
2310	int flags = ZFS_IMPORT_NORMAL;
2311	uint32_t rewind_policy = ZPOOL_NO_REWIND;
2312	boolean_t dryrun = B_FALSE;
2313	boolean_t do_rewind = B_FALSE;
2314	boolean_t xtreme_rewind = B_FALSE;
2315	uint64_t pool_state, txg = -1ULL;
2316	char *cachefile = NULL;
2317	importargs_t idata = { 0 };
2318	char *endptr;
2319
2320
2321	struct option long_options[] = {
2322		{"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2323		{0, 0, 0, 0}
2324	};
2325
2326	/* check options */
2327	while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:tT:VX",
2328	    long_options, NULL)) != -1) {
2329		switch (c) {
2330		case 'a':
2331			do_all = B_TRUE;
2332			break;
2333		case 'c':
2334			cachefile = optarg;
2335			break;
2336		case 'd':
2337			if (searchdirs == NULL) {
2338				searchdirs = safe_malloc(sizeof (char *));
2339			} else {
2340				char **tmp = safe_malloc((nsearch + 1) *
2341				    sizeof (char *));
2342				bcopy(searchdirs, tmp, nsearch *
2343				    sizeof (char *));
2344				free(searchdirs);
2345				searchdirs = tmp;
2346			}
2347			searchdirs[nsearch++] = optarg;
2348			break;
2349		case 'D':
2350			do_destroyed = B_TRUE;
2351			break;
2352		case 'f':
2353			flags |= ZFS_IMPORT_ANY_HOST;
2354			break;
2355		case 'F':
2356			do_rewind = B_TRUE;
2357			break;
2358		case 'm':
2359			flags |= ZFS_IMPORT_MISSING_LOG;
2360			break;
2361		case 'n':
2362			dryrun = B_TRUE;
2363			break;
2364		case 'N':
2365			flags |= ZFS_IMPORT_ONLY;
2366			break;
2367		case 'o':
2368			if ((propval = strchr(optarg, '=')) != NULL) {
2369				*propval = '\0';
2370				propval++;
2371				if (add_prop_list(optarg, propval,
2372				    &props, B_TRUE))
2373					goto error;
2374			} else {
2375				mntopts = optarg;
2376			}
2377			break;
2378		case 'R':
2379			if (add_prop_list(zpool_prop_to_name(
2380			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2381				goto error;
2382			if (add_prop_list_default(zpool_prop_to_name(
2383			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2384				goto error;
2385			break;
2386		case 't':
2387			flags |= ZFS_IMPORT_TEMP_NAME;
2388			if (add_prop_list_default(zpool_prop_to_name(
2389			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2390				goto error;
2391			break;
2392		case 'T':
2393			errno = 0;
2394			txg = strtoull(optarg, &endptr, 0);
2395			if (errno != 0 || *endptr != '\0') {
2396				(void) fprintf(stderr,
2397				    gettext("invalid txg value\n"));
2398				usage(B_FALSE);
2399			}
2400			rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2401			break;
2402		case 'V':
2403			flags |= ZFS_IMPORT_VERBATIM;
2404			break;
2405		case 'X':
2406			xtreme_rewind = B_TRUE;
2407			break;
2408		case CHECKPOINT_OPT:
2409			flags |= ZFS_IMPORT_CHECKPOINT;
2410			break;
2411		case ':':
2412			(void) fprintf(stderr, gettext("missing argument for "
2413			    "'%c' option\n"), optopt);
2414			usage(B_FALSE);
2415			break;
2416		case '?':
2417			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2418			    optopt);
2419			usage(B_FALSE);
2420		}
2421	}
2422
2423	argc -= optind;
2424	argv += optind;
2425
2426	if (cachefile && nsearch != 0) {
2427		(void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2428		usage(B_FALSE);
2429	}
2430
2431	if ((dryrun || xtreme_rewind) && !do_rewind) {
2432		(void) fprintf(stderr,
2433		    gettext("-n or -X only meaningful with -F\n"));
2434		usage(B_FALSE);
2435	}
2436	if (dryrun)
2437		rewind_policy = ZPOOL_TRY_REWIND;
2438	else if (do_rewind)
2439		rewind_policy = ZPOOL_DO_REWIND;
2440	if (xtreme_rewind)
2441		rewind_policy |= ZPOOL_EXTREME_REWIND;
2442
2443	/* In the future, we can capture further policy and include it here */
2444	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2445	    nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
2446	    nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
2447	    rewind_policy) != 0)
2448		goto error;
2449
2450	if (searchdirs == NULL) {
2451		searchdirs = safe_malloc(sizeof (char *));
2452		searchdirs[0] = "/dev";
2453		nsearch = 1;
2454	}
2455
2456	/* check argument count */
2457	if (do_all) {
2458		if (argc != 0) {
2459			(void) fprintf(stderr, gettext("too many arguments\n"));
2460			usage(B_FALSE);
2461		}
2462	} else {
2463		if (argc > 2) {
2464			(void) fprintf(stderr, gettext("too many arguments\n"));
2465			usage(B_FALSE);
2466		}
2467
2468		/*
2469		 * Check for the SYS_CONFIG privilege.  We do this explicitly
2470		 * here because otherwise any attempt to discover pools will
2471		 * silently fail.
2472		 */
2473		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2474			(void) fprintf(stderr, gettext("cannot "
2475			    "discover pools: permission denied\n"));
2476			free(searchdirs);
2477			nvlist_free(policy);
2478			return (1);
2479		}
2480	}
2481
2482	/*
2483	 * Depending on the arguments given, we do one of the following:
2484	 *
2485	 *	<none>	Iterate through all pools and display information about
2486	 *		each one.
2487	 *
2488	 *	-a	Iterate through all pools and try to import each one.
2489	 *
2490	 *	<id>	Find the pool that corresponds to the given GUID/pool
2491	 *		name and import that one.
2492	 *
2493	 *	-D	Above options applies only to destroyed pools.
2494	 */
2495	if (argc != 0) {
2496		char *endptr;
2497
2498		errno = 0;
2499		searchguid = strtoull(argv[0], &endptr, 10);
2500		if (errno != 0 || *endptr != '\0') {
2501			searchname = argv[0];
2502			searchguid = 0;
2503		}
2504		found_config = NULL;
2505
2506		/*
2507		 * User specified a name or guid.  Ensure it's unique.
2508		 */
2509		idata.unique = B_TRUE;
2510	}
2511
2512
2513	idata.path = searchdirs;
2514	idata.paths = nsearch;
2515	idata.poolname = searchname;
2516	idata.guid = searchguid;
2517	idata.cachefile = cachefile;
2518	idata.policy = policy;
2519
2520	pools = zpool_search_import(g_zfs, &idata);
2521
2522	if (pools != NULL && idata.exists &&
2523	    (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2524		(void) fprintf(stderr, gettext("cannot import '%s': "
2525		    "a pool with that name already exists\n"),
2526		    argv[0]);
2527		(void) fprintf(stderr, gettext("use the form 'zpool import "
2528		    "[-t] <pool | id> <newpool>' to give it a new temporary "
2529		    "or permanent name\n"));
2530		err = 1;
2531	} else if (pools == NULL && idata.exists) {
2532		(void) fprintf(stderr, gettext("cannot import '%s': "
2533		    "a pool with that name is already created/imported,\n"),
2534		    argv[0]);
2535		(void) fprintf(stderr, gettext("and no additional pools "
2536		    "with that name were found\n"));
2537		err = 1;
2538	} else if (pools == NULL) {
2539		if (argc != 0) {
2540			(void) fprintf(stderr, gettext("cannot import '%s': "
2541			    "no such pool available\n"), argv[0]);
2542		}
2543		err = 1;
2544	}
2545
2546	if (err == 1) {
2547		free(searchdirs);
2548		nvlist_free(policy);
2549		return (1);
2550	}
2551
2552	/*
2553	 * At this point we have a list of import candidate configs. Even if
2554	 * we were searching by pool name or guid, we still need to
2555	 * post-process the list to deal with pool state and possible
2556	 * duplicate names.
2557	 */
2558	err = 0;
2559	elem = NULL;
2560	first = B_TRUE;
2561	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2562
2563		verify(nvpair_value_nvlist(elem, &config) == 0);
2564
2565		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2566		    &pool_state) == 0);
2567		if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2568			continue;
2569		if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2570			continue;
2571
2572		verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
2573		    policy) == 0);
2574
2575		if (argc == 0) {
2576			if (first)
2577				first = B_FALSE;
2578			else if (!do_all)
2579				(void) printf("\n");
2580
2581			if (do_all) {
2582				err |= do_import(config, NULL, mntopts,
2583				    props, flags);
2584			} else {
2585				show_import(config);
2586			}
2587		} else if (searchname != NULL) {
2588			char *name;
2589
2590			/*
2591			 * We are searching for a pool based on name.
2592			 */
2593			verify(nvlist_lookup_string(config,
2594			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2595
2596			if (strcmp(name, searchname) == 0) {
2597				if (found_config != NULL) {
2598					(void) fprintf(stderr, gettext(
2599					    "cannot import '%s': more than "
2600					    "one matching pool\n"), searchname);
2601					(void) fprintf(stderr, gettext(
2602					    "import by numeric ID instead\n"));
2603					err = B_TRUE;
2604				}
2605				found_config = config;
2606			}
2607		} else {
2608			uint64_t guid;
2609
2610			/*
2611			 * Search for a pool by guid.
2612			 */
2613			verify(nvlist_lookup_uint64(config,
2614			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2615
2616			if (guid == searchguid)
2617				found_config = config;
2618		}
2619	}
2620
2621	/*
2622	 * If we were searching for a specific pool, verify that we found a
2623	 * pool, and then do the import.
2624	 */
2625	if (argc != 0 && err == 0) {
2626		if (found_config == NULL) {
2627			(void) fprintf(stderr, gettext("cannot import '%s': "
2628			    "no such pool available\n"), argv[0]);
2629			err = B_TRUE;
2630		} else {
2631			err |= do_import(found_config, argc == 1 ? NULL :
2632			    argv[1], mntopts, props, flags);
2633		}
2634	}
2635
2636	/*
2637	 * If we were just looking for pools, report an error if none were
2638	 * found.
2639	 */
2640	if (argc == 0 && first)
2641		(void) fprintf(stderr,
2642		    gettext("no pools available to import\n"));
2643
2644error:
2645	nvlist_free(props);
2646	nvlist_free(pools);
2647	nvlist_free(policy);
2648	free(searchdirs);
2649
2650	return (err ? 1 : 0);
2651}
2652
2653typedef struct iostat_cbdata {
2654	boolean_t cb_verbose;
2655	int cb_namewidth;
2656	int cb_iteration;
2657	zpool_list_t *cb_list;
2658} iostat_cbdata_t;
2659
2660static void
2661print_iostat_separator(iostat_cbdata_t *cb)
2662{
2663	int i = 0;
2664
2665	for (i = 0; i < cb->cb_namewidth; i++)
2666		(void) printf("-");
2667	(void) printf("  -----  -----  -----  -----  -----  -----\n");
2668}
2669
2670static void
2671print_iostat_header(iostat_cbdata_t *cb)
2672{
2673	(void) printf("%*s     capacity     operations    bandwidth\n",
2674	    cb->cb_namewidth, "");
2675	(void) printf("%-*s  alloc   free   read  write   read  write\n",
2676	    cb->cb_namewidth, "pool");
2677	print_iostat_separator(cb);
2678}
2679
2680/*
2681 * Display a single statistic.
2682 */
2683static void
2684print_one_stat(uint64_t value)
2685{
2686	char buf[64];
2687
2688	zfs_nicenum(value, buf, sizeof (buf));
2689	(void) printf("  %5s", buf);
2690}
2691
2692/*
2693 * Print out all the statistics for the given vdev.  This can either be the
2694 * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2695 * is a verbose output, and we don't want to display the toplevel pool stats.
2696 */
2697void
2698print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2699    nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2700{
2701	nvlist_t **oldchild, **newchild;
2702	uint_t c, children;
2703	vdev_stat_t *oldvs, *newvs;
2704	vdev_stat_t zerovs = { 0 };
2705	uint64_t tdelta;
2706	double scale;
2707	char *vname;
2708
2709	if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2710		return;
2711
2712	if (oldnv != NULL) {
2713		verify(nvlist_lookup_uint64_array(oldnv,
2714		    ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2715	} else {
2716		oldvs = &zerovs;
2717	}
2718
2719	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2720	    (uint64_t **)&newvs, &c) == 0);
2721
2722	if (strlen(name) + depth > cb->cb_namewidth)
2723		(void) printf("%*s%s", depth, "", name);
2724	else
2725		(void) printf("%*s%s%*s", depth, "", name,
2726		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
2727
2728	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2729
2730	if (tdelta == 0)
2731		scale = 1.0;
2732	else
2733		scale = (double)NANOSEC / tdelta;
2734
2735	/* only toplevel vdevs have capacity stats */
2736	if (newvs->vs_space == 0) {
2737		(void) printf("      -      -");
2738	} else {
2739		print_one_stat(newvs->vs_alloc);
2740		print_one_stat(newvs->vs_space - newvs->vs_alloc);
2741	}
2742
2743	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2744	    oldvs->vs_ops[ZIO_TYPE_READ])));
2745
2746	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2747	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
2748
2749	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2750	    oldvs->vs_bytes[ZIO_TYPE_READ])));
2751
2752	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2753	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2754
2755	(void) printf("\n");
2756
2757	if (!cb->cb_verbose)
2758		return;
2759
2760	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2761	    &newchild, &children) != 0)
2762		return;
2763
2764	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2765	    &oldchild, &c) != 0)
2766		return;
2767
2768	for (c = 0; c < children; c++) {
2769		uint64_t ishole = B_FALSE, islog = B_FALSE;
2770
2771		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2772		    &ishole);
2773
2774		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2775		    &islog);
2776
2777		if (ishole || islog)
2778			continue;
2779
2780		vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2781		print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2782		    newchild[c], cb, depth + 2);
2783		free(vname);
2784	}
2785
2786	/*
2787	 * Log device section
2788	 */
2789
2790	if (num_logs(newnv) > 0) {
2791		(void) printf("%-*s      -      -      -      -      -      "
2792		    "-\n", cb->cb_namewidth, "logs");
2793
2794		for (c = 0; c < children; c++) {
2795			uint64_t islog = B_FALSE;
2796			(void) nvlist_lookup_uint64(newchild[c],
2797			    ZPOOL_CONFIG_IS_LOG, &islog);
2798
2799			if (islog) {
2800				vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2801				    B_FALSE);
2802				print_vdev_stats(zhp, vname, oldnv ?
2803				    oldchild[c] : NULL, newchild[c],
2804				    cb, depth + 2);
2805				free(vname);
2806			}
2807		}
2808
2809	}
2810
2811	/*
2812	 * Include level 2 ARC devices in iostat output
2813	 */
2814	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2815	    &newchild, &children) != 0)
2816		return;
2817
2818	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2819	    &oldchild, &c) != 0)
2820		return;
2821
2822	if (children > 0) {
2823		(void) printf("%-*s      -      -      -      -      -      "
2824		    "-\n", cb->cb_namewidth, "cache");
2825		for (c = 0; c < children; c++) {
2826			vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2827			    B_FALSE);
2828			print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2829			    newchild[c], cb, depth + 2);
2830			free(vname);
2831		}
2832	}
2833}
2834
2835static int
2836refresh_iostat(zpool_handle_t *zhp, void *data)
2837{
2838	iostat_cbdata_t *cb = data;
2839	boolean_t missing;
2840
2841	/*
2842	 * If the pool has disappeared, remove it from the list and continue.
2843	 */
2844	if (zpool_refresh_stats(zhp, &missing) != 0)
2845		return (-1);
2846
2847	if (missing)
2848		pool_list_remove(cb->cb_list, zhp);
2849
2850	return (0);
2851}
2852
2853/*
2854 * Callback to print out the iostats for the given pool.
2855 */
2856int
2857print_iostat(zpool_handle_t *zhp, void *data)
2858{
2859	iostat_cbdata_t *cb = data;
2860	nvlist_t *oldconfig, *newconfig;
2861	nvlist_t *oldnvroot, *newnvroot;
2862
2863	newconfig = zpool_get_config(zhp, &oldconfig);
2864
2865	if (cb->cb_iteration == 1)
2866		oldconfig = NULL;
2867
2868	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2869	    &newnvroot) == 0);
2870
2871	if (oldconfig == NULL)
2872		oldnvroot = NULL;
2873	else
2874		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2875		    &oldnvroot) == 0);
2876
2877	/*
2878	 * Print out the statistics for the pool.
2879	 */
2880	print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2881
2882	if (cb->cb_verbose)
2883		print_iostat_separator(cb);
2884
2885	return (0);
2886}
2887
2888int
2889get_namewidth(zpool_handle_t *zhp, void *data)
2890{
2891	iostat_cbdata_t *cb = data;
2892	nvlist_t *config, *nvroot;
2893
2894	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2895		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2896		    &nvroot) == 0);
2897		if (!cb->cb_verbose)
2898			cb->cb_namewidth = strlen(zpool_get_name(zhp));
2899		else
2900			cb->cb_namewidth = max_width(zhp, nvroot, 0,
2901			    cb->cb_namewidth);
2902	}
2903
2904	/*
2905	 * The width must fall into the range [10,38].  The upper limit is the
2906	 * maximum we can have and still fit in 80 columns.
2907	 */
2908	if (cb->cb_namewidth < 10)
2909		cb->cb_namewidth = 10;
2910	if (cb->cb_namewidth > 38)
2911		cb->cb_namewidth = 38;
2912
2913	return (0);
2914}
2915
2916/*
2917 * Parse the input string, get the 'interval' and 'count' value if there is one.
2918 */
2919static void
2920get_interval_count(int *argcp, char **argv, unsigned long *iv,
2921    unsigned long *cnt)
2922{
2923	unsigned long interval = 0, count = 0;
2924	int argc = *argcp, errno;
2925
2926	/*
2927	 * Determine if the last argument is an integer or a pool name
2928	 */
2929	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2930		char *end;
2931
2932		errno = 0;
2933		interval = strtoul(argv[argc - 1], &end, 10);
2934
2935		if (*end == '\0' && errno == 0) {
2936			if (interval == 0) {
2937				(void) fprintf(stderr, gettext("interval "
2938				    "cannot be zero\n"));
2939				usage(B_FALSE);
2940			}
2941			/*
2942			 * Ignore the last parameter
2943			 */
2944			argc--;
2945		} else {
2946			/*
2947			 * If this is not a valid number, just plow on.  The
2948			 * user will get a more informative error message later
2949			 * on.
2950			 */
2951			interval = 0;
2952		}
2953	}
2954
2955	/*
2956	 * If the last argument is also an integer, then we have both a count
2957	 * and an interval.
2958	 */
2959	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2960		char *end;
2961
2962		errno = 0;
2963		count = interval;
2964		interval = strtoul(argv[argc - 1], &end, 10);
2965
2966		if (*end == '\0' && errno == 0) {
2967			if (interval == 0) {
2968				(void) fprintf(stderr, gettext("interval "
2969				    "cannot be zero\n"));
2970				usage(B_FALSE);
2971			}
2972
2973			/*
2974			 * Ignore the last parameter
2975			 */
2976			argc--;
2977		} else {
2978			interval = 0;
2979		}
2980	}
2981
2982	*iv = interval;
2983	*cnt = count;
2984	*argcp = argc;
2985}
2986
2987static void
2988get_timestamp_arg(char c)
2989{
2990	if (c == 'u')
2991		timestamp_fmt = UDATE;
2992	else if (c == 'd')
2993		timestamp_fmt = DDATE;
2994	else
2995		usage(B_FALSE);
2996}
2997
2998/*
2999 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
3000 *
3001 *	-v	Display statistics for individual vdevs
3002 *	-T	Display a timestamp in date(1) or Unix format
3003 *
3004 * This command can be tricky because we want to be able to deal with pool
3005 * creation/destruction as well as vdev configuration changes.  The bulk of this
3006 * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
3007 * on pool_list_update() to detect the addition of new pools.  Configuration
3008 * changes are all handled within libzfs.
3009 */
3010int
3011zpool_do_iostat(int argc, char **argv)
3012{
3013	int c;
3014	int ret;
3015	int npools;
3016	unsigned long interval = 0, count = 0;
3017	zpool_list_t *list;
3018	boolean_t verbose = B_FALSE;
3019	iostat_cbdata_t cb;
3020
3021	/* check options */
3022	while ((c = getopt(argc, argv, "T:v")) != -1) {
3023		switch (c) {
3024		case 'T':
3025			get_timestamp_arg(*optarg);
3026			break;
3027		case 'v':
3028			verbose = B_TRUE;
3029			break;
3030		case '?':
3031			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3032			    optopt);
3033			usage(B_FALSE);
3034		}
3035	}
3036
3037	argc -= optind;
3038	argv += optind;
3039
3040	get_interval_count(&argc, argv, &interval, &count);
3041
3042	/*
3043	 * Construct the list of all interesting pools.
3044	 */
3045	ret = 0;
3046	if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
3047		return (1);
3048
3049	if (pool_list_count(list) == 0 && argc != 0) {
3050		pool_list_free(list);
3051		return (1);
3052	}
3053
3054	if (pool_list_count(list) == 0 && interval == 0) {
3055		pool_list_free(list);
3056		(void) fprintf(stderr, gettext("no pools available\n"));
3057		return (1);
3058	}
3059
3060	/*
3061	 * Enter the main iostat loop.
3062	 */
3063	cb.cb_list = list;
3064	cb.cb_verbose = verbose;
3065	cb.cb_iteration = 0;
3066	cb.cb_namewidth = 0;
3067
3068	for (;;) {
3069		pool_list_update(list);
3070
3071		if ((npools = pool_list_count(list)) == 0)
3072			break;
3073
3074		/*
3075		 * Refresh all statistics.  This is done as an explicit step
3076		 * before calculating the maximum name width, so that any
3077		 * configuration changes are properly accounted for.
3078		 */
3079		(void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
3080
3081		/*
3082		 * Iterate over all pools to determine the maximum width
3083		 * for the pool / device name column across all pools.
3084		 */
3085		cb.cb_namewidth = 0;
3086		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3087
3088		if (timestamp_fmt != NODATE)
3089			print_timestamp(timestamp_fmt);
3090
3091		/*
3092		 * If it's the first time, or verbose mode, print the header.
3093		 */
3094		if (++cb.cb_iteration == 1 || verbose)
3095			print_iostat_header(&cb);
3096
3097		(void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
3098
3099		/*
3100		 * If there's more than one pool, and we're not in verbose mode
3101		 * (which prints a separator for us), then print a separator.
3102		 */
3103		if (npools > 1 && !verbose)
3104			print_iostat_separator(&cb);
3105
3106		if (verbose)
3107			(void) printf("\n");
3108
3109		/*
3110		 * Flush the output so that redirection to a file isn't buffered
3111		 * indefinitely.
3112		 */
3113		(void) fflush(stdout);
3114
3115		if (interval == 0)
3116			break;
3117
3118		if (count != 0 && --count == 0)
3119			break;
3120
3121		(void) sleep(interval);
3122	}
3123
3124	pool_list_free(list);
3125
3126	return (ret);
3127}
3128
3129typedef struct list_cbdata {
3130	boolean_t	cb_verbose;
3131	int		cb_namewidth;
3132	boolean_t	cb_scripted;
3133	zprop_list_t	*cb_proplist;
3134	boolean_t	cb_literal;
3135} list_cbdata_t;
3136
3137/*
3138 * Given a list of columns to display, output appropriate headers for each one.
3139 */
3140static void
3141print_header(list_cbdata_t *cb)
3142{
3143	zprop_list_t *pl = cb->cb_proplist;
3144	char headerbuf[ZPOOL_MAXPROPLEN];
3145	const char *header;
3146	boolean_t first = B_TRUE;
3147	boolean_t right_justify;
3148	size_t width = 0;
3149
3150	for (; pl != NULL; pl = pl->pl_next) {
3151		width = pl->pl_width;
3152		if (first && cb->cb_verbose) {
3153			/*
3154			 * Reset the width to accommodate the verbose listing
3155			 * of devices.
3156			 */
3157			width = cb->cb_namewidth;
3158		}
3159
3160		if (!first)
3161			(void) printf("  ");
3162		else
3163			first = B_FALSE;
3164
3165		right_justify = B_FALSE;
3166		if (pl->pl_prop != ZPROP_INVAL) {
3167			header = zpool_prop_column_name(pl->pl_prop);
3168			right_justify = zpool_prop_align_right(pl->pl_prop);
3169		} else {
3170			int i;
3171
3172			for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3173				headerbuf[i] = toupper(pl->pl_user_prop[i]);
3174			headerbuf[i] = '\0';
3175			header = headerbuf;
3176		}
3177
3178		if (pl->pl_next == NULL && !right_justify)
3179			(void) printf("%s", header);
3180		else if (right_justify)
3181			(void) printf("%*s", width, header);
3182		else
3183			(void) printf("%-*s", width, header);
3184
3185	}
3186
3187	(void) printf("\n");
3188}
3189
3190/*
3191 * Given a pool and a list of properties, print out all the properties according
3192 * to the described layout.
3193 */
3194static void
3195print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3196{
3197	zprop_list_t *pl = cb->cb_proplist;
3198	boolean_t first = B_TRUE;
3199	char property[ZPOOL_MAXPROPLEN];
3200	char *propstr;
3201	boolean_t right_justify;
3202	size_t width;
3203
3204	for (; pl != NULL; pl = pl->pl_next) {
3205
3206		width = pl->pl_width;
3207		if (first && cb->cb_verbose) {
3208			/*
3209			 * Reset the width to accommodate the verbose listing
3210			 * of devices.
3211			 */
3212			width = cb->cb_namewidth;
3213		}
3214
3215		if (!first) {
3216			if (cb->cb_scripted)
3217				(void) printf("\t");
3218			else
3219				(void) printf("  ");
3220		} else {
3221			first = B_FALSE;
3222		}
3223
3224		right_justify = B_FALSE;
3225		if (pl->pl_prop != ZPROP_INVAL) {
3226			if (zpool_get_prop(zhp, pl->pl_prop, property,
3227			    sizeof (property), NULL, cb->cb_literal) != 0)
3228				propstr = "-";
3229			else
3230				propstr = property;
3231
3232			right_justify = zpool_prop_align_right(pl->pl_prop);
3233		} else if ((zpool_prop_feature(pl->pl_user_prop) ||
3234		    zpool_prop_unsupported(pl->pl_user_prop)) &&
3235		    zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3236		    sizeof (property)) == 0) {
3237			propstr = property;
3238		} else {
3239			propstr = "-";
3240		}
3241
3242
3243		/*
3244		 * If this is being called in scripted mode, or if this is the
3245		 * last column and it is left-justified, don't include a width
3246		 * format specifier.
3247		 */
3248		if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3249			(void) printf("%s", propstr);
3250		else if (right_justify)
3251			(void) printf("%*s", width, propstr);
3252		else
3253			(void) printf("%-*s", width, propstr);
3254	}
3255
3256	(void) printf("\n");
3257}
3258
3259static void
3260print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3261    boolean_t valid)
3262{
3263	char propval[64];
3264	boolean_t fixed;
3265	size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3266
3267	switch (prop) {
3268	case ZPOOL_PROP_EXPANDSZ:
3269	case ZPOOL_PROP_CHECKPOINT:
3270		if (value == 0)
3271			(void) strlcpy(propval, "-", sizeof (propval));
3272		else
3273			zfs_nicenum(value, propval, sizeof (propval));
3274		break;
3275	case ZPOOL_PROP_FRAGMENTATION:
3276		if (value == ZFS_FRAG_INVALID) {
3277			(void) strlcpy(propval, "-", sizeof (propval));
3278		} else {
3279			(void) snprintf(propval, sizeof (propval), "%llu%%",
3280			    value);
3281		}
3282		break;
3283	case ZPOOL_PROP_CAPACITY:
3284		(void) snprintf(propval, sizeof (propval), "%llu%%", value);
3285		break;
3286	default:
3287		zfs_nicenum(value, propval, sizeof (propval));
3288	}
3289
3290	if (!valid)
3291		(void) strlcpy(propval, "-", sizeof (propval));
3292
3293	if (scripted)
3294		(void) printf("\t%s", propval);
3295	else
3296		(void) printf("  %*s", width, propval);
3297}
3298
3299void
3300print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3301    list_cbdata_t *cb, int depth)
3302{
3303	nvlist_t **child;
3304	vdev_stat_t *vs;
3305	uint_t c, children;
3306	char *vname;
3307	boolean_t scripted = cb->cb_scripted;
3308	uint64_t islog = B_FALSE;
3309	boolean_t haslog = B_FALSE;
3310	char *dashes = "%-*s      -      -      -         -      -      -\n";
3311
3312	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3313	    (uint64_t **)&vs, &c) == 0);
3314
3315	if (name != NULL) {
3316		boolean_t toplevel = (vs->vs_space != 0);
3317		uint64_t cap;
3318
3319		if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3320			return;
3321
3322		if (scripted)
3323			(void) printf("\t%s", name);
3324		else if (strlen(name) + depth > cb->cb_namewidth)
3325			(void) printf("%*s%s", depth, "", name);
3326		else
3327			(void) printf("%*s%s%*s", depth, "", name,
3328			    (int)(cb->cb_namewidth - strlen(name) - depth), "");
3329
3330		/*
3331		 * Print the properties for the individual vdevs. Some
3332		 * properties are only applicable to toplevel vdevs. The
3333		 * 'toplevel' boolean value is passed to the print_one_column()
3334		 * to indicate that the value is valid.
3335		 */
3336		print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3337		    toplevel);
3338		print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3339		    toplevel);
3340		print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3341		    scripted, toplevel);
3342		print_one_column(ZPOOL_PROP_CHECKPOINT,
3343		    vs->vs_checkpoint_space, scripted, toplevel);
3344		print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3345		    B_TRUE);
3346		print_one_column(ZPOOL_PROP_FRAGMENTATION,
3347		    vs->vs_fragmentation, scripted,
3348		    (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3349		cap = (vs->vs_space == 0) ? 0 :
3350		    (vs->vs_alloc * 100 / vs->vs_space);
3351		print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3352		(void) printf("\n");
3353	}
3354
3355	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3356	    &child, &children) != 0)
3357		return;
3358
3359	for (c = 0; c < children; c++) {
3360		uint64_t ishole = B_FALSE;
3361
3362		if (nvlist_lookup_uint64(child[c],
3363		    ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3364			continue;
3365
3366		if (nvlist_lookup_uint64(child[c],
3367		    ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3368			haslog = B_TRUE;
3369			continue;
3370		}
3371
3372		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3373		print_list_stats(zhp, vname, child[c], cb, depth + 2);
3374		free(vname);
3375	}
3376
3377	if (haslog == B_TRUE) {
3378		/* LINTED E_SEC_PRINTF_VAR_FMT */
3379		(void) printf(dashes, cb->cb_namewidth, "log");
3380		for (c = 0; c < children; c++) {
3381			if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3382			    &islog) != 0 || !islog)
3383				continue;
3384			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3385			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3386			free(vname);
3387		}
3388	}
3389
3390	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3391	    &child, &children) == 0 && children > 0) {
3392		/* LINTED E_SEC_PRINTF_VAR_FMT */
3393		(void) printf(dashes, cb->cb_namewidth, "cache");
3394		for (c = 0; c < children; c++) {
3395			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3396			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3397			free(vname);
3398		}
3399	}
3400
3401	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3402	    &children) == 0 && children > 0) {
3403		/* LINTED E_SEC_PRINTF_VAR_FMT */
3404		(void) printf(dashes, cb->cb_namewidth, "spare");
3405		for (c = 0; c < children; c++) {
3406			vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3407			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3408			free(vname);
3409		}
3410	}
3411}
3412
3413
3414/*
3415 * Generic callback function to list a pool.
3416 */
3417int
3418list_callback(zpool_handle_t *zhp, void *data)
3419{
3420	list_cbdata_t *cbp = data;
3421	nvlist_t *config;
3422	nvlist_t *nvroot;
3423
3424	config = zpool_get_config(zhp, NULL);
3425
3426	print_pool(zhp, cbp);
3427	if (!cbp->cb_verbose)
3428		return (0);
3429
3430	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3431	    &nvroot) == 0);
3432	print_list_stats(zhp, NULL, nvroot, cbp, 0);
3433
3434	return (0);
3435}
3436
3437/*
3438 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3439 *
3440 *	-H	Scripted mode.  Don't display headers, and separate properties
3441 *		by a single tab.
3442 *	-o	List of properties to display.  Defaults to
3443 *		"name,size,allocated,free,expandsize,fragmentation,capacity,"
3444 *		"dedupratio,health,altroot"
3445 *	-p	Diplay values in parsable (exact) format.
3446 *	-T	Display a timestamp in date(1) or Unix format
3447 *
3448 * List all pools in the system, whether or not they're healthy.  Output space
3449 * statistics for each one, as well as health status summary.
3450 */
3451int
3452zpool_do_list(int argc, char **argv)
3453{
3454	int c;
3455	int ret;
3456	list_cbdata_t cb = { 0 };
3457	static char default_props[] =
3458	    "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
3459	    "capacity,dedupratio,health,altroot";
3460	char *props = default_props;
3461	unsigned long interval = 0, count = 0;
3462	zpool_list_t *list;
3463	boolean_t first = B_TRUE;
3464
3465	/* check options */
3466	while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3467		switch (c) {
3468		case 'H':
3469			cb.cb_scripted = B_TRUE;
3470			break;
3471		case 'o':
3472			props = optarg;
3473			break;
3474		case 'p':
3475			cb.cb_literal = B_TRUE;
3476			break;
3477		case 'T':
3478			get_timestamp_arg(*optarg);
3479			break;
3480		case 'v':
3481			cb.cb_verbose = B_TRUE;
3482			break;
3483		case ':':
3484			(void) fprintf(stderr, gettext("missing argument for "
3485			    "'%c' option\n"), optopt);
3486			usage(B_FALSE);
3487			break;
3488		case '?':
3489			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3490			    optopt);
3491			usage(B_FALSE);
3492		}
3493	}
3494
3495	argc -= optind;
3496	argv += optind;
3497
3498	get_interval_count(&argc, argv, &interval, &count);
3499
3500	if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3501		usage(B_FALSE);
3502
3503	for (;;) {
3504		if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3505		    &ret)) == NULL)
3506			return (1);
3507
3508		if (pool_list_count(list) == 0)
3509			break;
3510
3511		cb.cb_namewidth = 0;
3512		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3513
3514		if (timestamp_fmt != NODATE)
3515			print_timestamp(timestamp_fmt);
3516
3517		if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3518			print_header(&cb);
3519			first = B_FALSE;
3520		}
3521		ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3522
3523		if (interval == 0)
3524			break;
3525
3526		if (count != 0 && --count == 0)
3527			break;
3528
3529		pool_list_free(list);
3530		(void) sleep(interval);
3531	}
3532
3533	if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3534		(void) printf(gettext("no pools available\n"));
3535		ret = 0;
3536	}
3537
3538	pool_list_free(list);
3539	zprop_free_list(cb.cb_proplist);
3540	return (ret);
3541}
3542
3543static int
3544zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3545{
3546	boolean_t force = B_FALSE;
3547	int c;
3548	nvlist_t *nvroot;
3549	char *poolname, *old_disk, *new_disk;
3550	zpool_handle_t *zhp;
3551	zpool_boot_label_t boot_type;
3552	uint64_t boot_size;
3553	int ret;
3554
3555	/* check options */
3556	while ((c = getopt(argc, argv, "f")) != -1) {
3557		switch (c) {
3558		case 'f':
3559			force = B_TRUE;
3560			break;
3561		case '?':
3562			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3563			    optopt);
3564			usage(B_FALSE);
3565		}
3566	}
3567
3568	argc -= optind;
3569	argv += optind;
3570
3571	/* get pool name and check number of arguments */
3572	if (argc < 1) {
3573		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3574		usage(B_FALSE);
3575	}
3576
3577	poolname = argv[0];
3578
3579	if (argc < 2) {
3580		(void) fprintf(stderr,
3581		    gettext("missing <device> specification\n"));
3582		usage(B_FALSE);
3583	}
3584
3585	old_disk = argv[1];
3586
3587	if (argc < 3) {
3588		if (!replacing) {
3589			(void) fprintf(stderr,
3590			    gettext("missing <new_device> specification\n"));
3591			usage(B_FALSE);
3592		}
3593		new_disk = old_disk;
3594		argc -= 1;
3595		argv += 1;
3596	} else {
3597		new_disk = argv[2];
3598		argc -= 2;
3599		argv += 2;
3600	}
3601
3602	if (argc > 1) {
3603		(void) fprintf(stderr, gettext("too many arguments\n"));
3604		usage(B_FALSE);
3605	}
3606
3607	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3608		return (1);
3609
3610	if (zpool_get_config(zhp, NULL) == NULL) {
3611		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3612		    poolname);
3613		zpool_close(zhp);
3614		return (1);
3615	}
3616
3617	if (zpool_is_bootable(zhp))
3618		boot_type = ZPOOL_COPY_BOOT_LABEL;
3619	else
3620		boot_type = ZPOOL_NO_BOOT_LABEL;
3621
3622	boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3623	nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3624	    boot_type, boot_size, argc, argv);
3625	if (nvroot == NULL) {
3626		zpool_close(zhp);
3627		return (1);
3628	}
3629
3630	ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3631
3632	nvlist_free(nvroot);
3633	zpool_close(zhp);
3634
3635	return (ret);
3636}
3637
3638/*
3639 * zpool replace [-f] <pool> <device> <new_device>
3640 *
3641 *	-f	Force attach, even if <new_device> appears to be in use.
3642 *
3643 * Replace <device> with <new_device>.
3644 */
3645/* ARGSUSED */
3646int
3647zpool_do_replace(int argc, char **argv)
3648{
3649	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3650}
3651
3652/*
3653 * zpool attach [-f] <pool> <device> <new_device>
3654 *
3655 *	-f	Force attach, even if <new_device> appears to be in use.
3656 *
3657 * Attach <new_device> to the mirror containing <device>.  If <device> is not
3658 * part of a mirror, then <device> will be transformed into a mirror of
3659 * <device> and <new_device>.  In either case, <new_device> will begin life
3660 * with a DTL of [0, now], and will immediately begin to resilver itself.
3661 */
3662int
3663zpool_do_attach(int argc, char **argv)
3664{
3665	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3666}
3667
3668/*
3669 * zpool detach [-f] <pool> <device>
3670 *
3671 *	-f	Force detach of <device>, even if DTLs argue against it
3672 *		(not supported yet)
3673 *
3674 * Detach a device from a mirror.  The operation will be refused if <device>
3675 * is the last device in the mirror, or if the DTLs indicate that this device
3676 * has the only valid copy of some data.
3677 */
3678/* ARGSUSED */
3679int
3680zpool_do_detach(int argc, char **argv)
3681{
3682	int c;
3683	char *poolname, *path;
3684	zpool_handle_t *zhp;
3685	int ret;
3686
3687	/* check options */
3688	while ((c = getopt(argc, argv, "f")) != -1) {
3689		switch (c) {
3690		case 'f':
3691		case '?':
3692			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3693			    optopt);
3694			usage(B_FALSE);
3695		}
3696	}
3697
3698	argc -= optind;
3699	argv += optind;
3700
3701	/* get pool name and check number of arguments */
3702	if (argc < 1) {
3703		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3704		usage(B_FALSE);
3705	}
3706
3707	if (argc < 2) {
3708		(void) fprintf(stderr,
3709		    gettext("missing <device> specification\n"));
3710		usage(B_FALSE);
3711	}
3712
3713	poolname = argv[0];
3714	path = argv[1];
3715
3716	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3717		return (1);
3718
3719	ret = zpool_vdev_detach(zhp, path);
3720
3721	zpool_close(zhp);
3722
3723	return (ret);
3724}
3725
3726/*
3727 * zpool split [-n] [-o prop=val] ...
3728 *		[-o mntopt] ...
3729 *		[-R altroot] <pool> <newpool> [<device> ...]
3730 *
3731 *	-n	Do not split the pool, but display the resulting layout if
3732 *		it were to be split.
3733 *	-o	Set property=value, or set mount options.
3734 *	-R	Mount the split-off pool under an alternate root.
3735 *
3736 * Splits the named pool and gives it the new pool name.  Devices to be split
3737 * off may be listed, provided that no more than one device is specified
3738 * per top-level vdev mirror.  The newly split pool is left in an exported
3739 * state unless -R is specified.
3740 *
3741 * Restrictions: the top-level of the pool pool must only be made up of
3742 * mirrors; all devices in the pool must be healthy; no device may be
3743 * undergoing a resilvering operation.
3744 */
3745int
3746zpool_do_split(int argc, char **argv)
3747{
3748	char *srcpool, *newpool, *propval;
3749	char *mntopts = NULL;
3750	splitflags_t flags;
3751	int c, ret = 0;
3752	zpool_handle_t *zhp;
3753	nvlist_t *config, *props = NULL;
3754
3755	flags.dryrun = B_FALSE;
3756	flags.import = B_FALSE;
3757
3758	/* check options */
3759	while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3760		switch (c) {
3761		case 'R':
3762			flags.import = B_TRUE;
3763			if (add_prop_list(
3764			    zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3765			    &props, B_TRUE) != 0) {
3766				nvlist_free(props);
3767				usage(B_FALSE);
3768			}
3769			break;
3770		case 'n':
3771			flags.dryrun = B_TRUE;
3772			break;
3773		case 'o':
3774			if ((propval = strchr(optarg, '=')) != NULL) {
3775				*propval = '\0';
3776				propval++;
3777				if (add_prop_list(optarg, propval,
3778				    &props, B_TRUE) != 0) {
3779					nvlist_free(props);
3780					usage(B_FALSE);
3781				}
3782			} else {
3783				mntopts = optarg;
3784			}
3785			break;
3786		case ':':
3787			(void) fprintf(stderr, gettext("missing argument for "
3788			    "'%c' option\n"), optopt);
3789			usage(B_FALSE);
3790			break;
3791		case '?':
3792			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3793			    optopt);
3794			usage(B_FALSE);
3795			break;
3796		}
3797	}
3798
3799	if (!flags.import && mntopts != NULL) {
3800		(void) fprintf(stderr, gettext("setting mntopts is only "
3801		    "valid when importing the pool\n"));
3802		usage(B_FALSE);
3803	}
3804
3805	argc -= optind;
3806	argv += optind;
3807
3808	if (argc < 1) {
3809		(void) fprintf(stderr, gettext("Missing pool name\n"));
3810		usage(B_FALSE);
3811	}
3812	if (argc < 2) {
3813		(void) fprintf(stderr, gettext("Missing new pool name\n"));
3814		usage(B_FALSE);
3815	}
3816
3817	srcpool = argv[0];
3818	newpool = argv[1];
3819
3820	argc -= 2;
3821	argv += 2;
3822
3823	if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3824		return (1);
3825
3826	config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3827	if (config == NULL) {
3828		ret = 1;
3829	} else {
3830		if (flags.dryrun) {
3831			(void) printf(gettext("would create '%s' with the "
3832			    "following layout:\n\n"), newpool);
3833			print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3834		}
3835		nvlist_free(config);
3836	}
3837
3838	zpool_close(zhp);
3839
3840	if (ret != 0 || flags.dryrun || !flags.import)
3841		return (ret);
3842
3843	/*
3844	 * The split was successful. Now we need to open the new
3845	 * pool and import it.
3846	 */
3847	if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3848		return (1);
3849	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3850	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3851		ret = 1;
3852		(void) fprintf(stderr, gettext("Split was successful, but "
3853		    "the datasets could not all be mounted\n"));
3854		(void) fprintf(stderr, gettext("Try doing '%s' with a "
3855		    "different altroot\n"), "zpool import");
3856	}
3857	zpool_close(zhp);
3858
3859	return (ret);
3860}
3861
3862
3863
3864/*
3865 * zpool online <pool> <device> ...
3866 */
3867int
3868zpool_do_online(int argc, char **argv)
3869{
3870	int c, i;
3871	char *poolname;
3872	zpool_handle_t *zhp;
3873	int ret = 0;
3874	vdev_state_t newstate;
3875	int flags = 0;
3876
3877	/* check options */
3878	while ((c = getopt(argc, argv, "et")) != -1) {
3879		switch (c) {
3880		case 'e':
3881			flags |= ZFS_ONLINE_EXPAND;
3882			break;
3883		case 't':
3884		case '?':
3885			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3886			    optopt);
3887			usage(B_FALSE);
3888		}
3889	}
3890
3891	argc -= optind;
3892	argv += optind;
3893
3894	/* get pool name and check number of arguments */
3895	if (argc < 1) {
3896		(void) fprintf(stderr, gettext("missing pool name\n"));
3897		usage(B_FALSE);
3898	}
3899	if (argc < 2) {
3900		(void) fprintf(stderr, gettext("missing device name\n"));
3901		usage(B_FALSE);
3902	}
3903
3904	poolname = argv[0];
3905
3906	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3907		return (1);
3908
3909	for (i = 1; i < argc; i++) {
3910		if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3911			if (newstate != VDEV_STATE_HEALTHY) {
3912				(void) printf(gettext("warning: device '%s' "
3913				    "onlined, but remains in faulted state\n"),
3914				    argv[i]);
3915				if (newstate == VDEV_STATE_FAULTED)
3916					(void) printf(gettext("use 'zpool "
3917					    "clear' to restore a faulted "
3918					    "device\n"));
3919				else
3920					(void) printf(gettext("use 'zpool "
3921					    "replace' to replace devices "
3922					    "that are no longer present\n"));
3923			}
3924		} else {
3925			ret = 1;
3926		}
3927	}
3928
3929	zpool_close(zhp);
3930
3931	return (ret);
3932}
3933
3934/*
3935 * zpool offline [-ft] <pool> <device> ...
3936 *
3937 *	-f	Force the device into the offline state, even if doing
3938 *		so would appear to compromise pool availability.
3939 *		(not supported yet)
3940 *
3941 *	-t	Only take the device off-line temporarily.  The offline
3942 *		state will not be persistent across reboots.
3943 */
3944/* ARGSUSED */
3945int
3946zpool_do_offline(int argc, char **argv)
3947{
3948	int c, i;
3949	char *poolname;
3950	zpool_handle_t *zhp;
3951	int ret = 0;
3952	boolean_t istmp = B_FALSE;
3953
3954	/* check options */
3955	while ((c = getopt(argc, argv, "ft")) != -1) {
3956		switch (c) {
3957		case 't':
3958			istmp = B_TRUE;
3959			break;
3960		case 'f':
3961		case '?':
3962			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3963			    optopt);
3964			usage(B_FALSE);
3965		}
3966	}
3967
3968	argc -= optind;
3969	argv += optind;
3970
3971	/* get pool name and check number of arguments */
3972	if (argc < 1) {
3973		(void) fprintf(stderr, gettext("missing pool name\n"));
3974		usage(B_FALSE);
3975	}
3976	if (argc < 2) {
3977		(void) fprintf(stderr, gettext("missing device name\n"));
3978		usage(B_FALSE);
3979	}
3980
3981	poolname = argv[0];
3982
3983	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3984		return (1);
3985
3986	for (i = 1; i < argc; i++) {
3987		if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3988			ret = 1;
3989	}
3990
3991	zpool_close(zhp);
3992
3993	return (ret);
3994}
3995
3996/*
3997 * zpool clear <pool> [device]
3998 *
3999 * Clear all errors associated with a pool or a particular device.
4000 */
4001int
4002zpool_do_clear(int argc, char **argv)
4003{
4004	int c;
4005	int ret = 0;
4006	boolean_t dryrun = B_FALSE;
4007	boolean_t do_rewind = B_FALSE;
4008	boolean_t xtreme_rewind = B_FALSE;
4009	uint32_t rewind_policy = ZPOOL_NO_REWIND;
4010	nvlist_t *policy = NULL;
4011	zpool_handle_t *zhp;
4012	char *pool, *device;
4013
4014	/* check options */
4015	while ((c = getopt(argc, argv, "FnX")) != -1) {
4016		switch (c) {
4017		case 'F':
4018			do_rewind = B_TRUE;
4019			break;
4020		case 'n':
4021			dryrun = B_TRUE;
4022			break;
4023		case 'X':
4024			xtreme_rewind = B_TRUE;
4025			break;
4026		case '?':
4027			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4028			    optopt);
4029			usage(B_FALSE);
4030		}
4031	}
4032
4033	argc -= optind;
4034	argv += optind;
4035
4036	if (argc < 1) {
4037		(void) fprintf(stderr, gettext("missing pool name\n"));
4038		usage(B_FALSE);
4039	}
4040
4041	if (argc > 2) {
4042		(void) fprintf(stderr, gettext("too many arguments\n"));
4043		usage(B_FALSE);
4044	}
4045
4046	if ((dryrun || xtreme_rewind) && !do_rewind) {
4047		(void) fprintf(stderr,
4048		    gettext("-n or -X only meaningful with -F\n"));
4049		usage(B_FALSE);
4050	}
4051	if (dryrun)
4052		rewind_policy = ZPOOL_TRY_REWIND;
4053	else if (do_rewind)
4054		rewind_policy = ZPOOL_DO_REWIND;
4055	if (xtreme_rewind)
4056		rewind_policy |= ZPOOL_EXTREME_REWIND;
4057
4058	/* In future, further rewind policy choices can be passed along here */
4059	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
4060	    nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
4061	    rewind_policy) != 0) {
4062		return (1);
4063	}
4064
4065	pool = argv[0];
4066	device = argc == 2 ? argv[1] : NULL;
4067
4068	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
4069		nvlist_free(policy);
4070		return (1);
4071	}
4072
4073	if (zpool_clear(zhp, device, policy) != 0)
4074		ret = 1;
4075
4076	zpool_close(zhp);
4077
4078	nvlist_free(policy);
4079
4080	return (ret);
4081}
4082
4083/*
4084 * zpool reguid <pool>
4085 */
4086int
4087zpool_do_reguid(int argc, char **argv)
4088{
4089	int c;
4090	char *poolname;
4091	zpool_handle_t *zhp;
4092	int ret = 0;
4093
4094	/* check options */
4095	while ((c = getopt(argc, argv, "")) != -1) {
4096		switch (c) {
4097		case '?':
4098			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4099			    optopt);
4100			usage(B_FALSE);
4101		}
4102	}
4103
4104	argc -= optind;
4105	argv += optind;
4106
4107	/* get pool name and check number of arguments */
4108	if (argc < 1) {
4109		(void) fprintf(stderr, gettext("missing pool name\n"));
4110		usage(B_FALSE);
4111	}
4112
4113	if (argc > 1) {
4114		(void) fprintf(stderr, gettext("too many arguments\n"));
4115		usage(B_FALSE);
4116	}
4117
4118	poolname = argv[0];
4119	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4120		return (1);
4121
4122	ret = zpool_reguid(zhp);
4123
4124	zpool_close(zhp);
4125	return (ret);
4126}
4127
4128
4129/*
4130 * zpool reopen <pool>
4131 *
4132 * Reopen the pool so that the kernel can update the sizes of all vdevs.
4133 */
4134int
4135zpool_do_reopen(int argc, char **argv)
4136{
4137	int c;
4138	int ret = 0;
4139	zpool_handle_t *zhp;
4140	char *pool;
4141
4142	/* check options */
4143	while ((c = getopt(argc, argv, "")) != -1) {
4144		switch (c) {
4145		case '?':
4146			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4147			    optopt);
4148			usage(B_FALSE);
4149		}
4150	}
4151
4152	argc--;
4153	argv++;
4154
4155	if (argc < 1) {
4156		(void) fprintf(stderr, gettext("missing pool name\n"));
4157		usage(B_FALSE);
4158	}
4159
4160	if (argc > 1) {
4161		(void) fprintf(stderr, gettext("too many arguments\n"));
4162		usage(B_FALSE);
4163	}
4164
4165	pool = argv[0];
4166	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4167		return (1);
4168
4169	ret = zpool_reopen(zhp);
4170	zpool_close(zhp);
4171	return (ret);
4172}
4173
4174typedef struct scrub_cbdata {
4175	int	cb_type;
4176	int	cb_argc;
4177	char	**cb_argv;
4178	pool_scrub_cmd_t cb_scrub_cmd;
4179} scrub_cbdata_t;
4180
4181static boolean_t
4182zpool_has_checkpoint(zpool_handle_t *zhp)
4183{
4184	nvlist_t *config, *nvroot;
4185
4186	config = zpool_get_config(zhp, NULL);
4187
4188	if (config != NULL) {
4189		pool_checkpoint_stat_t *pcs = NULL;
4190		uint_t c;
4191
4192		nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4193		(void) nvlist_lookup_uint64_array(nvroot,
4194		    ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4195
4196		if (pcs == NULL || pcs->pcs_state == CS_NONE)
4197			return (B_FALSE);
4198
4199		assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
4200		    pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4201		return (B_TRUE);
4202	}
4203
4204	return (B_FALSE);
4205}
4206
4207int
4208scrub_callback(zpool_handle_t *zhp, void *data)
4209{
4210	scrub_cbdata_t *cb = data;
4211	int err;
4212
4213	/*
4214	 * Ignore faulted pools.
4215	 */
4216	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4217		(void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4218		    "currently unavailable\n"), zpool_get_name(zhp));
4219		return (1);
4220	}
4221
4222	err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4223
4224	if (err == 0 && zpool_has_checkpoint(zhp) &&
4225	    cb->cb_type == POOL_SCAN_SCRUB) {
4226		(void) printf(gettext("warning: will not scrub state that "
4227		    "belongs to the checkpoint of pool '%s'\n"),
4228		    zpool_get_name(zhp));
4229	}
4230
4231	return (err != 0);
4232}
4233
4234/*
4235 * zpool scrub [-s | -p] <pool> ...
4236 *
4237 *	-s	Stop.  Stops any in-progress scrub.
4238 *	-p	Pause. Pause in-progress scrub.
4239 */
4240int
4241zpool_do_scrub(int argc, char **argv)
4242{
4243	int c;
4244	scrub_cbdata_t cb;
4245
4246	cb.cb_type = POOL_SCAN_SCRUB;
4247	cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4248
4249	/* check options */
4250	while ((c = getopt(argc, argv, "sp")) != -1) {
4251		switch (c) {
4252		case 's':
4253			cb.cb_type = POOL_SCAN_NONE;
4254			break;
4255		case 'p':
4256			cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4257			break;
4258		case '?':
4259			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4260			    optopt);
4261			usage(B_FALSE);
4262		}
4263	}
4264
4265	if (cb.cb_type == POOL_SCAN_NONE &&
4266	    cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4267		(void) fprintf(stderr, gettext("invalid option combination: "
4268		    "-s and -p are mutually exclusive\n"));
4269		usage(B_FALSE);
4270	}
4271
4272	cb.cb_argc = argc;
4273	cb.cb_argv = argv;
4274	argc -= optind;
4275	argv += optind;
4276
4277	if (argc < 1) {
4278		(void) fprintf(stderr, gettext("missing pool name argument\n"));
4279		usage(B_FALSE);
4280	}
4281
4282	return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4283}
4284
4285static void
4286zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
4287{
4288	uint_t children = 0;
4289	nvlist_t **child;
4290	uint_t i;
4291
4292	(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4293	    &child, &children);
4294
4295	if (children == 0) {
4296		char *path = zpool_vdev_name(g_zfs, zhp, nvroot, B_FALSE);
4297		fnvlist_add_boolean(res, path);
4298		free(path);
4299		return;
4300	}
4301
4302	for (i = 0; i < children; i++) {
4303		zpool_collect_leaves(zhp, child[i], res);
4304	}
4305}
4306
4307/*
4308 * zpool initialize [-cs] <pool> [<vdev> ...]
4309 * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
4310 * if none specified.
4311 *
4312 *	-c	Cancel. Ends active initializing.
4313 *	-s	Suspend. Initializing can then be restarted with no flags.
4314 */
4315int
4316zpool_do_initialize(int argc, char **argv)
4317{
4318	int c;
4319	char *poolname;
4320	zpool_handle_t *zhp;
4321	nvlist_t *vdevs;
4322	int err = 0;
4323
4324	struct option long_options[] = {
4325		{"cancel",	no_argument,		NULL, 'c'},
4326		{"suspend",	no_argument,		NULL, 's'},
4327		{0, 0, 0, 0}
4328	};
4329
4330	pool_initialize_func_t cmd_type = POOL_INITIALIZE_DO;
4331	while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) {
4332		switch (c) {
4333		case 'c':
4334			if (cmd_type != POOL_INITIALIZE_DO) {
4335				(void) fprintf(stderr, gettext("-c cannot be "
4336				    "combined with other options\n"));
4337				usage(B_FALSE);
4338			}
4339			cmd_type = POOL_INITIALIZE_CANCEL;
4340			break;
4341		case 's':
4342			if (cmd_type != POOL_INITIALIZE_DO) {
4343				(void) fprintf(stderr, gettext("-s cannot be "
4344				    "combined with other options\n"));
4345				usage(B_FALSE);
4346			}
4347			cmd_type = POOL_INITIALIZE_SUSPEND;
4348			break;
4349		case '?':
4350			if (optopt != 0) {
4351				(void) fprintf(stderr,
4352				    gettext("invalid option '%c'\n"), optopt);
4353			} else {
4354				(void) fprintf(stderr,
4355				    gettext("invalid option '%s'\n"),
4356				    argv[optind - 1]);
4357			}
4358			usage(B_FALSE);
4359		}
4360	}
4361
4362	argc -= optind;
4363	argv += optind;
4364
4365	if (argc < 1) {
4366		(void) fprintf(stderr, gettext("missing pool name argument\n"));
4367		usage(B_FALSE);
4368		return (-1);
4369	}
4370
4371	poolname = argv[0];
4372	zhp = zpool_open(g_zfs, poolname);
4373	if (zhp == NULL)
4374		return (-1);
4375
4376	vdevs = fnvlist_alloc();
4377	if (argc == 1) {
4378		/* no individual leaf vdevs specified, so add them all */
4379		nvlist_t *config = zpool_get_config(zhp, NULL);
4380		nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
4381		    ZPOOL_CONFIG_VDEV_TREE);
4382		zpool_collect_leaves(zhp, nvroot, vdevs);
4383	} else {
4384		int i;
4385		for (i = 1; i < argc; i++) {
4386			fnvlist_add_boolean(vdevs, argv[i]);
4387		}
4388	}
4389
4390	err = zpool_initialize(zhp, cmd_type, vdevs);
4391
4392	fnvlist_free(vdevs);
4393	zpool_close(zhp);
4394
4395	return (err);
4396}
4397
4398typedef struct status_cbdata {
4399	int		cb_count;
4400	boolean_t	cb_allpools;
4401	boolean_t	cb_verbose;
4402	boolean_t	cb_explain;
4403	boolean_t	cb_first;
4404	boolean_t	cb_dedup_stats;
4405} status_cbdata_t;
4406
4407/*
4408 * Print out detailed scrub status.
4409 */
4410static void
4411print_scan_status(pool_scan_stat_t *ps)
4412{
4413	time_t start, end, pause;
4414	uint64_t total_secs_left;
4415	uint64_t elapsed, secs_left, mins_left, hours_left, days_left;
4416	uint64_t pass_scanned, scanned, pass_issued, issued, total;
4417	uint_t scan_rate, issue_rate;
4418	double fraction_done;
4419	char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
4420	char srate_buf[7], irate_buf[7];
4421
4422	(void) printf(gettext("  scan: "));
4423
4424	/* If there's never been a scan, there's not much to say. */
4425	if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4426	    ps->pss_func >= POOL_SCAN_FUNCS) {
4427		(void) printf(gettext("none requested\n"));
4428		return;
4429	}
4430
4431	start = ps->pss_start_time;
4432	end = ps->pss_end_time;
4433	pause = ps->pss_pass_scrub_pause;
4434
4435	zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4436
4437	assert(ps->pss_func == POOL_SCAN_SCRUB ||
4438	    ps->pss_func == POOL_SCAN_RESILVER);
4439
4440	/* Scan is finished or canceled. */
4441	if (ps->pss_state == DSS_FINISHED) {
4442		total_secs_left = end - start;
4443		days_left = total_secs_left / 60 / 60 / 24;
4444		hours_left = (total_secs_left / 60 / 60) % 24;
4445		mins_left = (total_secs_left / 60) % 60;
4446		secs_left = (total_secs_left % 60);
4447
4448		if (ps->pss_func == POOL_SCAN_SCRUB) {
4449			(void) printf(gettext("scrub repaired %s "
4450                            "in %llu days %02llu:%02llu:%02llu "
4451			    "with %llu errors on %s"), processed_buf,
4452                            (u_longlong_t)days_left, (u_longlong_t)hours_left,
4453                            (u_longlong_t)mins_left, (u_longlong_t)secs_left,
4454                            (u_longlong_t)ps->pss_errors, ctime(&end));
4455		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4456                       (void) printf(gettext("resilvered %s "
4457                           "in %llu days %02llu:%02llu:%02llu "
4458                           "with %llu errors on %s"), processed_buf,
4459                           (u_longlong_t)days_left, (u_longlong_t)hours_left,
4460                           (u_longlong_t)mins_left, (u_longlong_t)secs_left,
4461                           (u_longlong_t)ps->pss_errors, ctime(&end));
4462
4463		}
4464
4465		return;
4466	} else if (ps->pss_state == DSS_CANCELED) {
4467		if (ps->pss_func == POOL_SCAN_SCRUB) {
4468			(void) printf(gettext("scrub canceled on %s"),
4469			    ctime(&end));
4470		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4471			(void) printf(gettext("resilver canceled on %s"),
4472			    ctime(&end));
4473		}
4474		return;
4475	}
4476
4477	assert(ps->pss_state == DSS_SCANNING);
4478
4479	/* Scan is in progress. Resilvers can't be paused. */
4480	if (ps->pss_func == POOL_SCAN_SCRUB) {
4481		if (pause == 0) {
4482			(void) printf(gettext("scrub in progress since %s"),
4483			    ctime(&start));
4484		} else {
4485			(void) printf(gettext("scrub paused since %s"),
4486			    ctime(&pause));
4487			(void) printf(gettext("\tscrub started on %s"),
4488			    ctime(&start));
4489		}
4490	} else if (ps->pss_func == POOL_SCAN_RESILVER) {
4491		(void) printf(gettext("resilver in progress since %s"),
4492		    ctime(&start));
4493	}
4494
4495	scanned = ps->pss_examined;
4496	pass_scanned = ps->pss_pass_exam;
4497	issued = ps->pss_issued;
4498	pass_issued = ps->pss_pass_issued;
4499	total = ps->pss_to_examine;
4500
4501	/* we are only done with a block once we have issued the IO for it */
4502	fraction_done = (double)issued / total;
4503
4504	/* elapsed time for this pass, rounding up to 1 if it's 0 */
4505	elapsed = time(NULL) - ps->pss_pass_start;
4506	elapsed -= ps->pss_pass_scrub_spent_paused;
4507	elapsed = (elapsed != 0) ? elapsed : 1;
4508
4509	scan_rate = pass_scanned / elapsed;
4510	issue_rate = pass_issued / elapsed;
4511	total_secs_left = (issue_rate != 0) ?
4512	    ((total - issued) / issue_rate) : UINT64_MAX;
4513
4514	days_left = total_secs_left / 60 / 60 / 24;
4515	hours_left = (total_secs_left / 60 / 60) % 24;
4516	mins_left = (total_secs_left / 60) % 60;
4517	secs_left = (total_secs_left % 60);
4518
4519	/* format all of the numbers we will be reporting */
4520	zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf));
4521	zfs_nicenum(issued, issued_buf, sizeof (issued_buf));
4522	zfs_nicenum(total, total_buf, sizeof (total_buf));
4523	zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf));
4524	zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf));
4525
4526	/* doo not print estimated time if we have a paused scrub */
4527	if (pause == 0) {
4528		(void) printf(gettext("\t%s scanned at %s/s, "
4529		    "%s issued at %s/s, %s total\n"),
4530		    scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
4531	} else {
4532		(void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
4533                    scanned_buf, issued_buf, total_buf);
4534	}
4535
4536	if (ps->pss_func == POOL_SCAN_RESILVER) {
4537		(void) printf(gettext("\t%s resilvered, %.2f%% done"),
4538		    processed_buf, 100 * fraction_done);
4539	} else if (ps->pss_func == POOL_SCAN_SCRUB) {
4540		(void) printf(gettext("\t%s repaired, %.2f%% done"),
4541		    processed_buf, 100 * fraction_done);
4542	}
4543
4544	if (pause == 0) {
4545		if (issue_rate >= 10 * 1024 * 1024) {
4546			(void) printf(gettext(", %llu days "
4547                            "%02llu:%02llu:%02llu to go\n"),
4548                            (u_longlong_t)days_left, (u_longlong_t)hours_left,
4549                            (u_longlong_t)mins_left, (u_longlong_t)secs_left);
4550		} else {
4551			(void) printf(gettext(", no estimated "
4552                            "completion time\n"));
4553		}
4554	} else {
4555		(void) printf(gettext("\n"));
4556	}
4557}
4558
4559/*
4560 * As we don't scrub checkpointed blocks, we want to warn the
4561 * user that we skipped scanning some blocks if a checkpoint exists
4562 * or existed at any time during the scan.
4563 */
4564static void
4565print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
4566{
4567	if (ps == NULL || pcs == NULL)
4568		return;
4569
4570	if (pcs->pcs_state == CS_NONE ||
4571	    pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
4572		return;
4573
4574	assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
4575
4576	if (ps->pss_state == DSS_NONE)
4577		return;
4578
4579	if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
4580	    ps->pss_end_time < pcs->pcs_start_time)
4581		return;
4582
4583	if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
4584		(void) printf(gettext("    scan warning: skipped blocks "
4585		    "that are only referenced by the checkpoint.\n"));
4586	} else {
4587		assert(ps->pss_state == DSS_SCANNING);
4588		(void) printf(gettext("    scan warning: skipping blocks "
4589		    "that are only referenced by the checkpoint.\n"));
4590	}
4591}
4592
4593/*
4594 * Print out detailed removal status.
4595 */
4596static void
4597print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4598{
4599	char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4600	time_t start, end;
4601	nvlist_t *config, *nvroot;
4602	nvlist_t **child;
4603	uint_t children;
4604	char *vdev_name;
4605
4606	if (prs == NULL || prs->prs_state == DSS_NONE)
4607		return;
4608
4609	/*
4610	 * Determine name of vdev.
4611	 */
4612	config = zpool_get_config(zhp, NULL);
4613	nvroot = fnvlist_lookup_nvlist(config,
4614	    ZPOOL_CONFIG_VDEV_TREE);
4615	verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4616	    &child, &children) == 0);
4617	assert(prs->prs_removing_vdev < children);
4618	vdev_name = zpool_vdev_name(g_zfs, zhp,
4619	    child[prs->prs_removing_vdev], B_TRUE);
4620
4621	(void) printf(gettext("remove: "));
4622
4623	start = prs->prs_start_time;
4624	end = prs->prs_end_time;
4625	zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4626
4627	/*
4628	 * Removal is finished or canceled.
4629	 */
4630	if (prs->prs_state == DSS_FINISHED) {
4631		uint64_t minutes_taken = (end - start) / 60;
4632
4633		(void) printf(gettext("Removal of vdev %llu copied %s "
4634		    "in %lluh%um, completed on %s"),
4635		    (longlong_t)prs->prs_removing_vdev,
4636		    copied_buf,
4637		    (u_longlong_t)(minutes_taken / 60),
4638		    (uint_t)(minutes_taken % 60),
4639		    ctime((time_t *)&end));
4640	} else if (prs->prs_state == DSS_CANCELED) {
4641		(void) printf(gettext("Removal of %s canceled on %s"),
4642		    vdev_name, ctime(&end));
4643	} else {
4644		uint64_t copied, total, elapsed, mins_left, hours_left;
4645		double fraction_done;
4646		uint_t rate;
4647
4648		assert(prs->prs_state == DSS_SCANNING);
4649
4650		/*
4651		 * Removal is in progress.
4652		 */
4653		(void) printf(gettext(
4654		    "Evacuation of %s in progress since %s"),
4655		    vdev_name, ctime(&start));
4656
4657		copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4658		total = prs->prs_to_copy;
4659		fraction_done = (double)copied / total;
4660
4661		/* elapsed time for this pass */
4662		elapsed = time(NULL) - prs->prs_start_time;
4663		elapsed = elapsed > 0 ? elapsed : 1;
4664		rate = copied / elapsed;
4665		rate = rate > 0 ? rate : 1;
4666		mins_left = ((total - copied) / rate) / 60;
4667		hours_left = mins_left / 60;
4668
4669		zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4670		zfs_nicenum(total, total_buf, sizeof (total_buf));
4671		zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4672
4673		/*
4674		 * do not print estimated time if hours_left is more than
4675		 * 30 days
4676		 */
4677		(void) printf(gettext("    %s copied out of %s at %s/s, "
4678		    "%.2f%% done"),
4679		    examined_buf, total_buf, rate_buf, 100 * fraction_done);
4680		if (hours_left < (30 * 24)) {
4681			(void) printf(gettext(", %lluh%um to go\n"),
4682			    (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4683		} else {
4684			(void) printf(gettext(
4685			    ", (copy is slow, no estimated time)\n"));
4686		}
4687	}
4688
4689	if (prs->prs_mapping_memory > 0) {
4690		char mem_buf[7];
4691		zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4692		(void) printf(gettext("    %s memory used for "
4693		    "removed device mappings\n"),
4694		    mem_buf);
4695	}
4696}
4697
4698static void
4699print_checkpoint_status(pool_checkpoint_stat_t *pcs)
4700{
4701	time_t start;
4702	char space_buf[7];
4703
4704	if (pcs == NULL || pcs->pcs_state == CS_NONE)
4705		return;
4706
4707	(void) printf(gettext("checkpoint: "));
4708
4709	start = pcs->pcs_start_time;
4710	zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
4711
4712	if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
4713		char *date = ctime(&start);
4714
4715		/*
4716		 * ctime() adds a newline at the end of the generated
4717		 * string, thus the weird format specifier and the
4718		 * strlen() call used to chop it off from the output.
4719		 */
4720		(void) printf(gettext("created %.*s, consumes %s\n"),
4721		    strlen(date) - 1, date, space_buf);
4722		return;
4723	}
4724
4725	assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4726
4727	(void) printf(gettext("discarding, %s remaining.\n"),
4728	    space_buf);
4729}
4730
4731static void
4732print_error_log(zpool_handle_t *zhp)
4733{
4734	nvlist_t *nverrlist = NULL;
4735	nvpair_t *elem;
4736	char *pathname;
4737	size_t len = MAXPATHLEN * 2;
4738
4739	if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4740		(void) printf("errors: List of errors unavailable "
4741		    "(insufficient privileges)\n");
4742		return;
4743	}
4744
4745	(void) printf("errors: Permanent errors have been "
4746	    "detected in the following files:\n\n");
4747
4748	pathname = safe_malloc(len);
4749	elem = NULL;
4750	while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4751		nvlist_t *nv;
4752		uint64_t dsobj, obj;
4753
4754		verify(nvpair_value_nvlist(elem, &nv) == 0);
4755		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4756		    &dsobj) == 0);
4757		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4758		    &obj) == 0);
4759		zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4760		(void) printf("%7s %s\n", "", pathname);
4761	}
4762	free(pathname);
4763	nvlist_free(nverrlist);
4764}
4765
4766static void
4767print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4768    int namewidth)
4769{
4770	uint_t i;
4771	char *name;
4772
4773	if (nspares == 0)
4774		return;
4775
4776	(void) printf(gettext("\tspares\n"));
4777
4778	for (i = 0; i < nspares; i++) {
4779		name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4780		print_status_config(zhp, name, spares[i],
4781		    namewidth, 2, B_TRUE);
4782		free(name);
4783	}
4784}
4785
4786static void
4787print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4788    int namewidth)
4789{
4790	uint_t i;
4791	char *name;
4792
4793	if (nl2cache == 0)
4794		return;
4795
4796	(void) printf(gettext("\tcache\n"));
4797
4798	for (i = 0; i < nl2cache; i++) {
4799		name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4800		print_status_config(zhp, name, l2cache[i],
4801		    namewidth, 2, B_FALSE);
4802		free(name);
4803	}
4804}
4805
4806static void
4807print_dedup_stats(nvlist_t *config)
4808{
4809	ddt_histogram_t *ddh;
4810	ddt_stat_t *dds;
4811	ddt_object_t *ddo;
4812	uint_t c;
4813
4814	/*
4815	 * If the pool was faulted then we may not have been able to
4816	 * obtain the config. Otherwise, if we have anything in the dedup
4817	 * table continue processing the stats.
4818	 */
4819	if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4820	    (uint64_t **)&ddo, &c) != 0)
4821		return;
4822
4823	(void) printf("\n");
4824	(void) printf(gettext(" dedup: "));
4825	if (ddo->ddo_count == 0) {
4826		(void) printf(gettext("no DDT entries\n"));
4827		return;
4828	}
4829
4830	(void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4831	    (u_longlong_t)ddo->ddo_count,
4832	    (u_longlong_t)ddo->ddo_dspace,
4833	    (u_longlong_t)ddo->ddo_mspace);
4834
4835	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4836	    (uint64_t **)&dds, &c) == 0);
4837	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4838	    (uint64_t **)&ddh, &c) == 0);
4839	zpool_dump_ddt(dds, ddh);
4840}
4841
4842/*
4843 * Display a summary of pool status.  Displays a summary such as:
4844 *
4845 *        pool: tank
4846 *	status: DEGRADED
4847 *	reason: One or more devices ...
4848 *         see: http://illumos.org/msg/ZFS-xxxx-01
4849 *	config:
4850 *		mirror		DEGRADED
4851 *                c1t0d0	OK
4852 *                c2t0d0	UNAVAIL
4853 *
4854 * When given the '-v' option, we print out the complete config.  If the '-e'
4855 * option is specified, then we print out error rate information as well.
4856 */
4857int
4858status_callback(zpool_handle_t *zhp, void *data)
4859{
4860	status_cbdata_t *cbp = data;
4861	nvlist_t *config, *nvroot;
4862	char *msgid;
4863	int reason;
4864	const char *health;
4865	uint_t c;
4866	vdev_stat_t *vs;
4867
4868	config = zpool_get_config(zhp, NULL);
4869	reason = zpool_get_status(zhp, &msgid);
4870
4871	cbp->cb_count++;
4872
4873	/*
4874	 * If we were given 'zpool status -x', only report those pools with
4875	 * problems.
4876	 */
4877	if (cbp->cb_explain &&
4878	    (reason == ZPOOL_STATUS_OK ||
4879	    reason == ZPOOL_STATUS_VERSION_OLDER ||
4880	    reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
4881	    reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4882		if (!cbp->cb_allpools) {
4883			(void) printf(gettext("pool '%s' is healthy\n"),
4884			    zpool_get_name(zhp));
4885			if (cbp->cb_first)
4886				cbp->cb_first = B_FALSE;
4887		}
4888		return (0);
4889	}
4890
4891	if (cbp->cb_first)
4892		cbp->cb_first = B_FALSE;
4893	else
4894		(void) printf("\n");
4895
4896	nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4897	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4898	    (uint64_t **)&vs, &c) == 0);
4899	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4900
4901	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4902	(void) printf(gettext(" state: %s\n"), health);
4903
4904	switch (reason) {
4905	case ZPOOL_STATUS_MISSING_DEV_R:
4906		(void) printf(gettext("status: One or more devices could not "
4907		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
4908		    "continue functioning in a degraded state.\n"));
4909		(void) printf(gettext("action: Attach the missing device and "
4910		    "online it using 'zpool online'.\n"));
4911		break;
4912
4913	case ZPOOL_STATUS_MISSING_DEV_NR:
4914		(void) printf(gettext("status: One or more devices could not "
4915		    "be opened.  There are insufficient\n\treplicas for the "
4916		    "pool to continue functioning.\n"));
4917		(void) printf(gettext("action: Attach the missing device and "
4918		    "online it using 'zpool online'.\n"));
4919		break;
4920
4921	case ZPOOL_STATUS_CORRUPT_LABEL_R:
4922		(void) printf(gettext("status: One or more devices could not "
4923		    "be used because the label is missing or\n\tinvalid.  "
4924		    "Sufficient replicas exist for the pool to continue\n\t"
4925		    "functioning in a degraded state.\n"));
4926		(void) printf(gettext("action: Replace the device using "
4927		    "'zpool replace'.\n"));
4928		break;
4929
4930	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4931		(void) printf(gettext("status: One or more devices could not "
4932		    "be used because the label is missing \n\tor invalid.  "
4933		    "There are insufficient replicas for the pool to "
4934		    "continue\n\tfunctioning.\n"));
4935		zpool_explain_recover(zpool_get_handle(zhp),
4936		    zpool_get_name(zhp), reason, config);
4937		break;
4938
4939	case ZPOOL_STATUS_FAILING_DEV:
4940		(void) printf(gettext("status: One or more devices has "
4941		    "experienced an unrecoverable error.  An\n\tattempt was "
4942		    "made to correct the error.  Applications are "
4943		    "unaffected.\n"));
4944		(void) printf(gettext("action: Determine if the device needs "
4945		    "to be replaced, and clear the errors\n\tusing "
4946		    "'zpool clear' or replace the device with 'zpool "
4947		    "replace'.\n"));
4948		break;
4949
4950	case ZPOOL_STATUS_OFFLINE_DEV:
4951		(void) printf(gettext("status: One or more devices has "
4952		    "been taken offline by the administrator.\n\tSufficient "
4953		    "replicas exist for the pool to continue functioning in "
4954		    "a\n\tdegraded state.\n"));
4955		(void) printf(gettext("action: Online the device using "
4956		    "'zpool online' or replace the device with\n\t'zpool "
4957		    "replace'.\n"));
4958		break;
4959
4960	case ZPOOL_STATUS_REMOVED_DEV:
4961		(void) printf(gettext("status: One or more devices has "
4962		    "been removed by the administrator.\n\tSufficient "
4963		    "replicas exist for the pool to continue functioning in "
4964		    "a\n\tdegraded state.\n"));
4965		(void) printf(gettext("action: Online the device using "
4966		    "'zpool online' or replace the device with\n\t'zpool "
4967		    "replace'.\n"));
4968		break;
4969
4970	case ZPOOL_STATUS_RESILVERING:
4971		(void) printf(gettext("status: One or more devices is "
4972		    "currently being resilvered.  The pool will\n\tcontinue "
4973		    "to function, possibly in a degraded state.\n"));
4974		(void) printf(gettext("action: Wait for the resilver to "
4975		    "complete.\n"));
4976		break;
4977
4978	case ZPOOL_STATUS_CORRUPT_DATA:
4979		(void) printf(gettext("status: One or more devices has "
4980		    "experienced an error resulting in data\n\tcorruption.  "
4981		    "Applications may be affected.\n"));
4982		(void) printf(gettext("action: Restore the file in question "
4983		    "if possible.  Otherwise restore the\n\tentire pool from "
4984		    "backup.\n"));
4985		break;
4986
4987	case ZPOOL_STATUS_CORRUPT_POOL:
4988		(void) printf(gettext("status: The pool metadata is corrupted "
4989		    "and the pool cannot be opened.\n"));
4990		zpool_explain_recover(zpool_get_handle(zhp),
4991		    zpool_get_name(zhp), reason, config);
4992		break;
4993
4994	case ZPOOL_STATUS_VERSION_OLDER:
4995		(void) printf(gettext("status: The pool is formatted using a "
4996		    "legacy on-disk format.  The pool can\n\tstill be used, "
4997		    "but some features are unavailable.\n"));
4998		(void) printf(gettext("action: Upgrade the pool using 'zpool "
4999		    "upgrade'.  Once this is done, the\n\tpool will no longer "
5000		    "be accessible on software that does not support feature\n"
5001		    "\tflags.\n"));
5002		break;
5003
5004	case ZPOOL_STATUS_VERSION_NEWER:
5005		(void) printf(gettext("status: The pool has been upgraded to a "
5006		    "newer, incompatible on-disk version.\n\tThe pool cannot "
5007		    "be accessed on this system.\n"));
5008		(void) printf(gettext("action: Access the pool from a system "
5009		    "running more recent software, or\n\trestore the pool from "
5010		    "backup.\n"));
5011		break;
5012
5013	case ZPOOL_STATUS_FEAT_DISABLED:
5014		(void) printf(gettext("status: Some supported features are not "
5015		    "enabled on the pool. The pool can\n\tstill be used, but "
5016		    "some features are unavailable.\n"));
5017		(void) printf(gettext("action: Enable all features using "
5018		    "'zpool upgrade'. Once this is done,\n\tthe pool may no "
5019		    "longer be accessible by software that does not support\n\t"
5020		    "the features. See zpool-features(7) for details.\n"));
5021		break;
5022
5023	case ZPOOL_STATUS_UNSUP_FEAT_READ:
5024		(void) printf(gettext("status: The pool cannot be accessed on "
5025		    "this system because it uses the\n\tfollowing feature(s) "
5026		    "not supported on this system:\n"));
5027		zpool_print_unsup_feat(config);
5028		(void) printf("\n");
5029		(void) printf(gettext("action: Access the pool from a system "
5030		    "that supports the required feature(s),\n\tor restore the "
5031		    "pool from backup.\n"));
5032		break;
5033
5034	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
5035		(void) printf(gettext("status: The pool can only be accessed "
5036		    "in read-only mode on this system. It\n\tcannot be "
5037		    "accessed in read-write mode because it uses the "
5038		    "following\n\tfeature(s) not supported on this system:\n"));
5039		zpool_print_unsup_feat(config);
5040		(void) printf("\n");
5041		(void) printf(gettext("action: The pool cannot be accessed in "
5042		    "read-write mode. Import the pool with\n"
5043		    "\t\"-o readonly=on\", access the pool from a system that "
5044		    "supports the\n\trequired feature(s), or restore the "
5045		    "pool from backup.\n"));
5046		break;
5047
5048	case ZPOOL_STATUS_FAULTED_DEV_R:
5049		(void) printf(gettext("status: One or more devices are "
5050		    "faulted in response to persistent errors.\n\tSufficient "
5051		    "replicas exist for the pool to continue functioning "
5052		    "in a\n\tdegraded state.\n"));
5053		(void) printf(gettext("action: Replace the faulted device, "
5054		    "or use 'zpool clear' to mark the device\n\trepaired.\n"));
5055		break;
5056
5057	case ZPOOL_STATUS_FAULTED_DEV_NR:
5058		(void) printf(gettext("status: One or more devices are "
5059		    "faulted in response to persistent errors.  There are "
5060		    "insufficient replicas for the pool to\n\tcontinue "
5061		    "functioning.\n"));
5062		(void) printf(gettext("action: Destroy and re-create the pool "
5063		    "from a backup source.  Manually marking the device\n"
5064		    "\trepaired using 'zpool clear' may allow some data "
5065		    "to be recovered.\n"));
5066		break;
5067
5068	case ZPOOL_STATUS_IO_FAILURE_WAIT:
5069	case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
5070		(void) printf(gettext("status: One or more devices are "
5071		    "faulted in response to IO failures.\n"));
5072		(void) printf(gettext("action: Make sure the affected devices "
5073		    "are connected, then run 'zpool clear'.\n"));
5074		break;
5075
5076	case ZPOOL_STATUS_BAD_LOG:
5077		(void) printf(gettext("status: An intent log record "
5078		    "could not be read.\n"
5079		    "\tWaiting for adminstrator intervention to fix the "
5080		    "faulted pool.\n"));
5081		(void) printf(gettext("action: Either restore the affected "
5082		    "device(s) and run 'zpool online',\n"
5083		    "\tor ignore the intent log records by running "
5084		    "'zpool clear'.\n"));
5085		break;
5086
5087	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
5088		(void) printf(gettext("status: One or more devices are "
5089		    "configured to use a non-native block size.\n"
5090		    "\tExpect reduced performance.\n"));
5091		(void) printf(gettext("action: Replace affected devices with "
5092		    "devices that support the\n\tconfigured block size, or "
5093		    "migrate data to a properly configured\n\tpool.\n"));
5094		break;
5095
5096	default:
5097		/*
5098		 * The remaining errors can't actually be generated, yet.
5099		 */
5100		assert(reason == ZPOOL_STATUS_OK);
5101	}
5102
5103	if (msgid != NULL)
5104		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
5105		    msgid);
5106
5107	if (config != NULL) {
5108		int namewidth;
5109		uint64_t nerr;
5110		nvlist_t **spares, **l2cache;
5111		uint_t nspares, nl2cache;
5112		pool_checkpoint_stat_t *pcs = NULL;
5113		pool_scan_stat_t *ps = NULL;
5114		pool_removal_stat_t *prs = NULL;
5115
5116		(void) nvlist_lookup_uint64_array(nvroot,
5117		    ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
5118		(void) nvlist_lookup_uint64_array(nvroot,
5119		    ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
5120		(void) nvlist_lookup_uint64_array(nvroot,
5121		    ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
5122
5123		print_scan_status(ps);
5124		print_checkpoint_scan_warning(ps, pcs);
5125		print_removal_status(zhp, prs);
5126		print_checkpoint_status(pcs);
5127
5128		namewidth = max_width(zhp, nvroot, 0, 0);
5129		if (namewidth < 10)
5130			namewidth = 10;
5131
5132		(void) printf(gettext("config:\n\n"));
5133		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
5134		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
5135		print_status_config(zhp, zpool_get_name(zhp), nvroot,
5136		    namewidth, 0, B_FALSE);
5137
5138		if (num_logs(nvroot) > 0)
5139			print_logs(zhp, nvroot, namewidth, B_TRUE);
5140		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5141		    &l2cache, &nl2cache) == 0)
5142			print_l2cache(zhp, l2cache, nl2cache, namewidth);
5143
5144		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5145		    &spares, &nspares) == 0)
5146			print_spares(zhp, spares, nspares, namewidth);
5147
5148		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5149		    &nerr) == 0) {
5150			nvlist_t *nverrlist = NULL;
5151
5152			/*
5153			 * If the approximate error count is small, get a
5154			 * precise count by fetching the entire log and
5155			 * uniquifying the results.
5156			 */
5157			if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
5158			    zpool_get_errlog(zhp, &nverrlist) == 0) {
5159				nvpair_t *elem;
5160
5161				elem = NULL;
5162				nerr = 0;
5163				while ((elem = nvlist_next_nvpair(nverrlist,
5164				    elem)) != NULL) {
5165					nerr++;
5166				}
5167			}
5168			nvlist_free(nverrlist);
5169
5170			(void) printf("\n");
5171
5172			if (nerr == 0)
5173				(void) printf(gettext("errors: No known data "
5174				    "errors\n"));
5175			else if (!cbp->cb_verbose)
5176				(void) printf(gettext("errors: %llu data "
5177				    "errors, use '-v' for a list\n"),
5178				    (u_longlong_t)nerr);
5179			else
5180				print_error_log(zhp);
5181		}
5182
5183		if (cbp->cb_dedup_stats)
5184			print_dedup_stats(config);
5185	} else {
5186		(void) printf(gettext("config: The configuration cannot be "
5187		    "determined.\n"));
5188	}
5189
5190	return (0);
5191}
5192
5193/*
5194 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
5195 *
5196 *	-v	Display complete error logs
5197 *	-x	Display only pools with potential problems
5198 *	-D	Display dedup status (undocumented)
5199 *	-T	Display a timestamp in date(1) or Unix format
5200 *
5201 * Describes the health status of all pools or some subset.
5202 */
5203int
5204zpool_do_status(int argc, char **argv)
5205{
5206	int c;
5207	int ret;
5208	unsigned long interval = 0, count = 0;
5209	status_cbdata_t cb = { 0 };
5210
5211	/* check options */
5212	while ((c = getopt(argc, argv, "vxDT:")) != -1) {
5213		switch (c) {
5214		case 'v':
5215			cb.cb_verbose = B_TRUE;
5216			break;
5217		case 'x':
5218			cb.cb_explain = B_TRUE;
5219			break;
5220		case 'D':
5221			cb.cb_dedup_stats = B_TRUE;
5222			break;
5223		case 'T':
5224			get_timestamp_arg(*optarg);
5225			break;
5226		case '?':
5227			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5228			    optopt);
5229			usage(B_FALSE);
5230		}
5231	}
5232
5233	argc -= optind;
5234	argv += optind;
5235
5236	get_interval_count(&argc, argv, &interval, &count);
5237
5238	if (argc == 0)
5239		cb.cb_allpools = B_TRUE;
5240
5241	cb.cb_first = B_TRUE;
5242
5243	for (;;) {
5244		if (timestamp_fmt != NODATE)
5245			print_timestamp(timestamp_fmt);
5246
5247		ret = for_each_pool(argc, argv, B_TRUE, NULL,
5248		    status_callback, &cb);
5249
5250		if (argc == 0 && cb.cb_count == 0)
5251			(void) printf(gettext("no pools available\n"));
5252		else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5253			(void) printf(gettext("all pools are healthy\n"));
5254
5255		if (ret != 0)
5256			return (ret);
5257
5258		if (interval == 0)
5259			break;
5260
5261		if (count != 0 && --count == 0)
5262			break;
5263
5264		(void) sleep(interval);
5265	}
5266
5267	return (0);
5268}
5269
5270typedef struct upgrade_cbdata {
5271	boolean_t	cb_first;
5272	boolean_t	cb_unavail;
5273	char		cb_poolname[ZFS_MAX_DATASET_NAME_LEN];
5274	int		cb_argc;
5275	uint64_t	cb_version;
5276	char		**cb_argv;
5277} upgrade_cbdata_t;
5278
5279#ifdef __FreeBSD__
5280static int
5281is_root_pool(zpool_handle_t *zhp)
5282{
5283	static struct statfs sfs;
5284	static char *poolname = NULL;
5285	static boolean_t stated = B_FALSE;
5286	char *slash;
5287
5288	if (!stated) {
5289		stated = B_TRUE;
5290		if (statfs("/", &sfs) == -1) {
5291			(void) fprintf(stderr,
5292			    "Unable to stat root file system: %s.\n",
5293			    strerror(errno));
5294			return (0);
5295		}
5296		if (strcmp(sfs.f_fstypename, "zfs") != 0)
5297			return (0);
5298		poolname = sfs.f_mntfromname;
5299		if ((slash = strchr(poolname, '/')) != NULL)
5300			*slash = '\0';
5301	}
5302	return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
5303}
5304
5305static void
5306root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
5307{
5308
5309	if (poolname[0] == '\0' && is_root_pool(zhp))
5310		(void) strlcpy(poolname, zpool_get_name(zhp), size);
5311}
5312#endif	/* FreeBSD */
5313
5314static int
5315upgrade_version(zpool_handle_t *zhp, uint64_t version)
5316{
5317	int ret;
5318	nvlist_t *config;
5319	uint64_t oldversion;
5320
5321	config = zpool_get_config(zhp, NULL);
5322	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5323	    &oldversion) == 0);
5324
5325	assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5326	assert(oldversion < version);
5327
5328	ret = zpool_upgrade(zhp, version);
5329	if (ret != 0)
5330		return (ret);
5331
5332	if (version >= SPA_VERSION_FEATURES) {
5333		(void) printf(gettext("Successfully upgraded "
5334		    "'%s' from version %llu to feature flags.\n"),
5335		    zpool_get_name(zhp), oldversion);
5336	} else {
5337		(void) printf(gettext("Successfully upgraded "
5338		    "'%s' from version %llu to version %llu.\n"),
5339		    zpool_get_name(zhp), oldversion, version);
5340	}
5341
5342	return (0);
5343}
5344
5345static int
5346upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5347{
5348	int i, ret, count;
5349	boolean_t firstff = B_TRUE;
5350	nvlist_t *enabled = zpool_get_features(zhp);
5351
5352	count = 0;
5353	for (i = 0; i < SPA_FEATURES; i++) {
5354		const char *fname = spa_feature_table[i].fi_uname;
5355		const char *fguid = spa_feature_table[i].fi_guid;
5356		if (!nvlist_exists(enabled, fguid)) {
5357			char *propname;
5358			verify(-1 != asprintf(&propname, "feature@%s", fname));
5359			ret = zpool_set_prop(zhp, propname,
5360			    ZFS_FEATURE_ENABLED);
5361			if (ret != 0) {
5362				free(propname);
5363				return (ret);
5364			}
5365			count++;
5366
5367			if (firstff) {
5368				(void) printf(gettext("Enabled the "
5369				    "following features on '%s':\n"),
5370				    zpool_get_name(zhp));
5371				firstff = B_FALSE;
5372			}
5373			(void) printf(gettext("  %s\n"), fname);
5374			free(propname);
5375		}
5376	}
5377
5378	if (countp != NULL)
5379		*countp = count;
5380	return (0);
5381}
5382
5383static int
5384upgrade_cb(zpool_handle_t *zhp, void *arg)
5385{
5386	upgrade_cbdata_t *cbp = arg;
5387	nvlist_t *config;
5388	uint64_t version;
5389	boolean_t printnl = B_FALSE;
5390	int ret;
5391
5392	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5393		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5394		    "currently unavailable.\n\n"), zpool_get_name(zhp));
5395		cbp->cb_unavail = B_TRUE;
5396		/* Allow iteration to continue. */
5397		return (0);
5398	}
5399
5400	config = zpool_get_config(zhp, NULL);
5401	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5402	    &version) == 0);
5403
5404	assert(SPA_VERSION_IS_SUPPORTED(version));
5405
5406	if (version < cbp->cb_version) {
5407		cbp->cb_first = B_FALSE;
5408		ret = upgrade_version(zhp, cbp->cb_version);
5409		if (ret != 0)
5410			return (ret);
5411#ifdef __FreeBSD__
5412		root_pool_upgrade_check(zhp, cbp->cb_poolname,
5413		    sizeof(cbp->cb_poolname));
5414#endif	/* __FreeBSD__ */
5415		printnl = B_TRUE;
5416
5417#ifdef illumos
5418		/*
5419		 * If they did "zpool upgrade -a", then we could
5420		 * be doing ioctls to different pools.  We need
5421		 * to log this history once to each pool, and bypass
5422		 * the normal history logging that happens in main().
5423		 */
5424		(void) zpool_log_history(g_zfs, history_str);
5425		log_history = B_FALSE;
5426#endif
5427	}
5428
5429	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5430		int count;
5431		ret = upgrade_enable_all(zhp, &count);
5432		if (ret != 0)
5433			return (ret);
5434
5435		if (count > 0) {
5436			cbp->cb_first = B_FALSE;
5437			printnl = B_TRUE;
5438#ifdef __FreeBSD__
5439			root_pool_upgrade_check(zhp, cbp->cb_poolname,
5440			    sizeof(cbp->cb_poolname));
5441#endif	/* __FreeBSD__ */
5442			/*
5443			 * If they did "zpool upgrade -a", then we could
5444			 * be doing ioctls to different pools.  We need
5445			 * to log this history once to each pool, and bypass
5446			 * the normal history logging that happens in main().
5447			 */
5448			(void) zpool_log_history(g_zfs, history_str);
5449			log_history = B_FALSE;
5450		}
5451	}
5452
5453	if (printnl) {
5454		(void) printf(gettext("\n"));
5455	}
5456
5457	return (0);
5458}
5459
5460static int
5461upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
5462{
5463	upgrade_cbdata_t *cbp = arg;
5464
5465	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5466		if (cbp->cb_first) {
5467			(void) fprintf(stderr, gettext("The following pools "
5468			    "are unavailable and cannot be upgraded as this "
5469			    "time.\n\n"));
5470			(void) fprintf(stderr, gettext("POOL\n"));
5471			(void) fprintf(stderr, gettext("------------\n"));
5472			cbp->cb_first = B_FALSE;
5473		}
5474		(void) printf(gettext("%s\n"), zpool_get_name(zhp));
5475		cbp->cb_unavail = B_TRUE;
5476	}
5477	return (0);
5478}
5479
5480static int
5481upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5482{
5483	upgrade_cbdata_t *cbp = arg;
5484	nvlist_t *config;
5485	uint64_t version;
5486
5487	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5488		/*
5489		 * This will have been reported by upgrade_list_unavail so
5490		 * just allow iteration to continue.
5491		 */
5492		cbp->cb_unavail = B_TRUE;
5493		return (0);
5494	}
5495
5496	config = zpool_get_config(zhp, NULL);
5497	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5498	    &version) == 0);
5499
5500	assert(SPA_VERSION_IS_SUPPORTED(version));
5501
5502	if (version < SPA_VERSION_FEATURES) {
5503		if (cbp->cb_first) {
5504			(void) printf(gettext("The following pools are "
5505			    "formatted with legacy version numbers and can\n"
5506			    "be upgraded to use feature flags.  After "
5507			    "being upgraded, these pools\nwill no "
5508			    "longer be accessible by software that does not "
5509			    "support feature\nflags.\n\n"));
5510			(void) printf(gettext("VER  POOL\n"));
5511			(void) printf(gettext("---  ------------\n"));
5512			cbp->cb_first = B_FALSE;
5513		}
5514
5515		(void) printf("%2llu   %s\n", (u_longlong_t)version,
5516		    zpool_get_name(zhp));
5517	}
5518
5519	return (0);
5520}
5521
5522static int
5523upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5524{
5525	upgrade_cbdata_t *cbp = arg;
5526	nvlist_t *config;
5527	uint64_t version;
5528
5529	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5530		/*
5531		 * This will have been reported by upgrade_list_unavail so
5532		 * just allow iteration to continue.
5533		 */
5534		cbp->cb_unavail = B_TRUE;
5535		return (0);
5536	}
5537
5538	config = zpool_get_config(zhp, NULL);
5539	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5540	    &version) == 0);
5541
5542	if (version >= SPA_VERSION_FEATURES) {
5543		int i;
5544		boolean_t poolfirst = B_TRUE;
5545		nvlist_t *enabled = zpool_get_features(zhp);
5546
5547		for (i = 0; i < SPA_FEATURES; i++) {
5548			const char *fguid = spa_feature_table[i].fi_guid;
5549			const char *fname = spa_feature_table[i].fi_uname;
5550			if (!nvlist_exists(enabled, fguid)) {
5551				if (cbp->cb_first) {
5552					(void) printf(gettext("\nSome "
5553					    "supported features are not "
5554					    "enabled on the following pools. "
5555					    "Once a\nfeature is enabled the "
5556					    "pool may become incompatible with "
5557					    "software\nthat does not support "
5558					    "the feature. See "
5559					    "zpool-features(7) for "
5560					    "details.\n\n"));
5561					(void) printf(gettext("POOL  "
5562					    "FEATURE\n"));
5563					(void) printf(gettext("------"
5564					    "---------\n"));
5565					cbp->cb_first = B_FALSE;
5566				}
5567
5568				if (poolfirst) {
5569					(void) printf(gettext("%s\n"),
5570					    zpool_get_name(zhp));
5571					poolfirst = B_FALSE;
5572				}
5573
5574				(void) printf(gettext("      %s\n"), fname);
5575			}
5576		}
5577	}
5578
5579	return (0);
5580}
5581
5582/* ARGSUSED */
5583static int
5584upgrade_one(zpool_handle_t *zhp, void *data)
5585{
5586	boolean_t printnl = B_FALSE;
5587	upgrade_cbdata_t *cbp = data;
5588	uint64_t cur_version;
5589	int ret;
5590
5591	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5592		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5593		    "is currently unavailable.\n\n"), zpool_get_name(zhp));
5594		cbp->cb_unavail = B_TRUE;
5595		return (1);
5596	}
5597
5598	if (strcmp("log", zpool_get_name(zhp)) == 0) {
5599		(void) printf(gettext("'log' is now a reserved word\n"
5600		    "Pool 'log' must be renamed using export and import"
5601		    " to upgrade.\n\n"));
5602		return (1);
5603	}
5604
5605	cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5606	if (cur_version > cbp->cb_version) {
5607		(void) printf(gettext("Pool '%s' is already formatted "
5608		    "using more current version '%llu'.\n\n"),
5609		    zpool_get_name(zhp), cur_version);
5610		return (0);
5611	}
5612
5613	if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5614		(void) printf(gettext("Pool '%s' is already formatted "
5615		    "using version %llu.\n\n"), zpool_get_name(zhp),
5616		    cbp->cb_version);
5617		return (0);
5618	}
5619
5620	if (cur_version != cbp->cb_version) {
5621		printnl = B_TRUE;
5622		ret = upgrade_version(zhp, cbp->cb_version);
5623		if (ret != 0)
5624			return (ret);
5625#ifdef __FreeBSD__
5626		root_pool_upgrade_check(zhp, cbp->cb_poolname,
5627		    sizeof(cbp->cb_poolname));
5628#endif	/* __FreeBSD__ */
5629	}
5630
5631	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5632		int count = 0;
5633		ret = upgrade_enable_all(zhp, &count);
5634		if (ret != 0)
5635			return (ret);
5636
5637		if (count != 0) {
5638			printnl = B_TRUE;
5639#ifdef __FreeBSD__
5640			root_pool_upgrade_check(zhp, cbp->cb_poolname,
5641			    sizeof(cbp->cb_poolname));
5642#endif	/* __FreeBSD __*/
5643		} else if (cur_version == SPA_VERSION) {
5644			(void) printf(gettext("Pool '%s' already has all "
5645			    "supported features enabled.\n\n"),
5646			    zpool_get_name(zhp));
5647		}
5648	}
5649
5650	if (printnl) {
5651		(void) printf(gettext("\n"));
5652	}
5653
5654	return (0);
5655}
5656
5657/*
5658 * zpool upgrade
5659 * zpool upgrade -v
5660 * zpool upgrade [-V version] <-a | pool ...>
5661 *
5662 * With no arguments, display downrev'd ZFS pool available for upgrade.
5663 * Individual pools can be upgraded by specifying the pool, and '-a' will
5664 * upgrade all pools.
5665 */
5666int
5667zpool_do_upgrade(int argc, char **argv)
5668{
5669	int c;
5670	upgrade_cbdata_t cb = { 0 };
5671	int ret = 0;
5672	boolean_t showversions = B_FALSE;
5673	boolean_t upgradeall = B_FALSE;
5674	char *end;
5675
5676
5677	/* check options */
5678	while ((c = getopt(argc, argv, ":avV:")) != -1) {
5679		switch (c) {
5680		case 'a':
5681			upgradeall = B_TRUE;
5682			break;
5683		case 'v':
5684			showversions = B_TRUE;
5685			break;
5686		case 'V':
5687			cb.cb_version = strtoll(optarg, &end, 10);
5688			if (*end != '\0' ||
5689			    !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5690				(void) fprintf(stderr,
5691				    gettext("invalid version '%s'\n"), optarg);
5692				usage(B_FALSE);
5693			}
5694			break;
5695		case ':':
5696			(void) fprintf(stderr, gettext("missing argument for "
5697			    "'%c' option\n"), optopt);
5698			usage(B_FALSE);
5699			break;
5700		case '?':
5701			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5702			    optopt);
5703			usage(B_FALSE);
5704		}
5705	}
5706
5707	cb.cb_argc = argc;
5708	cb.cb_argv = argv;
5709	argc -= optind;
5710	argv += optind;
5711
5712	if (cb.cb_version == 0) {
5713		cb.cb_version = SPA_VERSION;
5714	} else if (!upgradeall && argc == 0) {
5715		(void) fprintf(stderr, gettext("-V option is "
5716		    "incompatible with other arguments\n"));
5717		usage(B_FALSE);
5718	}
5719
5720	if (showversions) {
5721		if (upgradeall || argc != 0) {
5722			(void) fprintf(stderr, gettext("-v option is "
5723			    "incompatible with other arguments\n"));
5724			usage(B_FALSE);
5725		}
5726	} else if (upgradeall) {
5727		if (argc != 0) {
5728			(void) fprintf(stderr, gettext("-a option should not "
5729			    "be used along with a pool name\n"));
5730			usage(B_FALSE);
5731		}
5732	}
5733
5734	(void) printf(gettext("This system supports ZFS pool feature "
5735	    "flags.\n\n"));
5736	if (showversions) {
5737		int i;
5738
5739		(void) printf(gettext("The following features are "
5740		    "supported:\n\n"));
5741		(void) printf(gettext("FEAT DESCRIPTION\n"));
5742		(void) printf("----------------------------------------------"
5743		    "---------------\n");
5744		for (i = 0; i < SPA_FEATURES; i++) {
5745			zfeature_info_t *fi = &spa_feature_table[i];
5746			const char *ro =
5747			    (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5748			    " (read-only compatible)" : "";
5749
5750			(void) printf("%-37s%s\n", fi->fi_uname, ro);
5751			(void) printf("     %s\n", fi->fi_desc);
5752		}
5753		(void) printf("\n");
5754
5755		(void) printf(gettext("The following legacy versions are also "
5756		    "supported:\n\n"));
5757		(void) printf(gettext("VER  DESCRIPTION\n"));
5758		(void) printf("---  -----------------------------------------"
5759		    "---------------\n");
5760		(void) printf(gettext(" 1   Initial ZFS version\n"));
5761		(void) printf(gettext(" 2   Ditto blocks "
5762		    "(replicated metadata)\n"));
5763		(void) printf(gettext(" 3   Hot spares and double parity "
5764		    "RAID-Z\n"));
5765		(void) printf(gettext(" 4   zpool history\n"));
5766		(void) printf(gettext(" 5   Compression using the gzip "
5767		    "algorithm\n"));
5768		(void) printf(gettext(" 6   bootfs pool property\n"));
5769		(void) printf(gettext(" 7   Separate intent log devices\n"));
5770		(void) printf(gettext(" 8   Delegated administration\n"));
5771		(void) printf(gettext(" 9   refquota and refreservation "
5772		    "properties\n"));
5773		(void) printf(gettext(" 10  Cache devices\n"));
5774		(void) printf(gettext(" 11  Improved scrub performance\n"));
5775		(void) printf(gettext(" 12  Snapshot properties\n"));
5776		(void) printf(gettext(" 13  snapused property\n"));
5777		(void) printf(gettext(" 14  passthrough-x aclinherit\n"));
5778		(void) printf(gettext(" 15  user/group space accounting\n"));
5779		(void) printf(gettext(" 16  stmf property support\n"));
5780		(void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
5781		(void) printf(gettext(" 18  Snapshot user holds\n"));
5782		(void) printf(gettext(" 19  Log device removal\n"));
5783		(void) printf(gettext(" 20  Compression using zle "
5784		    "(zero-length encoding)\n"));
5785		(void) printf(gettext(" 21  Deduplication\n"));
5786		(void) printf(gettext(" 22  Received properties\n"));
5787		(void) printf(gettext(" 23  Slim ZIL\n"));
5788		(void) printf(gettext(" 24  System attributes\n"));
5789		(void) printf(gettext(" 25  Improved scrub stats\n"));
5790		(void) printf(gettext(" 26  Improved snapshot deletion "
5791		    "performance\n"));
5792		(void) printf(gettext(" 27  Improved snapshot creation "
5793		    "performance\n"));
5794		(void) printf(gettext(" 28  Multiple vdev replacements\n"));
5795		(void) printf(gettext("\nFor more information on a particular "
5796		    "version, including supported releases,\n"));
5797		(void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5798	} else if (argc == 0 && upgradeall) {
5799		cb.cb_first = B_TRUE;
5800		ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5801		if (ret == 0 && cb.cb_first) {
5802			if (cb.cb_version == SPA_VERSION) {
5803				(void) printf(gettext("All %spools are already "
5804				    "formatted using feature flags.\n\n"),
5805				    cb.cb_unavail ? gettext("available ") : "");
5806				(void) printf(gettext("Every %sfeature flags "
5807				    "pool already has all supported features "
5808				    "enabled.\n"),
5809				    cb.cb_unavail ? gettext("available ") : "");
5810			} else {
5811				(void) printf(gettext("All pools are already "
5812				    "formatted with version %llu or higher.\n"),
5813				    cb.cb_version);
5814			}
5815		}
5816	} else if (argc == 0) {
5817		cb.cb_first = B_TRUE;
5818		ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
5819		assert(ret == 0);
5820
5821		if (!cb.cb_first) {
5822			(void) fprintf(stderr, "\n");
5823		}
5824
5825		cb.cb_first = B_TRUE;
5826		ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5827		assert(ret == 0);
5828
5829		if (cb.cb_first) {
5830			(void) printf(gettext("All %spools are formatted using "
5831			    "feature flags.\n\n"), cb.cb_unavail ?
5832			    gettext("available ") : "");
5833		} else {
5834			(void) printf(gettext("\nUse 'zpool upgrade -v' "
5835			    "for a list of available legacy versions.\n"));
5836		}
5837
5838		cb.cb_first = B_TRUE;
5839		ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5840		assert(ret == 0);
5841
5842		if (cb.cb_first) {
5843			(void) printf(gettext("Every %sfeature flags pool has "
5844			    "all supported features enabled.\n"),
5845			    cb.cb_unavail ? gettext("available ") : "");
5846		} else {
5847			(void) printf(gettext("\n"));
5848		}
5849	} else {
5850		ret = for_each_pool(argc, argv, B_TRUE, NULL,
5851		    upgrade_one, &cb);
5852	}
5853
5854	if (cb.cb_poolname[0] != '\0') {
5855		(void) printf(
5856		    "If you boot from pool '%s', don't forget to update boot code.\n"
5857		    "Assuming you use GPT partitioning and da0 is your boot disk\n"
5858		    "the following command will do it:\n"
5859		    "\n"
5860		    "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
5861		    cb.cb_poolname);
5862	}
5863
5864	return (ret);
5865}
5866
5867typedef struct hist_cbdata {
5868	boolean_t first;
5869	boolean_t longfmt;
5870	boolean_t internal;
5871} hist_cbdata_t;
5872
5873static void
5874print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
5875{
5876	nvlist_t **records;
5877	uint_t numrecords;
5878	int i;
5879
5880	verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5881	    &records, &numrecords) == 0);
5882	for (i = 0; i < numrecords; i++) {
5883		nvlist_t *rec = records[i];
5884		char tbuf[30] = "";
5885
5886		if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5887			time_t tsec;
5888			struct tm t;
5889
5890			tsec = fnvlist_lookup_uint64(records[i],
5891			    ZPOOL_HIST_TIME);
5892			(void) localtime_r(&tsec, &t);
5893			(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5894		}
5895
5896		if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5897			(void) printf("%s %s", tbuf,
5898			    fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5899		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5900			int ievent =
5901			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5902			if (!cb->internal)
5903				continue;
5904			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5905				(void) printf("%s unrecognized record:\n",
5906				    tbuf);
5907				dump_nvlist(rec, 4);
5908				continue;
5909			}
5910			(void) printf("%s [internal %s txg:%lld] %s", tbuf,
5911			    zfs_history_event_names[ievent],
5912			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5913			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5914		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5915			if (!cb->internal)
5916				continue;
5917			(void) printf("%s [txg:%lld] %s", tbuf,
5918			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5919			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5920			if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5921				(void) printf(" %s (%llu)",
5922				    fnvlist_lookup_string(rec,
5923				    ZPOOL_HIST_DSNAME),
5924				    fnvlist_lookup_uint64(rec,
5925				    ZPOOL_HIST_DSID));
5926			}
5927			(void) printf(" %s", fnvlist_lookup_string(rec,
5928			    ZPOOL_HIST_INT_STR));
5929		} else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5930			if (!cb->internal)
5931				continue;
5932			(void) printf("%s ioctl %s\n", tbuf,
5933			    fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5934			if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5935				(void) printf("    input:\n");
5936				dump_nvlist(fnvlist_lookup_nvlist(rec,
5937				    ZPOOL_HIST_INPUT_NVL), 8);
5938			}
5939			if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5940				(void) printf("    output:\n");
5941				dump_nvlist(fnvlist_lookup_nvlist(rec,
5942				    ZPOOL_HIST_OUTPUT_NVL), 8);
5943			}
5944			if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5945				(void) printf("    errno: %lld\n",
5946				    fnvlist_lookup_int64(rec,
5947				    ZPOOL_HIST_ERRNO));
5948			}
5949		} else {
5950			if (!cb->internal)
5951				continue;
5952			(void) printf("%s unrecognized record:\n", tbuf);
5953			dump_nvlist(rec, 4);
5954		}
5955
5956		if (!cb->longfmt) {
5957			(void) printf("\n");
5958			continue;
5959		}
5960		(void) printf(" [");
5961		if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5962			uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5963			struct passwd *pwd = getpwuid(who);
5964			(void) printf("user %d ", (int)who);
5965			if (pwd != NULL)
5966				(void) printf("(%s) ", pwd->pw_name);
5967		}
5968		if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5969			(void) printf("on %s",
5970			    fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5971		}
5972		if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5973			(void) printf(":%s",
5974			    fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5975		}
5976		(void) printf("]");
5977		(void) printf("\n");
5978	}
5979}
5980
5981/*
5982 * Print out the command history for a specific pool.
5983 */
5984static int
5985get_history_one(zpool_handle_t *zhp, void *data)
5986{
5987	nvlist_t *nvhis;
5988	int ret;
5989	hist_cbdata_t *cb = (hist_cbdata_t *)data;
5990	uint64_t off = 0;
5991	boolean_t eof = B_FALSE;
5992
5993	cb->first = B_FALSE;
5994
5995	(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5996
5997	while (!eof) {
5998		if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
5999			return (ret);
6000
6001		print_history_records(nvhis, cb);
6002		nvlist_free(nvhis);
6003	}
6004	(void) printf("\n");
6005
6006	return (ret);
6007}
6008
6009/*
6010 * zpool history <pool>
6011 *
6012 * Displays the history of commands that modified pools.
6013 */
6014int
6015zpool_do_history(int argc, char **argv)
6016{
6017	hist_cbdata_t cbdata = { 0 };
6018	int ret;
6019	int c;
6020
6021	cbdata.first = B_TRUE;
6022	/* check options */
6023	while ((c = getopt(argc, argv, "li")) != -1) {
6024		switch (c) {
6025		case 'l':
6026			cbdata.longfmt = B_TRUE;
6027			break;
6028		case 'i':
6029			cbdata.internal = B_TRUE;
6030			break;
6031		case '?':
6032			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
6033			    optopt);
6034			usage(B_FALSE);
6035		}
6036	}
6037	argc -= optind;
6038	argv += optind;
6039
6040	ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
6041	    &cbdata);
6042
6043	if (argc == 0 && cbdata.first == B_TRUE) {
6044		(void) printf(gettext("no pools available\n"));
6045		return (0);
6046	}
6047
6048	return (ret);
6049}
6050
6051static int
6052get_callback(zpool_handle_t *zhp, void *data)
6053{
6054	zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
6055	char value[MAXNAMELEN];
6056	zprop_source_t srctype;
6057	zprop_list_t *pl;
6058
6059	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
6060
6061		/*
6062		 * Skip the special fake placeholder. This will also skip
6063		 * over the name property when 'all' is specified.
6064		 */
6065		if (pl->pl_prop == ZPOOL_PROP_NAME &&
6066		    pl == cbp->cb_proplist)
6067			continue;
6068
6069		if (pl->pl_prop == ZPROP_INVAL &&
6070		    (zpool_prop_feature(pl->pl_user_prop) ||
6071		    zpool_prop_unsupported(pl->pl_user_prop))) {
6072			srctype = ZPROP_SRC_LOCAL;
6073
6074			if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
6075			    value, sizeof (value)) == 0) {
6076				zprop_print_one_property(zpool_get_name(zhp),
6077				    cbp, pl->pl_user_prop, value, srctype,
6078				    NULL, NULL);
6079			}
6080		} else {
6081			if (zpool_get_prop(zhp, pl->pl_prop, value,
6082			    sizeof (value), &srctype, cbp->cb_literal) != 0)
6083				continue;
6084
6085			zprop_print_one_property(zpool_get_name(zhp), cbp,
6086			    zpool_prop_to_name(pl->pl_prop), value, srctype,
6087			    NULL, NULL);
6088		}
6089	}
6090	return (0);
6091}
6092
6093/*
6094 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
6095 *
6096 *	-H	Scripted mode.  Don't display headers, and separate properties
6097 *		by a single tab.
6098 *	-o	List of columns to display.  Defaults to
6099 *		"name,property,value,source".
6100 *	-p	Diplay values in parsable (exact) format.
6101 *
6102 * Get properties of pools in the system. Output space statistics
6103 * for each one as well as other attributes.
6104 */
6105int
6106zpool_do_get(int argc, char **argv)
6107{
6108	zprop_get_cbdata_t cb = { 0 };
6109	zprop_list_t fake_name = { 0 };
6110	int ret;
6111	int c, i;
6112	char *value;
6113
6114	cb.cb_first = B_TRUE;
6115
6116	/*
6117	 * Set up default columns and sources.
6118	 */
6119	cb.cb_sources = ZPROP_SRC_ALL;
6120	cb.cb_columns[0] = GET_COL_NAME;
6121	cb.cb_columns[1] = GET_COL_PROPERTY;
6122	cb.cb_columns[2] = GET_COL_VALUE;
6123	cb.cb_columns[3] = GET_COL_SOURCE;
6124	cb.cb_type = ZFS_TYPE_POOL;
6125
6126	/* check options */
6127	while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
6128		switch (c) {
6129		case 'p':
6130			cb.cb_literal = B_TRUE;
6131			break;
6132		case 'H':
6133			cb.cb_scripted = B_TRUE;
6134			break;
6135		case 'o':
6136			bzero(&cb.cb_columns, sizeof (cb.cb_columns));
6137			i = 0;
6138			while (*optarg != '\0') {
6139				static char *col_subopts[] =
6140				{ "name", "property", "value", "source",
6141				"all", NULL };
6142
6143				if (i == ZFS_GET_NCOLS) {
6144					(void) fprintf(stderr, gettext("too "
6145					"many fields given to -o "
6146					"option\n"));
6147					usage(B_FALSE);
6148				}
6149
6150				switch (getsubopt(&optarg, col_subopts,
6151				    &value)) {
6152				case 0:
6153					cb.cb_columns[i++] = GET_COL_NAME;
6154					break;
6155				case 1:
6156					cb.cb_columns[i++] = GET_COL_PROPERTY;
6157					break;
6158				case 2:
6159					cb.cb_columns[i++] = GET_COL_VALUE;
6160					break;
6161				case 3:
6162					cb.cb_columns[i++] = GET_COL_SOURCE;
6163					break;
6164				case 4:
6165					if (i > 0) {
6166						(void) fprintf(stderr,
6167						    gettext("\"all\" conflicts "
6168						    "with specific fields "
6169						    "given to -o option\n"));
6170						usage(B_FALSE);
6171					}
6172					cb.cb_columns[0] = GET_COL_NAME;
6173					cb.cb_columns[1] = GET_COL_PROPERTY;
6174					cb.cb_columns[2] = GET_COL_VALUE;
6175					cb.cb_columns[3] = GET_COL_SOURCE;
6176					i = ZFS_GET_NCOLS;
6177					break;
6178				default:
6179					(void) fprintf(stderr,
6180					    gettext("invalid column name "
6181					    "'%s'\n"), suboptarg);
6182					usage(B_FALSE);
6183				}
6184			}
6185			break;
6186		case '?':
6187			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
6188			    optopt);
6189			usage(B_FALSE);
6190		}
6191	}
6192
6193	argc -= optind;
6194	argv += optind;
6195
6196	if (argc < 1) {
6197		(void) fprintf(stderr, gettext("missing property "
6198		    "argument\n"));
6199		usage(B_FALSE);
6200	}
6201
6202	if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
6203	    ZFS_TYPE_POOL) != 0)
6204		usage(B_FALSE);
6205
6206	argc--;
6207	argv++;
6208
6209	if (cb.cb_proplist != NULL) {
6210		fake_name.pl_prop = ZPOOL_PROP_NAME;
6211		fake_name.pl_width = strlen(gettext("NAME"));
6212		fake_name.pl_next = cb.cb_proplist;
6213		cb.cb_proplist = &fake_name;
6214	}
6215
6216	ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
6217	    get_callback, &cb);
6218
6219	if (cb.cb_proplist == &fake_name)
6220		zprop_free_list(fake_name.pl_next);
6221	else
6222		zprop_free_list(cb.cb_proplist);
6223
6224	return (ret);
6225}
6226
6227typedef struct set_cbdata {
6228	char *cb_propname;
6229	char *cb_value;
6230	boolean_t cb_any_successful;
6231} set_cbdata_t;
6232
6233int
6234set_callback(zpool_handle_t *zhp, void *data)
6235{
6236	int error;
6237	set_cbdata_t *cb = (set_cbdata_t *)data;
6238
6239	error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
6240
6241	if (!error)
6242		cb->cb_any_successful = B_TRUE;
6243
6244	return (error);
6245}
6246
6247int
6248zpool_do_set(int argc, char **argv)
6249{
6250	set_cbdata_t cb = { 0 };
6251	int error;
6252
6253	if (argc > 1 && argv[1][0] == '-') {
6254		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
6255		    argv[1][1]);
6256		usage(B_FALSE);
6257	}
6258
6259	if (argc < 2) {
6260		(void) fprintf(stderr, gettext("missing property=value "
6261		    "argument\n"));
6262		usage(B_FALSE);
6263	}
6264
6265	if (argc < 3) {
6266		(void) fprintf(stderr, gettext("missing pool name\n"));
6267		usage(B_FALSE);
6268	}
6269
6270	if (argc > 3) {
6271		(void) fprintf(stderr, gettext("too many pool names\n"));
6272		usage(B_FALSE);
6273	}
6274
6275	cb.cb_propname = argv[1];
6276	cb.cb_value = strchr(cb.cb_propname, '=');
6277	if (cb.cb_value == NULL) {
6278		(void) fprintf(stderr, gettext("missing value in "
6279		    "property=value argument\n"));
6280		usage(B_FALSE);
6281	}
6282
6283	*(cb.cb_value) = '\0';
6284	cb.cb_value++;
6285
6286	error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6287	    set_callback, &cb);
6288
6289	return (error);
6290}
6291
6292static int
6293find_command_idx(char *command, int *idx)
6294{
6295	int i;
6296
6297	for (i = 0; i < NCOMMAND; i++) {
6298		if (command_table[i].name == NULL)
6299			continue;
6300
6301		if (strcmp(command, command_table[i].name) == 0) {
6302			*idx = i;
6303			return (0);
6304		}
6305	}
6306	return (1);
6307}
6308
6309int
6310main(int argc, char **argv)
6311{
6312	int ret = 0;
6313	int i;
6314	char *cmdname;
6315
6316	(void) setlocale(LC_ALL, "");
6317	(void) textdomain(TEXT_DOMAIN);
6318
6319	if ((g_zfs = libzfs_init()) == NULL) {
6320		(void) fprintf(stderr, gettext("internal error: failed to "
6321		    "initialize ZFS library\n"));
6322		return (1);
6323	}
6324
6325	libzfs_print_on_error(g_zfs, B_TRUE);
6326
6327	opterr = 0;
6328
6329	/*
6330	 * Make sure the user has specified some command.
6331	 */
6332	if (argc < 2) {
6333		(void) fprintf(stderr, gettext("missing command\n"));
6334		usage(B_FALSE);
6335	}
6336
6337	cmdname = argv[1];
6338
6339	/*
6340	 * Special case '-?'
6341	 */
6342	if (strcmp(cmdname, "-?") == 0)
6343		usage(B_TRUE);
6344
6345	zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6346
6347	/*
6348	 * Run the appropriate command.
6349	 */
6350	if (find_command_idx(cmdname, &i) == 0) {
6351		current_command = &command_table[i];
6352		ret = command_table[i].func(argc - 1, argv + 1);
6353	} else if (strchr(cmdname, '=')) {
6354		verify(find_command_idx("set", &i) == 0);
6355		current_command = &command_table[i];
6356		ret = command_table[i].func(argc, argv);
6357	} else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6358		/*
6359		 * 'freeze' is a vile debugging abomination, so we treat
6360		 * it as such.
6361		 */
6362		zfs_cmd_t zc = { 0 };
6363		(void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
6364		return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
6365	} else {
6366		(void) fprintf(stderr, gettext("unrecognized "
6367		    "command '%s'\n"), cmdname);
6368		usage(B_FALSE);
6369	}
6370
6371	if (ret == 0 && log_history)
6372		(void) zpool_log_history(g_zfs, history_str);
6373
6374	libzfs_fini(g_zfs);
6375
6376	/*
6377	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
6378	 * for the purposes of running ::findleaks.
6379	 */
6380	if (getenv("ZFS_ABORT") != NULL) {
6381		(void) printf("dumping core by request\n");
6382		abort();
6383	}
6384
6385	return (ret);
6386}
6387