zpool_main.c revision 286708
160812Sps/*
260786Sps * CDDL HEADER START
360786Sps *
460786Sps * The contents of this file are subject to the terms of the
560786Sps * Common Development and Distribution License (the "License").
660786Sps * You may not use this file except in compliance with the License.
760786Sps *
860786Sps * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
960786Sps * or http://www.opensolaris.org/os/licensing.
1060786Sps * See the License for the specific language governing permissions
1160786Sps * and limitations under the License.
1260786Sps *
1360786Sps * When distributing Covered Code, include this CDDL HEADER in each
1460786Sps * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1560786Sps * If applicable, add the following below this CDDL HEADER, with the
1660786Sps * fields enclosed by brackets "[]" replaced with your own identifying
1760786Sps * information: Portions Copyright [yyyy] [name of copyright owner]
1860786Sps *
1960786Sps * CDDL HEADER END
2060786Sps */
2160786Sps
2260786Sps/*
2360786Sps * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2460786Sps * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
2560786Sps * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
2660812Sps * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
2760786Sps * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
2860786Sps * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
2960786Sps */
3060786Sps
3160786Sps#include <solaris.h>
3260786Sps#include <assert.h>
3360786Sps#include <ctype.h>
3460786Sps#include <dirent.h>
3560786Sps#include <errno.h>
3660786Sps#include <fcntl.h>
3760786Sps#include <libgen.h>
3860786Sps#include <libintl.h>
3960786Sps#include <libuutil.h>
4060786Sps#include <locale.h>
4160786Sps#include <stdio.h>
4260786Sps#include <stdlib.h>
4360786Sps#include <string.h>
4460786Sps#include <strings.h>
4560786Sps#include <unistd.h>
4660786Sps#include <priv.h>
4760786Sps#include <pwd.h>
4860786Sps#include <zone.h>
4960786Sps#include <sys/time.h>
5060786Sps#include <zfs_prop.h>
5160786Sps#include <sys/fs/zfs.h>
5260786Sps#include <sys/stat.h>
5360786Sps
5460786Sps#include <libzfs.h>
5560786Sps
5660812Sps#include "zpool_util.h"
5763131Sps#include "zfs_comutil.h"
5860786Sps#include "zfeature_common.h"
5960786Sps
6060786Sps#include "statcommon.h"
6160786Sps
6260786Spsstatic int zpool_do_create(int, char **);
6360786Spsstatic int zpool_do_destroy(int, char **);
6460786Sps
6560786Spsstatic int zpool_do_add(int, char **);
6660786Spsstatic int zpool_do_remove(int, char **);
6760786Spsstatic int zpool_do_labelclear(int, char **);
6860786Sps
6960786Spsstatic int zpool_do_list(int, char **);
7060786Spsstatic int zpool_do_iostat(int, char **);
7160786Spsstatic int zpool_do_status(int, char **);
7260786Sps
7360786Spsstatic int zpool_do_online(int, char **);
7460786Spsstatic int zpool_do_offline(int, char **);
7560786Spsstatic int zpool_do_clear(int, char **);
7660786Spsstatic int zpool_do_reopen(int, char **);
7760786Sps
7860786Spsstatic int zpool_do_reguid(int, char **);
7960786Sps
8060786Spsstatic int zpool_do_attach(int, char **);
8160786Spsstatic int zpool_do_detach(int, char **);
8260786Spsstatic int zpool_do_replace(int, char **);
8360786Spsstatic int zpool_do_split(int, char **);
8460786Sps
8560786Spsstatic int zpool_do_scrub(int, char **);
8660786Sps
8760786Spsstatic int zpool_do_import(int, char **);
8860786Spsstatic int zpool_do_export(int, char **);
8960786Sps
9060786Spsstatic int zpool_do_upgrade(int, char **);
9160786Sps
9260786Spsstatic int zpool_do_history(int, char **);
9360786Sps
9460786Spsstatic int zpool_do_get(int, char **);
9560786Spsstatic int zpool_do_set(int, char **);
9660786Sps
9760786Sps/*
9860786Sps * These libumem hooks provide a reasonable set of defaults for the allocator's
9960786Sps * debugging facilities.
10060786Sps */
10160786Sps
10260786Sps#ifdef DEBUG
10360786Spsconst char *
10460786Sps_umem_debug_init(void)
10560786Sps{
10660786Sps	return ("default,verbose"); /* $UMEM_DEBUG setting */
10760786Sps}
10860786Sps
10960786Spsconst char *
11060786Sps_umem_logging_init(void)
11160786Sps{
11260786Sps	return ("fail,contents"); /* $UMEM_LOGGING setting */
11360786Sps}
11460786Sps#endif
11560786Sps
11660786Spstypedef enum {
11760786Sps	HELP_ADD,
11860786Sps	HELP_ATTACH,
11960786Sps	HELP_CLEAR,
12060786Sps	HELP_CREATE,
12160786Sps	HELP_DESTROY,
12260786Sps	HELP_DETACH,
12360786Sps	HELP_EXPORT,
12460786Sps	HELP_HISTORY,
12560786Sps	HELP_IMPORT,
12660786Sps	HELP_IOSTAT,
12760786Sps	HELP_LABELCLEAR,
12860786Sps	HELP_LIST,
12960786Sps	HELP_OFFLINE,
13060786Sps	HELP_ONLINE,
13160786Sps	HELP_REPLACE,
13260786Sps	HELP_REMOVE,
13360786Sps	HELP_SCRUB,
13460786Sps	HELP_STATUS,
13560786Sps	HELP_UPGRADE,
13660786Sps	HELP_GET,
13760786Sps	HELP_SET,
13860786Sps	HELP_SPLIT,
13960786Sps	HELP_REGUID,
14060786Sps	HELP_REOPEN
14160786Sps} zpool_help_t;
14260786Sps
14360786Sps
14460786Spstypedef struct zpool_command {
14560786Sps	const char	*name;
14660786Sps	int		(*func)(int, char **);
14760786Sps	zpool_help_t	usage;
14860786Sps} zpool_command_t;
14960786Sps
15060786Sps/*
15160786Sps * Master command table.  Each ZFS command has a name, associated function, and
15260786Sps * usage message.  The usage messages need to be internationalized, so we have
15360786Sps * to have a function to return the usage message based on a command index.
15460786Sps *
15560786Sps * These commands are organized according to how they are displayed in the usage
15660786Sps * message.  An empty command (one with a NULL name) indicates an empty line in
15760786Sps * the generic usage message.
15860786Sps */
15960786Spsstatic zpool_command_t command_table[] = {
16060786Sps	{ "create",	zpool_do_create,	HELP_CREATE		},
16160786Sps	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
16260786Sps	{ NULL },
16360786Sps	{ "add",	zpool_do_add,		HELP_ADD		},
16460786Sps	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
16560786Sps	{ NULL },
16660786Sps	{ "labelclear",	zpool_do_labelclear,	HELP_LABELCLEAR		},
16760786Sps	{ NULL },
16860786Sps	{ "list",	zpool_do_list,		HELP_LIST		},
16960786Sps	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
17060786Sps	{ "status",	zpool_do_status,	HELP_STATUS		},
17160786Sps	{ NULL },
17260786Sps	{ "online",	zpool_do_online,	HELP_ONLINE		},
17360786Sps	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
17460786Sps	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
17560786Sps	{ "reopen",	zpool_do_reopen,	HELP_REOPEN		},
17660786Sps	{ NULL },
17760786Sps	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
17860786Sps	{ "detach",	zpool_do_detach,	HELP_DETACH		},
17960786Sps	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
18060786Sps	{ "split",	zpool_do_split,		HELP_SPLIT		},
18160786Sps	{ NULL },
18260786Sps	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
18360786Sps	{ NULL },
18460786Sps	{ "import",	zpool_do_import,	HELP_IMPORT		},
18560786Sps	{ "export",	zpool_do_export,	HELP_EXPORT		},
18660786Sps	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
18760786Sps	{ "reguid",	zpool_do_reguid,	HELP_REGUID		},
18860786Sps	{ NULL },
18960786Sps	{ "history",	zpool_do_history,	HELP_HISTORY		},
19060786Sps	{ "get",	zpool_do_get,		HELP_GET		},
19160786Sps	{ "set",	zpool_do_set,		HELP_SET		},
19260786Sps};
19360786Sps
19460786Sps#define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
19560786Sps
19660786Spsstatic zpool_command_t *current_command;
19760786Spsstatic char history_str[HIS_MAX_RECORD_LEN];
19860786Spsstatic boolean_t log_history = B_TRUE;
19960786Spsstatic uint_t timestamp_fmt = NODATE;
20060786Sps
20160786Spsstatic const char *
20260786Spsget_usage(zpool_help_t idx) {
20360786Sps	switch (idx) {
20460786Sps	case HELP_ADD:
20560786Sps		return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
20660786Sps	case HELP_ATTACH:
20760786Sps		return (gettext("\tattach [-f] <pool> <device> "
20860786Sps		    "<new-device>\n"));
20960786Sps	case HELP_CLEAR:
21060786Sps		return (gettext("\tclear [-nF] <pool> [device]\n"));
21160786Sps	case HELP_CREATE:
21260786Sps		return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
21360786Sps		    "\t    [-O file-system-property=value] ... \n"
21460786Sps		    "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
21560786Sps	case HELP_DESTROY:
21660786Sps		return (gettext("\tdestroy [-f] <pool>\n"));
21760786Sps	case HELP_DETACH:
21860786Sps		return (gettext("\tdetach <pool> <device>\n"));
21960786Sps	case HELP_EXPORT:
22060786Sps		return (gettext("\texport [-f] <pool> ...\n"));
22160786Sps	case HELP_HISTORY:
22260786Sps		return (gettext("\thistory [-il] [<pool>] ...\n"));
22360786Sps	case HELP_IMPORT:
22460786Sps		return (gettext("\timport [-d dir] [-D]\n"
22560786Sps		    "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
22660786Sps		    "\timport [-o mntopts] [-o property=value] ... \n"
22760786Sps		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
22860786Sps		    "[-R root] [-F [-n]] -a\n"
22960786Sps		    "\timport [-o mntopts] [-o property=value] ... \n"
23060786Sps		    "\t    [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
23160786Sps		    "[-R root] [-F [-n]]\n"
23260786Sps		    "\t    <pool | id> [newpool]\n"));
23360786Sps	case HELP_IOSTAT:
23460786Sps		return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
23560786Sps		    "[count]]\n"));
23660786Sps	case HELP_LABELCLEAR:
23760786Sps		return (gettext("\tlabelclear [-f] <vdev>\n"));
23860786Sps	case HELP_LIST:
23960786Sps		return (gettext("\tlist [-Hpv] [-o property[,...]] "
24060786Sps		    "[-T d|u] [pool] ... [interval [count]]\n"));
24160786Sps	case HELP_OFFLINE:
24260786Sps		return (gettext("\toffline [-t] <pool> <device> ...\n"));
24360786Sps	case HELP_ONLINE:
24460786Sps		return (gettext("\tonline [-e] <pool> <device> ...\n"));
24560786Sps	case HELP_REPLACE:
24660786Sps		return (gettext("\treplace [-f] <pool> <device> "
24760786Sps		    "[new-device]\n"));
24860786Sps	case HELP_REMOVE:
24960786Sps		return (gettext("\tremove <pool> <device> ...\n"));
25060786Sps	case HELP_REOPEN:
25160786Sps		return (gettext("\treopen <pool>\n"));
25260786Sps	case HELP_SCRUB:
25360786Sps		return (gettext("\tscrub [-s] <pool> ...\n"));
25460786Sps	case HELP_STATUS:
25560786Sps		return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
25660786Sps		    "[count]]\n"));
25760786Sps	case HELP_UPGRADE:
25860786Sps		return (gettext("\tupgrade [-v]\n"
25960786Sps		    "\tupgrade [-V version] <-a | pool ...>\n"));
26060786Sps	case HELP_GET:
26160786Sps		return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
26260786Sps		    "<\"all\" | property[,...]> <pool> ...\n"));
26360786Sps	case HELP_SET:
26460786Sps		return (gettext("\tset <property=value> <pool> \n"));
26560786Sps	case HELP_SPLIT:
26660786Sps		return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
26760786Sps		    "\t    [-o property=value] <pool> <newpool> "
26860786Sps		    "[<device> ...]\n"));
26960786Sps	case HELP_REGUID:
27060786Sps		return (gettext("\treguid <pool>\n"));
27160786Sps	}
27260786Sps
27360786Sps	abort();
27460786Sps	/* NOTREACHED */
27560786Sps}
27660786Sps
27760786Sps
27860786Sps/*
27960786Sps * Callback routine that will print out a pool property value.
28060786Sps */
28160786Spsstatic int
28260786Spsprint_prop_cb(int prop, void *cb)
28360786Sps{
28460786Sps	FILE *fp = cb;
28560786Sps
28660786Sps	(void) fprintf(fp, "\t%-15s  ", zpool_prop_to_name(prop));
28760786Sps
28860786Sps	if (zpool_prop_readonly(prop))
28960786Sps		(void) fprintf(fp, "  NO   ");
29060786Sps	else
29160786Sps		(void) fprintf(fp, " YES   ");
29260786Sps
29360786Sps	if (zpool_prop_values(prop) == NULL)
29460786Sps		(void) fprintf(fp, "-\n");
29560786Sps	else
29660786Sps		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
29760786Sps
29860786Sps	return (ZPROP_CONT);
29960786Sps}
30060786Sps
30160786Sps/*
30260786Sps * Display usage message.  If we're inside a command, display only the usage for
30360786Sps * that command.  Otherwise, iterate over the entire command table and display
30460786Sps * a complete usage message.
30560786Sps */
30660786Spsvoid
30760786Spsusage(boolean_t requested)
30860786Sps{
30960786Sps	FILE *fp = requested ? stdout : stderr;
31060786Sps
31160786Sps	if (current_command == NULL) {
31260786Sps		int i;
31360786Sps
31460786Sps		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
31560786Sps		(void) fprintf(fp,
31660786Sps		    gettext("where 'command' is one of the following:\n\n"));
31760786Sps
31860786Sps		for (i = 0; i < NCOMMAND; i++) {
31960786Sps			if (command_table[i].name == NULL)
32060786Sps				(void) fprintf(fp, "\n");
32160786Sps			else
32260786Sps				(void) fprintf(fp, "%s",
32360786Sps				    get_usage(command_table[i].usage));
32460786Sps		}
32560786Sps	} else {
32660786Sps		(void) fprintf(fp, gettext("usage:\n"));
32760786Sps		(void) fprintf(fp, "%s", get_usage(current_command->usage));
32860786Sps	}
32960786Sps
33060786Sps	if (current_command != NULL &&
33160786Sps	    ((strcmp(current_command->name, "set") == 0) ||
33260786Sps	    (strcmp(current_command->name, "get") == 0) ||
33360786Sps	    (strcmp(current_command->name, "list") == 0))) {
33460786Sps
33560786Sps		(void) fprintf(fp,
33660786Sps		    gettext("\nthe following properties are supported:\n"));
33760786Sps
33860786Sps		(void) fprintf(fp, "\n\t%-15s  %s   %s\n\n",
33960786Sps		    "PROPERTY", "EDIT", "VALUES");
34060786Sps
34160786Sps		/* Iterate over all properties */
34260786Sps		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
34360786Sps		    ZFS_TYPE_POOL);
34460786Sps
34560786Sps		(void) fprintf(fp, "\t%-15s   ", "feature@...");
34660786Sps		(void) fprintf(fp, "YES   disabled | enabled | active\n");
34760786Sps
34860786Sps		(void) fprintf(fp, gettext("\nThe feature@ properties must be "
34960786Sps		    "appended with a feature name.\nSee zpool-features(7).\n"));
35060786Sps	}
35160786Sps
35260786Sps	/*
35360786Sps	 * See comments at end of main().
35460786Sps	 */
35560786Sps	if (getenv("ZFS_ABORT") != NULL) {
35660786Sps		(void) printf("dumping core by request\n");
35760786Sps		abort();
35860786Sps	}
35960786Sps
36060786Sps	exit(requested ? 0 : 2);
36160786Sps}
36260786Sps
36360786Spsvoid
36460786Spsprint_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
36560786Sps    boolean_t print_logs)
36660786Sps{
36760786Sps	nvlist_t **child;
36860786Sps	uint_t c, children;
36960786Sps	char *vname;
37060786Sps
37160786Sps	if (name != NULL)
37260786Sps		(void) printf("\t%*s%s\n", indent, "", name);
37360786Sps
37460786Sps	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
37560786Sps	    &child, &children) != 0)
37660786Sps		return;
37760786Sps
37860786Sps	for (c = 0; c < children; c++) {
37960786Sps		uint64_t is_log = B_FALSE;
38060786Sps
38160786Sps		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
38260786Sps		    &is_log);
38360786Sps		if ((is_log && !print_logs) || (!is_log && print_logs))
38460786Sps			continue;
38560786Sps
38660786Sps		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
38760786Sps		print_vdev_tree(zhp, vname, child[c], indent + 2,
38860786Sps		    B_FALSE);
38960786Sps		free(vname);
39060786Sps	}
39160786Sps}
39260786Sps
39360786Spsstatic boolean_t
39460786Spsprop_list_contains_feature(nvlist_t *proplist)
39560786Sps{
39660786Sps	nvpair_t *nvp;
39760786Sps	for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
39860786Sps	    nvp = nvlist_next_nvpair(proplist, nvp)) {
39960786Sps		if (zpool_prop_feature(nvpair_name(nvp)))
40060786Sps			return (B_TRUE);
40160786Sps	}
40260786Sps	return (B_FALSE);
40360786Sps}
40460786Sps
40560786Sps/*
40660786Sps * Add a property pair (name, string-value) into a property nvlist.
40760786Sps */
40860786Spsstatic int
40960786Spsadd_prop_list(const char *propname, char *propval, nvlist_t **props,
41060786Sps    boolean_t poolprop)
41160786Sps{
41260786Sps	zpool_prop_t prop = ZPROP_INVAL;
41360786Sps	zfs_prop_t fprop;
41460786Sps	nvlist_t *proplist;
41560786Sps	const char *normnm;
41660786Sps	char *strval;
41760786Sps
41860786Sps	if (*props == NULL &&
41960786Sps	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
42060786Sps		(void) fprintf(stderr,
42160786Sps		    gettext("internal error: out of memory\n"));
42260786Sps		return (1);
42360786Sps	}
42460786Sps
42560786Sps	proplist = *props;
42660786Sps
42760786Sps	if (poolprop) {
42860786Sps		const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
42960786Sps
43060786Sps		if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
43160786Sps		    !zpool_prop_feature(propname)) {
43260786Sps			(void) fprintf(stderr, gettext("property '%s' is "
43360786Sps			    "not a valid pool property\n"), propname);
43460786Sps			return (2);
43560786Sps		}
43660786Sps
43760786Sps		/*
43860786Sps		 * feature@ properties and version should not be specified
43960786Sps		 * at the same time.
44060786Sps		 */
44160786Sps		if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
44260786Sps		    nvlist_exists(proplist, vname)) ||
44360786Sps		    (prop == ZPOOL_PROP_VERSION &&
44460786Sps		    prop_list_contains_feature(proplist))) {
44560786Sps			(void) fprintf(stderr, gettext("'feature@' and "
44660786Sps			    "'version' properties cannot be specified "
44760786Sps			    "together\n"));
44860786Sps			return (2);
44960786Sps		}
45060786Sps
45160786Sps
45260786Sps		if (zpool_prop_feature(propname))
45360786Sps			normnm = propname;
45460786Sps		else
45560786Sps			normnm = zpool_prop_to_name(prop);
45660786Sps	} else {
45760786Sps		if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
45860786Sps			normnm = zfs_prop_to_name(fprop);
45960786Sps		} else {
46060786Sps			normnm = propname;
46160786Sps		}
46260786Sps	}
46360786Sps
46460786Sps	if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
46560786Sps	    prop != ZPOOL_PROP_CACHEFILE) {
46660786Sps		(void) fprintf(stderr, gettext("property '%s' "
46760786Sps		    "specified multiple times\n"), propname);
46860786Sps		return (2);
46960786Sps	}
47060786Sps
47160786Sps	if (nvlist_add_string(proplist, normnm, propval) != 0) {
47260786Sps		(void) fprintf(stderr, gettext("internal "
47360786Sps		    "error: out of memory\n"));
47460786Sps		return (1);
47560786Sps	}
47660786Sps
47760786Sps	return (0);
47860786Sps}
47960786Sps
48060786Sps/*
48160786Sps * zpool add [-fn] <pool> <vdev> ...
48260786Sps *
48360786Sps *	-f	Force addition of devices, even if they appear in use
48460786Sps *	-n	Do not add the devices, but display the resulting layout if
48560786Sps *		they were to be added.
48660786Sps *
48760786Sps * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
48860786Sps * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
48960786Sps * libzfs.
49060786Sps */
49160786Spsint
49260786Spszpool_do_add(int argc, char **argv)
49360786Sps{
49460786Sps	boolean_t force = B_FALSE;
49560786Sps	boolean_t dryrun = B_FALSE;
49660786Sps	int c;
49760786Sps	nvlist_t *nvroot;
49860786Sps	char *poolname;
49960786Sps	int ret;
50060786Sps	zpool_handle_t *zhp;
50160786Sps	nvlist_t *config;
50260786Sps
50360786Sps	/* check options */
50460786Sps	while ((c = getopt(argc, argv, "fn")) != -1) {
50560786Sps		switch (c) {
50660786Sps		case 'f':
50760786Sps			force = B_TRUE;
50860786Sps			break;
50960786Sps		case 'n':
51060786Sps			dryrun = B_TRUE;
51160786Sps			break;
51260786Sps		case '?':
51360786Sps			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
51460786Sps			    optopt);
51563131Sps			usage(B_FALSE);
51663131Sps		}
51760786Sps	}
51860786Sps
51960786Sps	argc -= optind;
52060786Sps	argv += optind;
52160786Sps
52260786Sps	/* get pool name and check number of arguments */
52360786Sps	if (argc < 1) {
52460786Sps		(void) fprintf(stderr, gettext("missing pool name argument\n"));
52560786Sps		usage(B_FALSE);
52660786Sps	}
52760786Sps	if (argc < 2) {
52860786Sps		(void) fprintf(stderr, gettext("missing vdev specification\n"));
52960786Sps		usage(B_FALSE);
53060786Sps	}
53160786Sps
53260786Sps	poolname = argv[0];
53360786Sps
53460786Sps	argc--;
53560786Sps	argv++;
53660786Sps
53760786Sps	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
53860786Sps		return (1);
53960786Sps
54060786Sps	if ((config = zpool_get_config(zhp, NULL)) == NULL) {
54160786Sps		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
54260786Sps		    poolname);
54360786Sps		zpool_close(zhp);
54460786Sps		return (1);
54560786Sps	}
54660786Sps
54760786Sps	/* pass off to get_vdev_spec for processing */
54860786Sps	nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
54960786Sps	    argc, argv);
55060786Sps	if (nvroot == NULL) {
55160786Sps		zpool_close(zhp);
55260786Sps		return (1);
55360786Sps	}
55460786Sps
55560786Sps	if (dryrun) {
55660786Sps		nvlist_t *poolnvroot;
55760786Sps
55860786Sps		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
55960786Sps		    &poolnvroot) == 0);
56060786Sps
56160786Sps		(void) printf(gettext("would update '%s' to the following "
56260786Sps		    "configuration:\n"), zpool_get_name(zhp));
56360786Sps
56460786Sps		/* print original main pool and new tree */
56560786Sps		print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
56660786Sps		print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
56760786Sps
56860786Sps		/* Do the same for the logs */
56960786Sps		if (num_logs(poolnvroot) > 0) {
57060786Sps			print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
57160786Sps			print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
57260786Sps		} else if (num_logs(nvroot) > 0) {
57360786Sps			print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
57460786Sps		}
57560786Sps
57660786Sps		ret = 0;
57760786Sps	} else {
57860786Sps		ret = (zpool_add(zhp, nvroot) != 0);
57960786Sps	}
58060786Sps
58160786Sps	nvlist_free(nvroot);
58260786Sps	zpool_close(zhp);
58360786Sps
58460786Sps	return (ret);
58560786Sps}
58660786Sps
58760786Sps/*
58860786Sps * zpool remove  <pool> <vdev> ...
58960786Sps *
59060786Sps * Removes the given vdev from the pool.  Currently, this supports removing
59160786Sps * spares, cache, and log devices from the pool.
59260786Sps */
59360786Spsint
59460786Spszpool_do_remove(int argc, char **argv)
59560786Sps{
59660786Sps	char *poolname;
59760786Sps	int i, ret = 0;
59860786Sps	zpool_handle_t *zhp;
59960786Sps
60060786Sps	argc--;
60160786Sps	argv++;
60260786Sps
60360786Sps	/* get pool name and check number of arguments */
60460786Sps	if (argc < 1) {
60560786Sps		(void) fprintf(stderr, gettext("missing pool name argument\n"));
60660786Sps		usage(B_FALSE);
60760786Sps	}
60860786Sps	if (argc < 2) {
60960786Sps		(void) fprintf(stderr, gettext("missing device\n"));
61060786Sps		usage(B_FALSE);
61160786Sps	}
61260786Sps
61360786Sps	poolname = argv[0];
61460786Sps
61560786Sps	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
61660786Sps		return (1);
61760786Sps
61860786Sps	for (i = 1; i < argc; i++) {
61960786Sps		if (zpool_vdev_remove(zhp, argv[i]) != 0)
62060786Sps			ret = 1;
62160786Sps	}
62260786Sps
62360786Sps	return (ret);
62460786Sps}
62560786Sps
62660786Sps/*
62760786Sps * zpool labelclear <vdev>
62860786Sps *
62960786Sps * Verifies that the vdev is not active and zeros out the label information
63060786Sps * on the device.
63160786Sps */
63260786Spsint
63360786Spszpool_do_labelclear(int argc, char **argv)
63460786Sps{
63560786Sps	char *vdev, *name;
63660786Sps	int c, fd = -1, ret = 0;
63760786Sps	pool_state_t state;
63860786Sps	boolean_t inuse = B_FALSE;
63960786Sps	boolean_t force = B_FALSE;
64060786Sps
64160786Sps	/* check options */
64260786Sps	while ((c = getopt(argc, argv, "f")) != -1) {
64360786Sps		switch (c) {
64460786Sps		case 'f':
64560786Sps			force = B_TRUE;
64660786Sps			break;
64760786Sps		default:
64860786Sps			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
64960786Sps			    optopt);
65060786Sps			usage(B_FALSE);
65160786Sps		}
65260786Sps	}
65360786Sps
65460786Sps	argc -= optind;
65560786Sps	argv += optind;
65660786Sps
65760786Sps	/* get vdev name */
65860786Sps	if (argc < 1) {
65960786Sps		(void) fprintf(stderr, gettext("missing vdev device name\n"));
66060786Sps		usage(B_FALSE);
66160786Sps	}
66260786Sps
66360786Sps	vdev = argv[0];
66460786Sps	if ((fd = open(vdev, O_RDWR)) < 0) {
66560786Sps		(void) fprintf(stderr, gettext("Unable to open %s\n"), vdev);
66660786Sps		return (B_FALSE);
66760786Sps	}
66860786Sps
66960786Sps	name = NULL;
67060786Sps	if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0) {
67160786Sps		if (force)
67260786Sps			goto wipe_label;
67360786Sps
67460786Sps		(void) fprintf(stderr,
67560786Sps		    gettext("Unable to determine pool state for %s\n"
67660786Sps		    "Use -f to force the clearing any label data\n"), vdev);
67760786Sps
67860786Sps		return (1);
67960786Sps	}
68060786Sps
68160786Sps	if (inuse) {
68260786Sps		switch (state) {
68360786Sps		default:
68460786Sps		case POOL_STATE_ACTIVE:
68560786Sps		case POOL_STATE_SPARE:
68660786Sps		case POOL_STATE_L2CACHE:
68760786Sps			(void) fprintf(stderr,
68860786Spsgettext("labelclear operation failed.\n"
68960786Sps	"\tVdev %s is a member (%s), of pool \"%s\".\n"
69060786Sps	"\tTo remove label information from this device, export or destroy\n"
69160786Sps	"\tthe pool, or remove %s from the configuration of this pool\n"
69260786Sps	"\tand retry the labelclear operation\n"),
69360786Sps			    vdev, zpool_pool_state_to_name(state), name, vdev);
69460786Sps			ret = 1;
69560786Sps			goto errout;
69660786Sps
69760786Sps		case POOL_STATE_EXPORTED:
69860786Sps			if (force)
69960786Sps				break;
70060786Sps
70160786Sps			(void) fprintf(stderr,
70260786Spsgettext("labelclear operation failed.\n"
70360786Sps	"\tVdev %s is a member of the exported pool \"%s\".\n"
70460786Sps	"\tUse \"zpool labelclear -f %s\" to force the removal of label\n"
70560786Sps	"\tinformation.\n"),
70660786Sps			    vdev, name, vdev);
70760786Sps			ret = 1;
70860786Sps			goto errout;
70960786Sps
71060786Sps		case POOL_STATE_POTENTIALLY_ACTIVE:
71160786Sps			if (force)
71260786Sps				break;
71360786Sps
71460786Sps			(void) fprintf(stderr,
71560786Spsgettext("labelclear operation failed.\n"
71660786Sps	"\tVdev %s is a member of the pool \"%s\".\n"
71760786Sps	"\tThis pool is unknown to this system, but may be active on\n"
71860786Sps	"\tanother system. Use \'zpool labelclear -f %s\' to force the\n"
71960786Sps	"\tremoval of label information.\n"),
72060786Sps			    vdev, name, vdev);
72160786Sps			ret = 1;
72260786Sps			goto errout;
72360786Sps
72460786Sps		case POOL_STATE_DESTROYED:
72560786Sps			/* inuse should never be set for a destoryed pool... */
72660786Sps			break;
72760786Sps		}
72860786Sps	}
72960786Sps
73060786Spswipe_label:
73160786Sps	if (zpool_clear_label(fd) != 0) {
73260786Sps		(void) fprintf(stderr,
73360786Sps		    gettext("Label clear failed on vdev %s\n"), vdev);
73460786Sps		ret = 1;
73560786Sps	}
73660786Sps
73760786Spserrout:
73860786Sps	close(fd);
73960786Sps	if (name != NULL)
74060786Sps		free(name);
74160786Sps
74260786Sps	return (ret);
74360786Sps}
74460786Sps
74560786Sps/*
74660786Sps * zpool create [-fnd] [-o property=value] ...
74760786Sps *		[-O file-system-property=value] ...
74860786Sps *		[-R root] [-m mountpoint] <pool> <dev> ...
74960786Sps *
75060786Sps *	-f	Force creation, even if devices appear in use
75160786Sps *	-n	Do not create the pool, but display the resulting layout if it
75260786Sps *		were to be created.
75360786Sps *      -R	Create a pool under an alternate root
75460786Sps *      -m	Set default mountpoint for the root dataset.  By default it's
75560786Sps *		'/<pool>'
75660786Sps *	-o	Set property=value.
75760786Sps *	-d	Don't automatically enable all supported pool features
75860786Sps *		(individual features can be enabled with -o).
75960786Sps *	-O	Set fsproperty=value in the pool's root file system
76060786Sps *
76160786Sps * Creates the named pool according to the given vdev specification.  The
76260786Sps * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
76360786Sps * we get the nvlist back from get_vdev_spec(), we either print out the contents
76460786Sps * (if '-n' was specified), or pass it to libzfs to do the creation.
76560786Sps */
76660786Spsint
76760786Spszpool_do_create(int argc, char **argv)
76860786Sps{
76960786Sps	boolean_t force = B_FALSE;
77060786Sps	boolean_t dryrun = B_FALSE;
77160786Sps	boolean_t enable_all_pool_feat = B_TRUE;
77260786Sps	int c;
77360786Sps	nvlist_t *nvroot = NULL;
77460786Sps	char *poolname;
77560786Sps	int ret = 1;
77660786Sps	char *altroot = NULL;
77760786Sps	char *mountpoint = NULL;
77860786Sps	nvlist_t *fsprops = NULL;
77960786Sps	nvlist_t *props = NULL;
78060786Sps	char *propval;
78160786Sps
78260786Sps	/* check options */
78360786Sps	while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) {
78460786Sps		switch (c) {
78560786Sps		case 'f':
78660786Sps			force = B_TRUE;
78760786Sps			break;
78860786Sps		case 'n':
78960786Sps			dryrun = B_TRUE;
79060786Sps			break;
79160786Sps		case 'd':
79260786Sps			enable_all_pool_feat = B_FALSE;
79360786Sps			break;
79460786Sps		case 'R':
79560786Sps			altroot = optarg;
79660786Sps			if (add_prop_list(zpool_prop_to_name(
79760786Sps			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
79860786Sps				goto errout;
79960786Sps			if (nvlist_lookup_string(props,
80060786Sps			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
80160786Sps			    &propval) == 0)
80260786Sps				break;
80360786Sps			if (add_prop_list(zpool_prop_to_name(
80460786Sps			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
80560786Sps				goto errout;
80660786Sps			break;
80760786Sps		case 'm':
80860786Sps			/* Equivalent to -O mountpoint=optarg */
80960786Sps			mountpoint = optarg;
81060786Sps			break;
81160786Sps		case 'o':
81260786Sps			if ((propval = strchr(optarg, '=')) == NULL) {
81360786Sps				(void) fprintf(stderr, gettext("missing "
81460786Sps				    "'=' for -o option\n"));
81560786Sps				goto errout;
81660786Sps			}
81760786Sps			*propval = '\0';
81860786Sps			propval++;
81960786Sps
82060786Sps			if (add_prop_list(optarg, propval, &props, B_TRUE))
82160786Sps				goto errout;
82260786Sps
82360786Sps			/*
82460786Sps			 * If the user is creating a pool that doesn't support
82560786Sps			 * feature flags, don't enable any features.
82660786Sps			 */
82760786Sps			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
82860786Sps				char *end;
82960786Sps				u_longlong_t ver;
83060786Sps
83160786Sps				ver = strtoull(propval, &end, 10);
83260786Sps				if (*end == '\0' &&
83360786Sps				    ver < SPA_VERSION_FEATURES) {
83460786Sps					enable_all_pool_feat = B_FALSE;
83560786Sps				}
83660786Sps			}
83760786Sps			if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
83860786Sps				altroot = propval;
83960786Sps			break;
84060786Sps		case 'O':
84160786Sps			if ((propval = strchr(optarg, '=')) == NULL) {
84260786Sps				(void) fprintf(stderr, gettext("missing "
84360786Sps				    "'=' for -O option\n"));
84460786Sps				goto errout;
84560786Sps			}
84660786Sps			*propval = '\0';
84760786Sps			propval++;
84860786Sps
84960786Sps			/*
85060786Sps			 * Mountpoints are checked and then added later.
85160786Sps			 * Uniquely among properties, they can be specified
85260786Sps			 * more than once, to avoid conflict with -m.
85360786Sps			 */
85460786Sps			if (0 == strcmp(optarg,
85560786Sps			    zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
85660786Sps				mountpoint = propval;
85760786Sps			} else if (add_prop_list(optarg, propval, &fsprops,
85860786Sps			    B_FALSE)) {
85960786Sps				goto errout;
86060786Sps			}
86160786Sps			break;
86260786Sps		case ':':
86360786Sps			(void) fprintf(stderr, gettext("missing argument for "
86460786Sps			    "'%c' option\n"), optopt);
86560786Sps			goto badusage;
86660786Sps		case '?':
86760786Sps			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
86860786Sps			    optopt);
86960786Sps			goto badusage;
87060786Sps		}
87160786Sps	}
87260786Sps
87360786Sps	argc -= optind;
87460786Sps	argv += optind;
87560786Sps
87660786Sps	/* get pool name and check number of arguments */
87760786Sps	if (argc < 1) {
87860786Sps		(void) fprintf(stderr, gettext("missing pool name argument\n"));
87960786Sps		goto badusage;
88060786Sps	}
88160786Sps	if (argc < 2) {
88260786Sps		(void) fprintf(stderr, gettext("missing vdev specification\n"));
88360786Sps		goto badusage;
88460786Sps	}
88560786Sps
88660786Sps	poolname = argv[0];
88760786Sps
88860786Sps	/*
88960786Sps	 * As a special case, check for use of '/' in the name, and direct the
89060786Sps	 * user to use 'zfs create' instead.
89160786Sps	 */
89260786Sps	if (strchr(poolname, '/') != NULL) {
89360786Sps		(void) fprintf(stderr, gettext("cannot create '%s': invalid "
89460786Sps		    "character '/' in pool name\n"), poolname);
89560786Sps		(void) fprintf(stderr, gettext("use 'zfs create' to "
89660786Sps		    "create a dataset\n"));
89760786Sps		goto errout;
89860786Sps	}
89960786Sps
90060786Sps	/* pass off to get_vdev_spec for bulk processing */
90160786Sps	nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
90260786Sps	    argc - 1, argv + 1);
90360786Sps	if (nvroot == NULL)
90460786Sps		goto errout;
90560786Sps
90660786Sps	/* make_root_vdev() allows 0 toplevel children if there are spares */
90760786Sps	if (!zfs_allocatable_devs(nvroot)) {
90860786Sps		(void) fprintf(stderr, gettext("invalid vdev "
90960786Sps		    "specification: at least one toplevel vdev must be "
91060786Sps		    "specified\n"));
91160786Sps		goto errout;
91260786Sps	}
91360786Sps
91460786Sps	if (altroot != NULL && altroot[0] != '/') {
91560786Sps		(void) fprintf(stderr, gettext("invalid alternate root '%s': "
91660786Sps		    "must be an absolute path\n"), altroot);
91760786Sps		goto errout;
91860786Sps	}
91960786Sps
92060786Sps	/*
92160786Sps	 * Check the validity of the mountpoint and direct the user to use the
92260786Sps	 * '-m' mountpoint option if it looks like its in use.
92360786Sps	 * Ignore the checks if the '-f' option is given.
92460786Sps	 */
92560786Sps	if (!force && (mountpoint == NULL ||
92660786Sps	    (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
92760786Sps	    strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) {
92860786Sps		char buf[MAXPATHLEN];
92960786Sps		DIR *dirp;
93060786Sps
93160786Sps		if (mountpoint && mountpoint[0] != '/') {
93260786Sps			(void) fprintf(stderr, gettext("invalid mountpoint "
93360786Sps			    "'%s': must be an absolute path, 'legacy', or "
93460786Sps			    "'none'\n"), mountpoint);
93560786Sps			goto errout;
93660786Sps		}
93760786Sps
93860786Sps		if (mountpoint == NULL) {
93960786Sps			if (altroot != NULL)
94060786Sps				(void) snprintf(buf, sizeof (buf), "%s/%s",
94160786Sps				    altroot, poolname);
94260786Sps			else
94360786Sps				(void) snprintf(buf, sizeof (buf), "/%s",
94460786Sps				    poolname);
94560786Sps		} else {
94660786Sps			if (altroot != NULL)
94760786Sps				(void) snprintf(buf, sizeof (buf), "%s%s",
94860786Sps				    altroot, mountpoint);
94960786Sps			else
95060786Sps				(void) snprintf(buf, sizeof (buf), "%s",
95160786Sps				    mountpoint);
95260786Sps		}
95360786Sps
95460786Sps		if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
95560786Sps			(void) fprintf(stderr, gettext("mountpoint '%s' : "
95660786Sps			    "%s\n"), buf, strerror(errno));
95760786Sps			(void) fprintf(stderr, gettext("use '-m' "
95860786Sps			    "option to provide a different default\n"));
95960786Sps			goto errout;
96060786Sps		} else if (dirp) {
96160786Sps			int count = 0;
96260786Sps
96360786Sps			while (count < 3 && readdir(dirp) != NULL)
96460786Sps				count++;
96560786Sps			(void) closedir(dirp);
96660786Sps
96760786Sps			if (count > 2) {
96860786Sps				(void) fprintf(stderr, gettext("mountpoint "
96960786Sps				    "'%s' exists and is not empty\n"), buf);
97060786Sps				(void) fprintf(stderr, gettext("use '-m' "
97160786Sps				    "option to provide a "
97260786Sps				    "different default\n"));
97360786Sps				goto errout;
97460786Sps			}
97560786Sps		}
97660786Sps	}
97760786Sps
97860786Sps	/*
97960786Sps	 * Now that the mountpoint's validity has been checked, ensure that
98060786Sps	 * the property is set appropriately prior to creating the pool.
98160786Sps	 */
98260786Sps	if (mountpoint != NULL) {
98360786Sps		ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
98460786Sps		    mountpoint, &fsprops, B_FALSE);
98560786Sps		if (ret != 0)
98660786Sps			goto errout;
98760786Sps	}
98860786Sps
98960786Sps	ret = 1;
99060786Sps	if (dryrun) {
99160786Sps		/*
99260786Sps		 * For a dry run invocation, print out a basic message and run
99360786Sps		 * through all the vdevs in the list and print out in an
99460786Sps		 * appropriate hierarchy.
99560786Sps		 */
99660786Sps		(void) printf(gettext("would create '%s' with the "
99760786Sps		    "following layout:\n\n"), poolname);
99860786Sps
99960786Sps		print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
100060786Sps		if (num_logs(nvroot) > 0)
100160786Sps			print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
100260786Sps
100360786Sps		ret = 0;
100460786Sps	} else {
100560786Sps		/*
100660786Sps		 * Hand off to libzfs.
100760786Sps		 */
100860786Sps		if (enable_all_pool_feat) {
100960786Sps			spa_feature_t i;
101060786Sps			for (i = 0; i < SPA_FEATURES; i++) {
101160786Sps				char propname[MAXPATHLEN];
101260786Sps				zfeature_info_t *feat = &spa_feature_table[i];
101360786Sps
101460786Sps				(void) snprintf(propname, sizeof (propname),
101560786Sps				    "feature@%s", feat->fi_uname);
101660786Sps
101760786Sps				/*
101860786Sps				 * Skip feature if user specified it manually
101960786Sps				 * on the command line.
102060786Sps				 */
102160786Sps				if (nvlist_exists(props, propname))
102260786Sps					continue;
102360786Sps
102460786Sps				ret = add_prop_list(propname,
102560786Sps				    ZFS_FEATURE_ENABLED, &props, B_TRUE);
102660786Sps				if (ret != 0)
102760786Sps					goto errout;
102860786Sps			}
102960786Sps		}
103060786Sps
103160786Sps		ret = 1;
103260786Sps		if (zpool_create(g_zfs, poolname,
103360786Sps		    nvroot, props, fsprops) == 0) {
103460786Sps			zfs_handle_t *pool = zfs_open(g_zfs, poolname,
103560786Sps			    ZFS_TYPE_FILESYSTEM);
103660786Sps			if (pool != NULL) {
103760786Sps				if (zfs_mount(pool, NULL, 0) == 0)
103860786Sps					ret = zfs_shareall(pool);
103960786Sps				zfs_close(pool);
104060786Sps			}
104160786Sps		} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
104260786Sps			(void) fprintf(stderr, gettext("pool name may have "
104360786Sps			    "been omitted\n"));
104460786Sps		}
104560786Sps	}
104660786Sps
104760786Spserrout:
104860786Sps	nvlist_free(nvroot);
104960786Sps	nvlist_free(fsprops);
105060786Sps	nvlist_free(props);
105160786Sps	return (ret);
105260786Spsbadusage:
105360786Sps	nvlist_free(fsprops);
105460786Sps	nvlist_free(props);
105560786Sps	usage(B_FALSE);
105660786Sps	return (2);
105760786Sps}
105860786Sps
105960786Sps/*
106060786Sps * zpool destroy <pool>
106160786Sps *
106260786Sps * 	-f	Forcefully unmount any datasets
106360786Sps *
106460786Sps * Destroy the given pool.  Automatically unmounts any datasets in the pool.
106560786Sps */
106660786Spsint
106760786Spszpool_do_destroy(int argc, char **argv)
106860786Sps{
106960786Sps	boolean_t force = B_FALSE;
107060786Sps	int c;
107160786Sps	char *pool;
107260786Sps	zpool_handle_t *zhp;
107360786Sps	int ret;
107460786Sps
107560786Sps	/* check options */
107660786Sps	while ((c = getopt(argc, argv, "f")) != -1) {
107760786Sps		switch (c) {
107860786Sps		case 'f':
107960786Sps			force = B_TRUE;
108060786Sps			break;
108160786Sps		case '?':
108260786Sps			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
108360786Sps			    optopt);
108460786Sps			usage(B_FALSE);
108560786Sps		}
108660786Sps	}
108760786Sps
108860786Sps	argc -= optind;
108960786Sps	argv += optind;
109060786Sps
109160786Sps	/* check arguments */
109260786Sps	if (argc < 1) {
109360786Sps		(void) fprintf(stderr, gettext("missing pool argument\n"));
109460786Sps		usage(B_FALSE);
109560786Sps	}
109660786Sps	if (argc > 1) {
109760786Sps		(void) fprintf(stderr, gettext("too many arguments\n"));
109860786Sps		usage(B_FALSE);
109960786Sps	}
110060786Sps
110160786Sps	pool = argv[0];
110260786Sps
110360786Sps	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
110460786Sps		/*
110560786Sps		 * As a special case, check for use of '/' in the name, and
110660786Sps		 * direct the user to use 'zfs destroy' instead.
110760786Sps		 */
110860786Sps		if (strchr(pool, '/') != NULL)
110960786Sps			(void) fprintf(stderr, gettext("use 'zfs destroy' to "
111060786Sps			    "destroy a dataset\n"));
111160786Sps		return (1);
111260786Sps	}
111360786Sps
111460786Sps	if (zpool_disable_datasets(zhp, force) != 0) {
111560786Sps		(void) fprintf(stderr, gettext("could not destroy '%s': "
111660786Sps		    "could not unmount datasets\n"), zpool_get_name(zhp));
111760786Sps		return (1);
111860786Sps	}
111960786Sps
112060786Sps	/* The history must be logged as part of the export */
112160786Sps	log_history = B_FALSE;
112260786Sps
112360786Sps	ret = (zpool_destroy(zhp, history_str) != 0);
112460786Sps
112560786Sps	zpool_close(zhp);
112660786Sps
112760786Sps	return (ret);
112860786Sps}
112960786Sps
113060786Sps/*
113160786Sps * zpool export [-f] <pool> ...
113260786Sps *
113360786Sps *	-f	Forcefully unmount datasets
113460786Sps *
113560786Sps * Export the given pools.  By default, the command will attempt to cleanly
113660786Sps * unmount any active datasets within the pool.  If the '-f' flag is specified,
113760786Sps * then the datasets will be forcefully unmounted.
113860786Sps */
113960786Spsint
114060786Spszpool_do_export(int argc, char **argv)
114160786Sps{
114260786Sps	boolean_t force = B_FALSE;
114360786Sps	boolean_t hardforce = B_FALSE;
114460786Sps	int c;
114560786Sps	zpool_handle_t *zhp;
114660786Sps	int ret;
114760786Sps	int i;
114860786Sps
114960786Sps	/* check options */
115060786Sps	while ((c = getopt(argc, argv, "fF")) != -1) {
115160786Sps		switch (c) {
115260786Sps		case 'f':
115360786Sps			force = B_TRUE;
115460786Sps			break;
115560786Sps		case 'F':
115660786Sps			hardforce = B_TRUE;
115760786Sps			break;
115860786Sps		case '?':
115960786Sps			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
116060786Sps			    optopt);
116160786Sps			usage(B_FALSE);
116260786Sps		}
116360786Sps	}
116460786Sps
116560786Sps	argc -= optind;
116660786Sps	argv += optind;
116760786Sps
116860786Sps	/* check arguments */
116960786Sps	if (argc < 1) {
117060786Sps		(void) fprintf(stderr, gettext("missing pool argument\n"));
117160786Sps		usage(B_FALSE);
117260786Sps	}
117360786Sps
117460786Sps	ret = 0;
117560786Sps	for (i = 0; i < argc; i++) {
117660786Sps		if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
117760786Sps			ret = 1;
117860786Sps			continue;
117960786Sps		}
118060786Sps
118160786Sps		if (zpool_disable_datasets(zhp, force) != 0) {
118260786Sps			ret = 1;
118360786Sps			zpool_close(zhp);
118460786Sps			continue;
118560786Sps		}
118660786Sps
118760786Sps		/* The history must be logged as part of the export */
118860786Sps		log_history = B_FALSE;
118960786Sps
119060786Sps		if (hardforce) {
119160786Sps			if (zpool_export_force(zhp, history_str) != 0)
119260786Sps				ret = 1;
119360786Sps		} else if (zpool_export(zhp, force, history_str) != 0) {
119460786Sps			ret = 1;
119560786Sps		}
119660786Sps
119760786Sps		zpool_close(zhp);
119860786Sps	}
119960786Sps
120060786Sps	return (ret);
120160786Sps}
120260786Sps
120360786Sps/*
120460786Sps * Given a vdev configuration, determine the maximum width needed for the device
120560786Sps * name column.
120660786Sps */
120760786Spsstatic int
120860786Spsmax_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
120960786Sps{
121060786Sps	char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
121160786Sps	nvlist_t **child;
121260786Sps	uint_t c, children;
121360786Sps	int ret;
121460786Sps
121560786Sps	if (strlen(name) + depth > max)
121660786Sps		max = strlen(name) + depth;
121760786Sps
121860786Sps	free(name);
121960786Sps
122060786Sps	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
122160786Sps	    &child, &children) == 0) {
122260786Sps		for (c = 0; c < children; c++)
122360786Sps			if ((ret = max_width(zhp, child[c], depth + 2,
122460786Sps			    max)) > max)
122560786Sps				max = ret;
122660786Sps	}
122760786Sps
122860786Sps	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
122960786Sps	    &child, &children) == 0) {
123060786Sps		for (c = 0; c < children; c++)
123160786Sps			if ((ret = max_width(zhp, child[c], depth + 2,
123260786Sps			    max)) > max)
123360786Sps				max = ret;
123460786Sps	}
123560786Sps
123660786Sps	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
123760786Sps	    &child, &children) == 0) {
123860786Sps		for (c = 0; c < children; c++)
123960786Sps			if ((ret = max_width(zhp, child[c], depth + 2,
124060786Sps			    max)) > max)
124160786Sps				max = ret;
124260786Sps	}
124360786Sps
124460786Sps
124560786Sps	return (max);
124660786Sps}
124760786Sps
124860786Spstypedef struct spare_cbdata {
124960786Sps	uint64_t	cb_guid;
125060786Sps	zpool_handle_t	*cb_zhp;
125160786Sps} spare_cbdata_t;
125260786Sps
125360786Spsstatic boolean_t
125460786Spsfind_vdev(nvlist_t *nv, uint64_t search)
125560786Sps{
125660786Sps	uint64_t guid;
125760786Sps	nvlist_t **child;
125860786Sps	uint_t c, children;
125960786Sps
126060786Sps	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
126160786Sps	    search == guid)
126260786Sps		return (B_TRUE);
126360786Sps
126460786Sps	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
126560786Sps	    &child, &children) == 0) {
126660786Sps		for (c = 0; c < children; c++)
126760786Sps			if (find_vdev(child[c], search))
126860786Sps				return (B_TRUE);
126960786Sps	}
127060786Sps
127160786Sps	return (B_FALSE);
127260786Sps}
127360786Sps
127460786Spsstatic int
127560786Spsfind_spare(zpool_handle_t *zhp, void *data)
127660786Sps{
127760786Sps	spare_cbdata_t *cbp = data;
127860786Sps	nvlist_t *config, *nvroot;
127960786Sps
128060786Sps	config = zpool_get_config(zhp, NULL);
128160786Sps	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
128260786Sps	    &nvroot) == 0);
128360786Sps
128460786Sps	if (find_vdev(nvroot, cbp->cb_guid)) {
128560786Sps		cbp->cb_zhp = zhp;
128660786Sps		return (1);
128760786Sps	}
128860786Sps
128960786Sps	zpool_close(zhp);
129060786Sps	return (0);
129160786Sps}
129260786Sps
129360786Sps/*
129460786Sps * Print out configuration state as requested by status_callback.
129560786Sps */
129660786Spsvoid
129760786Spsprint_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
129860786Sps    int namewidth, int depth, boolean_t isspare)
129960786Sps{
130060786Sps	nvlist_t **child;
130160786Sps	uint_t c, vsc, children;
130260786Sps	pool_scan_stat_t *ps = NULL;
130360786Sps	vdev_stat_t *vs;
130460786Sps	char rbuf[6], wbuf[6], cbuf[6];
130560786Sps	char *vname;
130660786Sps	uint64_t notpresent;
130760786Sps	uint64_t ashift;
130860786Sps	spare_cbdata_t cb;
130960786Sps	const char *state;
131060786Sps
131160786Sps	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
131260786Sps	    &child, &children) != 0)
131360786Sps		children = 0;
131460786Sps
131560786Sps	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
131660786Sps	    (uint64_t **)&vs, &vsc) == 0);
131760786Sps
131860786Sps	state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
131960786Sps	if (isspare) {
132060786Sps		/*
132160786Sps		 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
132260786Sps		 * online drives.
132360786Sps		 */
132460786Sps		if (vs->vs_aux == VDEV_AUX_SPARED)
132560786Sps			state = "INUSE";
132660786Sps		else if (vs->vs_state == VDEV_STATE_HEALTHY)
132760786Sps			state = "AVAIL";
132860786Sps	}
132960786Sps
133060786Sps	(void) printf("\t%*s%-*s  %-8s", depth, "", namewidth - depth,
133160786Sps	    name, state);
133260786Sps
133360786Sps	if (!isspare) {
133460786Sps		zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
133560786Sps		zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
133660786Sps		zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
133760786Sps		(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
133860786Sps	}
133960786Sps
134060786Sps	if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
134160786Sps	    &notpresent) == 0 ||
134260786Sps	    vs->vs_state <= VDEV_STATE_CANT_OPEN) {
134360786Sps		char *path;
134460786Sps		if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0)
134560786Sps			(void) printf("  was %s", path);
134660786Sps	} else if (vs->vs_aux != 0) {
134760786Sps		(void) printf("  ");
134860786Sps
134960786Sps		switch (vs->vs_aux) {
135060786Sps		case VDEV_AUX_OPEN_FAILED:
135160786Sps			(void) printf(gettext("cannot open"));
135260786Sps			break;
135360786Sps
135460786Sps		case VDEV_AUX_BAD_GUID_SUM:
135560786Sps			(void) printf(gettext("missing device"));
135660786Sps			break;
135760786Sps
135860786Sps		case VDEV_AUX_NO_REPLICAS:
135960786Sps			(void) printf(gettext("insufficient replicas"));
136060786Sps			break;
136160786Sps
136260786Sps		case VDEV_AUX_VERSION_NEWER:
136360786Sps			(void) printf(gettext("newer version"));
1364			break;
1365
1366		case VDEV_AUX_UNSUP_FEAT:
1367			(void) printf(gettext("unsupported feature(s)"));
1368			break;
1369
1370		case VDEV_AUX_ASHIFT_TOO_BIG:
1371			(void) printf(gettext("unsupported minimum blocksize"));
1372			break;
1373
1374		case VDEV_AUX_SPARED:
1375			verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1376			    &cb.cb_guid) == 0);
1377			if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1378				if (strcmp(zpool_get_name(cb.cb_zhp),
1379				    zpool_get_name(zhp)) == 0)
1380					(void) printf(gettext("currently in "
1381					    "use"));
1382				else
1383					(void) printf(gettext("in use by "
1384					    "pool '%s'"),
1385					    zpool_get_name(cb.cb_zhp));
1386				zpool_close(cb.cb_zhp);
1387			} else {
1388				(void) printf(gettext("currently in use"));
1389			}
1390			break;
1391
1392		case VDEV_AUX_ERR_EXCEEDED:
1393			(void) printf(gettext("too many errors"));
1394			break;
1395
1396		case VDEV_AUX_IO_FAILURE:
1397			(void) printf(gettext("experienced I/O failures"));
1398			break;
1399
1400		case VDEV_AUX_BAD_LOG:
1401			(void) printf(gettext("bad intent log"));
1402			break;
1403
1404		case VDEV_AUX_EXTERNAL:
1405			(void) printf(gettext("external device fault"));
1406			break;
1407
1408		case VDEV_AUX_SPLIT_POOL:
1409			(void) printf(gettext("split into new pool"));
1410			break;
1411
1412		default:
1413			(void) printf(gettext("corrupted data"));
1414			break;
1415		}
1416	} else if (children == 0 && !isspare &&
1417	    VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
1418	    vs->vs_configured_ashift < vs->vs_physical_ashift) {
1419		(void) printf(
1420		    gettext("  block size: %dB configured, %dB native"),
1421		    1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
1422	}
1423
1424	(void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1425	    (uint64_t **)&ps, &c);
1426
1427	if (ps && ps->pss_state == DSS_SCANNING &&
1428	    vs->vs_scan_processed != 0 && children == 0) {
1429		(void) printf(gettext("  (%s)"),
1430		    (ps->pss_func == POOL_SCAN_RESILVER) ?
1431		    "resilvering" : "repairing");
1432	}
1433
1434	(void) printf("\n");
1435
1436	for (c = 0; c < children; c++) {
1437		uint64_t islog = B_FALSE, ishole = B_FALSE;
1438
1439		/* Don't print logs or holes here */
1440		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1441		    &islog);
1442		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1443		    &ishole);
1444		if (islog || ishole)
1445			continue;
1446		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1447		print_status_config(zhp, vname, child[c],
1448		    namewidth, depth + 2, isspare);
1449		free(vname);
1450	}
1451}
1452
1453
1454/*
1455 * Print the configuration of an exported pool.  Iterate over all vdevs in the
1456 * pool, printing out the name and status for each one.
1457 */
1458void
1459print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1460{
1461	nvlist_t **child;
1462	uint_t c, children;
1463	vdev_stat_t *vs;
1464	char *type, *vname;
1465
1466	verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1467	if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1468	    strcmp(type, VDEV_TYPE_HOLE) == 0)
1469		return;
1470
1471	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1472	    (uint64_t **)&vs, &c) == 0);
1473
1474	(void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1475	(void) printf("  %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1476
1477	if (vs->vs_aux != 0) {
1478		(void) printf("  ");
1479
1480		switch (vs->vs_aux) {
1481		case VDEV_AUX_OPEN_FAILED:
1482			(void) printf(gettext("cannot open"));
1483			break;
1484
1485		case VDEV_AUX_BAD_GUID_SUM:
1486			(void) printf(gettext("missing device"));
1487			break;
1488
1489		case VDEV_AUX_NO_REPLICAS:
1490			(void) printf(gettext("insufficient replicas"));
1491			break;
1492
1493		case VDEV_AUX_VERSION_NEWER:
1494			(void) printf(gettext("newer version"));
1495			break;
1496
1497		case VDEV_AUX_UNSUP_FEAT:
1498			(void) printf(gettext("unsupported feature(s)"));
1499			break;
1500
1501		case VDEV_AUX_ERR_EXCEEDED:
1502			(void) printf(gettext("too many errors"));
1503			break;
1504
1505		default:
1506			(void) printf(gettext("corrupted data"));
1507			break;
1508		}
1509	}
1510	(void) printf("\n");
1511
1512	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1513	    &child, &children) != 0)
1514		return;
1515
1516	for (c = 0; c < children; c++) {
1517		uint64_t is_log = B_FALSE;
1518
1519		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1520		    &is_log);
1521		if (is_log)
1522			continue;
1523
1524		vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1525		print_import_config(vname, child[c], namewidth, depth + 2);
1526		free(vname);
1527	}
1528
1529	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1530	    &child, &children) == 0) {
1531		(void) printf(gettext("\tcache\n"));
1532		for (c = 0; c < children; c++) {
1533			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1534			(void) printf("\t  %s\n", vname);
1535			free(vname);
1536		}
1537	}
1538
1539	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1540	    &child, &children) == 0) {
1541		(void) printf(gettext("\tspares\n"));
1542		for (c = 0; c < children; c++) {
1543			vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1544			(void) printf("\t  %s\n", vname);
1545			free(vname);
1546		}
1547	}
1548}
1549
1550/*
1551 * Print log vdevs.
1552 * Logs are recorded as top level vdevs in the main pool child array
1553 * but with "is_log" set to 1. We use either print_status_config() or
1554 * print_import_config() to print the top level logs then any log
1555 * children (eg mirrored slogs) are printed recursively - which
1556 * works because only the top level vdev is marked "is_log"
1557 */
1558static void
1559print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1560{
1561	uint_t c, children;
1562	nvlist_t **child;
1563
1564	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1565	    &children) != 0)
1566		return;
1567
1568	(void) printf(gettext("\tlogs\n"));
1569
1570	for (c = 0; c < children; c++) {
1571		uint64_t is_log = B_FALSE;
1572		char *name;
1573
1574		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1575		    &is_log);
1576		if (!is_log)
1577			continue;
1578		name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1579		if (verbose)
1580			print_status_config(zhp, name, child[c], namewidth,
1581			    2, B_FALSE);
1582		else
1583			print_import_config(name, child[c], namewidth, 2);
1584		free(name);
1585	}
1586}
1587
1588/*
1589 * Display the status for the given pool.
1590 */
1591static void
1592show_import(nvlist_t *config)
1593{
1594	uint64_t pool_state;
1595	vdev_stat_t *vs;
1596	char *name;
1597	uint64_t guid;
1598	char *msgid;
1599	nvlist_t *nvroot;
1600	int reason;
1601	const char *health;
1602	uint_t vsc;
1603	int namewidth;
1604	char *comment;
1605
1606	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1607	    &name) == 0);
1608	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1609	    &guid) == 0);
1610	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1611	    &pool_state) == 0);
1612	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1613	    &nvroot) == 0);
1614
1615	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1616	    (uint64_t **)&vs, &vsc) == 0);
1617	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1618
1619	reason = zpool_import_status(config, &msgid);
1620
1621	(void) printf(gettext("   pool: %s\n"), name);
1622	(void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
1623	(void) printf(gettext("  state: %s"), health);
1624	if (pool_state == POOL_STATE_DESTROYED)
1625		(void) printf(gettext(" (DESTROYED)"));
1626	(void) printf("\n");
1627
1628	switch (reason) {
1629	case ZPOOL_STATUS_MISSING_DEV_R:
1630	case ZPOOL_STATUS_MISSING_DEV_NR:
1631	case ZPOOL_STATUS_BAD_GUID_SUM:
1632		(void) printf(gettext(" status: One or more devices are "
1633		    "missing from the system.\n"));
1634		break;
1635
1636	case ZPOOL_STATUS_CORRUPT_LABEL_R:
1637	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1638		(void) printf(gettext(" status: One or more devices contains "
1639		    "corrupted data.\n"));
1640		break;
1641
1642	case ZPOOL_STATUS_CORRUPT_DATA:
1643		(void) printf(
1644		    gettext(" status: The pool data is corrupted.\n"));
1645		break;
1646
1647	case ZPOOL_STATUS_OFFLINE_DEV:
1648		(void) printf(gettext(" status: One or more devices "
1649		    "are offlined.\n"));
1650		break;
1651
1652	case ZPOOL_STATUS_CORRUPT_POOL:
1653		(void) printf(gettext(" status: The pool metadata is "
1654		    "corrupted.\n"));
1655		break;
1656
1657	case ZPOOL_STATUS_VERSION_OLDER:
1658		(void) printf(gettext(" status: The pool is formatted using a "
1659		    "legacy on-disk version.\n"));
1660		break;
1661
1662	case ZPOOL_STATUS_VERSION_NEWER:
1663		(void) printf(gettext(" status: The pool is formatted using an "
1664		    "incompatible version.\n"));
1665		break;
1666
1667	case ZPOOL_STATUS_FEAT_DISABLED:
1668		(void) printf(gettext(" status: Some supported features are "
1669		    "not enabled on the pool.\n"));
1670		break;
1671
1672	case ZPOOL_STATUS_UNSUP_FEAT_READ:
1673		(void) printf(gettext("status: The pool uses the following "
1674		    "feature(s) not supported on this sytem:\n"));
1675		zpool_print_unsup_feat(config);
1676		break;
1677
1678	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1679		(void) printf(gettext("status: The pool can only be accessed "
1680		    "in read-only mode on this system. It\n\tcannot be "
1681		    "accessed in read-write mode because it uses the "
1682		    "following\n\tfeature(s) not supported on this system:\n"));
1683		zpool_print_unsup_feat(config);
1684		break;
1685
1686	case ZPOOL_STATUS_HOSTID_MISMATCH:
1687		(void) printf(gettext(" status: The pool was last accessed by "
1688		    "another system.\n"));
1689		break;
1690
1691	case ZPOOL_STATUS_FAULTED_DEV_R:
1692	case ZPOOL_STATUS_FAULTED_DEV_NR:
1693		(void) printf(gettext(" status: One or more devices are "
1694		    "faulted.\n"));
1695		break;
1696
1697	case ZPOOL_STATUS_BAD_LOG:
1698		(void) printf(gettext(" status: An intent log record cannot be "
1699		    "read.\n"));
1700		break;
1701
1702	case ZPOOL_STATUS_RESILVERING:
1703		(void) printf(gettext(" status: One or more devices were being "
1704		    "resilvered.\n"));
1705		break;
1706
1707	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
1708		(void) printf(gettext("status: One or more devices were "
1709		    "configured to use a non-native block size.\n"
1710		    "\tExpect reduced performance.\n"));
1711		break;
1712
1713	default:
1714		/*
1715		 * No other status can be seen when importing pools.
1716		 */
1717		assert(reason == ZPOOL_STATUS_OK);
1718	}
1719
1720	/*
1721	 * Print out an action according to the overall state of the pool.
1722	 */
1723	if (vs->vs_state == VDEV_STATE_HEALTHY) {
1724		if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1725		    reason == ZPOOL_STATUS_FEAT_DISABLED) {
1726			(void) printf(gettext(" action: The pool can be "
1727			    "imported using its name or numeric identifier, "
1728			    "though\n\tsome features will not be available "
1729			    "without an explicit 'zpool upgrade'.\n"));
1730		} else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1731			(void) printf(gettext(" action: The pool can be "
1732			    "imported using its name or numeric "
1733			    "identifier and\n\tthe '-f' flag.\n"));
1734		} else {
1735			(void) printf(gettext(" action: The pool can be "
1736			    "imported using its name or numeric "
1737			    "identifier.\n"));
1738		}
1739	} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1740		(void) printf(gettext(" action: The pool can be imported "
1741		    "despite missing or damaged devices.  The\n\tfault "
1742		    "tolerance of the pool may be compromised if imported.\n"));
1743	} else {
1744		switch (reason) {
1745		case ZPOOL_STATUS_VERSION_NEWER:
1746			(void) printf(gettext(" action: The pool cannot be "
1747			    "imported.  Access the pool on a system running "
1748			    "newer\n\tsoftware, or recreate the pool from "
1749			    "backup.\n"));
1750			break;
1751		case ZPOOL_STATUS_UNSUP_FEAT_READ:
1752			(void) printf(gettext("action: The pool cannot be "
1753			    "imported. Access the pool on a system that "
1754			    "supports\n\tthe required feature(s), or recreate "
1755			    "the pool from backup.\n"));
1756			break;
1757		case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1758			(void) printf(gettext("action: The pool cannot be "
1759			    "imported in read-write mode. Import the pool "
1760			    "with\n"
1761			    "\t\"-o readonly=on\", access the pool on a system "
1762			    "that supports the\n\trequired feature(s), or "
1763			    "recreate the pool from backup.\n"));
1764			break;
1765		case ZPOOL_STATUS_MISSING_DEV_R:
1766		case ZPOOL_STATUS_MISSING_DEV_NR:
1767		case ZPOOL_STATUS_BAD_GUID_SUM:
1768			(void) printf(gettext(" action: The pool cannot be "
1769			    "imported. Attach the missing\n\tdevices and try "
1770			    "again.\n"));
1771			break;
1772		default:
1773			(void) printf(gettext(" action: The pool cannot be "
1774			    "imported due to damaged devices or data.\n"));
1775		}
1776	}
1777
1778	/* Print the comment attached to the pool. */
1779	if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1780		(void) printf(gettext("comment: %s\n"), comment);
1781
1782	/*
1783	 * If the state is "closed" or "can't open", and the aux state
1784	 * is "corrupt data":
1785	 */
1786	if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1787	    (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1788	    (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1789		if (pool_state == POOL_STATE_DESTROYED)
1790			(void) printf(gettext("\tThe pool was destroyed, "
1791			    "but can be imported using the '-Df' flags.\n"));
1792		else if (pool_state != POOL_STATE_EXPORTED)
1793			(void) printf(gettext("\tThe pool may be active on "
1794			    "another system, but can be imported using\n\t"
1795			    "the '-f' flag.\n"));
1796	}
1797
1798	if (msgid != NULL)
1799		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
1800		    msgid);
1801
1802	(void) printf(gettext(" config:\n\n"));
1803
1804	namewidth = max_width(NULL, nvroot, 0, 0);
1805	if (namewidth < 10)
1806		namewidth = 10;
1807
1808	print_import_config(name, nvroot, namewidth, 0);
1809	if (num_logs(nvroot) > 0)
1810		print_logs(NULL, nvroot, namewidth, B_FALSE);
1811
1812	if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1813		(void) printf(gettext("\n\tAdditional devices are known to "
1814		    "be part of this pool, though their\n\texact "
1815		    "configuration cannot be determined.\n"));
1816	}
1817}
1818
1819/*
1820 * Perform the import for the given configuration.  This passes the heavy
1821 * lifting off to zpool_import_props(), and then mounts the datasets contained
1822 * within the pool.
1823 */
1824static int
1825do_import(nvlist_t *config, const char *newname, const char *mntopts,
1826    nvlist_t *props, int flags)
1827{
1828	zpool_handle_t *zhp;
1829	char *name;
1830	uint64_t state;
1831	uint64_t version;
1832
1833	verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1834	    &name) == 0);
1835
1836	verify(nvlist_lookup_uint64(config,
1837	    ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1838	verify(nvlist_lookup_uint64(config,
1839	    ZPOOL_CONFIG_VERSION, &version) == 0);
1840	if (!SPA_VERSION_IS_SUPPORTED(version)) {
1841		(void) fprintf(stderr, gettext("cannot import '%s': pool "
1842		    "is formatted using an unsupported ZFS version\n"), name);
1843		return (1);
1844	} else if (state != POOL_STATE_EXPORTED &&
1845	    !(flags & ZFS_IMPORT_ANY_HOST)) {
1846		uint64_t hostid;
1847
1848		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1849		    &hostid) == 0) {
1850			if ((unsigned long)hostid != gethostid()) {
1851				char *hostname;
1852				uint64_t timestamp;
1853				time_t t;
1854
1855				verify(nvlist_lookup_string(config,
1856				    ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1857				verify(nvlist_lookup_uint64(config,
1858				    ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1859				t = timestamp;
1860				(void) fprintf(stderr, gettext("cannot import "
1861				    "'%s': pool may be in use from other "
1862				    "system, it was last accessed by %s "
1863				    "(hostid: 0x%lx) on %s"), name, hostname,
1864				    (unsigned long)hostid,
1865				    asctime(localtime(&t)));
1866				(void) fprintf(stderr, gettext("use '-f' to "
1867				    "import anyway\n"));
1868				return (1);
1869			}
1870		} else {
1871			(void) fprintf(stderr, gettext("cannot import '%s': "
1872			    "pool may be in use from other system\n"), name);
1873			(void) fprintf(stderr, gettext("use '-f' to import "
1874			    "anyway\n"));
1875			return (1);
1876		}
1877	}
1878
1879	if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
1880		return (1);
1881
1882	if (newname != NULL)
1883		name = (char *)newname;
1884
1885	if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
1886		return (1);
1887
1888	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1889	    !(flags & ZFS_IMPORT_ONLY) &&
1890	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1891		zpool_close(zhp);
1892		return (1);
1893	}
1894
1895	zpool_close(zhp);
1896	return (0);
1897}
1898
1899/*
1900 * zpool import [-d dir] [-D]
1901 *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1902 *              [-d dir | -c cachefile] [-f] -a
1903 *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1904 *              [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
1905 *
1906 *	 -c	Read pool information from a cachefile instead of searching
1907 *		devices.
1908 *
1909 *       -d	Scan in a specific directory, other than /dev/dsk.  More than
1910 *		one directory can be specified using multiple '-d' options.
1911 *
1912 *       -D     Scan for previously destroyed pools or import all or only
1913 *              specified destroyed pools.
1914 *
1915 *       -R	Temporarily import the pool, with all mountpoints relative to
1916 *		the given root.  The pool will remain exported when the machine
1917 *		is rebooted.
1918 *
1919 *       -V	Import even in the presence of faulted vdevs.  This is an
1920 *       	intentionally undocumented option for testing purposes, and
1921 *       	treats the pool configuration as complete, leaving any bad
1922 *		vdevs in the FAULTED state. In other words, it does verbatim
1923 *		import.
1924 *
1925 *       -f	Force import, even if it appears that the pool is active.
1926 *
1927 *       -F     Attempt rewind if necessary.
1928 *
1929 *       -n     See if rewind would work, but don't actually rewind.
1930 *
1931 *       -N     Import the pool but don't mount datasets.
1932 *
1933 *       -T     Specify a starting txg to use for import. This option is
1934 *       	intentionally undocumented option for testing purposes.
1935 *
1936 *       -a	Import all pools found.
1937 *
1938 *       -o	Set property=value and/or temporary mount options (without '=').
1939 *
1940 * The import command scans for pools to import, and import pools based on pool
1941 * name and GUID.  The pool can also be renamed as part of the import process.
1942 */
1943int
1944zpool_do_import(int argc, char **argv)
1945{
1946	char **searchdirs = NULL;
1947	int nsearch = 0;
1948	int c;
1949	int err = 0;
1950	nvlist_t *pools = NULL;
1951	boolean_t do_all = B_FALSE;
1952	boolean_t do_destroyed = B_FALSE;
1953	char *mntopts = NULL;
1954	nvpair_t *elem;
1955	nvlist_t *config;
1956	uint64_t searchguid = 0;
1957	char *searchname = NULL;
1958	char *propval;
1959	nvlist_t *found_config;
1960	nvlist_t *policy = NULL;
1961	nvlist_t *props = NULL;
1962	boolean_t first;
1963	int flags = ZFS_IMPORT_NORMAL;
1964	uint32_t rewind_policy = ZPOOL_NO_REWIND;
1965	boolean_t dryrun = B_FALSE;
1966	boolean_t do_rewind = B_FALSE;
1967	boolean_t xtreme_rewind = B_FALSE;
1968	uint64_t pool_state, txg = -1ULL;
1969	char *cachefile = NULL;
1970	importargs_t idata = { 0 };
1971	char *endptr;
1972
1973	/* check options */
1974	while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:R:T:VX")) != -1) {
1975		switch (c) {
1976		case 'a':
1977			do_all = B_TRUE;
1978			break;
1979		case 'c':
1980			cachefile = optarg;
1981			break;
1982		case 'd':
1983			if (searchdirs == NULL) {
1984				searchdirs = safe_malloc(sizeof (char *));
1985			} else {
1986				char **tmp = safe_malloc((nsearch + 1) *
1987				    sizeof (char *));
1988				bcopy(searchdirs, tmp, nsearch *
1989				    sizeof (char *));
1990				free(searchdirs);
1991				searchdirs = tmp;
1992			}
1993			searchdirs[nsearch++] = optarg;
1994			break;
1995		case 'D':
1996			do_destroyed = B_TRUE;
1997			break;
1998		case 'f':
1999			flags |= ZFS_IMPORT_ANY_HOST;
2000			break;
2001		case 'F':
2002			do_rewind = B_TRUE;
2003			break;
2004		case 'm':
2005			flags |= ZFS_IMPORT_MISSING_LOG;
2006			break;
2007		case 'n':
2008			dryrun = B_TRUE;
2009			break;
2010		case 'N':
2011			flags |= ZFS_IMPORT_ONLY;
2012			break;
2013		case 'o':
2014			if ((propval = strchr(optarg, '=')) != NULL) {
2015				*propval = '\0';
2016				propval++;
2017				if (add_prop_list(optarg, propval,
2018				    &props, B_TRUE))
2019					goto error;
2020			} else {
2021				mntopts = optarg;
2022			}
2023			break;
2024		case 'R':
2025			if (add_prop_list(zpool_prop_to_name(
2026			    ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2027				goto error;
2028			if (nvlist_lookup_string(props,
2029			    zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2030			    &propval) == 0)
2031				break;
2032			if (add_prop_list(zpool_prop_to_name(
2033			    ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2034				goto error;
2035			break;
2036		case 'T':
2037			errno = 0;
2038			txg = strtoull(optarg, &endptr, 0);
2039			if (errno != 0 || *endptr != '\0') {
2040				(void) fprintf(stderr,
2041				    gettext("invalid txg value\n"));
2042				usage(B_FALSE);
2043			}
2044			rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2045			break;
2046		case 'V':
2047			flags |= ZFS_IMPORT_VERBATIM;
2048			break;
2049		case 'X':
2050			xtreme_rewind = B_TRUE;
2051			break;
2052		case ':':
2053			(void) fprintf(stderr, gettext("missing argument for "
2054			    "'%c' option\n"), optopt);
2055			usage(B_FALSE);
2056			break;
2057		case '?':
2058			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2059			    optopt);
2060			usage(B_FALSE);
2061		}
2062	}
2063
2064	argc -= optind;
2065	argv += optind;
2066
2067	if (cachefile && nsearch != 0) {
2068		(void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2069		usage(B_FALSE);
2070	}
2071
2072	if ((dryrun || xtreme_rewind) && !do_rewind) {
2073		(void) fprintf(stderr,
2074		    gettext("-n or -X only meaningful with -F\n"));
2075		usage(B_FALSE);
2076	}
2077	if (dryrun)
2078		rewind_policy = ZPOOL_TRY_REWIND;
2079	else if (do_rewind)
2080		rewind_policy = ZPOOL_DO_REWIND;
2081	if (xtreme_rewind)
2082		rewind_policy |= ZPOOL_EXTREME_REWIND;
2083
2084	/* In the future, we can capture further policy and include it here */
2085	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2086	    nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
2087	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2088		goto error;
2089
2090	if (searchdirs == NULL) {
2091		searchdirs = safe_malloc(sizeof (char *));
2092		searchdirs[0] = "/dev";
2093		nsearch = 1;
2094	}
2095
2096	/* check argument count */
2097	if (do_all) {
2098		if (argc != 0) {
2099			(void) fprintf(stderr, gettext("too many arguments\n"));
2100			usage(B_FALSE);
2101		}
2102	} else {
2103		if (argc > 2) {
2104			(void) fprintf(stderr, gettext("too many arguments\n"));
2105			usage(B_FALSE);
2106		}
2107
2108		/*
2109		 * Check for the SYS_CONFIG privilege.  We do this explicitly
2110		 * here because otherwise any attempt to discover pools will
2111		 * silently fail.
2112		 */
2113		if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2114			(void) fprintf(stderr, gettext("cannot "
2115			    "discover pools: permission denied\n"));
2116			free(searchdirs);
2117			nvlist_free(policy);
2118			return (1);
2119		}
2120	}
2121
2122	/*
2123	 * Depending on the arguments given, we do one of the following:
2124	 *
2125	 *	<none>	Iterate through all pools and display information about
2126	 *		each one.
2127	 *
2128	 *	-a	Iterate through all pools and try to import each one.
2129	 *
2130	 *	<id>	Find the pool that corresponds to the given GUID/pool
2131	 *		name and import that one.
2132	 *
2133	 *	-D	Above options applies only to destroyed pools.
2134	 */
2135	if (argc != 0) {
2136		char *endptr;
2137
2138		errno = 0;
2139		searchguid = strtoull(argv[0], &endptr, 10);
2140		if (errno != 0 || *endptr != '\0') {
2141			searchname = argv[0];
2142			searchguid = 0;
2143		}
2144		found_config = NULL;
2145
2146		/*
2147		 * User specified a name or guid.  Ensure it's unique.
2148		 */
2149		idata.unique = B_TRUE;
2150	}
2151
2152
2153	idata.path = searchdirs;
2154	idata.paths = nsearch;
2155	idata.poolname = searchname;
2156	idata.guid = searchguid;
2157	idata.cachefile = cachefile;
2158
2159	pools = zpool_search_import(g_zfs, &idata);
2160
2161	if (pools != NULL && idata.exists &&
2162	    (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2163		(void) fprintf(stderr, gettext("cannot import '%s': "
2164		    "a pool with that name already exists\n"),
2165		    argv[0]);
2166		(void) fprintf(stderr, gettext("use the form '%s "
2167		    "<pool | id> <newpool>' to give it a new name\n"),
2168		    "zpool import");
2169		err = 1;
2170	} else if (pools == NULL && idata.exists) {
2171		(void) fprintf(stderr, gettext("cannot import '%s': "
2172		    "a pool with that name is already created/imported,\n"),
2173		    argv[0]);
2174		(void) fprintf(stderr, gettext("and no additional pools "
2175		    "with that name were found\n"));
2176		err = 1;
2177	} else if (pools == NULL) {
2178		if (argc != 0) {
2179			(void) fprintf(stderr, gettext("cannot import '%s': "
2180			    "no such pool available\n"), argv[0]);
2181		}
2182		err = 1;
2183	}
2184
2185	if (err == 1) {
2186		free(searchdirs);
2187		nvlist_free(policy);
2188		return (1);
2189	}
2190
2191	/*
2192	 * At this point we have a list of import candidate configs. Even if
2193	 * we were searching by pool name or guid, we still need to
2194	 * post-process the list to deal with pool state and possible
2195	 * duplicate names.
2196	 */
2197	err = 0;
2198	elem = NULL;
2199	first = B_TRUE;
2200	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2201
2202		verify(nvpair_value_nvlist(elem, &config) == 0);
2203
2204		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2205		    &pool_state) == 0);
2206		if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2207			continue;
2208		if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2209			continue;
2210
2211		verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2212		    policy) == 0);
2213
2214		if (argc == 0) {
2215			if (first)
2216				first = B_FALSE;
2217			else if (!do_all)
2218				(void) printf("\n");
2219
2220			if (do_all) {
2221				err |= do_import(config, NULL, mntopts,
2222				    props, flags);
2223			} else {
2224				show_import(config);
2225			}
2226		} else if (searchname != NULL) {
2227			char *name;
2228
2229			/*
2230			 * We are searching for a pool based on name.
2231			 */
2232			verify(nvlist_lookup_string(config,
2233			    ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2234
2235			if (strcmp(name, searchname) == 0) {
2236				if (found_config != NULL) {
2237					(void) fprintf(stderr, gettext(
2238					    "cannot import '%s': more than "
2239					    "one matching pool\n"), searchname);
2240					(void) fprintf(stderr, gettext(
2241					    "import by numeric ID instead\n"));
2242					err = B_TRUE;
2243				}
2244				found_config = config;
2245			}
2246		} else {
2247			uint64_t guid;
2248
2249			/*
2250			 * Search for a pool by guid.
2251			 */
2252			verify(nvlist_lookup_uint64(config,
2253			    ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2254
2255			if (guid == searchguid)
2256				found_config = config;
2257		}
2258	}
2259
2260	/*
2261	 * If we were searching for a specific pool, verify that we found a
2262	 * pool, and then do the import.
2263	 */
2264	if (argc != 0 && err == 0) {
2265		if (found_config == NULL) {
2266			(void) fprintf(stderr, gettext("cannot import '%s': "
2267			    "no such pool available\n"), argv[0]);
2268			err = B_TRUE;
2269		} else {
2270			err |= do_import(found_config, argc == 1 ? NULL :
2271			    argv[1], mntopts, props, flags);
2272		}
2273	}
2274
2275	/*
2276	 * If we were just looking for pools, report an error if none were
2277	 * found.
2278	 */
2279	if (argc == 0 && first)
2280		(void) fprintf(stderr,
2281		    gettext("no pools available to import\n"));
2282
2283error:
2284	nvlist_free(props);
2285	nvlist_free(pools);
2286	nvlist_free(policy);
2287	free(searchdirs);
2288
2289	return (err ? 1 : 0);
2290}
2291
2292typedef struct iostat_cbdata {
2293	boolean_t cb_verbose;
2294	int cb_namewidth;
2295	int cb_iteration;
2296	zpool_list_t *cb_list;
2297} iostat_cbdata_t;
2298
2299static void
2300print_iostat_separator(iostat_cbdata_t *cb)
2301{
2302	int i = 0;
2303
2304	for (i = 0; i < cb->cb_namewidth; i++)
2305		(void) printf("-");
2306	(void) printf("  -----  -----  -----  -----  -----  -----\n");
2307}
2308
2309static void
2310print_iostat_header(iostat_cbdata_t *cb)
2311{
2312	(void) printf("%*s     capacity     operations    bandwidth\n",
2313	    cb->cb_namewidth, "");
2314	(void) printf("%-*s  alloc   free   read  write   read  write\n",
2315	    cb->cb_namewidth, "pool");
2316	print_iostat_separator(cb);
2317}
2318
2319/*
2320 * Display a single statistic.
2321 */
2322static void
2323print_one_stat(uint64_t value)
2324{
2325	char buf[64];
2326
2327	zfs_nicenum(value, buf, sizeof (buf));
2328	(void) printf("  %5s", buf);
2329}
2330
2331/*
2332 * Print out all the statistics for the given vdev.  This can either be the
2333 * toplevel configuration, or called recursively.  If 'name' is NULL, then this
2334 * is a verbose output, and we don't want to display the toplevel pool stats.
2335 */
2336void
2337print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2338    nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2339{
2340	nvlist_t **oldchild, **newchild;
2341	uint_t c, children;
2342	vdev_stat_t *oldvs, *newvs;
2343	vdev_stat_t zerovs = { 0 };
2344	uint64_t tdelta;
2345	double scale;
2346	char *vname;
2347
2348	if (oldnv != NULL) {
2349		verify(nvlist_lookup_uint64_array(oldnv,
2350		    ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2351	} else {
2352		oldvs = &zerovs;
2353	}
2354
2355	verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2356	    (uint64_t **)&newvs, &c) == 0);
2357
2358	if (strlen(name) + depth > cb->cb_namewidth)
2359		(void) printf("%*s%s", depth, "", name);
2360	else
2361		(void) printf("%*s%s%*s", depth, "", name,
2362		    (int)(cb->cb_namewidth - strlen(name) - depth), "");
2363
2364	tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2365
2366	if (tdelta == 0)
2367		scale = 1.0;
2368	else
2369		scale = (double)NANOSEC / tdelta;
2370
2371	/* only toplevel vdevs have capacity stats */
2372	if (newvs->vs_space == 0) {
2373		(void) printf("      -      -");
2374	} else {
2375		print_one_stat(newvs->vs_alloc);
2376		print_one_stat(newvs->vs_space - newvs->vs_alloc);
2377	}
2378
2379	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2380	    oldvs->vs_ops[ZIO_TYPE_READ])));
2381
2382	print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2383	    oldvs->vs_ops[ZIO_TYPE_WRITE])));
2384
2385	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2386	    oldvs->vs_bytes[ZIO_TYPE_READ])));
2387
2388	print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2389	    oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2390
2391	(void) printf("\n");
2392
2393	if (!cb->cb_verbose)
2394		return;
2395
2396	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2397	    &newchild, &children) != 0)
2398		return;
2399
2400	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2401	    &oldchild, &c) != 0)
2402		return;
2403
2404	for (c = 0; c < children; c++) {
2405		uint64_t ishole = B_FALSE, islog = B_FALSE;
2406
2407		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2408		    &ishole);
2409
2410		(void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2411		    &islog);
2412
2413		if (ishole || islog)
2414			continue;
2415
2416		vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2417		print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2418		    newchild[c], cb, depth + 2);
2419		free(vname);
2420	}
2421
2422	/*
2423	 * Log device section
2424	 */
2425
2426	if (num_logs(newnv) > 0) {
2427		(void) printf("%-*s      -      -      -      -      -      "
2428		    "-\n", cb->cb_namewidth, "logs");
2429
2430		for (c = 0; c < children; c++) {
2431			uint64_t islog = B_FALSE;
2432			(void) nvlist_lookup_uint64(newchild[c],
2433			    ZPOOL_CONFIG_IS_LOG, &islog);
2434
2435			if (islog) {
2436				vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2437				    B_FALSE);
2438				print_vdev_stats(zhp, vname, oldnv ?
2439				    oldchild[c] : NULL, newchild[c],
2440				    cb, depth + 2);
2441				free(vname);
2442			}
2443		}
2444
2445	}
2446
2447	/*
2448	 * Include level 2 ARC devices in iostat output
2449	 */
2450	if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2451	    &newchild, &children) != 0)
2452		return;
2453
2454	if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2455	    &oldchild, &c) != 0)
2456		return;
2457
2458	if (children > 0) {
2459		(void) printf("%-*s      -      -      -      -      -      "
2460		    "-\n", cb->cb_namewidth, "cache");
2461		for (c = 0; c < children; c++) {
2462			vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2463			    B_FALSE);
2464			print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2465			    newchild[c], cb, depth + 2);
2466			free(vname);
2467		}
2468	}
2469}
2470
2471static int
2472refresh_iostat(zpool_handle_t *zhp, void *data)
2473{
2474	iostat_cbdata_t *cb = data;
2475	boolean_t missing;
2476
2477	/*
2478	 * If the pool has disappeared, remove it from the list and continue.
2479	 */
2480	if (zpool_refresh_stats(zhp, &missing) != 0)
2481		return (-1);
2482
2483	if (missing)
2484		pool_list_remove(cb->cb_list, zhp);
2485
2486	return (0);
2487}
2488
2489/*
2490 * Callback to print out the iostats for the given pool.
2491 */
2492int
2493print_iostat(zpool_handle_t *zhp, void *data)
2494{
2495	iostat_cbdata_t *cb = data;
2496	nvlist_t *oldconfig, *newconfig;
2497	nvlist_t *oldnvroot, *newnvroot;
2498
2499	newconfig = zpool_get_config(zhp, &oldconfig);
2500
2501	if (cb->cb_iteration == 1)
2502		oldconfig = NULL;
2503
2504	verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2505	    &newnvroot) == 0);
2506
2507	if (oldconfig == NULL)
2508		oldnvroot = NULL;
2509	else
2510		verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2511		    &oldnvroot) == 0);
2512
2513	/*
2514	 * Print out the statistics for the pool.
2515	 */
2516	print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2517
2518	if (cb->cb_verbose)
2519		print_iostat_separator(cb);
2520
2521	return (0);
2522}
2523
2524int
2525get_namewidth(zpool_handle_t *zhp, void *data)
2526{
2527	iostat_cbdata_t *cb = data;
2528	nvlist_t *config, *nvroot;
2529
2530	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2531		verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2532		    &nvroot) == 0);
2533		if (!cb->cb_verbose)
2534			cb->cb_namewidth = strlen(zpool_get_name(zhp));
2535		else
2536			cb->cb_namewidth = max_width(zhp, nvroot, 0,
2537			    cb->cb_namewidth);
2538	}
2539
2540	/*
2541	 * The width must fall into the range [10,38].  The upper limit is the
2542	 * maximum we can have and still fit in 80 columns.
2543	 */
2544	if (cb->cb_namewidth < 10)
2545		cb->cb_namewidth = 10;
2546	if (cb->cb_namewidth > 38)
2547		cb->cb_namewidth = 38;
2548
2549	return (0);
2550}
2551
2552/*
2553 * Parse the input string, get the 'interval' and 'count' value if there is one.
2554 */
2555static void
2556get_interval_count(int *argcp, char **argv, unsigned long *iv,
2557    unsigned long *cnt)
2558{
2559	unsigned long interval = 0, count = 0;
2560	int argc = *argcp, errno;
2561
2562	/*
2563	 * Determine if the last argument is an integer or a pool name
2564	 */
2565	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2566		char *end;
2567
2568		errno = 0;
2569		interval = strtoul(argv[argc - 1], &end, 10);
2570
2571		if (*end == '\0' && errno == 0) {
2572			if (interval == 0) {
2573				(void) fprintf(stderr, gettext("interval "
2574				    "cannot be zero\n"));
2575				usage(B_FALSE);
2576			}
2577			/*
2578			 * Ignore the last parameter
2579			 */
2580			argc--;
2581		} else {
2582			/*
2583			 * If this is not a valid number, just plow on.  The
2584			 * user will get a more informative error message later
2585			 * on.
2586			 */
2587			interval = 0;
2588		}
2589	}
2590
2591	/*
2592	 * If the last argument is also an integer, then we have both a count
2593	 * and an interval.
2594	 */
2595	if (argc > 0 && isdigit(argv[argc - 1][0])) {
2596		char *end;
2597
2598		errno = 0;
2599		count = interval;
2600		interval = strtoul(argv[argc - 1], &end, 10);
2601
2602		if (*end == '\0' && errno == 0) {
2603			if (interval == 0) {
2604				(void) fprintf(stderr, gettext("interval "
2605				    "cannot be zero\n"));
2606				usage(B_FALSE);
2607			}
2608
2609			/*
2610			 * Ignore the last parameter
2611			 */
2612			argc--;
2613		} else {
2614			interval = 0;
2615		}
2616	}
2617
2618	*iv = interval;
2619	*cnt = count;
2620	*argcp = argc;
2621}
2622
2623static void
2624get_timestamp_arg(char c)
2625{
2626	if (c == 'u')
2627		timestamp_fmt = UDATE;
2628	else if (c == 'd')
2629		timestamp_fmt = DDATE;
2630	else
2631		usage(B_FALSE);
2632}
2633
2634/*
2635 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2636 *
2637 *	-v	Display statistics for individual vdevs
2638 *	-T	Display a timestamp in date(1) or Unix format
2639 *
2640 * This command can be tricky because we want to be able to deal with pool
2641 * creation/destruction as well as vdev configuration changes.  The bulk of this
2642 * processing is handled by the pool_list_* routines in zpool_iter.c.  We rely
2643 * on pool_list_update() to detect the addition of new pools.  Configuration
2644 * changes are all handled within libzfs.
2645 */
2646int
2647zpool_do_iostat(int argc, char **argv)
2648{
2649	int c;
2650	int ret;
2651	int npools;
2652	unsigned long interval = 0, count = 0;
2653	zpool_list_t *list;
2654	boolean_t verbose = B_FALSE;
2655	iostat_cbdata_t cb;
2656
2657	/* check options */
2658	while ((c = getopt(argc, argv, "T:v")) != -1) {
2659		switch (c) {
2660		case 'T':
2661			get_timestamp_arg(*optarg);
2662			break;
2663		case 'v':
2664			verbose = B_TRUE;
2665			break;
2666		case '?':
2667			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2668			    optopt);
2669			usage(B_FALSE);
2670		}
2671	}
2672
2673	argc -= optind;
2674	argv += optind;
2675
2676	get_interval_count(&argc, argv, &interval, &count);
2677
2678	/*
2679	 * Construct the list of all interesting pools.
2680	 */
2681	ret = 0;
2682	if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2683		return (1);
2684
2685	if (pool_list_count(list) == 0 && argc != 0) {
2686		pool_list_free(list);
2687		return (1);
2688	}
2689
2690	if (pool_list_count(list) == 0 && interval == 0) {
2691		pool_list_free(list);
2692		(void) fprintf(stderr, gettext("no pools available\n"));
2693		return (1);
2694	}
2695
2696	/*
2697	 * Enter the main iostat loop.
2698	 */
2699	cb.cb_list = list;
2700	cb.cb_verbose = verbose;
2701	cb.cb_iteration = 0;
2702	cb.cb_namewidth = 0;
2703
2704	for (;;) {
2705		pool_list_update(list);
2706
2707		if ((npools = pool_list_count(list)) == 0)
2708			break;
2709
2710		/*
2711		 * Refresh all statistics.  This is done as an explicit step
2712		 * before calculating the maximum name width, so that any
2713		 * configuration changes are properly accounted for.
2714		 */
2715		(void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2716
2717		/*
2718		 * Iterate over all pools to determine the maximum width
2719		 * for the pool / device name column across all pools.
2720		 */
2721		cb.cb_namewidth = 0;
2722		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2723
2724		if (timestamp_fmt != NODATE)
2725			print_timestamp(timestamp_fmt);
2726
2727		/*
2728		 * If it's the first time, or verbose mode, print the header.
2729		 */
2730		if (++cb.cb_iteration == 1 || verbose)
2731			print_iostat_header(&cb);
2732
2733		(void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2734
2735		/*
2736		 * If there's more than one pool, and we're not in verbose mode
2737		 * (which prints a separator for us), then print a separator.
2738		 */
2739		if (npools > 1 && !verbose)
2740			print_iostat_separator(&cb);
2741
2742		if (verbose)
2743			(void) printf("\n");
2744
2745		/*
2746		 * Flush the output so that redirection to a file isn't buffered
2747		 * indefinitely.
2748		 */
2749		(void) fflush(stdout);
2750
2751		if (interval == 0)
2752			break;
2753
2754		if (count != 0 && --count == 0)
2755			break;
2756
2757		(void) sleep(interval);
2758	}
2759
2760	pool_list_free(list);
2761
2762	return (ret);
2763}
2764
2765typedef struct list_cbdata {
2766	boolean_t	cb_verbose;
2767	int		cb_namewidth;
2768	boolean_t	cb_scripted;
2769	zprop_list_t	*cb_proplist;
2770	boolean_t	cb_literal;
2771} list_cbdata_t;
2772
2773/*
2774 * Given a list of columns to display, output appropriate headers for each one.
2775 */
2776static void
2777print_header(list_cbdata_t *cb)
2778{
2779	zprop_list_t *pl = cb->cb_proplist;
2780	char headerbuf[ZPOOL_MAXPROPLEN];
2781	const char *header;
2782	boolean_t first = B_TRUE;
2783	boolean_t right_justify;
2784	size_t width = 0;
2785
2786	for (; pl != NULL; pl = pl->pl_next) {
2787		width = pl->pl_width;
2788		if (first && cb->cb_verbose) {
2789			/*
2790			 * Reset the width to accommodate the verbose listing
2791			 * of devices.
2792			 */
2793			width = cb->cb_namewidth;
2794		}
2795
2796		if (!first)
2797			(void) printf("  ");
2798		else
2799			first = B_FALSE;
2800
2801		right_justify = B_FALSE;
2802		if (pl->pl_prop != ZPROP_INVAL) {
2803			header = zpool_prop_column_name(pl->pl_prop);
2804			right_justify = zpool_prop_align_right(pl->pl_prop);
2805		} else {
2806			int i;
2807
2808			for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
2809				headerbuf[i] = toupper(pl->pl_user_prop[i]);
2810			headerbuf[i] = '\0';
2811			header = headerbuf;
2812		}
2813
2814		if (pl->pl_next == NULL && !right_justify)
2815			(void) printf("%s", header);
2816		else if (right_justify)
2817			(void) printf("%*s", width, header);
2818		else
2819			(void) printf("%-*s", width, header);
2820
2821	}
2822
2823	(void) printf("\n");
2824}
2825
2826/*
2827 * Given a pool and a list of properties, print out all the properties according
2828 * to the described layout.
2829 */
2830static void
2831print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
2832{
2833	zprop_list_t *pl = cb->cb_proplist;
2834	boolean_t first = B_TRUE;
2835	char property[ZPOOL_MAXPROPLEN];
2836	char *propstr;
2837	boolean_t right_justify;
2838	size_t width;
2839
2840	for (; pl != NULL; pl = pl->pl_next) {
2841
2842		width = pl->pl_width;
2843		if (first && cb->cb_verbose) {
2844			/*
2845			 * Reset the width to accommodate the verbose listing
2846			 * of devices.
2847			 */
2848			width = cb->cb_namewidth;
2849		}
2850
2851		if (!first) {
2852			if (cb->cb_scripted)
2853				(void) printf("\t");
2854			else
2855				(void) printf("  ");
2856		} else {
2857			first = B_FALSE;
2858		}
2859
2860		right_justify = B_FALSE;
2861		if (pl->pl_prop != ZPROP_INVAL) {
2862			if (zpool_get_prop(zhp, pl->pl_prop, property,
2863			    sizeof (property), NULL, cb->cb_literal) != 0)
2864				propstr = "-";
2865			else
2866				propstr = property;
2867
2868			right_justify = zpool_prop_align_right(pl->pl_prop);
2869		} else if ((zpool_prop_feature(pl->pl_user_prop) ||
2870		    zpool_prop_unsupported(pl->pl_user_prop)) &&
2871		    zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
2872		    sizeof (property)) == 0) {
2873			propstr = property;
2874		} else {
2875			propstr = "-";
2876		}
2877
2878
2879		/*
2880		 * If this is being called in scripted mode, or if this is the
2881		 * last column and it is left-justified, don't include a width
2882		 * format specifier.
2883		 */
2884		if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
2885			(void) printf("%s", propstr);
2886		else if (right_justify)
2887			(void) printf("%*s", width, propstr);
2888		else
2889			(void) printf("%-*s", width, propstr);
2890	}
2891
2892	(void) printf("\n");
2893}
2894
2895static void
2896print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
2897    boolean_t valid)
2898{
2899	char propval[64];
2900	boolean_t fixed;
2901	size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
2902
2903	switch (prop) {
2904	case ZPOOL_PROP_EXPANDSZ:
2905		if (value == 0)
2906			(void) strlcpy(propval, "-", sizeof (propval));
2907		else
2908			zfs_nicenum(value, propval, sizeof (propval));
2909		break;
2910	case ZPOOL_PROP_FRAGMENTATION:
2911		if (value == ZFS_FRAG_INVALID) {
2912			(void) strlcpy(propval, "-", sizeof (propval));
2913		} else {
2914			(void) snprintf(propval, sizeof (propval), "%llu%%",
2915			    value);
2916		}
2917		break;
2918	case ZPOOL_PROP_CAPACITY:
2919		(void) snprintf(propval, sizeof (propval), "%llu%%", value);
2920		break;
2921	default:
2922		zfs_nicenum(value, propval, sizeof (propval));
2923	}
2924
2925	if (!valid)
2926		(void) strlcpy(propval, "-", sizeof (propval));
2927
2928	if (scripted)
2929		(void) printf("\t%s", propval);
2930	else
2931		(void) printf("  %*s", width, propval);
2932}
2933
2934void
2935print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2936    list_cbdata_t *cb, int depth)
2937{
2938	nvlist_t **child;
2939	vdev_stat_t *vs;
2940	uint_t c, children;
2941	char *vname;
2942	boolean_t scripted = cb->cb_scripted;
2943
2944	verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2945	    (uint64_t **)&vs, &c) == 0);
2946
2947	if (name != NULL) {
2948		boolean_t toplevel = (vs->vs_space != 0);
2949		uint64_t cap;
2950
2951		if (scripted)
2952			(void) printf("\t%s", name);
2953		else if (strlen(name) + depth > cb->cb_namewidth)
2954			(void) printf("%*s%s", depth, "", name);
2955		else
2956			(void) printf("%*s%s%*s", depth, "", name,
2957			    (int)(cb->cb_namewidth - strlen(name) - depth), "");
2958
2959		/*
2960		 * Print the properties for the individual vdevs. Some
2961		 * properties are only applicable to toplevel vdevs. The
2962		 * 'toplevel' boolean value is passed to the print_one_column()
2963		 * to indicate that the value is valid.
2964		 */
2965		print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
2966		    toplevel);
2967		print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
2968		    toplevel);
2969		print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
2970		    scripted, toplevel);
2971		print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
2972		    B_TRUE);
2973		print_one_column(ZPOOL_PROP_FRAGMENTATION,
2974		    vs->vs_fragmentation, scripted,
2975		    (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
2976		cap = (vs->vs_space == 0) ? 0 :
2977		    (vs->vs_alloc * 100 / vs->vs_space);
2978		print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
2979		(void) printf("\n");
2980	}
2981
2982	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2983	    &child, &children) != 0)
2984		return;
2985
2986	for (c = 0; c < children; c++) {
2987		uint64_t ishole = B_FALSE;
2988
2989		if (nvlist_lookup_uint64(child[c],
2990		    ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
2991			continue;
2992
2993		vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
2994		print_list_stats(zhp, vname, child[c], cb, depth + 2);
2995		free(vname);
2996	}
2997
2998	/*
2999	 * Include level 2 ARC devices in iostat output
3000	 */
3001	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3002	    &child, &children) != 0)
3003		return;
3004
3005	if (children > 0) {
3006		(void) printf("%-*s      -      -      -      -      -      "
3007		    "-\n", cb->cb_namewidth, "cache");
3008		for (c = 0; c < children; c++) {
3009			vname = zpool_vdev_name(g_zfs, zhp, child[c],
3010			    B_FALSE);
3011			print_list_stats(zhp, vname, child[c], cb, depth + 2);
3012			free(vname);
3013		}
3014	}
3015}
3016
3017
3018/*
3019 * Generic callback function to list a pool.
3020 */
3021int
3022list_callback(zpool_handle_t *zhp, void *data)
3023{
3024	list_cbdata_t *cbp = data;
3025	nvlist_t *config;
3026	nvlist_t *nvroot;
3027
3028	config = zpool_get_config(zhp, NULL);
3029
3030	print_pool(zhp, cbp);
3031	if (!cbp->cb_verbose)
3032		return (0);
3033
3034	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3035	    &nvroot) == 0);
3036	print_list_stats(zhp, NULL, nvroot, cbp, 0);
3037
3038	return (0);
3039}
3040
3041/*
3042 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3043 *
3044 *	-H	Scripted mode.  Don't display headers, and separate properties
3045 *		by a single tab.
3046 *	-o	List of properties to display.  Defaults to
3047 *		"name,size,allocated,free,expandsize,fragmentation,capacity,"
3048 *		"dedupratio,health,altroot"
3049 * 	-p	Diplay values in parsable (exact) format.
3050 *	-T	Display a timestamp in date(1) or Unix format
3051 *
3052 * List all pools in the system, whether or not they're healthy.  Output space
3053 * statistics for each one, as well as health status summary.
3054 */
3055int
3056zpool_do_list(int argc, char **argv)
3057{
3058	int c;
3059	int ret;
3060	list_cbdata_t cb = { 0 };
3061	static char default_props[] =
3062	    "name,size,allocated,free,expandsize,fragmentation,capacity,"
3063	    "dedupratio,health,altroot";
3064	char *props = default_props;
3065	unsigned long interval = 0, count = 0;
3066	zpool_list_t *list;
3067	boolean_t first = B_TRUE;
3068
3069	/* check options */
3070	while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3071		switch (c) {
3072		case 'H':
3073			cb.cb_scripted = B_TRUE;
3074			break;
3075		case 'o':
3076			props = optarg;
3077			break;
3078		case 'p':
3079			cb.cb_literal = B_TRUE;
3080			break;
3081		case 'T':
3082			get_timestamp_arg(*optarg);
3083			break;
3084		case 'v':
3085			cb.cb_verbose = B_TRUE;
3086			break;
3087		case ':':
3088			(void) fprintf(stderr, gettext("missing argument for "
3089			    "'%c' option\n"), optopt);
3090			usage(B_FALSE);
3091			break;
3092		case '?':
3093			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3094			    optopt);
3095			usage(B_FALSE);
3096		}
3097	}
3098
3099	argc -= optind;
3100	argv += optind;
3101
3102	get_interval_count(&argc, argv, &interval, &count);
3103
3104	if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3105		usage(B_FALSE);
3106
3107	for (;;) {
3108		if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3109		    &ret)) == NULL)
3110			return (1);
3111
3112		if (pool_list_count(list) == 0)
3113			break;
3114
3115		cb.cb_namewidth = 0;
3116		(void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3117
3118		if (timestamp_fmt != NODATE)
3119			print_timestamp(timestamp_fmt);
3120
3121		if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3122			print_header(&cb);
3123			first = B_FALSE;
3124		}
3125		ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3126
3127		if (interval == 0)
3128			break;
3129
3130		if (count != 0 && --count == 0)
3131			break;
3132
3133		pool_list_free(list);
3134		(void) sleep(interval);
3135	}
3136
3137	if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3138		(void) printf(gettext("no pools available\n"));
3139		ret = 0;
3140	}
3141
3142	pool_list_free(list);
3143	zprop_free_list(cb.cb_proplist);
3144	return (ret);
3145}
3146
3147static nvlist_t *
3148zpool_get_vdev_by_name(nvlist_t *nv, char *name)
3149{
3150	nvlist_t **child;
3151	uint_t c, children;
3152	nvlist_t *match;
3153	char *path;
3154
3155	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3156	    &child, &children) != 0) {
3157		verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
3158		if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
3159			name += sizeof(_PATH_DEV) - 1;
3160		if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
3161			path += sizeof(_PATH_DEV) - 1;
3162		if (strcmp(name, path) == 0)
3163			return (nv);
3164		return (NULL);
3165	}
3166
3167	for (c = 0; c < children; c++)
3168		if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
3169			return (match);
3170
3171	return (NULL);
3172}
3173
3174static int
3175zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3176{
3177	boolean_t force = B_FALSE;
3178	int c;
3179	nvlist_t *nvroot;
3180	char *poolname, *old_disk, *new_disk;
3181	zpool_handle_t *zhp;
3182	int ret;
3183
3184	/* check options */
3185	while ((c = getopt(argc, argv, "f")) != -1) {
3186		switch (c) {
3187		case 'f':
3188			force = B_TRUE;
3189			break;
3190		case '?':
3191			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3192			    optopt);
3193			usage(B_FALSE);
3194		}
3195	}
3196
3197	argc -= optind;
3198	argv += optind;
3199
3200	/* get pool name and check number of arguments */
3201	if (argc < 1) {
3202		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3203		usage(B_FALSE);
3204	}
3205
3206	poolname = argv[0];
3207
3208	if (argc < 2) {
3209		(void) fprintf(stderr,
3210		    gettext("missing <device> specification\n"));
3211		usage(B_FALSE);
3212	}
3213
3214	old_disk = argv[1];
3215
3216	if (argc < 3) {
3217		if (!replacing) {
3218			(void) fprintf(stderr,
3219			    gettext("missing <new_device> specification\n"));
3220			usage(B_FALSE);
3221		}
3222		new_disk = old_disk;
3223		argc -= 1;
3224		argv += 1;
3225	} else {
3226		new_disk = argv[2];
3227		argc -= 2;
3228		argv += 2;
3229	}
3230
3231	if (argc > 1) {
3232		(void) fprintf(stderr, gettext("too many arguments\n"));
3233		usage(B_FALSE);
3234	}
3235
3236	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3237		return (1);
3238
3239	if (zpool_get_config(zhp, NULL) == NULL) {
3240		(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3241		    poolname);
3242		zpool_close(zhp);
3243		return (1);
3244	}
3245
3246	nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3247	    argc, argv);
3248	if (nvroot == NULL) {
3249		zpool_close(zhp);
3250		return (1);
3251	}
3252
3253	ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3254
3255	nvlist_free(nvroot);
3256	zpool_close(zhp);
3257
3258	return (ret);
3259}
3260
3261/*
3262 * zpool replace [-f] <pool> <device> <new_device>
3263 *
3264 *	-f	Force attach, even if <new_device> appears to be in use.
3265 *
3266 * Replace <device> with <new_device>.
3267 */
3268/* ARGSUSED */
3269int
3270zpool_do_replace(int argc, char **argv)
3271{
3272	return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3273}
3274
3275/*
3276 * zpool attach [-f] <pool> <device> <new_device>
3277 *
3278 *	-f	Force attach, even if <new_device> appears to be in use.
3279 *
3280 * Attach <new_device> to the mirror containing <device>.  If <device> is not
3281 * part of a mirror, then <device> will be transformed into a mirror of
3282 * <device> and <new_device>.  In either case, <new_device> will begin life
3283 * with a DTL of [0, now], and will immediately begin to resilver itself.
3284 */
3285int
3286zpool_do_attach(int argc, char **argv)
3287{
3288	return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3289}
3290
3291/*
3292 * zpool detach [-f] <pool> <device>
3293 *
3294 *	-f	Force detach of <device>, even if DTLs argue against it
3295 *		(not supported yet)
3296 *
3297 * Detach a device from a mirror.  The operation will be refused if <device>
3298 * is the last device in the mirror, or if the DTLs indicate that this device
3299 * has the only valid copy of some data.
3300 */
3301/* ARGSUSED */
3302int
3303zpool_do_detach(int argc, char **argv)
3304{
3305	int c;
3306	char *poolname, *path;
3307	zpool_handle_t *zhp;
3308	int ret;
3309
3310	/* check options */
3311	while ((c = getopt(argc, argv, "f")) != -1) {
3312		switch (c) {
3313		case 'f':
3314		case '?':
3315			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3316			    optopt);
3317			usage(B_FALSE);
3318		}
3319	}
3320
3321	argc -= optind;
3322	argv += optind;
3323
3324	/* get pool name and check number of arguments */
3325	if (argc < 1) {
3326		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3327		usage(B_FALSE);
3328	}
3329
3330	if (argc < 2) {
3331		(void) fprintf(stderr,
3332		    gettext("missing <device> specification\n"));
3333		usage(B_FALSE);
3334	}
3335
3336	poolname = argv[0];
3337	path = argv[1];
3338
3339	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3340		return (1);
3341
3342	ret = zpool_vdev_detach(zhp, path);
3343
3344	zpool_close(zhp);
3345
3346	return (ret);
3347}
3348
3349/*
3350 * zpool split [-n] [-o prop=val] ...
3351 *		[-o mntopt] ...
3352 *		[-R altroot] <pool> <newpool> [<device> ...]
3353 *
3354 *	-n	Do not split the pool, but display the resulting layout if
3355 *		it were to be split.
3356 *	-o	Set property=value, or set mount options.
3357 *	-R	Mount the split-off pool under an alternate root.
3358 *
3359 * Splits the named pool and gives it the new pool name.  Devices to be split
3360 * off may be listed, provided that no more than one device is specified
3361 * per top-level vdev mirror.  The newly split pool is left in an exported
3362 * state unless -R is specified.
3363 *
3364 * Restrictions: the top-level of the pool pool must only be made up of
3365 * mirrors; all devices in the pool must be healthy; no device may be
3366 * undergoing a resilvering operation.
3367 */
3368int
3369zpool_do_split(int argc, char **argv)
3370{
3371	char *srcpool, *newpool, *propval;
3372	char *mntopts = NULL;
3373	splitflags_t flags;
3374	int c, ret = 0;
3375	zpool_handle_t *zhp;
3376	nvlist_t *config, *props = NULL;
3377
3378	flags.dryrun = B_FALSE;
3379	flags.import = B_FALSE;
3380
3381	/* check options */
3382	while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3383		switch (c) {
3384		case 'R':
3385			flags.import = B_TRUE;
3386			if (add_prop_list(
3387			    zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3388			    &props, B_TRUE) != 0) {
3389				if (props)
3390					nvlist_free(props);
3391				usage(B_FALSE);
3392			}
3393			break;
3394		case 'n':
3395			flags.dryrun = B_TRUE;
3396			break;
3397		case 'o':
3398			if ((propval = strchr(optarg, '=')) != NULL) {
3399				*propval = '\0';
3400				propval++;
3401				if (add_prop_list(optarg, propval,
3402				    &props, B_TRUE) != 0) {
3403					if (props)
3404						nvlist_free(props);
3405					usage(B_FALSE);
3406				}
3407			} else {
3408				mntopts = optarg;
3409			}
3410			break;
3411		case ':':
3412			(void) fprintf(stderr, gettext("missing argument for "
3413			    "'%c' option\n"), optopt);
3414			usage(B_FALSE);
3415			break;
3416		case '?':
3417			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3418			    optopt);
3419			usage(B_FALSE);
3420			break;
3421		}
3422	}
3423
3424	if (!flags.import && mntopts != NULL) {
3425		(void) fprintf(stderr, gettext("setting mntopts is only "
3426		    "valid when importing the pool\n"));
3427		usage(B_FALSE);
3428	}
3429
3430	argc -= optind;
3431	argv += optind;
3432
3433	if (argc < 1) {
3434		(void) fprintf(stderr, gettext("Missing pool name\n"));
3435		usage(B_FALSE);
3436	}
3437	if (argc < 2) {
3438		(void) fprintf(stderr, gettext("Missing new pool name\n"));
3439		usage(B_FALSE);
3440	}
3441
3442	srcpool = argv[0];
3443	newpool = argv[1];
3444
3445	argc -= 2;
3446	argv += 2;
3447
3448	if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3449		return (1);
3450
3451	config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3452	if (config == NULL) {
3453		ret = 1;
3454	} else {
3455		if (flags.dryrun) {
3456			(void) printf(gettext("would create '%s' with the "
3457			    "following layout:\n\n"), newpool);
3458			print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3459		}
3460		nvlist_free(config);
3461	}
3462
3463	zpool_close(zhp);
3464
3465	if (ret != 0 || flags.dryrun || !flags.import)
3466		return (ret);
3467
3468	/*
3469	 * The split was successful. Now we need to open the new
3470	 * pool and import it.
3471	 */
3472	if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3473		return (1);
3474	if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3475	    zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3476		ret = 1;
3477		(void) fprintf(stderr, gettext("Split was successful, but "
3478		    "the datasets could not all be mounted\n"));
3479		(void) fprintf(stderr, gettext("Try doing '%s' with a "
3480		    "different altroot\n"), "zpool import");
3481	}
3482	zpool_close(zhp);
3483
3484	return (ret);
3485}
3486
3487
3488
3489/*
3490 * zpool online <pool> <device> ...
3491 */
3492int
3493zpool_do_online(int argc, char **argv)
3494{
3495	int c, i;
3496	char *poolname;
3497	zpool_handle_t *zhp;
3498	int ret = 0;
3499	vdev_state_t newstate;
3500	int flags = 0;
3501
3502	/* check options */
3503	while ((c = getopt(argc, argv, "et")) != -1) {
3504		switch (c) {
3505		case 'e':
3506			flags |= ZFS_ONLINE_EXPAND;
3507			break;
3508		case 't':
3509		case '?':
3510			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3511			    optopt);
3512			usage(B_FALSE);
3513		}
3514	}
3515
3516	argc -= optind;
3517	argv += optind;
3518
3519	/* get pool name and check number of arguments */
3520	if (argc < 1) {
3521		(void) fprintf(stderr, gettext("missing pool name\n"));
3522		usage(B_FALSE);
3523	}
3524	if (argc < 2) {
3525		(void) fprintf(stderr, gettext("missing device name\n"));
3526		usage(B_FALSE);
3527	}
3528
3529	poolname = argv[0];
3530
3531	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3532		return (1);
3533
3534	for (i = 1; i < argc; i++) {
3535		if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3536			if (newstate != VDEV_STATE_HEALTHY) {
3537				(void) printf(gettext("warning: device '%s' "
3538				    "onlined, but remains in faulted state\n"),
3539				    argv[i]);
3540				if (newstate == VDEV_STATE_FAULTED)
3541					(void) printf(gettext("use 'zpool "
3542					    "clear' to restore a faulted "
3543					    "device\n"));
3544				else
3545					(void) printf(gettext("use 'zpool "
3546					    "replace' to replace devices "
3547					    "that are no longer present\n"));
3548			}
3549		} else {
3550			ret = 1;
3551		}
3552	}
3553
3554	zpool_close(zhp);
3555
3556	return (ret);
3557}
3558
3559/*
3560 * zpool offline [-ft] <pool> <device> ...
3561 *
3562 *	-f	Force the device into the offline state, even if doing
3563 *		so would appear to compromise pool availability.
3564 *		(not supported yet)
3565 *
3566 *	-t	Only take the device off-line temporarily.  The offline
3567 *		state will not be persistent across reboots.
3568 */
3569/* ARGSUSED */
3570int
3571zpool_do_offline(int argc, char **argv)
3572{
3573	int c, i;
3574	char *poolname;
3575	zpool_handle_t *zhp;
3576	int ret = 0;
3577	boolean_t istmp = B_FALSE;
3578
3579	/* check options */
3580	while ((c = getopt(argc, argv, "ft")) != -1) {
3581		switch (c) {
3582		case 't':
3583			istmp = B_TRUE;
3584			break;
3585		case 'f':
3586		case '?':
3587			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3588			    optopt);
3589			usage(B_FALSE);
3590		}
3591	}
3592
3593	argc -= optind;
3594	argv += optind;
3595
3596	/* get pool name and check number of arguments */
3597	if (argc < 1) {
3598		(void) fprintf(stderr, gettext("missing pool name\n"));
3599		usage(B_FALSE);
3600	}
3601	if (argc < 2) {
3602		(void) fprintf(stderr, gettext("missing device name\n"));
3603		usage(B_FALSE);
3604	}
3605
3606	poolname = argv[0];
3607
3608	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3609		return (1);
3610
3611	for (i = 1; i < argc; i++) {
3612		if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3613			ret = 1;
3614	}
3615
3616	zpool_close(zhp);
3617
3618	return (ret);
3619}
3620
3621/*
3622 * zpool clear <pool> [device]
3623 *
3624 * Clear all errors associated with a pool or a particular device.
3625 */
3626int
3627zpool_do_clear(int argc, char **argv)
3628{
3629	int c;
3630	int ret = 0;
3631	boolean_t dryrun = B_FALSE;
3632	boolean_t do_rewind = B_FALSE;
3633	boolean_t xtreme_rewind = B_FALSE;
3634	uint32_t rewind_policy = ZPOOL_NO_REWIND;
3635	nvlist_t *policy = NULL;
3636	zpool_handle_t *zhp;
3637	char *pool, *device;
3638
3639	/* check options */
3640	while ((c = getopt(argc, argv, "FnX")) != -1) {
3641		switch (c) {
3642		case 'F':
3643			do_rewind = B_TRUE;
3644			break;
3645		case 'n':
3646			dryrun = B_TRUE;
3647			break;
3648		case 'X':
3649			xtreme_rewind = B_TRUE;
3650			break;
3651		case '?':
3652			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3653			    optopt);
3654			usage(B_FALSE);
3655		}
3656	}
3657
3658	argc -= optind;
3659	argv += optind;
3660
3661	if (argc < 1) {
3662		(void) fprintf(stderr, gettext("missing pool name\n"));
3663		usage(B_FALSE);
3664	}
3665
3666	if (argc > 2) {
3667		(void) fprintf(stderr, gettext("too many arguments\n"));
3668		usage(B_FALSE);
3669	}
3670
3671	if ((dryrun || xtreme_rewind) && !do_rewind) {
3672		(void) fprintf(stderr,
3673		    gettext("-n or -X only meaningful with -F\n"));
3674		usage(B_FALSE);
3675	}
3676	if (dryrun)
3677		rewind_policy = ZPOOL_TRY_REWIND;
3678	else if (do_rewind)
3679		rewind_policy = ZPOOL_DO_REWIND;
3680	if (xtreme_rewind)
3681		rewind_policy |= ZPOOL_EXTREME_REWIND;
3682
3683	/* In future, further rewind policy choices can be passed along here */
3684	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3685	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3686		return (1);
3687
3688	pool = argv[0];
3689	device = argc == 2 ? argv[1] : NULL;
3690
3691	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3692		nvlist_free(policy);
3693		return (1);
3694	}
3695
3696	if (zpool_clear(zhp, device, policy) != 0)
3697		ret = 1;
3698
3699	zpool_close(zhp);
3700
3701	nvlist_free(policy);
3702
3703	return (ret);
3704}
3705
3706/*
3707 * zpool reguid <pool>
3708 */
3709int
3710zpool_do_reguid(int argc, char **argv)
3711{
3712	int c;
3713	char *poolname;
3714	zpool_handle_t *zhp;
3715	int ret = 0;
3716
3717	/* check options */
3718	while ((c = getopt(argc, argv, "")) != -1) {
3719		switch (c) {
3720		case '?':
3721			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3722			    optopt);
3723			usage(B_FALSE);
3724		}
3725	}
3726
3727	argc -= optind;
3728	argv += optind;
3729
3730	/* get pool name and check number of arguments */
3731	if (argc < 1) {
3732		(void) fprintf(stderr, gettext("missing pool name\n"));
3733		usage(B_FALSE);
3734	}
3735
3736	if (argc > 1) {
3737		(void) fprintf(stderr, gettext("too many arguments\n"));
3738		usage(B_FALSE);
3739	}
3740
3741	poolname = argv[0];
3742	if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3743		return (1);
3744
3745	ret = zpool_reguid(zhp);
3746
3747	zpool_close(zhp);
3748	return (ret);
3749}
3750
3751
3752/*
3753 * zpool reopen <pool>
3754 *
3755 * Reopen the pool so that the kernel can update the sizes of all vdevs.
3756 */
3757int
3758zpool_do_reopen(int argc, char **argv)
3759{
3760	int c;
3761	int ret = 0;
3762	zpool_handle_t *zhp;
3763	char *pool;
3764
3765	/* check options */
3766	while ((c = getopt(argc, argv, "")) != -1) {
3767		switch (c) {
3768		case '?':
3769			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3770			    optopt);
3771			usage(B_FALSE);
3772		}
3773	}
3774
3775	argc--;
3776	argv++;
3777
3778	if (argc < 1) {
3779		(void) fprintf(stderr, gettext("missing pool name\n"));
3780		usage(B_FALSE);
3781	}
3782
3783	if (argc > 1) {
3784		(void) fprintf(stderr, gettext("too many arguments\n"));
3785		usage(B_FALSE);
3786	}
3787
3788	pool = argv[0];
3789	if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
3790		return (1);
3791
3792	ret = zpool_reopen(zhp);
3793	zpool_close(zhp);
3794	return (ret);
3795}
3796
3797typedef struct scrub_cbdata {
3798	int	cb_type;
3799	int	cb_argc;
3800	char	**cb_argv;
3801} scrub_cbdata_t;
3802
3803int
3804scrub_callback(zpool_handle_t *zhp, void *data)
3805{
3806	scrub_cbdata_t *cb = data;
3807	int err;
3808
3809	/*
3810	 * Ignore faulted pools.
3811	 */
3812	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3813		(void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3814		    "currently unavailable\n"), zpool_get_name(zhp));
3815		return (1);
3816	}
3817
3818	err = zpool_scan(zhp, cb->cb_type);
3819
3820	return (err != 0);
3821}
3822
3823/*
3824 * zpool scrub [-s] <pool> ...
3825 *
3826 *	-s	Stop.  Stops any in-progress scrub.
3827 */
3828int
3829zpool_do_scrub(int argc, char **argv)
3830{
3831	int c;
3832	scrub_cbdata_t cb;
3833
3834	cb.cb_type = POOL_SCAN_SCRUB;
3835
3836	/* check options */
3837	while ((c = getopt(argc, argv, "s")) != -1) {
3838		switch (c) {
3839		case 's':
3840			cb.cb_type = POOL_SCAN_NONE;
3841			break;
3842		case '?':
3843			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3844			    optopt);
3845			usage(B_FALSE);
3846		}
3847	}
3848
3849	cb.cb_argc = argc;
3850	cb.cb_argv = argv;
3851	argc -= optind;
3852	argv += optind;
3853
3854	if (argc < 1) {
3855		(void) fprintf(stderr, gettext("missing pool name argument\n"));
3856		usage(B_FALSE);
3857	}
3858
3859	return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
3860}
3861
3862typedef struct status_cbdata {
3863	int		cb_count;
3864	boolean_t	cb_allpools;
3865	boolean_t	cb_verbose;
3866	boolean_t	cb_explain;
3867	boolean_t	cb_first;
3868	boolean_t	cb_dedup_stats;
3869} status_cbdata_t;
3870
3871/*
3872 * Print out detailed scrub status.
3873 */
3874void
3875print_scan_status(pool_scan_stat_t *ps)
3876{
3877	time_t start, end;
3878	uint64_t elapsed, mins_left, hours_left;
3879	uint64_t pass_exam, examined, total;
3880	uint_t rate;
3881	double fraction_done;
3882	char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
3883
3884	(void) printf(gettext("  scan: "));
3885
3886	/* If there's never been a scan, there's not much to say. */
3887	if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
3888	    ps->pss_func >= POOL_SCAN_FUNCS) {
3889		(void) printf(gettext("none requested\n"));
3890		return;
3891	}
3892
3893	start = ps->pss_start_time;
3894	end = ps->pss_end_time;
3895	zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
3896
3897	assert(ps->pss_func == POOL_SCAN_SCRUB ||
3898	    ps->pss_func == POOL_SCAN_RESILVER);
3899	/*
3900	 * Scan is finished or canceled.
3901	 */
3902	if (ps->pss_state == DSS_FINISHED) {
3903		uint64_t minutes_taken = (end - start) / 60;
3904		char *fmt;
3905
3906		if (ps->pss_func == POOL_SCAN_SCRUB) {
3907			fmt = gettext("scrub repaired %s in %lluh%um with "
3908			    "%llu errors on %s");
3909		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
3910			fmt = gettext("resilvered %s in %lluh%um with "
3911			    "%llu errors on %s");
3912		}
3913		/* LINTED */
3914		(void) printf(fmt, processed_buf,
3915		    (u_longlong_t)(minutes_taken / 60),
3916		    (uint_t)(minutes_taken % 60),
3917		    (u_longlong_t)ps->pss_errors,
3918		    ctime((time_t *)&end));
3919		return;
3920	} else if (ps->pss_state == DSS_CANCELED) {
3921		if (ps->pss_func == POOL_SCAN_SCRUB) {
3922			(void) printf(gettext("scrub canceled on %s"),
3923			    ctime(&end));
3924		} else if (ps->pss_func == POOL_SCAN_RESILVER) {
3925			(void) printf(gettext("resilver canceled on %s"),
3926			    ctime(&end));
3927		}
3928		return;
3929	}
3930
3931	assert(ps->pss_state == DSS_SCANNING);
3932
3933	/*
3934	 * Scan is in progress.
3935	 */
3936	if (ps->pss_func == POOL_SCAN_SCRUB) {
3937		(void) printf(gettext("scrub in progress since %s"),
3938		    ctime(&start));
3939	} else if (ps->pss_func == POOL_SCAN_RESILVER) {
3940		(void) printf(gettext("resilver in progress since %s"),
3941		    ctime(&start));
3942	}
3943
3944	examined = ps->pss_examined ? ps->pss_examined : 1;
3945	total = ps->pss_to_examine;
3946	fraction_done = (double)examined / total;
3947
3948	/* elapsed time for this pass */
3949	elapsed = time(NULL) - ps->pss_pass_start;
3950	elapsed = elapsed ? elapsed : 1;
3951	pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
3952	rate = pass_exam / elapsed;
3953	rate = rate ? rate : 1;
3954	mins_left = ((total - examined) / rate) / 60;
3955	hours_left = mins_left / 60;
3956
3957	zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
3958	zfs_nicenum(total, total_buf, sizeof (total_buf));
3959	zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
3960
3961	/*
3962	 * do not print estimated time if hours_left is more than 30 days
3963	 */
3964	(void) printf(gettext("        %s scanned out of %s at %s/s"),
3965	    examined_buf, total_buf, rate_buf);
3966	if (hours_left < (30 * 24)) {
3967		(void) printf(gettext(", %lluh%um to go\n"),
3968		    (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
3969	} else {
3970		(void) printf(gettext(
3971		    ", (scan is slow, no estimated time)\n"));
3972	}
3973
3974	if (ps->pss_func == POOL_SCAN_RESILVER) {
3975		(void) printf(gettext("        %s resilvered, %.2f%% done\n"),
3976		    processed_buf, 100 * fraction_done);
3977	} else if (ps->pss_func == POOL_SCAN_SCRUB) {
3978		(void) printf(gettext("        %s repaired, %.2f%% done\n"),
3979		    processed_buf, 100 * fraction_done);
3980	}
3981}
3982
3983static void
3984print_error_log(zpool_handle_t *zhp)
3985{
3986	nvlist_t *nverrlist = NULL;
3987	nvpair_t *elem;
3988	char *pathname;
3989	size_t len = MAXPATHLEN * 2;
3990
3991	if (zpool_get_errlog(zhp, &nverrlist) != 0) {
3992		(void) printf("errors: List of errors unavailable "
3993		    "(insufficient privileges)\n");
3994		return;
3995	}
3996
3997	(void) printf("errors: Permanent errors have been "
3998	    "detected in the following files:\n\n");
3999
4000	pathname = safe_malloc(len);
4001	elem = NULL;
4002	while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4003		nvlist_t *nv;
4004		uint64_t dsobj, obj;
4005
4006		verify(nvpair_value_nvlist(elem, &nv) == 0);
4007		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4008		    &dsobj) == 0);
4009		verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4010		    &obj) == 0);
4011		zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4012		(void) printf("%7s %s\n", "", pathname);
4013	}
4014	free(pathname);
4015	nvlist_free(nverrlist);
4016}
4017
4018static void
4019print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4020    int namewidth)
4021{
4022	uint_t i;
4023	char *name;
4024
4025	if (nspares == 0)
4026		return;
4027
4028	(void) printf(gettext("\tspares\n"));
4029
4030	for (i = 0; i < nspares; i++) {
4031		name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4032		print_status_config(zhp, name, spares[i],
4033		    namewidth, 2, B_TRUE);
4034		free(name);
4035	}
4036}
4037
4038static void
4039print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4040    int namewidth)
4041{
4042	uint_t i;
4043	char *name;
4044
4045	if (nl2cache == 0)
4046		return;
4047
4048	(void) printf(gettext("\tcache\n"));
4049
4050	for (i = 0; i < nl2cache; i++) {
4051		name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4052		print_status_config(zhp, name, l2cache[i],
4053		    namewidth, 2, B_FALSE);
4054		free(name);
4055	}
4056}
4057
4058static void
4059print_dedup_stats(nvlist_t *config)
4060{
4061	ddt_histogram_t *ddh;
4062	ddt_stat_t *dds;
4063	ddt_object_t *ddo;
4064	uint_t c;
4065
4066	/*
4067	 * If the pool was faulted then we may not have been able to
4068	 * obtain the config. Otherwise, if we have anything in the dedup
4069	 * table continue processing the stats.
4070	 */
4071	if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4072	    (uint64_t **)&ddo, &c) != 0)
4073		return;
4074
4075	(void) printf("\n");
4076	(void) printf(gettext(" dedup: "));
4077	if (ddo->ddo_count == 0) {
4078		(void) printf(gettext("no DDT entries\n"));
4079		return;
4080	}
4081
4082	(void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4083	    (u_longlong_t)ddo->ddo_count,
4084	    (u_longlong_t)ddo->ddo_dspace,
4085	    (u_longlong_t)ddo->ddo_mspace);
4086
4087	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4088	    (uint64_t **)&dds, &c) == 0);
4089	verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4090	    (uint64_t **)&ddh, &c) == 0);
4091	zpool_dump_ddt(dds, ddh);
4092}
4093
4094/*
4095 * Display a summary of pool status.  Displays a summary such as:
4096 *
4097 *        pool: tank
4098 *	status: DEGRADED
4099 *	reason: One or more devices ...
4100 *         see: http://illumos.org/msg/ZFS-xxxx-01
4101 *	config:
4102 *		mirror		DEGRADED
4103 *                c1t0d0	OK
4104 *                c2t0d0	UNAVAIL
4105 *
4106 * When given the '-v' option, we print out the complete config.  If the '-e'
4107 * option is specified, then we print out error rate information as well.
4108 */
4109int
4110status_callback(zpool_handle_t *zhp, void *data)
4111{
4112	status_cbdata_t *cbp = data;
4113	nvlist_t *config, *nvroot;
4114	char *msgid;
4115	int reason;
4116	const char *health;
4117	uint_t c;
4118	vdev_stat_t *vs;
4119
4120	config = zpool_get_config(zhp, NULL);
4121	reason = zpool_get_status(zhp, &msgid);
4122
4123	cbp->cb_count++;
4124
4125	/*
4126	 * If we were given 'zpool status -x', only report those pools with
4127	 * problems.
4128	 */
4129	if (cbp->cb_explain &&
4130	    (reason == ZPOOL_STATUS_OK ||
4131	    reason == ZPOOL_STATUS_VERSION_OLDER ||
4132	    reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
4133	    reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4134		if (!cbp->cb_allpools) {
4135			(void) printf(gettext("pool '%s' is healthy\n"),
4136			    zpool_get_name(zhp));
4137			if (cbp->cb_first)
4138				cbp->cb_first = B_FALSE;
4139		}
4140		return (0);
4141	}
4142
4143	if (cbp->cb_first)
4144		cbp->cb_first = B_FALSE;
4145	else
4146		(void) printf("\n");
4147
4148	verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4149	    &nvroot) == 0);
4150	verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4151	    (uint64_t **)&vs, &c) == 0);
4152	health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4153
4154	(void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
4155	(void) printf(gettext(" state: %s\n"), health);
4156
4157	switch (reason) {
4158	case ZPOOL_STATUS_MISSING_DEV_R:
4159		(void) printf(gettext("status: One or more devices could not "
4160		    "be opened.  Sufficient replicas exist for\n\tthe pool to "
4161		    "continue functioning in a degraded state.\n"));
4162		(void) printf(gettext("action: Attach the missing device and "
4163		    "online it using 'zpool online'.\n"));
4164		break;
4165
4166	case ZPOOL_STATUS_MISSING_DEV_NR:
4167		(void) printf(gettext("status: One or more devices could not "
4168		    "be opened.  There are insufficient\n\treplicas for the "
4169		    "pool to continue functioning.\n"));
4170		(void) printf(gettext("action: Attach the missing device and "
4171		    "online it using 'zpool online'.\n"));
4172		break;
4173
4174	case ZPOOL_STATUS_CORRUPT_LABEL_R:
4175		(void) printf(gettext("status: One or more devices could not "
4176		    "be used because the label is missing or\n\tinvalid.  "
4177		    "Sufficient replicas exist for the pool to continue\n\t"
4178		    "functioning in a degraded state.\n"));
4179		(void) printf(gettext("action: Replace the device using "
4180		    "'zpool replace'.\n"));
4181		break;
4182
4183	case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4184		(void) printf(gettext("status: One or more devices could not "
4185		    "be used because the label is missing \n\tor invalid.  "
4186		    "There are insufficient replicas for the pool to "
4187		    "continue\n\tfunctioning.\n"));
4188		zpool_explain_recover(zpool_get_handle(zhp),
4189		    zpool_get_name(zhp), reason, config);
4190		break;
4191
4192	case ZPOOL_STATUS_FAILING_DEV:
4193		(void) printf(gettext("status: One or more devices has "
4194		    "experienced an unrecoverable error.  An\n\tattempt was "
4195		    "made to correct the error.  Applications are "
4196		    "unaffected.\n"));
4197		(void) printf(gettext("action: Determine if the device needs "
4198		    "to be replaced, and clear the errors\n\tusing "
4199		    "'zpool clear' or replace the device with 'zpool "
4200		    "replace'.\n"));
4201		break;
4202
4203	case ZPOOL_STATUS_OFFLINE_DEV:
4204		(void) printf(gettext("status: One or more devices has "
4205		    "been taken offline by the administrator.\n\tSufficient "
4206		    "replicas exist for the pool to continue functioning in "
4207		    "a\n\tdegraded state.\n"));
4208		(void) printf(gettext("action: Online the device using "
4209		    "'zpool online' or replace the device with\n\t'zpool "
4210		    "replace'.\n"));
4211		break;
4212
4213	case ZPOOL_STATUS_REMOVED_DEV:
4214		(void) printf(gettext("status: One or more devices has "
4215		    "been removed by the administrator.\n\tSufficient "
4216		    "replicas exist for the pool to continue functioning in "
4217		    "a\n\tdegraded state.\n"));
4218		(void) printf(gettext("action: Online the device using "
4219		    "'zpool online' or replace the device with\n\t'zpool "
4220		    "replace'.\n"));
4221		break;
4222
4223	case ZPOOL_STATUS_RESILVERING:
4224		(void) printf(gettext("status: One or more devices is "
4225		    "currently being resilvered.  The pool will\n\tcontinue "
4226		    "to function, possibly in a degraded state.\n"));
4227		(void) printf(gettext("action: Wait for the resilver to "
4228		    "complete.\n"));
4229		break;
4230
4231	case ZPOOL_STATUS_CORRUPT_DATA:
4232		(void) printf(gettext("status: One or more devices has "
4233		    "experienced an error resulting in data\n\tcorruption.  "
4234		    "Applications may be affected.\n"));
4235		(void) printf(gettext("action: Restore the file in question "
4236		    "if possible.  Otherwise restore the\n\tentire pool from "
4237		    "backup.\n"));
4238		break;
4239
4240	case ZPOOL_STATUS_CORRUPT_POOL:
4241		(void) printf(gettext("status: The pool metadata is corrupted "
4242		    "and the pool cannot be opened.\n"));
4243		zpool_explain_recover(zpool_get_handle(zhp),
4244		    zpool_get_name(zhp), reason, config);
4245		break;
4246
4247	case ZPOOL_STATUS_VERSION_OLDER:
4248		(void) printf(gettext("status: The pool is formatted using a "
4249		    "legacy on-disk format.  The pool can\n\tstill be used, "
4250		    "but some features are unavailable.\n"));
4251		(void) printf(gettext("action: Upgrade the pool using 'zpool "
4252		    "upgrade'.  Once this is done, the\n\tpool will no longer "
4253		    "be accessible on software that does not support feature\n"
4254		    "\tflags.\n"));
4255		break;
4256
4257	case ZPOOL_STATUS_VERSION_NEWER:
4258		(void) printf(gettext("status: The pool has been upgraded to a "
4259		    "newer, incompatible on-disk version.\n\tThe pool cannot "
4260		    "be accessed on this system.\n"));
4261		(void) printf(gettext("action: Access the pool from a system "
4262		    "running more recent software, or\n\trestore the pool from "
4263		    "backup.\n"));
4264		break;
4265
4266	case ZPOOL_STATUS_FEAT_DISABLED:
4267		(void) printf(gettext("status: Some supported features are not "
4268		    "enabled on the pool. The pool can\n\tstill be used, but "
4269		    "some features are unavailable.\n"));
4270		(void) printf(gettext("action: Enable all features using "
4271		    "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4272		    "longer be accessible by software that does not support\n\t"
4273		    "the features. See zpool-features(7) for details.\n"));
4274		break;
4275
4276	case ZPOOL_STATUS_UNSUP_FEAT_READ:
4277		(void) printf(gettext("status: The pool cannot be accessed on "
4278		    "this system because it uses the\n\tfollowing feature(s) "
4279		    "not supported on this system:\n"));
4280		zpool_print_unsup_feat(config);
4281		(void) printf("\n");
4282		(void) printf(gettext("action: Access the pool from a system "
4283		    "that supports the required feature(s),\n\tor restore the "
4284		    "pool from backup.\n"));
4285		break;
4286
4287	case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4288		(void) printf(gettext("status: The pool can only be accessed "
4289		    "in read-only mode on this system. It\n\tcannot be "
4290		    "accessed in read-write mode because it uses the "
4291		    "following\n\tfeature(s) not supported on this system:\n"));
4292		zpool_print_unsup_feat(config);
4293		(void) printf("\n");
4294		(void) printf(gettext("action: The pool cannot be accessed in "
4295		    "read-write mode. Import the pool with\n"
4296		    "\t\"-o readonly=on\", access the pool from a system that "
4297		    "supports the\n\trequired feature(s), or restore the "
4298		    "pool from backup.\n"));
4299		break;
4300
4301	case ZPOOL_STATUS_FAULTED_DEV_R:
4302		(void) printf(gettext("status: One or more devices are "
4303		    "faulted in response to persistent errors.\n\tSufficient "
4304		    "replicas exist for the pool to continue functioning "
4305		    "in a\n\tdegraded state.\n"));
4306		(void) printf(gettext("action: Replace the faulted device, "
4307		    "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4308		break;
4309
4310	case ZPOOL_STATUS_FAULTED_DEV_NR:
4311		(void) printf(gettext("status: One or more devices are "
4312		    "faulted in response to persistent errors.  There are "
4313		    "insufficient replicas for the pool to\n\tcontinue "
4314		    "functioning.\n"));
4315		(void) printf(gettext("action: Destroy and re-create the pool "
4316		    "from a backup source.  Manually marking the device\n"
4317		    "\trepaired using 'zpool clear' may allow some data "
4318		    "to be recovered.\n"));
4319		break;
4320
4321	case ZPOOL_STATUS_IO_FAILURE_WAIT:
4322	case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4323		(void) printf(gettext("status: One or more devices are "
4324		    "faulted in response to IO failures.\n"));
4325		(void) printf(gettext("action: Make sure the affected devices "
4326		    "are connected, then run 'zpool clear'.\n"));
4327		break;
4328
4329	case ZPOOL_STATUS_BAD_LOG:
4330		(void) printf(gettext("status: An intent log record "
4331		    "could not be read.\n"
4332		    "\tWaiting for adminstrator intervention to fix the "
4333		    "faulted pool.\n"));
4334		(void) printf(gettext("action: Either restore the affected "
4335		    "device(s) and run 'zpool online',\n"
4336		    "\tor ignore the intent log records by running "
4337		    "'zpool clear'.\n"));
4338		break;
4339
4340	case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
4341		(void) printf(gettext("status: One or more devices are "
4342		    "configured to use a non-native block size.\n"
4343		    "\tExpect reduced performance.\n"));
4344		(void) printf(gettext("action: Replace affected devices with "
4345		    "devices that support the\n\tconfigured block size, or "
4346		    "migrate data to a properly configured\n\tpool.\n"));
4347		break;
4348
4349	default:
4350		/*
4351		 * The remaining errors can't actually be generated, yet.
4352		 */
4353		assert(reason == ZPOOL_STATUS_OK);
4354	}
4355
4356	if (msgid != NULL)
4357		(void) printf(gettext("   see: http://illumos.org/msg/%s\n"),
4358		    msgid);
4359
4360	if (config != NULL) {
4361		int namewidth;
4362		uint64_t nerr;
4363		nvlist_t **spares, **l2cache;
4364		uint_t nspares, nl2cache;
4365		pool_scan_stat_t *ps = NULL;
4366
4367		(void) nvlist_lookup_uint64_array(nvroot,
4368		    ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4369		print_scan_status(ps);
4370
4371		namewidth = max_width(zhp, nvroot, 0, 0);
4372		if (namewidth < 10)
4373			namewidth = 10;
4374
4375		(void) printf(gettext("config:\n\n"));
4376		(void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
4377		    "NAME", "STATE", "READ", "WRITE", "CKSUM");
4378		print_status_config(zhp, zpool_get_name(zhp), nvroot,
4379		    namewidth, 0, B_FALSE);
4380
4381		if (num_logs(nvroot) > 0)
4382			print_logs(zhp, nvroot, namewidth, B_TRUE);
4383		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4384		    &l2cache, &nl2cache) == 0)
4385			print_l2cache(zhp, l2cache, nl2cache, namewidth);
4386
4387		if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4388		    &spares, &nspares) == 0)
4389			print_spares(zhp, spares, nspares, namewidth);
4390
4391		if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4392		    &nerr) == 0) {
4393			nvlist_t *nverrlist = NULL;
4394
4395			/*
4396			 * If the approximate error count is small, get a
4397			 * precise count by fetching the entire log and
4398			 * uniquifying the results.
4399			 */
4400			if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4401			    zpool_get_errlog(zhp, &nverrlist) == 0) {
4402				nvpair_t *elem;
4403
4404				elem = NULL;
4405				nerr = 0;
4406				while ((elem = nvlist_next_nvpair(nverrlist,
4407				    elem)) != NULL) {
4408					nerr++;
4409				}
4410			}
4411			nvlist_free(nverrlist);
4412
4413			(void) printf("\n");
4414
4415			if (nerr == 0)
4416				(void) printf(gettext("errors: No known data "
4417				    "errors\n"));
4418			else if (!cbp->cb_verbose)
4419				(void) printf(gettext("errors: %llu data "
4420				    "errors, use '-v' for a list\n"),
4421				    (u_longlong_t)nerr);
4422			else
4423				print_error_log(zhp);
4424		}
4425
4426		if (cbp->cb_dedup_stats)
4427			print_dedup_stats(config);
4428	} else {
4429		(void) printf(gettext("config: The configuration cannot be "
4430		    "determined.\n"));
4431	}
4432
4433	return (0);
4434}
4435
4436/*
4437 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4438 *
4439 *	-v	Display complete error logs
4440 *	-x	Display only pools with potential problems
4441 *	-D	Display dedup status (undocumented)
4442 *	-T	Display a timestamp in date(1) or Unix format
4443 *
4444 * Describes the health status of all pools or some subset.
4445 */
4446int
4447zpool_do_status(int argc, char **argv)
4448{
4449	int c;
4450	int ret;
4451	unsigned long interval = 0, count = 0;
4452	status_cbdata_t cb = { 0 };
4453
4454	/* check options */
4455	while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4456		switch (c) {
4457		case 'v':
4458			cb.cb_verbose = B_TRUE;
4459			break;
4460		case 'x':
4461			cb.cb_explain = B_TRUE;
4462			break;
4463		case 'D':
4464			cb.cb_dedup_stats = B_TRUE;
4465			break;
4466		case 'T':
4467			get_timestamp_arg(*optarg);
4468			break;
4469		case '?':
4470			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4471			    optopt);
4472			usage(B_FALSE);
4473		}
4474	}
4475
4476	argc -= optind;
4477	argv += optind;
4478
4479	get_interval_count(&argc, argv, &interval, &count);
4480
4481	if (argc == 0)
4482		cb.cb_allpools = B_TRUE;
4483
4484	cb.cb_first = B_TRUE;
4485
4486	for (;;) {
4487		if (timestamp_fmt != NODATE)
4488			print_timestamp(timestamp_fmt);
4489
4490		ret = for_each_pool(argc, argv, B_TRUE, NULL,
4491		    status_callback, &cb);
4492
4493		if (argc == 0 && cb.cb_count == 0)
4494			(void) printf(gettext("no pools available\n"));
4495		else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4496			(void) printf(gettext("all pools are healthy\n"));
4497
4498		if (ret != 0)
4499			return (ret);
4500
4501		if (interval == 0)
4502			break;
4503
4504		if (count != 0 && --count == 0)
4505			break;
4506
4507		(void) sleep(interval);
4508	}
4509
4510	return (0);
4511}
4512
4513typedef struct upgrade_cbdata {
4514	boolean_t	cb_first;
4515	boolean_t	cb_unavail;
4516	char		cb_poolname[ZPOOL_MAXNAMELEN];
4517	int		cb_argc;
4518	uint64_t	cb_version;
4519	char		**cb_argv;
4520} upgrade_cbdata_t;
4521
4522#ifdef __FreeBSD__
4523static int
4524is_root_pool(zpool_handle_t *zhp)
4525{
4526	static struct statfs sfs;
4527	static char *poolname = NULL;
4528	static boolean_t stated = B_FALSE;
4529	char *slash;
4530
4531	if (!stated) {
4532		stated = B_TRUE;
4533		if (statfs("/", &sfs) == -1) {
4534			(void) fprintf(stderr,
4535			    "Unable to stat root file system: %s.\n",
4536			    strerror(errno));
4537			return (0);
4538		}
4539		if (strcmp(sfs.f_fstypename, "zfs") != 0)
4540			return (0);
4541		poolname = sfs.f_mntfromname;
4542		if ((slash = strchr(poolname, '/')) != NULL)
4543			*slash = '\0';
4544	}
4545	return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
4546}
4547
4548static void
4549root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
4550{
4551
4552	if (poolname[0] == '\0' && is_root_pool(zhp))
4553		(void) strlcpy(poolname, zpool_get_name(zhp), size);
4554}
4555#endif	/* FreeBSD */
4556
4557static int
4558upgrade_version(zpool_handle_t *zhp, uint64_t version)
4559{
4560	int ret;
4561	nvlist_t *config;
4562	uint64_t oldversion;
4563
4564	config = zpool_get_config(zhp, NULL);
4565	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4566	    &oldversion) == 0);
4567
4568	assert(SPA_VERSION_IS_SUPPORTED(oldversion));
4569	assert(oldversion < version);
4570
4571	ret = zpool_upgrade(zhp, version);
4572	if (ret != 0)
4573		return (ret);
4574
4575	if (version >= SPA_VERSION_FEATURES) {
4576		(void) printf(gettext("Successfully upgraded "
4577		    "'%s' from version %llu to feature flags.\n"),
4578		    zpool_get_name(zhp), oldversion);
4579	} else {
4580		(void) printf(gettext("Successfully upgraded "
4581		    "'%s' from version %llu to version %llu.\n"),
4582		    zpool_get_name(zhp), oldversion, version);
4583	}
4584
4585	return (0);
4586}
4587
4588static int
4589upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4590{
4591	int i, ret, count;
4592	boolean_t firstff = B_TRUE;
4593	nvlist_t *enabled = zpool_get_features(zhp);
4594
4595	count = 0;
4596	for (i = 0; i < SPA_FEATURES; i++) {
4597		const char *fname = spa_feature_table[i].fi_uname;
4598		const char *fguid = spa_feature_table[i].fi_guid;
4599		if (!nvlist_exists(enabled, fguid)) {
4600			char *propname;
4601			verify(-1 != asprintf(&propname, "feature@%s", fname));
4602			ret = zpool_set_prop(zhp, propname,
4603			    ZFS_FEATURE_ENABLED);
4604			if (ret != 0) {
4605				free(propname);
4606				return (ret);
4607			}
4608			count++;
4609
4610			if (firstff) {
4611				(void) printf(gettext("Enabled the "
4612				    "following features on '%s':\n"),
4613				    zpool_get_name(zhp));
4614				firstff = B_FALSE;
4615			}
4616			(void) printf(gettext("  %s\n"), fname);
4617			free(propname);
4618		}
4619	}
4620
4621	if (countp != NULL)
4622		*countp = count;
4623	return (0);
4624}
4625
4626static int
4627upgrade_cb(zpool_handle_t *zhp, void *arg)
4628{
4629	upgrade_cbdata_t *cbp = arg;
4630	nvlist_t *config;
4631	uint64_t version;
4632	boolean_t printnl = B_FALSE;
4633	int ret;
4634
4635	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4636		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
4637		    "currently unavailable.\n\n"), zpool_get_name(zhp));
4638		cbp->cb_unavail = B_TRUE;
4639		/* Allow iteration to continue. */
4640		return (0);
4641	}
4642
4643	config = zpool_get_config(zhp, NULL);
4644	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4645	    &version) == 0);
4646
4647	assert(SPA_VERSION_IS_SUPPORTED(version));
4648
4649	if (version < cbp->cb_version) {
4650		cbp->cb_first = B_FALSE;
4651		ret = upgrade_version(zhp, cbp->cb_version);
4652		if (ret != 0)
4653			return (ret);
4654#ifdef __FreeBSD__
4655		root_pool_upgrade_check(zhp, cbp->cb_poolname,
4656		    sizeof(cbp->cb_poolname));
4657#endif	/* __FreeBSD__ */
4658		printnl = B_TRUE;
4659
4660#ifdef illumos
4661		/*
4662		 * If they did "zpool upgrade -a", then we could
4663		 * be doing ioctls to different pools.  We need
4664		 * to log this history once to each pool, and bypass
4665		 * the normal history logging that happens in main().
4666		 */
4667		(void) zpool_log_history(g_zfs, history_str);
4668		log_history = B_FALSE;
4669#endif
4670	}
4671
4672	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4673		int count;
4674		ret = upgrade_enable_all(zhp, &count);
4675		if (ret != 0)
4676			return (ret);
4677
4678		if (count > 0) {
4679			cbp->cb_first = B_FALSE;
4680			printnl = B_TRUE;
4681#ifdef __FreeBSD__
4682			root_pool_upgrade_check(zhp, cbp->cb_poolname,
4683			    sizeof(cbp->cb_poolname));
4684#endif	/* __FreeBSD__ */
4685			/*
4686			 * If they did "zpool upgrade -a", then we could
4687			 * be doing ioctls to different pools.  We need
4688			 * to log this history once to each pool, and bypass
4689			 * the normal history logging that happens in main().
4690			 */
4691			(void) zpool_log_history(g_zfs, history_str);
4692			log_history = B_FALSE;
4693		}
4694	}
4695
4696	if (printnl) {
4697		(void) printf(gettext("\n"));
4698	}
4699
4700	return (0);
4701}
4702
4703static int
4704upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
4705{
4706	upgrade_cbdata_t *cbp = arg;
4707
4708	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4709		if (cbp->cb_first) {
4710			(void) fprintf(stderr, gettext("The following pools "
4711			    "are unavailable and cannot be upgraded as this "
4712			    "time.\n\n"));
4713			(void) fprintf(stderr, gettext("POOL\n"));
4714			(void) fprintf(stderr, gettext("------------\n"));
4715			cbp->cb_first = B_FALSE;
4716		}
4717		(void) printf(gettext("%s\n"), zpool_get_name(zhp));
4718		cbp->cb_unavail = B_TRUE;
4719	}
4720	return (0);
4721}
4722
4723static int
4724upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
4725{
4726	upgrade_cbdata_t *cbp = arg;
4727	nvlist_t *config;
4728	uint64_t version;
4729
4730	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4731		/*
4732		 * This will have been reported by upgrade_list_unavail so
4733		 * just allow iteration to continue.
4734		 */
4735		cbp->cb_unavail = B_TRUE;
4736		return (0);
4737	}
4738
4739	config = zpool_get_config(zhp, NULL);
4740	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4741	    &version) == 0);
4742
4743	assert(SPA_VERSION_IS_SUPPORTED(version));
4744
4745	if (version < SPA_VERSION_FEATURES) {
4746		if (cbp->cb_first) {
4747			(void) printf(gettext("The following pools are "
4748			    "formatted with legacy version numbers and can\n"
4749			    "be upgraded to use feature flags.  After "
4750			    "being upgraded, these pools\nwill no "
4751			    "longer be accessible by software that does not "
4752			    "support feature\nflags.\n\n"));
4753			(void) printf(gettext("VER  POOL\n"));
4754			(void) printf(gettext("---  ------------\n"));
4755			cbp->cb_first = B_FALSE;
4756		}
4757
4758		(void) printf("%2llu   %s\n", (u_longlong_t)version,
4759		    zpool_get_name(zhp));
4760	}
4761
4762	return (0);
4763}
4764
4765static int
4766upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
4767{
4768	upgrade_cbdata_t *cbp = arg;
4769	nvlist_t *config;
4770	uint64_t version;
4771
4772	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4773		/*
4774		 * This will have been reported by upgrade_list_unavail so
4775		 * just allow iteration to continue.
4776		 */
4777		cbp->cb_unavail = B_TRUE;
4778		return (0);
4779	}
4780
4781	config = zpool_get_config(zhp, NULL);
4782	verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4783	    &version) == 0);
4784
4785	if (version >= SPA_VERSION_FEATURES) {
4786		int i;
4787		boolean_t poolfirst = B_TRUE;
4788		nvlist_t *enabled = zpool_get_features(zhp);
4789
4790		for (i = 0; i < SPA_FEATURES; i++) {
4791			const char *fguid = spa_feature_table[i].fi_guid;
4792			const char *fname = spa_feature_table[i].fi_uname;
4793			if (!nvlist_exists(enabled, fguid)) {
4794				if (cbp->cb_first) {
4795					(void) printf(gettext("\nSome "
4796					    "supported features are not "
4797					    "enabled on the following pools. "
4798					    "Once a\nfeature is enabled the "
4799					    "pool may become incompatible with "
4800					    "software\nthat does not support "
4801					    "the feature. See "
4802					    "zpool-features(7) for "
4803					    "details.\n\n"));
4804					(void) printf(gettext("POOL  "
4805					    "FEATURE\n"));
4806					(void) printf(gettext("------"
4807					    "---------\n"));
4808					cbp->cb_first = B_FALSE;
4809				}
4810
4811				if (poolfirst) {
4812					(void) printf(gettext("%s\n"),
4813					    zpool_get_name(zhp));
4814					poolfirst = B_FALSE;
4815				}
4816
4817				(void) printf(gettext("      %s\n"), fname);
4818			}
4819		}
4820	}
4821
4822	return (0);
4823}
4824
4825/* ARGSUSED */
4826static int
4827upgrade_one(zpool_handle_t *zhp, void *data)
4828{
4829	boolean_t printnl = B_FALSE;
4830	upgrade_cbdata_t *cbp = data;
4831	uint64_t cur_version;
4832	int ret;
4833
4834	if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4835		(void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
4836		    "is currently unavailable.\n\n"), zpool_get_name(zhp));
4837		cbp->cb_unavail = B_TRUE;
4838		return (1);
4839	}
4840
4841	if (strcmp("log", zpool_get_name(zhp)) == 0) {
4842		(void) printf(gettext("'log' is now a reserved word\n"
4843		    "Pool 'log' must be renamed using export and import"
4844		    " to upgrade.\n\n"));
4845		return (1);
4846	}
4847
4848	cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4849	if (cur_version > cbp->cb_version) {
4850		(void) printf(gettext("Pool '%s' is already formatted "
4851		    "using more current version '%llu'.\n\n"),
4852		    zpool_get_name(zhp), cur_version);
4853		return (0);
4854	}
4855
4856	if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
4857		(void) printf(gettext("Pool '%s' is already formatted "
4858		    "using version %llu.\n\n"), zpool_get_name(zhp),
4859		    cbp->cb_version);
4860		return (0);
4861	}
4862
4863	if (cur_version != cbp->cb_version) {
4864		printnl = B_TRUE;
4865		ret = upgrade_version(zhp, cbp->cb_version);
4866		if (ret != 0)
4867			return (ret);
4868#ifdef __FreeBSD__
4869		root_pool_upgrade_check(zhp, cbp->cb_poolname,
4870		    sizeof(cbp->cb_poolname));
4871#endif	/* __FreeBSD__ */
4872	}
4873
4874	if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4875		int count = 0;
4876		ret = upgrade_enable_all(zhp, &count);
4877		if (ret != 0)
4878			return (ret);
4879
4880		if (count != 0) {
4881			printnl = B_TRUE;
4882#ifdef __FreeBSD__
4883			root_pool_upgrade_check(zhp, cbp->cb_poolname,
4884			    sizeof(cbp->cb_poolname));
4885#endif	/* __FreeBSD __*/
4886		} else if (cur_version == SPA_VERSION) {
4887			(void) printf(gettext("Pool '%s' already has all "
4888			    "supported features enabled.\n\n"),
4889			    zpool_get_name(zhp));
4890		}
4891	}
4892
4893	if (printnl) {
4894		(void) printf(gettext("\n"));
4895	}
4896
4897	return (0);
4898}
4899
4900/*
4901 * zpool upgrade
4902 * zpool upgrade -v
4903 * zpool upgrade [-V version] <-a | pool ...>
4904 *
4905 * With no arguments, display downrev'd ZFS pool available for upgrade.
4906 * Individual pools can be upgraded by specifying the pool, and '-a' will
4907 * upgrade all pools.
4908 */
4909int
4910zpool_do_upgrade(int argc, char **argv)
4911{
4912	int c;
4913	upgrade_cbdata_t cb = { 0 };
4914	int ret = 0;
4915	boolean_t showversions = B_FALSE;
4916	boolean_t upgradeall = B_FALSE;
4917	char *end;
4918
4919
4920	/* check options */
4921	while ((c = getopt(argc, argv, ":avV:")) != -1) {
4922		switch (c) {
4923		case 'a':
4924			upgradeall = B_TRUE;
4925			break;
4926		case 'v':
4927			showversions = B_TRUE;
4928			break;
4929		case 'V':
4930			cb.cb_version = strtoll(optarg, &end, 10);
4931			if (*end != '\0' ||
4932			    !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
4933				(void) fprintf(stderr,
4934				    gettext("invalid version '%s'\n"), optarg);
4935				usage(B_FALSE);
4936			}
4937			break;
4938		case ':':
4939			(void) fprintf(stderr, gettext("missing argument for "
4940			    "'%c' option\n"), optopt);
4941			usage(B_FALSE);
4942			break;
4943		case '?':
4944			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4945			    optopt);
4946			usage(B_FALSE);
4947		}
4948	}
4949
4950	cb.cb_argc = argc;
4951	cb.cb_argv = argv;
4952	argc -= optind;
4953	argv += optind;
4954
4955	if (cb.cb_version == 0) {
4956		cb.cb_version = SPA_VERSION;
4957	} else if (!upgradeall && argc == 0) {
4958		(void) fprintf(stderr, gettext("-V option is "
4959		    "incompatible with other arguments\n"));
4960		usage(B_FALSE);
4961	}
4962
4963	if (showversions) {
4964		if (upgradeall || argc != 0) {
4965			(void) fprintf(stderr, gettext("-v option is "
4966			    "incompatible with other arguments\n"));
4967			usage(B_FALSE);
4968		}
4969	} else if (upgradeall) {
4970		if (argc != 0) {
4971			(void) fprintf(stderr, gettext("-a option should not "
4972			    "be used along with a pool name\n"));
4973			usage(B_FALSE);
4974		}
4975	}
4976
4977	(void) printf(gettext("This system supports ZFS pool feature "
4978	    "flags.\n\n"));
4979	if (showversions) {
4980		int i;
4981
4982		(void) printf(gettext("The following features are "
4983		    "supported:\n\n"));
4984		(void) printf(gettext("FEAT DESCRIPTION\n"));
4985		(void) printf("----------------------------------------------"
4986		    "---------------\n");
4987		for (i = 0; i < SPA_FEATURES; i++) {
4988			zfeature_info_t *fi = &spa_feature_table[i];
4989			const char *ro =
4990			    (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
4991			    " (read-only compatible)" : "";
4992
4993			(void) printf("%-37s%s\n", fi->fi_uname, ro);
4994			(void) printf("     %s\n", fi->fi_desc);
4995		}
4996		(void) printf("\n");
4997
4998		(void) printf(gettext("The following legacy versions are also "
4999		    "supported:\n\n"));
5000		(void) printf(gettext("VER  DESCRIPTION\n"));
5001		(void) printf("---  -----------------------------------------"
5002		    "---------------\n");
5003		(void) printf(gettext(" 1   Initial ZFS version\n"));
5004		(void) printf(gettext(" 2   Ditto blocks "
5005		    "(replicated metadata)\n"));
5006		(void) printf(gettext(" 3   Hot spares and double parity "
5007		    "RAID-Z\n"));
5008		(void) printf(gettext(" 4   zpool history\n"));
5009		(void) printf(gettext(" 5   Compression using the gzip "
5010		    "algorithm\n"));
5011		(void) printf(gettext(" 6   bootfs pool property\n"));
5012		(void) printf(gettext(" 7   Separate intent log devices\n"));
5013		(void) printf(gettext(" 8   Delegated administration\n"));
5014		(void) printf(gettext(" 9   refquota and refreservation "
5015		    "properties\n"));
5016		(void) printf(gettext(" 10  Cache devices\n"));
5017		(void) printf(gettext(" 11  Improved scrub performance\n"));
5018		(void) printf(gettext(" 12  Snapshot properties\n"));
5019		(void) printf(gettext(" 13  snapused property\n"));
5020		(void) printf(gettext(" 14  passthrough-x aclinherit\n"));
5021		(void) printf(gettext(" 15  user/group space accounting\n"));
5022		(void) printf(gettext(" 16  stmf property support\n"));
5023		(void) printf(gettext(" 17  Triple-parity RAID-Z\n"));
5024		(void) printf(gettext(" 18  Snapshot user holds\n"));
5025		(void) printf(gettext(" 19  Log device removal\n"));
5026		(void) printf(gettext(" 20  Compression using zle "
5027		    "(zero-length encoding)\n"));
5028		(void) printf(gettext(" 21  Deduplication\n"));
5029		(void) printf(gettext(" 22  Received properties\n"));
5030		(void) printf(gettext(" 23  Slim ZIL\n"));
5031		(void) printf(gettext(" 24  System attributes\n"));
5032		(void) printf(gettext(" 25  Improved scrub stats\n"));
5033		(void) printf(gettext(" 26  Improved snapshot deletion "
5034		    "performance\n"));
5035		(void) printf(gettext(" 27  Improved snapshot creation "
5036		    "performance\n"));
5037		(void) printf(gettext(" 28  Multiple vdev replacements\n"));
5038		(void) printf(gettext("\nFor more information on a particular "
5039		    "version, including supported releases,\n"));
5040		(void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5041	} else if (argc == 0 && upgradeall) {
5042		cb.cb_first = B_TRUE;
5043		ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5044		if (ret == 0 && cb.cb_first) {
5045			if (cb.cb_version == SPA_VERSION) {
5046				(void) printf(gettext("All %spools are already "
5047				    "formatted using feature flags.\n\n"),
5048				    cb.cb_unavail ? gettext("available ") : "");
5049				(void) printf(gettext("Every %sfeature flags "
5050				    "pool already has all supported features "
5051				    "enabled.\n"),
5052				    cb.cb_unavail ? gettext("available ") : "");
5053			} else {
5054				(void) printf(gettext("All pools are already "
5055				    "formatted with version %llu or higher.\n"),
5056				    cb.cb_version);
5057			}
5058		}
5059	} else if (argc == 0) {
5060		cb.cb_first = B_TRUE;
5061		ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
5062		assert(ret == 0);
5063
5064		if (!cb.cb_first) {
5065			(void) fprintf(stderr, "\n");
5066		}
5067
5068		cb.cb_first = B_TRUE;
5069		ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5070		assert(ret == 0);
5071
5072		if (cb.cb_first) {
5073			(void) printf(gettext("All %spools are formatted using "
5074			    "feature flags.\n\n"), cb.cb_unavail ?
5075			    gettext("available ") : "");
5076		} else {
5077			(void) printf(gettext("\nUse 'zpool upgrade -v' "
5078			    "for a list of available legacy versions.\n"));
5079		}
5080
5081		cb.cb_first = B_TRUE;
5082		ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5083		assert(ret == 0);
5084
5085		if (cb.cb_first) {
5086			(void) printf(gettext("Every %sfeature flags pool has "
5087			    "all supported features enabled.\n"),
5088			    cb.cb_unavail ? gettext("available ") : "");
5089		} else {
5090			(void) printf(gettext("\n"));
5091		}
5092	} else {
5093		ret = for_each_pool(argc, argv, B_TRUE, NULL,
5094		    upgrade_one, &cb);
5095	}
5096
5097	if (cb.cb_poolname[0] != '\0') {
5098		(void) printf(
5099		    "If you boot from pool '%s', don't forget to update boot code.\n"
5100		    "Assuming you use GPT partitioning and da0 is your boot disk\n"
5101		    "the following command will do it:\n"
5102		    "\n"
5103		    "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
5104		    cb.cb_poolname);
5105	}
5106
5107	return (ret);
5108}
5109
5110typedef struct hist_cbdata {
5111	boolean_t first;
5112	boolean_t longfmt;
5113	boolean_t internal;
5114} hist_cbdata_t;
5115
5116/*
5117 * Print out the command history for a specific pool.
5118 */
5119static int
5120get_history_one(zpool_handle_t *zhp, void *data)
5121{
5122	nvlist_t *nvhis;
5123	nvlist_t **records;
5124	uint_t numrecords;
5125	int ret, i;
5126	hist_cbdata_t *cb = (hist_cbdata_t *)data;
5127
5128	cb->first = B_FALSE;
5129
5130	(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5131
5132	if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5133		return (ret);
5134
5135	verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5136	    &records, &numrecords) == 0);
5137	for (i = 0; i < numrecords; i++) {
5138		nvlist_t *rec = records[i];
5139		char tbuf[30] = "";
5140
5141		if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5142			time_t tsec;
5143			struct tm t;
5144
5145			tsec = fnvlist_lookup_uint64(records[i],
5146			    ZPOOL_HIST_TIME);
5147			(void) localtime_r(&tsec, &t);
5148			(void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5149		}
5150
5151		if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5152			(void) printf("%s %s", tbuf,
5153			    fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5154		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5155			int ievent =
5156			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5157			if (!cb->internal)
5158				continue;
5159			if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5160				(void) printf("%s unrecognized record:\n",
5161				    tbuf);
5162				dump_nvlist(rec, 4);
5163				continue;
5164			}
5165			(void) printf("%s [internal %s txg:%lld] %s", tbuf,
5166			    zfs_history_event_names[ievent],
5167			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5168			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5169		} else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5170			if (!cb->internal)
5171				continue;
5172			(void) printf("%s [txg:%lld] %s", tbuf,
5173			    fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5174			    fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5175			if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5176				(void) printf(" %s (%llu)",
5177				    fnvlist_lookup_string(rec,
5178				    ZPOOL_HIST_DSNAME),
5179				    fnvlist_lookup_uint64(rec,
5180				    ZPOOL_HIST_DSID));
5181			}
5182			(void) printf(" %s", fnvlist_lookup_string(rec,
5183			    ZPOOL_HIST_INT_STR));
5184		} else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5185			if (!cb->internal)
5186				continue;
5187			(void) printf("%s ioctl %s\n", tbuf,
5188			    fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5189			if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5190				(void) printf("    input:\n");
5191				dump_nvlist(fnvlist_lookup_nvlist(rec,
5192				    ZPOOL_HIST_INPUT_NVL), 8);
5193			}
5194			if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5195				(void) printf("    output:\n");
5196				dump_nvlist(fnvlist_lookup_nvlist(rec,
5197				    ZPOOL_HIST_OUTPUT_NVL), 8);
5198			}
5199		} else {
5200			if (!cb->internal)
5201				continue;
5202			(void) printf("%s unrecognized record:\n", tbuf);
5203			dump_nvlist(rec, 4);
5204		}
5205
5206		if (!cb->longfmt) {
5207			(void) printf("\n");
5208			continue;
5209		}
5210		(void) printf(" [");
5211		if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5212			uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5213			struct passwd *pwd = getpwuid(who);
5214			(void) printf("user %d ", (int)who);
5215			if (pwd != NULL)
5216				(void) printf("(%s) ", pwd->pw_name);
5217		}
5218		if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5219			(void) printf("on %s",
5220			    fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5221		}
5222		if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5223			(void) printf(":%s",
5224			    fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5225		}
5226		(void) printf("]");
5227		(void) printf("\n");
5228	}
5229	(void) printf("\n");
5230	nvlist_free(nvhis);
5231
5232	return (ret);
5233}
5234
5235/*
5236 * zpool history <pool>
5237 *
5238 * Displays the history of commands that modified pools.
5239 */
5240int
5241zpool_do_history(int argc, char **argv)
5242{
5243	hist_cbdata_t cbdata = { 0 };
5244	int ret;
5245	int c;
5246
5247	cbdata.first = B_TRUE;
5248	/* check options */
5249	while ((c = getopt(argc, argv, "li")) != -1) {
5250		switch (c) {
5251		case 'l':
5252			cbdata.longfmt = B_TRUE;
5253			break;
5254		case 'i':
5255			cbdata.internal = B_TRUE;
5256			break;
5257		case '?':
5258			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5259			    optopt);
5260			usage(B_FALSE);
5261		}
5262	}
5263	argc -= optind;
5264	argv += optind;
5265
5266	ret = for_each_pool(argc, argv, B_FALSE,  NULL, get_history_one,
5267	    &cbdata);
5268
5269	if (argc == 0 && cbdata.first == B_TRUE) {
5270		(void) printf(gettext("no pools available\n"));
5271		return (0);
5272	}
5273
5274	return (ret);
5275}
5276
5277static int
5278get_callback(zpool_handle_t *zhp, void *data)
5279{
5280	zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5281	char value[MAXNAMELEN];
5282	zprop_source_t srctype;
5283	zprop_list_t *pl;
5284
5285	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5286
5287		/*
5288		 * Skip the special fake placeholder. This will also skip
5289		 * over the name property when 'all' is specified.
5290		 */
5291		if (pl->pl_prop == ZPOOL_PROP_NAME &&
5292		    pl == cbp->cb_proplist)
5293			continue;
5294
5295		if (pl->pl_prop == ZPROP_INVAL &&
5296		    (zpool_prop_feature(pl->pl_user_prop) ||
5297		    zpool_prop_unsupported(pl->pl_user_prop))) {
5298			srctype = ZPROP_SRC_LOCAL;
5299
5300			if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5301			    value, sizeof (value)) == 0) {
5302				zprop_print_one_property(zpool_get_name(zhp),
5303				    cbp, pl->pl_user_prop, value, srctype,
5304				    NULL, NULL);
5305			}
5306		} else {
5307			if (zpool_get_prop(zhp, pl->pl_prop, value,
5308			    sizeof (value), &srctype, cbp->cb_literal) != 0)
5309				continue;
5310
5311			zprop_print_one_property(zpool_get_name(zhp), cbp,
5312			    zpool_prop_to_name(pl->pl_prop), value, srctype,
5313			    NULL, NULL);
5314		}
5315	}
5316	return (0);
5317}
5318
5319/*
5320 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5321 *
5322 *	-H	Scripted mode.  Don't display headers, and separate properties
5323 *		by a single tab.
5324 *	-o	List of columns to display.  Defaults to
5325 *		"name,property,value,source".
5326 * 	-p	Diplay values in parsable (exact) format.
5327 *
5328 * Get properties of pools in the system. Output space statistics
5329 * for each one as well as other attributes.
5330 */
5331int
5332zpool_do_get(int argc, char **argv)
5333{
5334	zprop_get_cbdata_t cb = { 0 };
5335	zprop_list_t fake_name = { 0 };
5336	int ret;
5337	int c, i;
5338	char *value;
5339
5340	cb.cb_first = B_TRUE;
5341
5342	/*
5343	 * Set up default columns and sources.
5344	 */
5345	cb.cb_sources = ZPROP_SRC_ALL;
5346	cb.cb_columns[0] = GET_COL_NAME;
5347	cb.cb_columns[1] = GET_COL_PROPERTY;
5348	cb.cb_columns[2] = GET_COL_VALUE;
5349	cb.cb_columns[3] = GET_COL_SOURCE;
5350	cb.cb_type = ZFS_TYPE_POOL;
5351
5352	/* check options */
5353	while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5354		switch (c) {
5355		case 'p':
5356			cb.cb_literal = B_TRUE;
5357			break;
5358		case 'H':
5359			cb.cb_scripted = B_TRUE;
5360			break;
5361		case 'o':
5362			bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5363			i = 0;
5364			while (*optarg != '\0') {
5365				static char *col_subopts[] =
5366				{ "name", "property", "value", "source",
5367				"all", NULL };
5368
5369				if (i == ZFS_GET_NCOLS) {
5370					(void) fprintf(stderr, gettext("too "
5371					"many fields given to -o "
5372					"option\n"));
5373					usage(B_FALSE);
5374				}
5375
5376				switch (getsubopt(&optarg, col_subopts,
5377				    &value)) {
5378				case 0:
5379					cb.cb_columns[i++] = GET_COL_NAME;
5380					break;
5381				case 1:
5382					cb.cb_columns[i++] = GET_COL_PROPERTY;
5383					break;
5384				case 2:
5385					cb.cb_columns[i++] = GET_COL_VALUE;
5386					break;
5387				case 3:
5388					cb.cb_columns[i++] = GET_COL_SOURCE;
5389					break;
5390				case 4:
5391					if (i > 0) {
5392						(void) fprintf(stderr,
5393						    gettext("\"all\" conflicts "
5394						    "with specific fields "
5395						    "given to -o option\n"));
5396						usage(B_FALSE);
5397					}
5398					cb.cb_columns[0] = GET_COL_NAME;
5399					cb.cb_columns[1] = GET_COL_PROPERTY;
5400					cb.cb_columns[2] = GET_COL_VALUE;
5401					cb.cb_columns[3] = GET_COL_SOURCE;
5402					i = ZFS_GET_NCOLS;
5403					break;
5404				default:
5405					(void) fprintf(stderr,
5406					    gettext("invalid column name "
5407					    "'%s'\n"), value);
5408					usage(B_FALSE);
5409				}
5410			}
5411			break;
5412		case '?':
5413			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5414			    optopt);
5415			usage(B_FALSE);
5416		}
5417	}
5418
5419	argc -= optind;
5420	argv += optind;
5421
5422	if (argc < 1) {
5423		(void) fprintf(stderr, gettext("missing property "
5424		    "argument\n"));
5425		usage(B_FALSE);
5426	}
5427
5428	if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5429	    ZFS_TYPE_POOL) != 0)
5430		usage(B_FALSE);
5431
5432	argc--;
5433	argv++;
5434
5435	if (cb.cb_proplist != NULL) {
5436		fake_name.pl_prop = ZPOOL_PROP_NAME;
5437		fake_name.pl_width = strlen(gettext("NAME"));
5438		fake_name.pl_next = cb.cb_proplist;
5439		cb.cb_proplist = &fake_name;
5440	}
5441
5442	ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5443	    get_callback, &cb);
5444
5445	if (cb.cb_proplist == &fake_name)
5446		zprop_free_list(fake_name.pl_next);
5447	else
5448		zprop_free_list(cb.cb_proplist);
5449
5450	return (ret);
5451}
5452
5453typedef struct set_cbdata {
5454	char *cb_propname;
5455	char *cb_value;
5456	boolean_t cb_any_successful;
5457} set_cbdata_t;
5458
5459int
5460set_callback(zpool_handle_t *zhp, void *data)
5461{
5462	int error;
5463	set_cbdata_t *cb = (set_cbdata_t *)data;
5464
5465	error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5466
5467	if (!error)
5468		cb->cb_any_successful = B_TRUE;
5469
5470	return (error);
5471}
5472
5473int
5474zpool_do_set(int argc, char **argv)
5475{
5476	set_cbdata_t cb = { 0 };
5477	int error;
5478
5479	if (argc > 1 && argv[1][0] == '-') {
5480		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
5481		    argv[1][1]);
5482		usage(B_FALSE);
5483	}
5484
5485	if (argc < 2) {
5486		(void) fprintf(stderr, gettext("missing property=value "
5487		    "argument\n"));
5488		usage(B_FALSE);
5489	}
5490
5491	if (argc < 3) {
5492		(void) fprintf(stderr, gettext("missing pool name\n"));
5493		usage(B_FALSE);
5494	}
5495
5496	if (argc > 3) {
5497		(void) fprintf(stderr, gettext("too many pool names\n"));
5498		usage(B_FALSE);
5499	}
5500
5501	cb.cb_propname = argv[1];
5502	cb.cb_value = strchr(cb.cb_propname, '=');
5503	if (cb.cb_value == NULL) {
5504		(void) fprintf(stderr, gettext("missing value in "
5505		    "property=value argument\n"));
5506		usage(B_FALSE);
5507	}
5508
5509	*(cb.cb_value) = '\0';
5510	cb.cb_value++;
5511
5512	error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5513	    set_callback, &cb);
5514
5515	return (error);
5516}
5517
5518static int
5519find_command_idx(char *command, int *idx)
5520{
5521	int i;
5522
5523	for (i = 0; i < NCOMMAND; i++) {
5524		if (command_table[i].name == NULL)
5525			continue;
5526
5527		if (strcmp(command, command_table[i].name) == 0) {
5528			*idx = i;
5529			return (0);
5530		}
5531	}
5532	return (1);
5533}
5534
5535int
5536main(int argc, char **argv)
5537{
5538	int ret;
5539	int i;
5540	char *cmdname;
5541
5542	(void) setlocale(LC_ALL, "");
5543	(void) textdomain(TEXT_DOMAIN);
5544
5545	if ((g_zfs = libzfs_init()) == NULL) {
5546		(void) fprintf(stderr, gettext("internal error: failed to "
5547		    "initialize ZFS library\n"));
5548		return (1);
5549	}
5550
5551	libzfs_print_on_error(g_zfs, B_TRUE);
5552
5553	opterr = 0;
5554
5555	/*
5556	 * Make sure the user has specified some command.
5557	 */
5558	if (argc < 2) {
5559		(void) fprintf(stderr, gettext("missing command\n"));
5560		usage(B_FALSE);
5561	}
5562
5563	cmdname = argv[1];
5564
5565	/*
5566	 * Special case '-?'
5567	 */
5568	if (strcmp(cmdname, "-?") == 0)
5569		usage(B_TRUE);
5570
5571	zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5572
5573	/*
5574	 * Run the appropriate command.
5575	 */
5576	if (find_command_idx(cmdname, &i) == 0) {
5577		current_command = &command_table[i];
5578		ret = command_table[i].func(argc - 1, argv + 1);
5579	} else if (strchr(cmdname, '=')) {
5580		verify(find_command_idx("set", &i) == 0);
5581		current_command = &command_table[i];
5582		ret = command_table[i].func(argc, argv);
5583	} else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5584		/*
5585		 * 'freeze' is a vile debugging abomination, so we treat
5586		 * it as such.
5587		 */
5588		zfs_cmd_t zc = { 0 };
5589		(void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
5590		return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
5591	} else {
5592		(void) fprintf(stderr, gettext("unrecognized "
5593		    "command '%s'\n"), cmdname);
5594		usage(B_FALSE);
5595	}
5596
5597	if (ret == 0 && log_history)
5598		(void) zpool_log_history(g_zfs, history_str);
5599
5600	libzfs_fini(g_zfs);
5601
5602	/*
5603	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5604	 * for the purposes of running ::findleaks.
5605	 */
5606	if (getenv("ZFS_ABORT") != NULL) {
5607		(void) printf("dumping core by request\n");
5608		abort();
5609	}
5610
5611	return (ret);
5612}
5613