2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
5441d80alling * Common Development and Distribution License (the "License").
6441d80alling * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
233f9d6adLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
245cabbc6Prashanth Sreenivasa * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25e1d5e50Frederik Wessels * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
269edf9ebPrasad Joshi * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
27b327cd3Igor Kozhukhov * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
286401734Will Andrews * Copyright 2016 Nexenta Systems, Inc.
291702cceAlek Pinchuk * Copyright (c) 2017 Datto Inc.
30663207aDon Brady * Copyright (c) 2017, Intel Corporation.
31084fd14Brian Behlendorf * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
32dd50e0cTony Hutter * Copyright 2020 Joyent, Inc.
335711d39loli * Copyright (c) 2012 by Cyril Plisko. All rights reserved.
34c4e4d41Andy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
35fa9e406ahrens */
37fa9e406ahrens#include <assert.h>
38fa9e406ahrens#include <ctype.h>
39fa9e406ahrens#include <dirent.h>
40fa9e406ahrens#include <errno.h>
41fa9e406ahrens#include <fcntl.h>
428671400Serapheim Dimitropoulos#include <getopt.h>
43fa9e406ahrens#include <libgen.h>
44fa9e406ahrens#include <libintl.h>
45fa9e406ahrens#include <libuutil.h>
46fa9e406ahrens#include <locale.h>
47fa9e406ahrens#include <stdio.h>
48fa9e406ahrens#include <stdlib.h>
49fa9e406ahrens#include <string.h>
50fa9e406ahrens#include <strings.h>
51fa9e406ahrens#include <unistd.h>
52fa9e406ahrens#include <priv.h>
53ecd6cf8marks#include <pwd.h>
54ecd6cf8marks#include <zone.h>
554263d13George Wilson#include <zfs_prop.h>
56b1b8ab3lling#include <sys/fs/zfs.h>
57fa9e406ahrens#include <sys/stat.h>
58e0f1c0aOlaf Faaland#include <sys/debug.h>
59dd50e0cTony Hutter#include <math.h>
60dd50e0cTony Hutter#include <sys/sysmacros.h>
61dd50e0cTony Hutter#include <sys/termios.h>
63fa9e406ahrens#include <libzfs.h>
64d8ab6e1Don Brady#include <libzutil.h>
66fa9e406ahrens#include "zpool_util.h"
67b7b9745perrin#include "zfs_comutil.h"
68ad135b5Christopher Siden#include "zfeature_common.h"
7026fd770Krishnendu Sadhukhan - Sun Microsystems#include "statcommon.h"
7126fd770Krishnendu Sadhukhan - Sun Microsystems
72fa9e406ahrensstatic int zpool_do_create(int, char **);
73fa9e406ahrensstatic int zpool_do_destroy(int, char **);
75fa9e406ahrensstatic int zpool_do_add(int, char **);
7699653d4eschrockstatic int zpool_do_remove(int, char **);
776401734Will Andrewsstatic int zpool_do_labelclear(int, char **);
798671400Serapheim Dimitropoulosstatic int zpool_do_checkpoint(int, char **);
808671400Serapheim Dimitropoulos
81fa9e406ahrensstatic int zpool_do_list(int, char **);
82fa9e406ahrensstatic int zpool_do_iostat(int, char **);
83fa9e406ahrensstatic int zpool_do_status(int, char **);
85fa9e406ahrensstatic int zpool_do_online(int, char **);
86fa9e406ahrensstatic int zpool_do_offline(int, char **);
87ea8dc4beschrockstatic int zpool_do_clear(int, char **);
884263d13George Wilsonstatic int zpool_do_reopen(int, char **);
90e9103aaGarrett D'Amorestatic int zpool_do_reguid(int, char **);
91e9103aaGarrett D'Amore
92fa9e406ahrensstatic int zpool_do_attach(int, char **);
93fa9e406ahrensstatic int zpool_do_detach(int, char **);
94fa9e406ahrensstatic int zpool_do_replace(int, char **);
951195e68Mark J Musantestatic int zpool_do_split(int, char **);
97094e47eGeorge Wilsonstatic int zpool_do_initialize(int, char **);
98fa9e406ahrensstatic int zpool_do_scrub(int, char **);
99e4c795bTom Caputistatic int zpool_do_resilver(int, char **);
100084fd14Brian Behlendorfstatic int zpool_do_trim(int, char **);
102fa9e406ahrensstatic int zpool_do_import(int, char **);
103fa9e406ahrensstatic int zpool_do_export(int, char **);
105eaca9bbeschrockstatic int zpool_do_upgrade(int, char **);
10706eeb2aekstatic int zpool_do_history(int, char **);
109b1b8ab3llingstatic int zpool_do_get(int, char **);
110b1b8ab3llingstatic int zpool_do_set(int, char **);
1129c2acf0Alek Pinchukstatic int zpool_do_sync(int, char **);
1139c2acf0Alek Pinchuk
115fa9e406ahrens * These libumem hooks provide a reasonable set of defaults for the allocator's
116fa9e406ahrens * debugging facilities.
117fa9e406ahrens */
11929ab75crm#ifdef DEBUG
120fa9e406ahrensconst char *
123fa9e406ahrens	return ("default,verbose"); /* $UMEM_DEBUG setting */
126fa9e406ahrensconst char *
129fa9e406ahrens	return ("fail,contents"); /* $UMEM_LOGGING setting */
13365cd9f2eschrocktypedef enum {
13465cd9f2eschrock	HELP_ADD,
13565cd9f2eschrock	HELP_ATTACH,
136ea8dc4beschrock	HELP_CLEAR,
13765cd9f2eschrock	HELP_CREATE,
1388671400Serapheim Dimitropoulos	HELP_CHECKPOINT,
13965cd9f2eschrock	HELP_DESTROY,
14065cd9f2eschrock	HELP_DETACH,
14165cd9f2eschrock	HELP_EXPORT,
14206eeb2aek	HELP_HISTORY,
14365cd9f2eschrock	HELP_IMPORT,
14465cd9f2eschrock	HELP_IOSTAT,
1456401734Will Andrews	HELP_LABELCLEAR,
14665cd9f2eschrock	HELP_LIST,
14765cd9f2eschrock	HELP_OFFLINE,
14865cd9f2eschrock	HELP_ONLINE,
14965cd9f2eschrock	HELP_REPLACE,
15099653d4eschrock	HELP_REMOVE,
151094e47eGeorge Wilson	HELP_INITIALIZE,
15265cd9f2eschrock	HELP_SCRUB,
153e4c795bTom Caputi	HELP_RESILVER,
154084fd14Brian Behlendorf	HELP_TRIM,
155eaca9bbeschrock	HELP_STATUS,
156b1b8ab3lling	HELP_UPGRADE,
157b1b8ab3lling	HELP_GET,
1581195e68Mark J Musante	HELP_SET,
159e9103aaGarrett D'Amore	HELP_SPLIT,
1609c2acf0Alek Pinchuk	HELP_SYNC,
1614263d13George Wilson	HELP_REGUID,
1624263d13George Wilson	HELP_REOPEN
16365cd9f2eschrock} zpool_help_t;
166dd50e0cTony Hutter/*
167dd50e0cTony Hutter * Flags for stats to display with "zpool iostats"
168dd50e0cTony Hutter */
169dd50e0cTony Hutterenum iostat_type {
170dd50e0cTony Hutter	IOS_DEFAULT = 0,
171dd50e0cTony Hutter	IOS_LATENCY = 1,
172dd50e0cTony Hutter	IOS_QUEUES = 2,
173dd50e0cTony Hutter	IOS_L_HISTO = 3,
174dd50e0cTony Hutter	IOS_RQ_HISTO = 4,
175dd50e0cTony Hutter	IOS_COUNT,	/* always last element */
176dd50e0cTony Hutter};
177dd50e0cTony Hutter
178dd50e0cTony Hutter/* iostat_type entries as bitmasks */
179dd50e0cTony Hutter#define	IOS_DEFAULT_M	(1ULL << IOS_DEFAULT)
180dd50e0cTony Hutter#define	IOS_LATENCY_M	(1ULL << IOS_LATENCY)
181dd50e0cTony Hutter#define	IOS_QUEUES_M	(1ULL << IOS_QUEUES)
182dd50e0cTony Hutter#define	IOS_L_HISTO_M	(1ULL << IOS_L_HISTO)
183dd50e0cTony Hutter#define	IOS_RQ_HISTO_M	(1ULL << IOS_RQ_HISTO)
184dd50e0cTony Hutter
185dd50e0cTony Hutter/* Mask of all the histo bits */
186dd50e0cTony Hutter#define	IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
187dd50e0cTony Hutter
188dd50e0cTony Hutter/*
189dd50e0cTony Hutter * Lookup table for iostat flags to nvlist names.  Basically a list
190dd50e0cTony Hutter * of all the nvlists a flag requires.  Also specifies the order in
191dd50e0cTony Hutter * which data gets printed in zpool iostat.
192dd50e0cTony Hutter */
193dd50e0cTony Hutterstatic const char *vsx_type_to_nvlist[IOS_COUNT][13] = {
194dd50e0cTony Hutter	[IOS_L_HISTO] = {
195dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
196dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
197dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
198dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
199dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
200dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
201dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
202dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
203dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
204dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
205dd50e0cTony Hutter	    NULL},
206dd50e0cTony Hutter	[IOS_LATENCY] = {
207dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
208dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
209dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
210dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
211dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
212dd50e0cTony Hutter	    NULL},
213dd50e0cTony Hutter	[IOS_QUEUES] = {
220dd50e0cTony Hutter	    NULL},
221dd50e0cTony Hutter	[IOS_RQ_HISTO] = {
222dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
223dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
224dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
225dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
226dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
227dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
228dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
229dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
230dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
231dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
232dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
233dd50e0cTony Hutter	    ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
234dd50e0cTony Hutter	    NULL},
235dd50e0cTony Hutter};
236dd50e0cTony Hutter
237dd50e0cTony Hutter
238dd50e0cTony Hutter/*
239dd50e0cTony Hutter * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
240dd50e0cTony Hutter * Right now, only one histo bit is ever set at one time, so we can
241dd50e0cTony Hutter * just do a highbit64(a)
242dd50e0cTony Hutter */
243dd50e0cTony Hutter#define	IOS_HISTO_IDX(a)	(highbit64(a & IOS_ANYHISTO_M) - 1)
244dd50e0cTony Hutter
245fa9e406ahrenstypedef struct zpool_command {
246fa9e406ahrens	const char	*name;
247fa9e406ahrens	int		(*func)(int, char **);
24865cd9f2eschrock	zpool_help_t	usage;
249fa9e406ahrens} zpool_command_t;
252fa9e406ahrens * Master command table.  Each ZFS command has a name, associated function, and
253ea8dc4beschrock * usage message.  The usage messages need to be internationalized, so we have
254ea8dc4beschrock * to have a function to return the usage message based on a command index.
25565cd9f2eschrock *
25665cd9f2eschrock * These commands are organized according to how they are displayed in the usage
25765cd9f2eschrock * message.  An empty command (one with a NULL name) indicates an empty line in
25865cd9f2eschrock * the generic usage message.
259fa9e406ahrens */
260fa9e406ahrensstatic zpool_command_t command_table[] = {
26165cd9f2eschrock	{ "create",	zpool_do_create,	HELP_CREATE		},
26265cd9f2eschrock	{ "destroy",	zpool_do_destroy,	HELP_DESTROY		},
263fa9e406ahrens	{ NULL },
26465cd9f2eschrock	{ "add",	zpool_do_add,		HELP_ADD		},
26599653d4eschrock	{ "remove",	zpool_do_remove,	HELP_REMOVE		},
266fa9e406ahrens	{ NULL },
2676401734Will Andrews	{ "labelclear",	zpool_do_labelclear,	HELP_LABELCLEAR		},
2686401734Will Andrews	{ NULL },
2698671400Serapheim Dimitropoulos	{ "checkpoint",	zpool_do_checkpoint,	HELP_CHECKPOINT		},
2708671400Serapheim Dimitropoulos	{ NULL },
27165cd9f2eschrock	{ "list",	zpool_do_list,		HELP_LIST		},
27265cd9f2eschrock	{ "iostat",	zpool_do_iostat,	HELP_IOSTAT		},
27365cd9f2eschrock	{ "status",	zpool_do_status,	HELP_STATUS		},
274fa9e406ahrens	{ NULL },
27565cd9f2eschrock	{ "online",	zpool_do_online,	HELP_ONLINE		},
27665cd9f2eschrock	{ "offline",	zpool_do_offline,	HELP_OFFLINE		},
277ea8dc4beschrock	{ "clear",	zpool_do_clear,		HELP_CLEAR		},
2784263d13George Wilson	{ "reopen",	zpool_do_reopen,	HELP_REOPEN		},
279fa9e406ahrens	{ NULL },
28065cd9f2eschrock	{ "attach",	zpool_do_attach,	HELP_ATTACH		},
28165cd9f2eschrock	{ "detach",	zpool_do_detach,	HELP_DETACH		},
28265cd9f2eschrock	{ "replace",	zpool_do_replace,	HELP_REPLACE		},
2831195e68Mark J Musante	{ "split",	zpool_do_split,		HELP_SPLIT		},
284fa9e406ahrens	{ NULL },
285094e47eGeorge Wilson	{ "initialize",	zpool_do_initialize,	HELP_INITIALIZE		},
286e4c795bTom Caputi	{ "resilver",	zpool_do_resilver,	HELP_RESILVER		},
28765cd9f2eschrock	{ "scrub",	zpool_do_scrub,		HELP_SCRUB		},
288084fd14Brian Behlendorf	{ "trim",	zpool_do_trim,		HELP_TRIM		},
289fa9e406ahrens	{ NULL },
29065cd9f2eschrock	{ "import",	zpool_do_import,	HELP_IMPORT		},
29165cd9f2eschrock	{ "export",	zpool_do_export,	HELP_EXPORT		},
29206eeb2aek	{ "upgrade",	zpool_do_upgrade,	HELP_UPGRADE		},
293e9103aaGarrett D'Amore	{ "reguid",	zpool_do_reguid,	HELP_REGUID		},
29406eeb2aek	{ NULL },
295b1b8ab3lling	{ "history",	zpool_do_history,	HELP_HISTORY		},
296b1b8ab3lling	{ "get",	zpool_do_get,		HELP_GET		},
297b1b8ab3lling	{ "set",	zpool_do_set,		HELP_SET		},
2989c2acf0Alek Pinchuk	{ "sync",	zpool_do_sync,		HELP_SYNC		},
301dd50e0cTony Hutter#define	NCOMMAND	(ARRAY_SIZE(command_table))
303663207aDon Brady#define	VDEV_ALLOC_CLASS_LOGS	"logs"
304663207aDon Brady
3054445fffMatthew Ahrensstatic zpool_command_t *current_command;
3062a6b87fekstatic char history_str[HIS_MAX_RECORD_LEN];
3074445fffMatthew Ahrensstatic boolean_t log_history = B_TRUE;
30826fd770Krishnendu Sadhukhan - Sun Microsystemsstatic uint_t timestamp_fmt = NODATE;
30926fd770Krishnendu Sadhukhan - Sun Microsystems
31065cd9f2eschrockstatic const char *
3119a686fbPaul Dagnelieget_usage(zpool_help_t idx)
3129a686fbPaul Dagnelie{
31365cd9f2eschrock	switch (idx) {
31465cd9f2eschrock	case HELP_ADD:
3155711d39loli		return (gettext("\tadd [-fgLnP] [-o property=value] "
3165711d39loli		    "<pool> <vdev> ...\n"));
31765cd9f2eschrock	case HELP_ATTACH:
3185711d39loli		return (gettext("\tattach [-f] [-o property=value] "
3195711d39loli		    "<pool> <device> <new-device>\n"));
320ea8dc4beschrock	case HELP_CLEAR:
321468c413Tim Haley		return (gettext("\tclear [-nF] <pool> [device]\n"));
32265cd9f2eschrock	case HELP_CREATE:
3237855d95Toomas Soome		return (gettext("\tcreate [-fnd] [-B] "
3247855d95Toomas Soome		    "[-o property=value] ... \n"
32504e5635Andriy Gapon		    "\t    [-O file-system-property=value] ...\n"
32604e5635Andriy Gapon		    "\t    [-m mountpoint] [-R root] [-t tempname] "
32704e5635Andriy Gapon		    "<pool> <vdev> ...\n"));
3288671400Serapheim Dimitropoulos	case HELP_CHECKPOINT:
3298671400Serapheim Dimitropoulos		return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
33065cd9f2eschrock	case HELP_DESTROY:
33165cd9f2eschrock		return (gettext("\tdestroy [-f] <pool>\n"));
33265cd9f2eschrock	case HELP_DETACH:
33365cd9f2eschrock		return (gettext("\tdetach <pool> <device>\n"));
33465cd9f2eschrock	case HELP_EXPORT:
33565cd9f2eschrock		return (gettext("\texport [-f] <pool> ...\n"));
33606eeb2aek	case HELP_HISTORY:
337ecd6cf8marks		return (gettext("\thistory [-il] [<pool>] ...\n"));
33865cd9f2eschrock	case HELP_IMPORT:
3394c58d71darrenm		return (gettext("\timport [-d dir] [-D]\n"
340eb63303Tom Caputi		    "\timport [-d dir | -c cachefile] [-F [-n]] [-l] "
341eb63303Tom Caputi		    "<pool | id>\n"
3422f8aaabeschrock		    "\timport [-o mntopts] [-o property=value] ... \n"
343eb63303Tom Caputi		    "\t    [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
344f9af39bGeorge Wilson		    "[-R root] [-F [-n]] -a\n"
3452f8aaabeschrock		    "\timport [-o mntopts] [-o property=value] ... \n"
346eb63303Tom Caputi		    "\t    [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
34704e5635Andriy Gapon		    "[-R root] [-F [-n]] [-t]\n"
3488671400Serapheim Dimitropoulos		    "\t    [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
34965cd9f2eschrock	case HELP_IOSTAT:
350dd50e0cTony Hutter		return (gettext("\tiostat "
351dd50e0cTony Hutter		    "[[-lq]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
35220f5062Jerry Jelinek		    "\t    [[pool] ...]|[pool vdev ...]|[vdev ...]]"
353dd50e0cTony Hutter		    " [[-n] interval [count]]\n"));
3546401734Will Andrews	case HELP_LABELCLEAR:
3556401734Will Andrews		return (gettext("\tlabelclear [-f] <vdev>\n"));
35665cd9f2eschrock	case HELP_LIST:
357663207aDon Brady		return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
3583f9d6adLin Ling		    "[-T d|u] [pool] ... [interval [count]]\n"));
35965cd9f2eschrock	case HELP_OFFLINE:
360441d80alling		return (gettext("\toffline [-t] <pool> <device> ...\n"));
36165cd9f2eschrock	case HELP_ONLINE:
362441d80alling		return (gettext("\tonline <pool> <device> ...\n"));
36365cd9f2eschrock	case HELP_REPLACE:
36465cd9f2eschrock		return (gettext("\treplace [-f] <pool> <device> "
365e45ce72ahrens		    "[new-device]\n"));
36699653d4eschrock	case HELP_REMOVE:
3675cabbc6Prashanth Sreenivasa		return (gettext("\tremove [-nps] <pool> <device> ...\n"));
3684263d13George Wilson	case HELP_REOPEN:
36931d7e8fGeorge Wilson		return (gettext("\treopen <pool>\n"));
370094e47eGeorge Wilson	case HELP_INITIALIZE:
371084fd14Brian Behlendorf		return (gettext("\tinitialize [-c | -s] <pool> "
372084fd14Brian Behlendorf		    "[<device> ...]\n"));
37365cd9f2eschrock	case HELP_SCRUB:
3741702cceAlek Pinchuk		return (gettext("\tscrub [-s | -p] <pool> ...\n"));
375e4c795bTom Caputi	case HELP_RESILVER:
376e4c795bTom Caputi		return (gettext("\tresilver <pool> ...\n"));
377084fd14Brian Behlendorf	case HELP_TRIM:
378084fd14Brian Behlendorf		return (gettext("\ttrim [-d] [-r <rate>] [-c | -s] <pool> "
379084fd14Brian Behlendorf		    "[<device> ...]\n"));
38065cd9f2eschrock	case HELP_STATUS:
381dd50e0cTony Hutter		return (gettext("\tstatus "
382dd50e0cTony Hutter		    "[-igLpPsvxD] [-T d|u] [pool] ... "
383663207aDon Brady		    "[interval [count]]\n"));
384eaca9bbeschrock	case HELP_UPGRADE:
385eaca9bbeschrock		return (gettext("\tupgrade\n"
386eaca9bbeschrock		    "\tupgrade -v\n"
387990b485lling		    "\tupgrade [-V version] <-a | pool ...>\n"));
388b1b8ab3lling	case HELP_GET:
389c58b352Adam Stevko		return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
390c58b352Adam Stevko		    "<\"all\" | property[,...]> <pool> ...\n"));
391b1b8ab3lling	case HELP_SET:
392b1b8ab3lling		return (gettext("\tset <property=value> <pool> \n"));
3931195e68Mark J Musante	case HELP_SPLIT:
394eb63303Tom Caputi		return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n"
3951195e68Mark J Musante		    "\t    [-o property=value] <pool> <newpool> "
3961195e68Mark J Musante		    "[<device> ...]\n"));
397e9103aaGarrett D'Amore	case HELP_REGUID:
398e9103aaGarrett D'Amore		return (gettext("\treguid <pool>\n"));
3999c2acf0Alek Pinchuk	case HELP_SYNC:
4009c2acf0Alek Pinchuk		return (gettext("\tsync [pool] ...\n"));
40165cd9f2eschrock	}
40365cd9f2eschrock	abort();
40465cd9f2eschrock	/* NOTREACHED */
407084fd14Brian Behlendorfstatic void
408084fd14Brian Behlendorfzpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
409084fd14Brian Behlendorf{
410084fd14Brian Behlendorf	uint_t children = 0;
411084fd14Brian Behlendorf	nvlist_t **child;
412084fd14Brian Behlendorf	uint_t i;
413084fd14Brian Behlendorf
414084fd14Brian Behlendorf	(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
415084fd14Brian Behlendorf	    &child, &children);
416084fd14Brian Behlendorf
417084fd14Brian Behlendorf	if (children == 0) {
418084fd14Brian Behlendorf		char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 0);
419084fd14Brian Behlendorf
420084fd14Brian Behlendorf		if (strcmp(path, VDEV_TYPE_INDIRECT) != 0)
421084fd14Brian Behlendorf			fnvlist_add_boolean(res, path);
422084fd14Brian Behlendorf
423084fd14Brian Behlendorf		free(path);
424084fd14Brian Behlendorf		return;
425084fd14Brian Behlendorf	}
426084fd14Brian Behlendorf
427084fd14Brian Behlendorf	for (i = 0; i < children; i++) {
428084fd14Brian Behlendorf		zpool_collect_leaves(zhp, child[i], res);
429084fd14Brian Behlendorf	}
430084fd14Brian Behlendorf}
433b1b8ab3lling * Callback routine that will print out a pool property value.
434b1b8ab3lling */
435990b485llingstatic int
436990b485llingprint_prop_cb(int prop, void *cb)
438b1b8ab3lling	FILE *fp = cb;
440663207aDon Brady	(void) fprintf(fp, "\t%-19s  ", zpool_prop_to_name(prop));
442990b485lling	if (zpool_prop_readonly(prop))
443990b485lling		(void) fprintf(fp, "  NO   ");
444990b485lling	else
445b24ab67Jeff Bonwick		(void) fprintf(fp, " YES   ");
447b1b8ab3lling	if (zpool_prop_values(prop) == NULL)
448b1b8ab3lling		(void) fprintf(fp, "-\n");
449b1b8ab3lling	else
450b1b8ab3lling		(void) fprintf(fp, "%s\n", zpool_prop_values(prop));
452990b485lling	return (ZPROP_CONT);
456fa9e406ahrens * Display usage message.  If we're inside a command, display only the usage for
457fa9e406ahrens * that command.  Otherwise, iterate over the entire command table and display
458fa9e406ahrens * a complete usage message.
459fa9e406ahrens */
46199653d4eschrockusage(boolean_t requested)
463fa9e406ahrens	FILE *fp = requested ? stdout : stderr;
465fa9e406ahrens	if (current_command == NULL) {
466fa9e406ahrens		int i;
468fa9e406ahrens		(void) fprintf(fp, gettext("usage: zpool command args ...\n"));
469fa9e406ahrens		(void) fprintf(fp,
470fa9e406ahrens		    gettext("where 'command' is one of the following:\n\n"));
472fa9e406ahrens		for (i = 0; i < NCOMMAND; i++) {
473fa9e406ahrens			if (command_table[i].name == NULL)
474fa9e406ahrens				(void) fprintf(fp, "\n");
475fa9e406ahrens			else
476fa9e406ahrens				(void) fprintf(fp, "%s",
47765cd9f2eschrock				    get_usage(command_table[i].usage));
478fa9e406ahrens		}
479fa9e406ahrens	} else {
480fa9e406ahrens		(void) fprintf(fp, gettext("usage:\n"));
48165cd9f2eschrock		(void) fprintf(fp, "%s", get_usage(current_command->usage));
482fa9e406ahrens	}
484b1b8ab3lling	if (current_command != NULL &&
485b1b8ab3lling	    ((strcmp(current_command->name, "set") == 0) ||
486990b485lling	    (strcmp(current_command->name, "get") == 0) ||
487990b485lling	    (strcmp(current_command->name, "list") == 0))) {
489b1b8ab3lling		(void) fprintf(fp,
490b1b8ab3lling		    gettext("\nthe following properties are supported:\n"));
492663207aDon Brady		(void) fprintf(fp, "\n\t%-19s  %s   %s\n\n",
493990b485lling		    "PROPERTY", "EDIT", "VALUES");
495b1b8ab3lling		/* Iterate over all properties */
496990b485lling		(void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
497990b485lling		    ZFS_TYPE_POOL);
498ad135b5Christopher Siden
499663207aDon Brady		(void) fprintf(fp, "\t%-19s   ", "feature@...");
500ad135b5Christopher Siden		(void) fprintf(fp, "YES   disabled | enabled | active\n");
501ad135b5Christopher Siden
502ad135b5Christopher Siden		(void) fprintf(fp, gettext("\nThe feature@ properties must be "
503ad135b5Christopher Siden		    "appended with a feature name.\nSee zpool-features(5).\n"));
504b1b8ab3lling	}
506e9dbad6eschrock	/*
507e9dbad6eschrock	 * See comments at end of main().
508e9dbad6eschrock	 */
509e9dbad6eschrock	if (getenv("ZFS_ABORT") != NULL) {
510e9dbad6eschrock		(void) printf("dumping core by request\n");
511e9dbad6eschrock		abort();
512e9dbad6eschrock	}
514fa9e406ahrens	exit(requested ? 0 : 2);
517663207aDon Brady/*
518663207aDon Brady * print a pool vdev config for dry runs
519663207aDon Brady */
520663207aDon Bradystatic void
5218654d02perrinprint_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
522663207aDon Brady    const char *match, int name_flags)
524fa9e406ahrens	nvlist_t **child;
525fa9e406ahrens	uint_t c, children;
526afefbcdeschrock	char *vname;
527663207aDon Brady	boolean_t printed = B_FALSE;
529fa9e406ahrens	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
530663207aDon Brady	    &child, &children) != 0) {
531663207aDon Brady		if (name != NULL)
532663207aDon Brady			(void) printf("\t%*s%s\n", indent, "", name);
533fa9e406ahrens		return;
534663207aDon Brady	}
536afefbcdeschrock	for (c = 0; c < children; c++) {
5378654d02perrin		uint64_t is_log = B_FALSE;
538663207aDon Brady		char *class = "";
5408654d02perrin		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
5418654d02perrin		    &is_log);
542663207aDon Brady		if (is_log)
543663207aDon Brady			class = VDEV_ALLOC_BIAS_LOG;
544663207aDon Brady		(void) nvlist_lookup_string(child[c],
545663207aDon Brady		    ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
546663207aDon Brady		if (strcmp(match, class) != 0)
5478654d02perrin			continue;
549663207aDon Brady		if (!printed && name != NULL) {
550663207aDon Brady			(void) printf("\t%*s%s\n", indent, "", name);
551663207aDon Brady			printed = B_TRUE;
552663207aDon Brady		}
553663207aDon Brady		vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
554663207aDon Brady		print_vdev_tree(zhp, vname, child[c], indent + 2, "",
555663207aDon Brady		    name_flags);
556afefbcdeschrock		free(vname);
557afefbcdeschrock	}
5605722177Christopher Sidenstatic boolean_t
5615722177Christopher Sidenprop_list_contains_feature(nvlist_t *proplist)
5625722177Christopher Siden{
5635722177Christopher Siden	nvpair_t *nvp;
5645722177Christopher Siden	for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
5655722177Christopher Siden	    nvp = nvlist_next_nvpair(proplist, nvp)) {
5665722177Christopher Siden		if (zpool_prop_feature(nvpair_name(nvp)))
5675722177Christopher Siden			return (B_TRUE);
5685722177Christopher Siden	}
5695722177Christopher Siden	return (B_FALSE);
5705722177Christopher Siden}
5715722177Christopher Siden
573990b485lling * Add a property pair (name, string-value) into a property nvlist.
574990b485lling */
575990b485llingstatic int
5760a48a24timhadd_prop_list(const char *propname, char *propval, nvlist_t **props,
5770a48a24timh    boolean_t poolprop)
579d2aa06eAndrew Stormont	zpool_prop_t prop = ZPOOL_PROP_INVAL;
5800a48a24timh	zfs_prop_t fprop;
581990b485lling	nvlist_t *proplist;
5820a48a24timh	const char *normnm;
5830a48a24timh	char *strval;
585990b485lling	if (*props == NULL &&
586990b485lling	    nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
587990b485lling		(void) fprintf(stderr,
588990b485lling		    gettext("internal error: out of memory\n"));
589990b485lling		return (1);
590990b485lling	}
592990b485lling	proplist = *props;
5940a48a24timh	if (poolprop) {
5955722177Christopher Siden		const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
5965722177Christopher Siden
597d2aa06eAndrew Stormont		if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
598ad135b5Christopher Siden		    !zpool_prop_feature(propname)) {
5990a48a24timh			(void) fprintf(stderr, gettext("property '%s' is "
6000a48a24timh			    "not a valid pool property\n"), propname);
6010a48a24timh			return (2);
6020a48a24timh		}
6035722177Christopher Siden
6045722177Christopher Siden		/*
6055722177Christopher Siden		 * feature@ properties and version should not be specified
6065722177Christopher Siden		 * at the same time.
6075722177Christopher Siden		 */
6084ae5f5fAlan Somers		if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
6095722177Christopher Siden		    nvlist_exists(proplist, vname)) ||
6105722177Christopher Siden		    (prop == ZPOOL_PROP_VERSION &&
6115722177Christopher Siden		    prop_list_contains_feature(proplist))) {
6125722177Christopher Siden			(void) fprintf(stderr, gettext("'feature@' and "
6135722177Christopher Siden			    "'version' properties cannot be specified "
6145722177Christopher Siden			    "together\n"));
6155722177Christopher Siden			return (2);
6165722177Christopher Siden		}
6175722177Christopher Siden
6185722177Christopher Siden
619ad135b5Christopher Siden		if (zpool_prop_feature(propname))
620ad135b5Christopher Siden			normnm = propname;
621ad135b5Christopher Siden		else
622ad135b5Christopher Siden			normnm = zpool_prop_to_name(prop);