1fa9e4066Sahrens /*
2fa9e4066Sahrens * CDDL HEADER START
3fa9e4066Sahrens *
4fa9e4066Sahrens * The contents of this file are subject to the terms of the
5441d80aaSlling * Common Development and Distribution License (the "License").
6441d80aaSlling * You may not use this file except in compliance with the License.
7fa9e4066Sahrens *
8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens * See the License for the specific language governing permissions
11fa9e4066Sahrens * and limitations under the License.
12fa9e4066Sahrens *
13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens *
19fa9e4066Sahrens * CDDL HEADER END
20fa9e4066Sahrens */
2199653d4eSeschrock
22fa9e4066Sahrens /*
233f9d6ad7SLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
245cabbc6bSPrashanth Sreenivasa * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25e1d5e507SFrederik Wessels * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
269edf9ebdSPrasad Joshi * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
27b327cd3fSIgor Kozhukhov * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
286401734dSWill Andrews * Copyright 2016 Nexenta Systems, Inc.
291702cce7SAlek Pinchuk * Copyright (c) 2017 Datto Inc.
30663207adSDon Brady * Copyright (c) 2017, Intel Corporation.
31084fd14fSBrian Behlendorf * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
32dd50e0ccSTony Hutter * Copyright 2020 Joyent, Inc.
335711d393Sloli10K * Copyright (c) 2012 by Cyril Plisko. All rights reserved.
34c4e4d410SAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
35fa9e4066Sahrens */
36fa9e4066Sahrens
37fa9e4066Sahrens #include <assert.h>
38fa9e4066Sahrens #include <ctype.h>
39fa9e4066Sahrens #include <dirent.h>
40fa9e4066Sahrens #include <errno.h>
41fa9e4066Sahrens #include <fcntl.h>
4286714001SSerapheim Dimitropoulos #include <getopt.h>
43fa9e4066Sahrens #include <libgen.h>
44fa9e4066Sahrens #include <libintl.h>
45fa9e4066Sahrens #include <libuutil.h>
46fa9e4066Sahrens #include <locale.h>
47fa9e4066Sahrens #include <stdio.h>
48fa9e4066Sahrens #include <stdlib.h>
49fa9e4066Sahrens #include <string.h>
50fa9e4066Sahrens #include <strings.h>
51fa9e4066Sahrens #include <unistd.h>
52fa9e4066Sahrens #include <priv.h>
53ecd6cf80Smarks #include <pwd.h>
54ecd6cf80Smarks #include <zone.h>
554263d13fSGeorge Wilson #include <zfs_prop.h>
56b1b8ab34Slling #include <sys/fs/zfs.h>
57fa9e4066Sahrens #include <sys/stat.h>
58e0f1c0afSOlaf Faaland #include <sys/debug.h>
59dd50e0ccSTony Hutter #include <math.h>
60dd50e0ccSTony Hutter #include <sys/sysmacros.h>
61dd50e0ccSTony Hutter #include <sys/termios.h>
62fa9e4066Sahrens
63fa9e4066Sahrens #include <libzfs.h>
64d8ab6e12SDon Brady #include <libzutil.h>
65fa9e4066Sahrens
66fa9e4066Sahrens #include "zpool_util.h"
67b7b97454Sperrin #include "zfs_comutil.h"
68ad135b5dSChristopher Siden #include "zfeature_common.h"
69fa9e4066Sahrens
7026fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h"
7126fd7700SKrishnendu Sadhukhan - Sun Microsystems
72436b964bSToomas Soome libzfs_handle_t *g_zfs;
73436b964bSToomas Soome
74fa9e4066Sahrens static int zpool_do_create(int, char **);
75fa9e4066Sahrens static int zpool_do_destroy(int, char **);
76fa9e4066Sahrens
77fa9e4066Sahrens static int zpool_do_add(int, char **);
7899653d4eSeschrock static int zpool_do_remove(int, char **);
796401734dSWill Andrews static int zpool_do_labelclear(int, char **);
80fa9e4066Sahrens
8186714001SSerapheim Dimitropoulos static int zpool_do_checkpoint(int, char **);
8286714001SSerapheim Dimitropoulos
83fa9e4066Sahrens static int zpool_do_list(int, char **);
84fa9e4066Sahrens static int zpool_do_iostat(int, char **);
85fa9e4066Sahrens static int zpool_do_status(int, char **);
86fa9e4066Sahrens
87fa9e4066Sahrens static int zpool_do_online(int, char **);
88fa9e4066Sahrens static int zpool_do_offline(int, char **);
89ea8dc4b6Seschrock static int zpool_do_clear(int, char **);
904263d13fSGeorge Wilson static int zpool_do_reopen(int, char **);
91fa9e4066Sahrens
92e9103aaeSGarrett D'Amore static int zpool_do_reguid(int, char **);
93e9103aaeSGarrett D'Amore
94fa9e4066Sahrens static int zpool_do_attach(int, char **);
95fa9e4066Sahrens static int zpool_do_detach(int, char **);
96fa9e4066Sahrens static int zpool_do_replace(int, char **);
971195e687SMark J Musante static int zpool_do_split(int, char **);
98fa9e4066Sahrens
99094e47e9SGeorge Wilson static int zpool_do_initialize(int, char **);
100fa9e4066Sahrens static int zpool_do_scrub(int, char **);
101e4c795beSTom Caputi static int zpool_do_resilver(int, char **);
102084fd14fSBrian Behlendorf static int zpool_do_trim(int, char **);
103fa9e4066Sahrens
104fa9e4066Sahrens static int zpool_do_import(int, char **);
105fa9e4066Sahrens static int zpool_do_export(int, char **);
106fa9e4066Sahrens
107eaca9bbdSeschrock static int zpool_do_upgrade(int, char **);
108eaca9bbdSeschrock
10906eeb2adSek110237 static int zpool_do_history(int, char **);
11006eeb2adSek110237
111b1b8ab34Slling static int zpool_do_get(int, char **);
112b1b8ab34Slling static int zpool_do_set(int, char **);
113b1b8ab34Slling
1149c2acf00SAlek Pinchuk static int zpool_do_sync(int, char **);
1159c2acf00SAlek Pinchuk
116fa9e4066Sahrens /*
117fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's
118fa9e4066Sahrens * debugging facilities.
119fa9e4066Sahrens */
12029ab75c9Srm160521
12129ab75c9Srm160521 #ifdef DEBUG
122fa9e4066Sahrens const char *
_umem_debug_init(void)12399653d4eSeschrock _umem_debug_init(void)
124fa9e4066Sahrens {
125fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */
126fa9e4066Sahrens }
127fa9e4066Sahrens
128fa9e4066Sahrens const char *
_umem_logging_init(void)129fa9e4066Sahrens _umem_logging_init(void)
130fa9e4066Sahrens {
131fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */
132fa9e4066Sahrens }
13329ab75c9Srm160521 #endif
134fa9e4066Sahrens
13565cd9f28Seschrock typedef enum {
13665cd9f28Seschrock HELP_ADD,
13765cd9f28Seschrock HELP_ATTACH,
138ea8dc4b6Seschrock HELP_CLEAR,
13965cd9f28Seschrock HELP_CREATE,
14086714001SSerapheim Dimitropoulos HELP_CHECKPOINT,
14165cd9f28Seschrock HELP_DESTROY,
14265cd9f28Seschrock HELP_DETACH,
14365cd9f28Seschrock HELP_EXPORT,
14406eeb2adSek110237 HELP_HISTORY,
14565cd9f28Seschrock HELP_IMPORT,
14665cd9f28Seschrock HELP_IOSTAT,
1476401734dSWill Andrews HELP_LABELCLEAR,
14865cd9f28Seschrock HELP_LIST,
14965cd9f28Seschrock HELP_OFFLINE,
15065cd9f28Seschrock HELP_ONLINE,
15165cd9f28Seschrock HELP_REPLACE,
15299653d4eSeschrock HELP_REMOVE,
153094e47e9SGeorge Wilson HELP_INITIALIZE,
15465cd9f28Seschrock HELP_SCRUB,
155e4c795beSTom Caputi HELP_RESILVER,
156084fd14fSBrian Behlendorf HELP_TRIM,
157eaca9bbdSeschrock HELP_STATUS,
158b1b8ab34Slling HELP_UPGRADE,
159b1b8ab34Slling HELP_GET,
1601195e687SMark J Musante HELP_SET,
161e9103aaeSGarrett D'Amore HELP_SPLIT,
1629c2acf00SAlek Pinchuk HELP_SYNC,
1634263d13fSGeorge Wilson HELP_REGUID,
1644263d13fSGeorge Wilson HELP_REOPEN
16565cd9f28Seschrock } zpool_help_t;
16665cd9f28Seschrock
16765cd9f28Seschrock
168dd50e0ccSTony Hutter /*
169dd50e0ccSTony Hutter * Flags for stats to display with "zpool iostats"
170dd50e0ccSTony Hutter */
171dd50e0ccSTony Hutter enum iostat_type {
172dd50e0ccSTony Hutter IOS_DEFAULT = 0,
173dd50e0ccSTony Hutter IOS_LATENCY = 1,
174dd50e0ccSTony Hutter IOS_QUEUES = 2,
175dd50e0ccSTony Hutter IOS_L_HISTO = 3,
176dd50e0ccSTony Hutter IOS_RQ_HISTO = 4,
177dd50e0ccSTony Hutter IOS_COUNT, /* always last element */
178dd50e0ccSTony Hutter };
179dd50e0ccSTony Hutter
180dd50e0ccSTony Hutter /* iostat_type entries as bitmasks */
181dd50e0ccSTony Hutter #define IOS_DEFAULT_M (1ULL << IOS_DEFAULT)
182dd50e0ccSTony Hutter #define IOS_LATENCY_M (1ULL << IOS_LATENCY)
183dd50e0ccSTony Hutter #define IOS_QUEUES_M (1ULL << IOS_QUEUES)
184dd50e0ccSTony Hutter #define IOS_L_HISTO_M (1ULL << IOS_L_HISTO)
185dd50e0ccSTony Hutter #define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO)
186dd50e0ccSTony Hutter
187dd50e0ccSTony Hutter /* Mask of all the histo bits */
188dd50e0ccSTony Hutter #define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
189dd50e0ccSTony Hutter
190dd50e0ccSTony Hutter /*
191dd50e0ccSTony Hutter * Lookup table for iostat flags to nvlist names. Basically a list
192dd50e0ccSTony Hutter * of all the nvlists a flag requires. Also specifies the order in
193dd50e0ccSTony Hutter * which data gets printed in zpool iostat.
194dd50e0ccSTony Hutter */
195dd50e0ccSTony Hutter static const char *vsx_type_to_nvlist[IOS_COUNT][13] = {
196dd50e0ccSTony Hutter [IOS_L_HISTO] = {
197dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
198dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
199dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
200dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
201dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
202dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
203dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
204dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
205dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
206dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
207dd50e0ccSTony Hutter NULL},
208dd50e0ccSTony Hutter [IOS_LATENCY] = {
209dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
210dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
211dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
212dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
213dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
214dd50e0ccSTony Hutter NULL},
215dd50e0ccSTony Hutter [IOS_QUEUES] = {
216dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
217dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
218dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
219dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
220dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
221dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
222dd50e0ccSTony Hutter NULL},
223dd50e0ccSTony Hutter [IOS_RQ_HISTO] = {
224dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
225dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
226dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
227dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
228dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
229dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
230dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
231dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
232dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
233dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
234dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
235dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
236dd50e0ccSTony Hutter NULL},
237dd50e0ccSTony Hutter };
238dd50e0ccSTony Hutter
239dd50e0ccSTony Hutter
240dd50e0ccSTony Hutter /*
241dd50e0ccSTony Hutter * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
242dd50e0ccSTony Hutter * Right now, only one histo bit is ever set at one time, so we can
243dd50e0ccSTony Hutter * just do a highbit64(a)
244dd50e0ccSTony Hutter */
245dd50e0ccSTony Hutter #define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1)
246dd50e0ccSTony Hutter
247fa9e4066Sahrens typedef struct zpool_command {
248fa9e4066Sahrens const char *name;
249fa9e4066Sahrens int (*func)(int, char **);
25065cd9f28Seschrock zpool_help_t usage;
251fa9e4066Sahrens } zpool_command_t;
252fa9e4066Sahrens
253fa9e4066Sahrens /*
254fa9e4066Sahrens * Master command table. Each ZFS command has a name, associated function, and
255ea8dc4b6Seschrock * usage message. The usage messages need to be internationalized, so we have
256ea8dc4b6Seschrock * to have a function to return the usage message based on a command index.
25765cd9f28Seschrock *
25865cd9f28Seschrock * These commands are organized according to how they are displayed in the usage
25965cd9f28Seschrock * message. An empty command (one with a NULL name) indicates an empty line in
26065cd9f28Seschrock * the generic usage message.
261fa9e4066Sahrens */
262fa9e4066Sahrens static zpool_command_t command_table[] = {
26365cd9f28Seschrock { "create", zpool_do_create, HELP_CREATE },
26465cd9f28Seschrock { "destroy", zpool_do_destroy, HELP_DESTROY },
265fa9e4066Sahrens { NULL },
26665cd9f28Seschrock { "add", zpool_do_add, HELP_ADD },
26799653d4eSeschrock { "remove", zpool_do_remove, HELP_REMOVE },
268fa9e4066Sahrens { NULL },
2696401734dSWill Andrews { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
2706401734dSWill Andrews { NULL },
27186714001SSerapheim Dimitropoulos { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT },
27286714001SSerapheim Dimitropoulos { NULL },
27365cd9f28Seschrock { "list", zpool_do_list, HELP_LIST },
27465cd9f28Seschrock { "iostat", zpool_do_iostat, HELP_IOSTAT },
27565cd9f28Seschrock { "status", zpool_do_status, HELP_STATUS },
276fa9e4066Sahrens { NULL },
27765cd9f28Seschrock { "online", zpool_do_online, HELP_ONLINE },
27865cd9f28Seschrock { "offline", zpool_do_offline, HELP_OFFLINE },
279ea8dc4b6Seschrock { "clear", zpool_do_clear, HELP_CLEAR },
2804263d13fSGeorge Wilson { "reopen", zpool_do_reopen, HELP_REOPEN },
281fa9e4066Sahrens { NULL },
28265cd9f28Seschrock { "attach", zpool_do_attach, HELP_ATTACH },
28365cd9f28Seschrock { "detach", zpool_do_detach, HELP_DETACH },
28465cd9f28Seschrock { "replace", zpool_do_replace, HELP_REPLACE },
2851195e687SMark J Musante { "split", zpool_do_split, HELP_SPLIT },
286fa9e4066Sahrens { NULL },
287094e47e9SGeorge Wilson { "initialize", zpool_do_initialize, HELP_INITIALIZE },
288e4c795beSTom Caputi { "resilver", zpool_do_resilver, HELP_RESILVER },
28965cd9f28Seschrock { "scrub", zpool_do_scrub, HELP_SCRUB },
290084fd14fSBrian Behlendorf { "trim", zpool_do_trim, HELP_TRIM },
291fa9e4066Sahrens { NULL },
29265cd9f28Seschrock { "import", zpool_do_import, HELP_IMPORT },
29365cd9f28Seschrock { "export", zpool_do_export, HELP_EXPORT },
29406eeb2adSek110237 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
295e9103aaeSGarrett D'Amore { "reguid", zpool_do_reguid, HELP_REGUID },
29606eeb2adSek110237 { NULL },
297b1b8ab34Slling { "history", zpool_do_history, HELP_HISTORY },
298b1b8ab34Slling { "get", zpool_do_get, HELP_GET },
299b1b8ab34Slling { "set", zpool_do_set, HELP_SET },
3009c2acf00SAlek Pinchuk { "sync", zpool_do_sync, HELP_SYNC },
301fa9e4066Sahrens };
302fa9e4066Sahrens
303dd50e0ccSTony Hutter #define NCOMMAND (ARRAY_SIZE(command_table))
304fa9e4066Sahrens
305663207adSDon Brady #define VDEV_ALLOC_CLASS_LOGS "logs"
306663207adSDon Brady
3074445fffbSMatthew Ahrens static zpool_command_t *current_command;
3082a6b87f0Sek110237 static char history_str[HIS_MAX_RECORD_LEN];
3094445fffbSMatthew Ahrens static boolean_t log_history = B_TRUE;
31026fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE;
31126fd7700SKrishnendu Sadhukhan - Sun Microsystems
31265cd9f28Seschrock static const char *
get_usage(zpool_help_t idx)3139a686fbcSPaul Dagnelie get_usage(zpool_help_t idx)
3149a686fbcSPaul Dagnelie {
31565cd9f28Seschrock switch (idx) {
31665cd9f28Seschrock case HELP_ADD:
3175711d393Sloli10K return (gettext("\tadd [-fgLnP] [-o property=value] "
3185711d393Sloli10K "<pool> <vdev> ...\n"));
31965cd9f28Seschrock case HELP_ATTACH:
3205711d393Sloli10K return (gettext("\tattach [-f] [-o property=value] "
3215711d393Sloli10K "<pool> <device> <new-device>\n"));
322ea8dc4b6Seschrock case HELP_CLEAR:
323468c413aSTim Haley return (gettext("\tclear [-nF] <pool> [device]\n"));
32465cd9f28Seschrock case HELP_CREATE:
3257855d95bSToomas Soome return (gettext("\tcreate [-fnd] [-B] "
3267855d95bSToomas Soome "[-o property=value] ... \n"
3270a48a24eStimh "\t [-O file-system-property=value] ...\n"
32804e56356SAndriy Gapon "\t [-m mountpoint] [-R root] [-t tempname] "
32904e56356SAndriy Gapon "<pool> <vdev> ...\n"));
33086714001SSerapheim Dimitropoulos case HELP_CHECKPOINT:
33186714001SSerapheim Dimitropoulos return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
33265cd9f28Seschrock case HELP_DESTROY:
33365cd9f28Seschrock return (gettext("\tdestroy [-f] <pool>\n"));
33465cd9f28Seschrock case HELP_DETACH:
33565cd9f28Seschrock return (gettext("\tdetach <pool> <device>\n"));
33665cd9f28Seschrock case HELP_EXPORT:
33765cd9f28Seschrock return (gettext("\texport [-f] <pool> ...\n"));
33806eeb2adSek110237 case HELP_HISTORY:
339ecd6cf80Smarks return (gettext("\thistory [-il] [<pool>] ...\n"));
34065cd9f28Seschrock case HELP_IMPORT:
3414c58d714Sdarrenm return (gettext("\timport [-d dir] [-D]\n"
342eb633035STom Caputi "\timport [-d dir | -c cachefile] [-F [-n]] [-l] "
343eb633035STom Caputi "<pool | id>\n"
3442f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n"
345eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
346f9af39baSGeorge Wilson "[-R root] [-F [-n]] -a\n"
3472f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n"
348eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
34904e56356SAndriy Gapon "[-R root] [-F [-n]] [-t]\n"
35086714001SSerapheim Dimitropoulos "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
35165cd9f28Seschrock case HELP_IOSTAT:
352dd50e0ccSTony Hutter return (gettext("\tiostat "
353dd50e0ccSTony Hutter "[[-lq]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
35420f5062bSJerry Jelinek "\t [[pool] ...]|[pool vdev ...]|[vdev ...]]"
355dd50e0ccSTony Hutter " [[-n] interval [count]]\n"));
3566401734dSWill Andrews case HELP_LABELCLEAR:
3576401734dSWill Andrews return (gettext("\tlabelclear [-f] <vdev>\n"));
35865cd9f28Seschrock case HELP_LIST:
359663207adSDon Brady return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
3603f9d6ad7SLin Ling "[-T d|u] [pool] ... [interval [count]]\n"));
36165cd9f28Seschrock case HELP_OFFLINE:
362441d80aaSlling return (gettext("\toffline [-t] <pool> <device> ...\n"));
36365cd9f28Seschrock case HELP_ONLINE:
3644283d10eScneira return (gettext("\tonline [-e] <pool> <device> ...\n"));
36565cd9f28Seschrock case HELP_REPLACE:
36665cd9f28Seschrock return (gettext("\treplace [-f] <pool> <device> "
367e45ce728Sahrens "[new-device]\n"));
36899653d4eSeschrock case HELP_REMOVE:
3695cabbc6bSPrashanth Sreenivasa return (gettext("\tremove [-nps] <pool> <device> ...\n"));
3704263d13fSGeorge Wilson case HELP_REOPEN:
37131d7e8faSGeorge Wilson return (gettext("\treopen <pool>\n"));
372094e47e9SGeorge Wilson case HELP_INITIALIZE:
373084fd14fSBrian Behlendorf return (gettext("\tinitialize [-c | -s] <pool> "
374084fd14fSBrian Behlendorf "[<device> ...]\n"));
37565cd9f28Seschrock case HELP_SCRUB:
3761702cce7SAlek Pinchuk return (gettext("\tscrub [-s | -p] <pool> ...\n"));
377e4c795beSTom Caputi case HELP_RESILVER:
378e4c795beSTom Caputi return (gettext("\tresilver <pool> ...\n"));
379084fd14fSBrian Behlendorf case HELP_TRIM:
380084fd14fSBrian Behlendorf return (gettext("\ttrim [-d] [-r <rate>] [-c | -s] <pool> "
381084fd14fSBrian Behlendorf "[<device> ...]\n"));
38265cd9f28Seschrock case HELP_STATUS:
383dd50e0ccSTony Hutter return (gettext("\tstatus "
384dd50e0ccSTony Hutter "[-igLpPsvxD] [-T d|u] [pool] ... "
385663207adSDon Brady "[interval [count]]\n"));
386eaca9bbdSeschrock case HELP_UPGRADE:
387eaca9bbdSeschrock return (gettext("\tupgrade\n"
388eaca9bbdSeschrock "\tupgrade -v\n"
389990b4856Slling "\tupgrade [-V version] <-a | pool ...>\n"));
390b1b8ab34Slling case HELP_GET:
391c58b3526SAdam Stevko return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
392c58b3526SAdam Stevko "<\"all\" | property[,...]> <pool> ...\n"));
393b1b8ab34Slling case HELP_SET:
394b1b8ab34Slling return (gettext("\tset <property=value> <pool> \n"));
3951195e687SMark J Musante case HELP_SPLIT:
396eb633035STom Caputi return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n"
3971195e687SMark J Musante "\t [-o property=value] <pool> <newpool> "
3981195e687SMark J Musante "[<device> ...]\n"));
399e9103aaeSGarrett D'Amore case HELP_REGUID:
400e9103aaeSGarrett D'Amore return (gettext("\treguid <pool>\n"));
4019c2acf00SAlek Pinchuk case HELP_SYNC:
4029c2acf00SAlek Pinchuk return (gettext("\tsync [pool] ...\n"));
40365cd9f28Seschrock }
40465cd9f28Seschrock
40565cd9f28Seschrock abort();
40665cd9f28Seschrock /* NOTREACHED */
40765cd9f28Seschrock }
40865cd9f28Seschrock
409084fd14fSBrian Behlendorf static void
zpool_collect_leaves(zpool_handle_t * zhp,nvlist_t * nvroot,nvlist_t * res)410084fd14fSBrian Behlendorf zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
411084fd14fSBrian Behlendorf {
412084fd14fSBrian Behlendorf uint_t children = 0;
413084fd14fSBrian Behlendorf nvlist_t **child;
414084fd14fSBrian Behlendorf uint_t i;
415084fd14fSBrian Behlendorf
416084fd14fSBrian Behlendorf (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
417084fd14fSBrian Behlendorf &child, &children);
418084fd14fSBrian Behlendorf
419084fd14fSBrian Behlendorf if (children == 0) {
420084fd14fSBrian Behlendorf char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 0);
421084fd14fSBrian Behlendorf
422084fd14fSBrian Behlendorf if (strcmp(path, VDEV_TYPE_INDIRECT) != 0)
423084fd14fSBrian Behlendorf fnvlist_add_boolean(res, path);
424084fd14fSBrian Behlendorf
425084fd14fSBrian Behlendorf free(path);
426084fd14fSBrian Behlendorf return;
427084fd14fSBrian Behlendorf }
428084fd14fSBrian Behlendorf
429084fd14fSBrian Behlendorf for (i = 0; i < children; i++) {
430084fd14fSBrian Behlendorf zpool_collect_leaves(zhp, child[i], res);
431084fd14fSBrian Behlendorf }
432084fd14fSBrian Behlendorf }
433fa9e4066Sahrens
434fa9e4066Sahrens /*
435b1b8ab34Slling * Callback routine that will print out a pool property value.
436b1b8ab34Slling */
437990b4856Slling static int
print_prop_cb(int prop,void * cb)438990b4856Slling print_prop_cb(int prop, void *cb)
439b1b8ab34Slling {
440b1b8ab34Slling FILE *fp = cb;
441b1b8ab34Slling
442663207adSDon Brady (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop));
443b1b8ab34Slling
444990b4856Slling if (zpool_prop_readonly(prop))
445990b4856Slling (void) fprintf(fp, " NO ");
446990b4856Slling else
447990b4856Slling (void) fprintf(fp, " YES ");
448990b4856Slling
449b1b8ab34Slling if (zpool_prop_values(prop) == NULL)
450b1b8ab34Slling (void) fprintf(fp, "-\n");
451b1b8ab34Slling else
452b1b8ab34Slling (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
453b1b8ab34Slling
454990b4856Slling return (ZPROP_CONT);
455b1b8ab34Slling }
456b1b8ab34Slling
457b1b8ab34Slling /*
458fa9e4066Sahrens * Display usage message. If we're inside a command, display only the usage for
459fa9e4066Sahrens * that command. Otherwise, iterate over the entire command table and display
460fa9e4066Sahrens * a complete usage message.
461fa9e4066Sahrens */
462fa9e4066Sahrens void
usage(boolean_t requested)46399653d4eSeschrock usage(boolean_t requested)
464fa9e4066Sahrens {
465fa9e4066Sahrens FILE *fp = requested ? stdout : stderr;
466fa9e4066Sahrens
467fa9e4066Sahrens if (current_command == NULL) {
468fa9e4066Sahrens int i;
469fa9e4066Sahrens
470fa9e4066Sahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
471fa9e4066Sahrens (void) fprintf(fp,
472fa9e4066Sahrens gettext("where 'command' is one of the following:\n\n"));
473fa9e4066Sahrens
474fa9e4066Sahrens for (i = 0; i < NCOMMAND; i++) {
475fa9e4066Sahrens if (command_table[i].name == NULL)
476fa9e4066Sahrens (void) fprintf(fp, "\n");
477fa9e4066Sahrens else
478fa9e4066Sahrens (void) fprintf(fp, "%s",
47965cd9f28Seschrock get_usage(command_table[i].usage));
480fa9e4066Sahrens }
481fa9e4066Sahrens } else {
482fa9e4066Sahrens (void) fprintf(fp, gettext("usage:\n"));
48365cd9f28Seschrock (void) fprintf(fp, "%s", get_usage(current_command->usage));
484fa9e4066Sahrens }
485fa9e4066Sahrens
486b1b8ab34Slling if (current_command != NULL &&
487b1b8ab34Slling ((strcmp(current_command->name, "set") == 0) ||
488990b4856Slling (strcmp(current_command->name, "get") == 0) ||
489990b4856Slling (strcmp(current_command->name, "list") == 0))) {
490b1b8ab34Slling
491b1b8ab34Slling (void) fprintf(fp,
492b1b8ab34Slling gettext("\nthe following properties are supported:\n"));
493b1b8ab34Slling
494663207adSDon Brady (void) fprintf(fp, "\n\t%-19s %s %s\n\n",
495990b4856Slling "PROPERTY", "EDIT", "VALUES");
496b1b8ab34Slling
497b1b8ab34Slling /* Iterate over all properties */
498990b4856Slling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
499990b4856Slling ZFS_TYPE_POOL);
500ad135b5dSChristopher Siden
501663207adSDon Brady (void) fprintf(fp, "\t%-19s ", "feature@...");
502ad135b5dSChristopher Siden (void) fprintf(fp, "YES disabled | enabled | active\n");
503ad135b5dSChristopher Siden
504ad135b5dSChristopher Siden (void) fprintf(fp, gettext("\nThe feature@ properties must be "
505bbf21555SRichard Lowe "appended with a feature name.\nSee zpool-features(7).\n"));
506b1b8ab34Slling }
507b1b8ab34Slling
508e9dbad6fSeschrock /*
509e9dbad6fSeschrock * See comments at end of main().
510e9dbad6fSeschrock */
511e9dbad6fSeschrock if (getenv("ZFS_ABORT") != NULL) {
512e9dbad6fSeschrock (void) printf("dumping core by request\n");
513e9dbad6fSeschrock abort();
514e9dbad6fSeschrock }
515e9dbad6fSeschrock
516fa9e4066Sahrens exit(requested ? 0 : 2);
517fa9e4066Sahrens }
518fa9e4066Sahrens
519663207adSDon Brady /*
520663207adSDon Brady * print a pool vdev config for dry runs
521663207adSDon Brady */
522663207adSDon Brady static void
print_vdev_tree(zpool_handle_t * zhp,const char * name,nvlist_t * nv,int indent,const char * match,int name_flags)5238654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
524663207adSDon Brady const char *match, int name_flags)
525fa9e4066Sahrens {
526fa9e4066Sahrens nvlist_t **child;
527fa9e4066Sahrens uint_t c, children;
528afefbcddSeschrock char *vname;
529663207adSDon Brady boolean_t printed = B_FALSE;
530fa9e4066Sahrens
531fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
532663207adSDon Brady &child, &children) != 0) {
533663207adSDon Brady if (name != NULL)
534663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name);
535fa9e4066Sahrens return;
536663207adSDon Brady }
537fa9e4066Sahrens
538afefbcddSeschrock for (c = 0; c < children; c++) {
5398654d025Sperrin uint64_t is_log = B_FALSE;
540663207adSDon Brady char *class = "";
5418654d025Sperrin
5428654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
5438654d025Sperrin &is_log);
544663207adSDon Brady if (is_log)
545663207adSDon Brady class = VDEV_ALLOC_BIAS_LOG;
546663207adSDon Brady (void) nvlist_lookup_string(child[c],
547663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
548663207adSDon Brady if (strcmp(match, class) != 0)
5498654d025Sperrin continue;
5508654d025Sperrin
551663207adSDon Brady if (!printed && name != NULL) {
552663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name);
553663207adSDon Brady printed = B_TRUE;
554663207adSDon Brady }
555663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
556663207adSDon Brady print_vdev_tree(zhp, vname, child[c], indent + 2, "",
557663207adSDon Brady name_flags);
558afefbcddSeschrock free(vname);
559afefbcddSeschrock }
560fa9e4066Sahrens }
561fa9e4066Sahrens
56257221772SChristopher Siden static boolean_t
prop_list_contains_feature(nvlist_t * proplist)56357221772SChristopher Siden prop_list_contains_feature(nvlist_t *proplist)
56457221772SChristopher Siden {
56557221772SChristopher Siden nvpair_t *nvp;
56657221772SChristopher Siden for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
56757221772SChristopher Siden nvp = nvlist_next_nvpair(proplist, nvp)) {
56857221772SChristopher Siden if (zpool_prop_feature(nvpair_name(nvp)))
56957221772SChristopher Siden return (B_TRUE);
57057221772SChristopher Siden }
57157221772SChristopher Siden return (B_FALSE);
57257221772SChristopher Siden }
57357221772SChristopher Siden
574fa9e4066Sahrens /*
575990b4856Slling * Add a property pair (name, string-value) into a property nvlist.
576990b4856Slling */
577990b4856Slling static int
add_prop_list(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)5780a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props,
5790a48a24eStimh boolean_t poolprop)
580990b4856Slling {
581d2aa06e8SAndrew Stormont zpool_prop_t prop = ZPOOL_PROP_INVAL;
5820a48a24eStimh zfs_prop_t fprop;
583990b4856Slling nvlist_t *proplist;
5840a48a24eStimh const char *normnm;
5850a48a24eStimh char *strval;
586990b4856Slling
587990b4856Slling if (*props == NULL &&
588990b4856Slling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
589990b4856Slling (void) fprintf(stderr,
590990b4856Slling gettext("internal error: out of memory\n"));
591990b4856Slling return (1);
592990b4856Slling }
593990b4856Slling
594990b4856Slling proplist = *props;
595990b4856Slling
5960a48a24eStimh if (poolprop) {
59757221772SChristopher Siden const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
59857221772SChristopher Siden
599d2aa06e8SAndrew Stormont if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
600ad135b5dSChristopher Siden !zpool_prop_feature(propname)) {
601990b4856Slling (void) fprintf(stderr, gettext("property '%s' is "
602990b4856Slling "not a valid pool property\n"), propname);
603990b4856Slling return (2);
604990b4856Slling }
60557221772SChristopher Siden
60657221772SChristopher Siden /*
60757221772SChristopher Siden * feature@ properties and version should not be specified
60857221772SChristopher Siden * at the same time.
60957221772SChristopher Siden */
6104ae5f5f0SAlan Somers if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
61157221772SChristopher Siden nvlist_exists(proplist, vname)) ||
61257221772SChristopher Siden (prop == ZPOOL_PROP_VERSION &&
61357221772SChristopher Siden prop_list_contains_feature(proplist))) {
61457221772SChristopher Siden (void) fprintf(stderr, gettext("'feature@' and "
61557221772SChristopher Siden "'version' properties cannot be specified "
61657221772SChristopher Siden "together\n"));
61757221772SChristopher Siden return (2);
61857221772SChristopher Siden }
61957221772SChristopher Siden
62057221772SChristopher Siden
621ad135b5dSChristopher Siden if (zpool_prop_feature(propname))
622ad135b5dSChristopher Siden normnm = propname;
623ad135b5dSChristopher Siden else
6240a48a24eStimh normnm = zpool_prop_to_name(prop);
6250a48a24eStimh } else {
62614843421SMatthew Ahrens if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
6270a48a24eStimh normnm = zfs_prop_to_name(fprop);
62814843421SMatthew Ahrens } else {
62914843421SMatthew Ahrens normnm = propname;
63014843421SMatthew Ahrens }
6310a48a24eStimh }
632990b4856Slling
6330a48a24eStimh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
6340a48a24eStimh prop != ZPOOL_PROP_CACHEFILE) {
635990b4856Slling (void) fprintf(stderr, gettext("property '%s' "
636990b4856Slling "specified multiple times\n"), propname);
637990b4856Slling return (2);
638990b4856Slling }
639990b4856Slling
6400a48a24eStimh if (nvlist_add_string(proplist, normnm, propval) != 0) {
641990b4856Slling (void) fprintf(stderr, gettext("internal "
642990b4856Slling "error: out of memory\n"));
643990b4856Slling return (1);
644990b4856Slling }
645990b4856Slling
646990b4856Slling return (0);
647990b4856Slling }
648990b4856Slling
649990b4856Slling /*
65004e56356SAndriy Gapon * Set a default property pair (name, string-value) in a property nvlist
65104e56356SAndriy Gapon */
65204e56356SAndriy Gapon static int
add_prop_list_default(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)65304e56356SAndriy Gapon add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
65404e56356SAndriy Gapon boolean_t poolprop)
65504e56356SAndriy Gapon {
65604e56356SAndriy Gapon char *pval;
65704e56356SAndriy Gapon
65804e56356SAndriy Gapon if (nvlist_lookup_string(*props, propname, &pval) == 0)
65904e56356SAndriy Gapon return (0);
66004e56356SAndriy Gapon
66104e56356SAndriy Gapon return (add_prop_list(propname, propval, props, poolprop));
66204e56356SAndriy Gapon }
66304e56356SAndriy Gapon
66404e56356SAndriy Gapon /*
665663207adSDon Brady * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
666fa9e4066Sahrens *
667fa9e4066Sahrens * -f Force addition of devices, even if they appear in use
668663207adSDon Brady * -g Display guid for individual vdev name.
669663207adSDon Brady * -L Follow links when resolving vdev path name.
670fa9e4066Sahrens * -n Do not add the devices, but display the resulting layout if
671fa9e4066Sahrens * they were to be added.
672663207adSDon Brady * -P Display full path for vdev name.
6735711d393Sloli10K * -o Set property=value.
674fa9e4066Sahrens *
675fa9e4066Sahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
676fa9e4066Sahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
677fa9e4066Sahrens * libzfs.
678fa9e4066Sahrens */
679fa9e4066Sahrens int
zpool_do_add(int argc,char ** argv)680fa9e4066Sahrens zpool_do_add(int argc, char **argv)
681fa9e4066Sahrens {
68299653d4eSeschrock boolean_t force = B_FALSE;
68399653d4eSeschrock boolean_t dryrun = B_FALSE;
684663207adSDon Brady int name_flags = 0;
685fa9e4066Sahrens int c;
686fa9e4066Sahrens nvlist_t *nvroot;
687fa9e4066Sahrens char *poolname;
6887855d95bSToomas Soome zpool_boot_label_t boot_type;
6897855d95bSToomas Soome uint64_t boot_size;
690fa9e4066Sahrens int ret;
691fa9e4066Sahrens zpool_handle_t *zhp;
692fa9e4066Sahrens nvlist_t *config;
6935711d393Sloli10K nvlist_t *props = NULL;
6945711d393Sloli10K char *propval;
695fa9e4066Sahrens
696fa9e4066Sahrens /* check options */
6975711d393Sloli10K while ((c = getopt(argc, argv, "fgLnPo:")) != -1) {
698fa9e4066Sahrens switch (c) {
699fa9e4066Sahrens case 'f':
70099653d4eSeschrock force = B_TRUE;
701fa9e4066Sahrens break;
702663207adSDon Brady case 'g':
703663207adSDon Brady name_flags |= VDEV_NAME_GUID;
704663207adSDon Brady break;
705663207adSDon Brady case 'L':
706663207adSDon Brady name_flags |= VDEV_NAME_FOLLOW_LINKS;
707663207adSDon Brady break;
708fa9e4066Sahrens case 'n':
70999653d4eSeschrock dryrun = B_TRUE;
710fa9e4066Sahrens break;
711663207adSDon Brady case 'P':
712663207adSDon Brady name_flags |= VDEV_NAME_PATH;
713663207adSDon Brady break;
7145711d393Sloli10K case 'o':
7155711d393Sloli10K if ((propval = strchr(optarg, '=')) == NULL) {
7165711d393Sloli10K (void) fprintf(stderr, gettext("missing "
7175711d393Sloli10K "'=' for -o option\n"));
7185711d393Sloli10K usage(B_FALSE);
7195711d393Sloli10K }
7205711d393Sloli10K *propval = '\0';
7215711d393Sloli10K propval++;
7225711d393Sloli10K
7235711d393Sloli10K if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
7245711d393Sloli10K (add_prop_list(optarg, propval, &props, B_TRUE)))
7255711d393Sloli10K usage(B_FALSE);
7265711d393Sloli10K break;
727fa9e4066Sahrens case '?':
728fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
729fa9e4066Sahrens optopt);
73099653d4eSeschrock usage(B_FALSE);
731fa9e4066Sahrens }
732fa9e4066Sahrens }
733fa9e4066Sahrens
734fa9e4066Sahrens argc -= optind;
735fa9e4066Sahrens argv += optind;
736fa9e4066Sahrens
737fa9e4066Sahrens /* get pool name and check number of arguments */
738fa9e4066Sahrens if (argc < 1) {
739fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n"));
74099653d4eSeschrock usage(B_FALSE);
741fa9e4066Sahrens }
742fa9e4066Sahrens if (argc < 2) {
743fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n"));
74499653d4eSeschrock usage(B_FALSE);
745fa9e4066Sahrens }
746fa9e4066Sahrens
747fa9e4066Sahrens poolname = argv[0];
748fa9e4066Sahrens
749fa9e4066Sahrens argc--;
750fa9e4066Sahrens argv++;
751fa9e4066Sahrens
75299653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
753fa9e4066Sahrens return (1);
754fa9e4066Sahrens
755088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) {
756fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
757fa9e4066Sahrens poolname);
758fa9e4066Sahrens zpool_close(zhp);
759fa9e4066Sahrens return (1);
760fa9e4066Sahrens }
761fa9e4066Sahrens
7627855d95bSToomas Soome if (zpool_is_bootable(zhp))
7637855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL;
7647855d95bSToomas Soome else
7657855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL;
7667855d95bSToomas Soome
7675711d393Sloli10K /* unless manually specified use "ashift" pool property (if set) */
7685711d393Sloli10K if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
7695711d393Sloli10K int intval;
7705711d393Sloli10K zprop_source_t src;
7715711d393Sloli10K char strval[ZPOOL_MAXPROPLEN];
7725711d393Sloli10K
7735711d393Sloli10K intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
7745711d393Sloli10K if (src != ZPROP_SRC_DEFAULT) {
7755711d393Sloli10K (void) sprintf(strval, "%" PRId32, intval);
7765711d393Sloli10K verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
7775711d393Sloli10K &props, B_TRUE) == 0);
7785711d393Sloli10K }
7795711d393Sloli10K }
7805711d393Sloli10K
781fa9e4066Sahrens /* pass off to get_vdev_spec for processing */
7827855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
7835711d393Sloli10K nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
7847855d95bSToomas Soome boot_type, boot_size, argc, argv);
785fa9e4066Sahrens if (nvroot == NULL) {
786fa9e4066Sahrens zpool_close(zhp);
787fa9e4066Sahrens return (1);
788fa9e4066Sahrens }
789fa9e4066Sahrens
790fa9e4066Sahrens if (dryrun) {
791fa9e4066Sahrens nvlist_t *poolnvroot;
792fa9e4066Sahrens
793fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
794fa9e4066Sahrens &poolnvroot) == 0);
795fa9e4066Sahrens
796fa9e4066Sahrens (void) printf(gettext("would update '%s' to the following "
797fa9e4066Sahrens "configuration:\n"), zpool_get_name(zhp));
798fa9e4066Sahrens
7998654d025Sperrin /* print original main pool and new tree */
800663207adSDon Brady print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
801663207adSDon Brady name_flags | VDEV_NAME_TYPE_ID);
802663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
8038654d025Sperrin
804663207adSDon Brady /* print other classes: 'dedup', 'special', and 'log' */
805663207adSDon Brady print_vdev_tree(zhp, "dedup", poolnvroot, 0,
806663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, name_flags);
807663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP,
808663207adSDon Brady name_flags);
809663207adSDon Brady
810663207adSDon Brady print_vdev_tree(zhp, "special", poolnvroot, 0,
811663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, name_flags);
812663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL,
813663207adSDon Brady name_flags);
814663207adSDon Brady
815663207adSDon Brady print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG,
816663207adSDon Brady name_flags);
817663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG,
818663207adSDon Brady name_flags);
819fa9e4066Sahrens
820fa9e4066Sahrens ret = 0;
821fa9e4066Sahrens } else {
822fa9e4066Sahrens ret = (zpool_add(zhp, nvroot) != 0);
823fa9e4066Sahrens }
824fa9e4066Sahrens
8255711d393Sloli10K nvlist_free(props);
82699653d4eSeschrock nvlist_free(nvroot);
82799653d4eSeschrock zpool_close(zhp);
82899653d4eSeschrock
82999653d4eSeschrock return (ret);
83099653d4eSeschrock }
83199653d4eSeschrock
83299653d4eSeschrock /*
833fa94a07fSbrendan * zpool remove <pool> <vdev> ...
83499653d4eSeschrock *
8355cabbc6bSPrashanth Sreenivasa * Removes the given vdev from the pool.
83699653d4eSeschrock */
83799653d4eSeschrock int
zpool_do_remove(int argc,char ** argv)83899653d4eSeschrock zpool_do_remove(int argc, char **argv)
83999653d4eSeschrock {
84099653d4eSeschrock char *poolname;
841fa94a07fSbrendan int i, ret = 0;
84299653d4eSeschrock zpool_handle_t *zhp;
8435cabbc6bSPrashanth Sreenivasa boolean_t stop = B_FALSE;
8445cabbc6bSPrashanth Sreenivasa boolean_t noop = B_FALSE;
8455cabbc6bSPrashanth Sreenivasa boolean_t parsable = B_FALSE;
846*ef150c2bSRichard Lowe int c;
84799653d4eSeschrock
8485cabbc6bSPrashanth Sreenivasa /* check options */
8495cabbc6bSPrashanth Sreenivasa while ((c = getopt(argc, argv, "nps")) != -1) {
8505cabbc6bSPrashanth Sreenivasa switch (c) {
8515cabbc6bSPrashanth Sreenivasa case 'n':
8525cabbc6bSPrashanth Sreenivasa noop = B_TRUE;
8535cabbc6bSPrashanth Sreenivasa break;
8545cabbc6bSPrashanth Sreenivasa case 'p':
8555cabbc6bSPrashanth Sreenivasa parsable = B_TRUE;
8565cabbc6bSPrashanth Sreenivasa break;
8575cabbc6bSPrashanth Sreenivasa case 's':
8585cabbc6bSPrashanth Sreenivasa stop = B_TRUE;
8595cabbc6bSPrashanth Sreenivasa break;
8605cabbc6bSPrashanth Sreenivasa case '?':
8615cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8625cabbc6bSPrashanth Sreenivasa optopt);
8635cabbc6bSPrashanth Sreenivasa usage(B_FALSE);
8645cabbc6bSPrashanth Sreenivasa }
8655cabbc6bSPrashanth Sreenivasa }
8665cabbc6bSPrashanth Sreenivasa
8675cabbc6bSPrashanth Sreenivasa argc -= optind;
8685cabbc6bSPrashanth Sreenivasa argv += optind;
86999653d4eSeschrock
87099653d4eSeschrock /* get pool name and check number of arguments */
87199653d4eSeschrock if (argc < 1) {
87299653d4eSeschrock (void) fprintf(stderr, gettext("missing pool name argument\n"));
87399653d4eSeschrock usage(B_FALSE);
87499653d4eSeschrock }
87599653d4eSeschrock
87699653d4eSeschrock poolname = argv[0];
87799653d4eSeschrock
87899653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
87999653d4eSeschrock return (1);
88099653d4eSeschrock
8815cabbc6bSPrashanth Sreenivasa if (stop && noop) {
8825cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("stop request ignored\n"));
8835cabbc6bSPrashanth Sreenivasa return (0);
8845cabbc6bSPrashanth Sreenivasa }
8855cabbc6bSPrashanth Sreenivasa
8865cabbc6bSPrashanth Sreenivasa if (stop) {
8875cabbc6bSPrashanth Sreenivasa if (argc > 1) {
8885cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("too many arguments\n"));
8895cabbc6bSPrashanth Sreenivasa usage(B_FALSE);
8905cabbc6bSPrashanth Sreenivasa }
8915cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove_cancel(zhp) != 0)
8925cabbc6bSPrashanth Sreenivasa ret = 1;
8935cabbc6bSPrashanth Sreenivasa } else {
8945cabbc6bSPrashanth Sreenivasa if (argc < 2) {
8955cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("missing device\n"));
8965cabbc6bSPrashanth Sreenivasa usage(B_FALSE);
8975cabbc6bSPrashanth Sreenivasa }
8985cabbc6bSPrashanth Sreenivasa
899fa94a07fSbrendan for (i = 1; i < argc; i++) {
9005cabbc6bSPrashanth Sreenivasa if (noop) {
9015cabbc6bSPrashanth Sreenivasa uint64_t size;
9025cabbc6bSPrashanth Sreenivasa
9035cabbc6bSPrashanth Sreenivasa if (zpool_vdev_indirect_size(zhp, argv[i],
9045cabbc6bSPrashanth Sreenivasa &size) != 0) {
9055cabbc6bSPrashanth Sreenivasa ret = 1;
9065cabbc6bSPrashanth Sreenivasa break;
9075cabbc6bSPrashanth Sreenivasa }
9085cabbc6bSPrashanth Sreenivasa if (parsable) {
9095cabbc6bSPrashanth Sreenivasa (void) printf("%s %llu\n",
9105cabbc6bSPrashanth Sreenivasa argv[i], size);
9115cabbc6bSPrashanth Sreenivasa } else {
9125cabbc6bSPrashanth Sreenivasa char valstr[32];
9135cabbc6bSPrashanth Sreenivasa zfs_nicenum(size, valstr,
9145cabbc6bSPrashanth Sreenivasa sizeof (valstr));
9155cabbc6bSPrashanth Sreenivasa (void) printf("Memory that will be "
9165cabbc6bSPrashanth Sreenivasa "used after removing %s: %s\n",
9175cabbc6bSPrashanth Sreenivasa argv[i], valstr);
9185cabbc6bSPrashanth Sreenivasa }
9195cabbc6bSPrashanth Sreenivasa } else {
920fa94a07fSbrendan if (zpool_vdev_remove(zhp, argv[i]) != 0)
921fa94a07fSbrendan ret = 1;
922fa94a07fSbrendan }
9235cabbc6bSPrashanth Sreenivasa }
9245cabbc6bSPrashanth Sreenivasa }
92599653d4eSeschrock
926fa9e4066Sahrens return (ret);
927fa9e4066Sahrens }
928fa9e4066Sahrens
929fa9e4066Sahrens /*
9306401734dSWill Andrews * zpool labelclear [-f] <vdev>
9316401734dSWill Andrews *
9326401734dSWill Andrews * -f Force clearing the label for the vdevs which are members of
9336401734dSWill Andrews * the exported or foreign pools.
9346401734dSWill Andrews *
9356401734dSWill Andrews * Verifies that the vdev is not active and zeros out the label information
9366401734dSWill Andrews * on the device.
9376401734dSWill Andrews */
9386401734dSWill Andrews int
zpool_do_labelclear(int argc,char ** argv)9396401734dSWill Andrews zpool_do_labelclear(int argc, char **argv)
9406401734dSWill Andrews {
9416401734dSWill Andrews char vdev[MAXPATHLEN];
9426401734dSWill Andrews char *name = NULL;
9436401734dSWill Andrews struct stat st;
9446401734dSWill Andrews int c, fd, ret = 0;
9456401734dSWill Andrews nvlist_t *config;
9466401734dSWill Andrews pool_state_t state;
9476401734dSWill Andrews boolean_t inuse = B_FALSE;
9486401734dSWill Andrews boolean_t force = B_FALSE;
9496401734dSWill Andrews
9506401734dSWill Andrews /* check options */
9516401734dSWill Andrews while ((c = getopt(argc, argv, "f")) != -1) {
9526401734dSWill Andrews switch (c) {
9536401734dSWill Andrews case 'f':
9546401734dSWill Andrews force = B_TRUE;
9556401734dSWill Andrews break;
9566401734dSWill Andrews default:
9576401734dSWill Andrews (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9586401734dSWill Andrews optopt);
9596401734dSWill Andrews usage(B_FALSE);
9606401734dSWill Andrews }
9616401734dSWill Andrews }
9626401734dSWill Andrews
9636401734dSWill Andrews argc -= optind;
9646401734dSWill Andrews argv += optind;
9656401734dSWill Andrews
9666401734dSWill Andrews /* get vdev name */
9676401734dSWill Andrews if (argc < 1) {
9686401734dSWill Andrews (void) fprintf(stderr, gettext("missing vdev name\n"));
9696401734dSWill Andrews usage(B_FALSE);
9706401734dSWill Andrews }
9716401734dSWill Andrews if (argc > 1) {
9726401734dSWill Andrews (void) fprintf(stderr, gettext("too many arguments\n"));
9736401734dSWill Andrews usage(B_FALSE);
9746401734dSWill Andrews }
9756401734dSWill Andrews
9766401734dSWill Andrews /*
9776401734dSWill Andrews * Check if we were given absolute path and use it as is.
9786401734dSWill Andrews * Otherwise if the provided vdev name doesn't point to a file,
9796401734dSWill Andrews * try prepending dsk path and appending s0.
9806401734dSWill Andrews */
9816401734dSWill Andrews (void) strlcpy(vdev, argv[0], sizeof (vdev));
9826401734dSWill Andrews if (vdev[0] != '/' && stat(vdev, &st) != 0) {
9836401734dSWill Andrews char *s;
9846401734dSWill Andrews
9856401734dSWill Andrews (void) snprintf(vdev, sizeof (vdev), "%s/%s",
9866401734dSWill Andrews ZFS_DISK_ROOT, argv[0]);
9876401734dSWill Andrews if ((s = strrchr(argv[0], 's')) == NULL ||
9886401734dSWill Andrews !isdigit(*(s + 1)))
9896401734dSWill Andrews (void) strlcat(vdev, "s0", sizeof (vdev));
9906401734dSWill Andrews if (stat(vdev, &st) != 0) {
9916401734dSWill Andrews (void) fprintf(stderr, gettext(
9926401734dSWill Andrews "failed to find device %s, try specifying absolute "
9936401734dSWill Andrews "path instead\n"), argv[0]);
9946401734dSWill Andrews return (1);
9956401734dSWill Andrews }
9966401734dSWill Andrews }
9976401734dSWill Andrews
9986401734dSWill Andrews if ((fd = open(vdev, O_RDWR)) < 0) {
9996401734dSWill Andrews (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
10006401734dSWill Andrews vdev, strerror(errno));
10016401734dSWill Andrews return (1);
10026401734dSWill Andrews }
10036401734dSWill Andrews
1004d8ab6e12SDon Brady if (zpool_read_label(fd, &config, NULL) != 0) {
10056401734dSWill Andrews (void) fprintf(stderr,
10066401734dSWill Andrews gettext("failed to read label from %s\n"), vdev);
10076401734dSWill Andrews return (1);
10086401734dSWill Andrews }
10096401734dSWill Andrews nvlist_free(config);
10106401734dSWill Andrews
10116401734dSWill Andrews ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
10126401734dSWill Andrews if (ret != 0) {
10136401734dSWill Andrews (void) fprintf(stderr,
10146401734dSWill Andrews gettext("failed to check state for %s\n"), vdev);
10156401734dSWill Andrews return (1);
10166401734dSWill Andrews }
10176401734dSWill Andrews
10186401734dSWill Andrews if (!inuse)
10196401734dSWill Andrews goto wipe_label;
10206401734dSWill Andrews
10216401734dSWill Andrews switch (state) {
10226401734dSWill Andrews default:
10236401734dSWill Andrews case POOL_STATE_ACTIVE:
10246401734dSWill Andrews case POOL_STATE_SPARE:
10256401734dSWill Andrews case POOL_STATE_L2CACHE:
10266401734dSWill Andrews (void) fprintf(stderr, gettext(
10276401734dSWill Andrews "%s is a member (%s) of pool \"%s\"\n"),
10286401734dSWill Andrews vdev, zpool_pool_state_to_name(state), name);
10296401734dSWill Andrews ret = 1;
10306401734dSWill Andrews goto errout;
10316401734dSWill Andrews
10326401734dSWill Andrews case POOL_STATE_EXPORTED:
10336401734dSWill Andrews if (force)
10346401734dSWill Andrews break;
10356401734dSWill Andrews (void) fprintf(stderr, gettext(
10366401734dSWill Andrews "use '-f' to override the following error:\n"
10376401734dSWill Andrews "%s is a member of exported pool \"%s\"\n"),
10386401734dSWill Andrews vdev, name);
10396401734dSWill Andrews ret = 1;
10406401734dSWill Andrews goto errout;
10416401734dSWill Andrews
10426401734dSWill Andrews case POOL_STATE_POTENTIALLY_ACTIVE:
10436401734dSWill Andrews if (force)
10446401734dSWill Andrews break;
10456401734dSWill Andrews (void) fprintf(stderr, gettext(
10466401734dSWill Andrews "use '-f' to override the following error:\n"
10476401734dSWill Andrews "%s is a member of potentially active pool \"%s\"\n"),
10486401734dSWill Andrews vdev, name);
10496401734dSWill Andrews ret = 1;
10506401734dSWill Andrews goto errout;
10516401734dSWill Andrews
10526401734dSWill Andrews case POOL_STATE_DESTROYED:
10536401734dSWill Andrews /* inuse should never be set for a destroyed pool */
10546401734dSWill Andrews assert(0);
10556401734dSWill Andrews break;
10566401734dSWill Andrews }
10576401734dSWill Andrews
10586401734dSWill Andrews wipe_label:
10596401734dSWill Andrews ret = zpool_clear_label(fd);
10606401734dSWill Andrews if (ret != 0) {
10616401734dSWill Andrews (void) fprintf(stderr,
10626401734dSWill Andrews gettext("failed to clear label for %s\n"), vdev);
10636401734dSWill Andrews }
10646401734dSWill Andrews
10656401734dSWill Andrews errout:
10666401734dSWill Andrews free(name);
10676401734dSWill Andrews (void) close(fd);
10686401734dSWill Andrews
10696401734dSWill Andrews return (ret);
10706401734dSWill Andrews }
10716401734dSWill Andrews
10726401734dSWill Andrews /*
10737855d95bSToomas Soome * zpool create [-fnd] [-B] [-o property=value] ...
10740a48a24eStimh * [-O file-system-property=value] ...
107504e56356SAndriy Gapon * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ...
1076fa9e4066Sahrens *
10777855d95bSToomas Soome * -B Create boot partition.
1078fa9e4066Sahrens * -f Force creation, even if devices appear in use
1079fa9e4066Sahrens * -n Do not create the pool, but display the resulting layout if it
1080fa9e4066Sahrens * were to be created.
1081fa9e4066Sahrens * -R Create a pool under an alternate root
1082fa9e4066Sahrens * -m Set default mountpoint for the root dataset. By default it's
1083fa9e4066Sahrens * '/<pool>'
108404e56356SAndriy Gapon * -t Use the temporary name until the pool is exported.
1085990b4856Slling * -o Set property=value.
1086f3434519SLOLi * -o Set feature@feature=enabled|disabled.
1087ad135b5dSChristopher Siden * -d Don't automatically enable all supported pool features
1088ad135b5dSChristopher Siden * (individual features can be enabled with -o).
10890a48a24eStimh * -O Set fsproperty=value in the pool's root file system
1090fa9e4066Sahrens *
1091b1b8ab34Slling * Creates the named pool according to the given vdev specification. The
1092fa9e4066Sahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
1093fa9e4066Sahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents
1094fa9e4066Sahrens * (if '-n' was specified), or pass it to libzfs to do the creation.
1095fa9e4066Sahrens */
10967855d95bSToomas Soome
10977855d95bSToomas Soome #define SYSTEM256 (256 * 1024 * 1024)
1098fa9e4066Sahrens int
zpool_do_create(int argc,char ** argv)1099fa9e4066Sahrens zpool_do_create(int argc, char **argv)
1100fa9e4066Sahrens {
110199653d4eSeschrock boolean_t force = B_FALSE;
110299653d4eSeschrock boolean_t dryrun = B_FALSE;
1103ad135b5dSChristopher Siden boolean_t enable_all_pool_feat = B_TRUE;
11047855d95bSToomas Soome zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
11057855d95bSToomas Soome uint64_t boot_size = 0;
1106fa9e4066Sahrens int c;
1107990b4856Slling nvlist_t *nvroot = NULL;
1108fa9e4066Sahrens char *poolname;
110904e56356SAndriy Gapon char *tname = NULL;
1110990b4856Slling int ret = 1;
1111fa9e4066Sahrens char *altroot = NULL;
1112fa9e4066Sahrens char *mountpoint = NULL;
11130a48a24eStimh nvlist_t *fsprops = NULL;
1114990b4856Slling nvlist_t *props = NULL;
11152f8aaab3Seschrock char *propval;
1116fa9e4066Sahrens
1117fa9e4066Sahrens /* check options */
111804e56356SAndriy Gapon while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) {
1119fa9e4066Sahrens switch (c) {
1120fa9e4066Sahrens case 'f':
112199653d4eSeschrock force = B_TRUE;
1122fa9e4066Sahrens break;
1123fa9e4066Sahrens case 'n':
112499653d4eSeschrock dryrun = B_TRUE;
1125fa9e4066Sahrens break;
1126ad135b5dSChristopher Siden case 'd':
1127ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE;
1128ad135b5dSChristopher Siden break;
11297855d95bSToomas Soome case 'B':
11307855d95bSToomas Soome /*
11317855d95bSToomas Soome * We should create the system partition.
11327855d95bSToomas Soome * Also make sure the size is set.
11337855d95bSToomas Soome */
11347855d95bSToomas Soome boot_type = ZPOOL_CREATE_BOOT_LABEL;
11357855d95bSToomas Soome if (boot_size == 0)
11367855d95bSToomas Soome boot_size = SYSTEM256;
11377855d95bSToomas Soome break;
1138fa9e4066Sahrens case 'R':
1139fa9e4066Sahrens altroot = optarg;
1140990b4856Slling if (add_prop_list(zpool_prop_to_name(
11410a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1142990b4856Slling goto errout;
114304e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name(
11440a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1145990b4856Slling goto errout;
1146fa9e4066Sahrens break;
1147fa9e4066Sahrens case 'm':
11488b713775SWill Andrews /* Equivalent to -O mountpoint=optarg */
1149fa9e4066Sahrens mountpoint = optarg;
1150fa9e4066Sahrens break;
1151990b4856Slling case 'o':
1152990b4856Slling if ((propval = strchr(optarg, '=')) == NULL) {
1153990b4856Slling (void) fprintf(stderr, gettext("missing "
1154990b4856Slling "'=' for -o option\n"));
1155990b4856Slling goto errout;
1156990b4856Slling }
1157990b4856Slling *propval = '\0';
1158990b4856Slling propval++;
1159990b4856Slling
11600a48a24eStimh if (add_prop_list(optarg, propval, &props, B_TRUE))
11610a48a24eStimh goto errout;
1162ad135b5dSChristopher Siden
1163ad135b5dSChristopher Siden /*
11647855d95bSToomas Soome * Get bootsize value for make_root_vdev().
11657855d95bSToomas Soome */
11667855d95bSToomas Soome if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
11677855d95bSToomas Soome if (zfs_nicestrtonum(g_zfs, propval,
11687855d95bSToomas Soome &boot_size) < 0 || boot_size == 0) {
11697855d95bSToomas Soome (void) fprintf(stderr,
11707855d95bSToomas Soome gettext("bad boot partition size "
11717855d95bSToomas Soome "'%s': %s\n"), propval,
11727855d95bSToomas Soome libzfs_error_description(g_zfs));
11737855d95bSToomas Soome goto errout;
11747855d95bSToomas Soome }
11757855d95bSToomas Soome }
11767855d95bSToomas Soome
11777855d95bSToomas Soome /*
1178ad135b5dSChristopher Siden * If the user is creating a pool that doesn't support
1179ad135b5dSChristopher Siden * feature flags, don't enable any features.
1180ad135b5dSChristopher Siden */
1181ad135b5dSChristopher Siden if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1182ad135b5dSChristopher Siden char *end;
1183ad135b5dSChristopher Siden u_longlong_t ver;
1184ad135b5dSChristopher Siden
1185ad135b5dSChristopher Siden ver = strtoull(propval, &end, 10);
1186ad135b5dSChristopher Siden if (*end == '\0' &&
1187ad135b5dSChristopher Siden ver < SPA_VERSION_FEATURES) {
1188ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE;
1189ad135b5dSChristopher Siden }
1190ad135b5dSChristopher Siden }
1191c423721fSXin Li if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1192c423721fSXin Li altroot = propval;
11930a48a24eStimh break;
11940a48a24eStimh case 'O':
11950a48a24eStimh if ((propval = strchr(optarg, '=')) == NULL) {
11960a48a24eStimh (void) fprintf(stderr, gettext("missing "
11970a48a24eStimh "'=' for -O option\n"));
11980a48a24eStimh goto errout;
11990a48a24eStimh }
12000a48a24eStimh *propval = '\0';
12010a48a24eStimh propval++;
12020a48a24eStimh
12038b713775SWill Andrews /*
12048b713775SWill Andrews * Mountpoints are checked and then added later.
12058b713775SWill Andrews * Uniquely among properties, they can be specified
12068b713775SWill Andrews * more than once, to avoid conflict with -m.
12078b713775SWill Andrews */
12088b713775SWill Andrews if (0 == strcmp(optarg,
12098b713775SWill Andrews zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
12108b713775SWill Andrews mountpoint = propval;
12118b713775SWill Andrews } else if (add_prop_list(optarg, propval, &fsprops,
12128b713775SWill Andrews B_FALSE)) {
1213990b4856Slling goto errout;
12148b713775SWill Andrews }
1215990b4856Slling break;
121604e56356SAndriy Gapon case 't':
121704e56356SAndriy Gapon /*
121804e56356SAndriy Gapon * Sanity check temporary pool name.
121904e56356SAndriy Gapon */
122004e56356SAndriy Gapon if (strchr(optarg, '/') != NULL) {
122104e56356SAndriy Gapon (void) fprintf(stderr, gettext("cannot create "
122204e56356SAndriy Gapon "'%s': invalid character '/' in temporary "
122304e56356SAndriy Gapon "name\n"), optarg);
122404e56356SAndriy Gapon (void) fprintf(stderr, gettext("use 'zfs "
122504e56356SAndriy Gapon "create' to create a dataset\n"));
122604e56356SAndriy Gapon goto errout;
122704e56356SAndriy Gapon }
122804e56356SAndriy Gapon
122904e56356SAndriy Gapon if (add_prop_list(zpool_prop_to_name(
123004e56356SAndriy Gapon ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
123104e56356SAndriy Gapon goto errout;
123204e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name(
123304e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
123404e56356SAndriy Gapon goto errout;
123504e56356SAndriy Gapon tname = optarg;
123604e56356SAndriy Gapon break;
1237fa9e4066Sahrens case ':':
1238fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for "
1239fa9e4066Sahrens "'%c' option\n"), optopt);
1240990b4856Slling goto badusage;
1241fa9e4066Sahrens case '?':
1242fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1243fa9e4066Sahrens optopt);
1244990b4856Slling goto badusage;
1245fa9e4066Sahrens }
1246fa9e4066Sahrens }
1247fa9e4066Sahrens
1248fa9e4066Sahrens argc -= optind;
1249fa9e4066Sahrens argv += optind;
1250fa9e4066Sahrens
1251fa9e4066Sahrens /* get pool name and check number of arguments */
1252fa9e4066Sahrens if (argc < 1) {
1253fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n"));
1254990b4856Slling goto badusage;
1255fa9e4066Sahrens }
1256fa9e4066Sahrens if (argc < 2) {
1257fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n"));
1258990b4856Slling goto badusage;
1259fa9e4066Sahrens }
1260fa9e4066Sahrens
1261fa9e4066Sahrens poolname = argv[0];
1262fa9e4066Sahrens
1263fa9e4066Sahrens /*
1264fa9e4066Sahrens * As a special case, check for use of '/' in the name, and direct the
1265fa9e4066Sahrens * user to use 'zfs create' instead.
1266fa9e4066Sahrens */
1267fa9e4066Sahrens if (strchr(poolname, '/') != NULL) {
1268fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1269fa9e4066Sahrens "character '/' in pool name\n"), poolname);
1270fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs create' to "
1271fa9e4066Sahrens "create a dataset\n"));
1272990b4856Slling goto errout;
1273fa9e4066Sahrens }
1274fa9e4066Sahrens
12757855d95bSToomas Soome /*
12767855d95bSToomas Soome * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
12777855d95bSToomas Soome * and not set otherwise.
12787855d95bSToomas Soome */
12797855d95bSToomas Soome if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
12807855d95bSToomas Soome const char *propname;
12817855d95bSToomas Soome char *strptr, *buf = NULL;
12827855d95bSToomas Soome int rv;
12837855d95bSToomas Soome
12847855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
12857855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) != 0) {
12867855d95bSToomas Soome (void) asprintf(&buf, "%" PRIu64, boot_size);
12877855d95bSToomas Soome if (buf == NULL) {
12887855d95bSToomas Soome (void) fprintf(stderr,
12897855d95bSToomas Soome gettext("internal error: out of memory\n"));
12907855d95bSToomas Soome goto errout;
12917855d95bSToomas Soome }
12927855d95bSToomas Soome rv = add_prop_list(propname, buf, &props, B_TRUE);
12937855d95bSToomas Soome free(buf);
12947855d95bSToomas Soome if (rv != 0)
12957855d95bSToomas Soome goto errout;
12967855d95bSToomas Soome }
12977855d95bSToomas Soome } else {
12987855d95bSToomas Soome const char *propname;
12997855d95bSToomas Soome char *strptr;
13007855d95bSToomas Soome
13017855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
13027855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) == 0) {
13037855d95bSToomas Soome (void) fprintf(stderr, gettext("error: setting boot "
13047855d95bSToomas Soome "partition size requires option '-B'\n"));
13057855d95bSToomas Soome goto errout;
13067855d95bSToomas Soome }
13077855d95bSToomas Soome }
13087855d95bSToomas Soome
1309fa9e4066Sahrens /* pass off to get_vdev_spec for bulk processing */
13105711d393Sloli10K nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
13117855d95bSToomas Soome boot_type, boot_size, argc - 1, argv + 1);
1312fa9e4066Sahrens if (nvroot == NULL)
13130a48a24eStimh goto errout;
1314fa9e4066Sahrens
131599653d4eSeschrock /* make_root_vdev() allows 0 toplevel children if there are spares */
1316b7b97454Sperrin if (!zfs_allocatable_devs(nvroot)) {
131799653d4eSeschrock (void) fprintf(stderr, gettext("invalid vdev "
131899653d4eSeschrock "specification: at least one toplevel vdev must be "
131999653d4eSeschrock "specified\n"));
1320990b4856Slling goto errout;
132199653d4eSeschrock }
132299653d4eSeschrock
1323fa9e4066Sahrens if (altroot != NULL && altroot[0] != '/') {
1324fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1325e9dbad6fSeschrock "must be an absolute path\n"), altroot);
1326990b4856Slling goto errout;
1327fa9e4066Sahrens }
1328fa9e4066Sahrens
1329fa9e4066Sahrens /*
1330fa9e4066Sahrens * Check the validity of the mountpoint and direct the user to use the
1331fa9e4066Sahrens * '-m' mountpoint option if it looks like its in use.
1332fa9e4066Sahrens */
1333fa9e4066Sahrens if (mountpoint == NULL ||
1334fa9e4066Sahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1335fa9e4066Sahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1336fa9e4066Sahrens char buf[MAXPATHLEN];
133711022c7cStimh DIR *dirp;
1338fa9e4066Sahrens
1339fa9e4066Sahrens if (mountpoint && mountpoint[0] != '/') {
1340fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid mountpoint "
1341fa9e4066Sahrens "'%s': must be an absolute path, 'legacy', or "
1342fa9e4066Sahrens "'none'\n"), mountpoint);
1343990b4856Slling goto errout;
1344fa9e4066Sahrens }
1345fa9e4066Sahrens
1346fa9e4066Sahrens if (mountpoint == NULL) {
1347fa9e4066Sahrens if (altroot != NULL)
1348fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s/%s",
1349fa9e4066Sahrens altroot, poolname);
1350fa9e4066Sahrens else
1351fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "/%s",
1352fa9e4066Sahrens poolname);
1353fa9e4066Sahrens } else {
1354fa9e4066Sahrens if (altroot != NULL)
1355fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s%s",
1356fa9e4066Sahrens altroot, mountpoint);
1357fa9e4066Sahrens else
1358fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s",
1359fa9e4066Sahrens mountpoint);
1360fa9e4066Sahrens }
1361fa9e4066Sahrens
136211022c7cStimh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
136311022c7cStimh (void) fprintf(stderr, gettext("mountpoint '%s' : "
136411022c7cStimh "%s\n"), buf, strerror(errno));
1365fa9e4066Sahrens (void) fprintf(stderr, gettext("use '-m' "
1366fa9e4066Sahrens "option to provide a different default\n"));
1367990b4856Slling goto errout;
136811022c7cStimh } else if (dirp) {
136911022c7cStimh int count = 0;
137011022c7cStimh
137111022c7cStimh while (count < 3 && readdir(dirp) != NULL)
137211022c7cStimh count++;
137311022c7cStimh (void) closedir(dirp);
137411022c7cStimh
137511022c7cStimh if (count > 2) {
137611022c7cStimh (void) fprintf(stderr, gettext("mountpoint "
137711022c7cStimh "'%s' exists and is not empty\n"), buf);
137811022c7cStimh (void) fprintf(stderr, gettext("use '-m' "
137911022c7cStimh "option to provide a "
138011022c7cStimh "different default\n"));
138111022c7cStimh goto errout;
138211022c7cStimh }
1383fa9e4066Sahrens }
1384fa9e4066Sahrens }
1385fa9e4066Sahrens
13868b713775SWill Andrews /*
13878b713775SWill Andrews * Now that the mountpoint's validity has been checked, ensure that
13888b713775SWill Andrews * the property is set appropriately prior to creating the pool.
13898b713775SWill Andrews */
13908b713775SWill Andrews if (mountpoint != NULL) {
13918b713775SWill Andrews ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
13928b713775SWill Andrews mountpoint, &fsprops, B_FALSE);
13938b713775SWill Andrews if (ret != 0)
13948b713775SWill Andrews goto errout;
13958b713775SWill Andrews }
13968b713775SWill Andrews
13978b713775SWill Andrews ret = 1;
1398fa9e4066Sahrens if (dryrun) {
1399fa9e4066Sahrens /*
1400fa9e4066Sahrens * For a dry run invocation, print out a basic message and run
1401fa9e4066Sahrens * through all the vdevs in the list and print out in an
1402fa9e4066Sahrens * appropriate hierarchy.
1403fa9e4066Sahrens */
1404fa9e4066Sahrens (void) printf(gettext("would create '%s' with the "
1405fa9e4066Sahrens "following layout:\n\n"), poolname);
1406fa9e4066Sahrens
1407663207adSDon Brady print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
1408663207adSDon Brady print_vdev_tree(NULL, "dedup", nvroot, 0,
1409663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, 0);
1410663207adSDon Brady print_vdev_tree(NULL, "special", nvroot, 0,
1411663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, 0);
1412663207adSDon Brady print_vdev_tree(NULL, "logs", nvroot, 0,
1413663207adSDon Brady VDEV_ALLOC_BIAS_LOG, 0);
1414fa9e4066Sahrens
1415fa9e4066Sahrens ret = 0;
1416fa9e4066Sahrens } else {
1417fa9e4066Sahrens /*
1418fa9e4066Sahrens * Hand off to libzfs.
1419fa9e4066Sahrens */
1420f3434519SLOLi
14212acef22dSMatthew Ahrens spa_feature_t i;
1422ad135b5dSChristopher Siden for (i = 0; i < SPA_FEATURES; i++) {
1423ad135b5dSChristopher Siden char propname[MAXPATHLEN];
1424f3434519SLOLi char *propval;
1425ad135b5dSChristopher Siden zfeature_info_t *feat = &spa_feature_table[i];
1426ad135b5dSChristopher Siden (void) snprintf(propname, sizeof (propname),
1427ad135b5dSChristopher Siden "feature@%s", feat->fi_uname);
1428ad135b5dSChristopher Siden
1429ad135b5dSChristopher Siden /*
1430f3434519SLOLi * Only features contained in props will be enabled:
1431f3434519SLOLi * remove from the nvlist every ZFS_FEATURE_DISABLED
1432f3434519SLOLi * value and add every missing ZFS_FEATURE_ENABLED if
1433f3434519SLOLi * enable_all_pool_feat is set.
1434ad135b5dSChristopher Siden */
1435f3434519SLOLi if (!nvlist_lookup_string(props, propname, &propval)) {
1436f3434519SLOLi if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0)
1437f3434519SLOLi (void) nvlist_remove_all(props,
1438f3434519SLOLi propname);
1439f3434519SLOLi } else if (enable_all_pool_feat) {
14408b713775SWill Andrews ret = add_prop_list(propname,
14418b713775SWill Andrews ZFS_FEATURE_ENABLED, &props, B_TRUE);
14428b713775SWill Andrews if (ret != 0)
1443ad135b5dSChristopher Siden goto errout;
1444ad135b5dSChristopher Siden }
1445ad135b5dSChristopher Siden }
14468b713775SWill Andrews
14478b713775SWill Andrews ret = 1;
14480a48a24eStimh if (zpool_create(g_zfs, poolname,
14490a48a24eStimh nvroot, props, fsprops) == 0) {
145004e56356SAndriy Gapon zfs_handle_t *pool = zfs_open(g_zfs,
145104e56356SAndriy Gapon tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1452fa9e4066Sahrens if (pool != NULL) {
1453fa9e4066Sahrens if (zfs_mount(pool, NULL, 0) == 0)
1454da6c28aaSamw ret = zfs_shareall(pool);
1455fa9e4066Sahrens zfs_close(pool);
1456fa9e4066Sahrens }
145799653d4eSeschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
145899653d4eSeschrock (void) fprintf(stderr, gettext("pool name may have "
145999653d4eSeschrock "been omitted\n"));
1460fa9e4066Sahrens }
1461fa9e4066Sahrens }
1462fa9e4066Sahrens
1463990b4856Slling errout:
1464fa9e4066Sahrens nvlist_free(nvroot);
14650a48a24eStimh nvlist_free(fsprops);
1466990b4856Slling nvlist_free(props);
1467fa9e4066Sahrens return (ret);
1468990b4856Slling badusage:
14690a48a24eStimh nvlist_free(fsprops);
1470990b4856Slling nvlist_free(props);
1471990b4856Slling usage(B_FALSE);
1472990b4856Slling return (2);
1473fa9e4066Sahrens }
1474fa9e4066Sahrens
1475fa9e4066Sahrens /*
1476fa9e4066Sahrens * zpool destroy <pool>
1477fa9e4066Sahrens *
1478fa9e4066Sahrens * -f Forcefully unmount any datasets
1479fa9e4066Sahrens *
1480fa9e4066Sahrens * Destroy the given pool. Automatically unmounts any datasets in the pool.
1481fa9e4066Sahrens */
1482fa9e4066Sahrens int
zpool_do_destroy(int argc,char ** argv)1483fa9e4066Sahrens zpool_do_destroy(int argc, char **argv)
1484fa9e4066Sahrens {
148599653d4eSeschrock boolean_t force = B_FALSE;
1486fa9e4066Sahrens int c;
1487fa9e4066Sahrens char *pool;
1488fa9e4066Sahrens zpool_handle_t *zhp;
1489fa9e4066Sahrens int ret;
1490fa9e4066Sahrens
1491fa9e4066Sahrens /* check options */
1492fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) {
1493fa9e4066Sahrens switch (c) {
1494fa9e4066Sahrens case 'f':
149599653d4eSeschrock force = B_TRUE;
1496fa9e4066Sahrens break;
1497fa9e4066Sahrens case '?':
1498fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1499fa9e4066Sahrens optopt);
150099653d4eSeschrock usage(B_FALSE);
1501fa9e4066Sahrens }
1502fa9e4066Sahrens }
1503fa9e4066Sahrens
1504fa9e4066Sahrens argc -= optind;
1505fa9e4066Sahrens argv += optind;
1506fa9e4066Sahrens
1507fa9e4066Sahrens /* check arguments */
1508fa9e4066Sahrens if (argc < 1) {
1509fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n"));
151099653d4eSeschrock usage(B_FALSE);
1511fa9e4066Sahrens }
1512fa9e4066Sahrens if (argc > 1) {
1513fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n"));
151499653d4eSeschrock usage(B_FALSE);
1515fa9e4066Sahrens }
1516fa9e4066Sahrens
1517fa9e4066Sahrens pool = argv[0];
1518fa9e4066Sahrens
151999653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1520fa9e4066Sahrens /*
1521fa9e4066Sahrens * As a special case, check for use of '/' in the name, and
1522fa9e4066Sahrens * direct the user to use 'zfs destroy' instead.
1523fa9e4066Sahrens */
1524fa9e4066Sahrens if (strchr(pool, '/') != NULL)
1525fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1526fa9e4066Sahrens "destroy a dataset\n"));
1527fa9e4066Sahrens return (1);
1528fa9e4066Sahrens }
1529fa9e4066Sahrens
1530f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) {
1531fa9e4066Sahrens (void) fprintf(stderr, gettext("could not destroy '%s': "
1532fa9e4066Sahrens "could not unmount datasets\n"), zpool_get_name(zhp));
1533fa9e4066Sahrens return (1);
1534fa9e4066Sahrens }
1535fa9e4066Sahrens
15364445fffbSMatthew Ahrens /* The history must be logged as part of the export */
15374445fffbSMatthew Ahrens log_history = B_FALSE;
15384445fffbSMatthew Ahrens
15394445fffbSMatthew Ahrens ret = (zpool_destroy(zhp, history_str) != 0);
1540fa9e4066Sahrens
1541fa9e4066Sahrens zpool_close(zhp);
1542fa9e4066Sahrens
1543fa9e4066Sahrens return (ret);
1544fa9e4066Sahrens }
1545fa9e4066Sahrens
1546fa9e4066Sahrens /*
1547fa9e4066Sahrens * zpool export [-f] <pool> ...
1548fa9e4066Sahrens *
1549fa9e4066Sahrens * -f Forcefully unmount datasets
1550fa9e4066Sahrens *
1551b1b8ab34Slling * Export the given pools. By default, the command will attempt to cleanly
1552fa9e4066Sahrens * unmount any active datasets within the pool. If the '-f' flag is specified,
1553fa9e4066Sahrens * then the datasets will be forcefully unmounted.
1554fa9e4066Sahrens */
1555fa9e4066Sahrens int
zpool_do_export(int argc,char ** argv)1556fa9e4066Sahrens zpool_do_export(int argc, char **argv)
1557fa9e4066Sahrens {
155899653d4eSeschrock boolean_t force = B_FALSE;
1559394ab0cbSGeorge Wilson boolean_t hardforce = B_FALSE;
1560fa9e4066Sahrens int c;
1561fa9e4066Sahrens zpool_handle_t *zhp;
1562fa9e4066Sahrens int ret;
1563fa9e4066Sahrens int i;
1564fa9e4066Sahrens
1565fa9e4066Sahrens /* check options */
1566394ab0cbSGeorge Wilson while ((c = getopt(argc, argv, "fF")) != -1) {
1567fa9e4066Sahrens switch (c) {
1568fa9e4066Sahrens case 'f':
156999653d4eSeschrock force = B_TRUE;
1570fa9e4066Sahrens break;
1571394ab0cbSGeorge Wilson case 'F':
1572394ab0cbSGeorge Wilson hardforce = B_TRUE;
1573394ab0cbSGeorge Wilson break;
1574fa9e4066Sahrens case '?':
1575fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1576fa9e4066Sahrens optopt);
157799653d4eSeschrock usage(B_FALSE);
1578fa9e4066Sahrens }
1579fa9e4066Sahrens }
1580fa9e4066Sahrens
1581fa9e4066Sahrens argc -= optind;
1582fa9e4066Sahrens argv += optind;
1583fa9e4066Sahrens
1584fa9e4066Sahrens /* check arguments */
1585fa9e4066Sahrens if (argc < 1) {
1586fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n"));
158799653d4eSeschrock usage(B_FALSE);
1588fa9e4066Sahrens }
1589fa9e4066Sahrens
1590fa9e4066Sahrens ret = 0;
1591fa9e4066Sahrens for (i = 0; i < argc; i++) {
159299653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1593fa9e4066Sahrens ret = 1;
1594fa9e4066Sahrens continue;
1595fa9e4066Sahrens }
1596fa9e4066Sahrens
1597f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) {
1598fa9e4066Sahrens ret = 1;
1599fa9e4066Sahrens zpool_close(zhp);
1600fa9e4066Sahrens continue;
1601fa9e4066Sahrens }
1602fa9e4066Sahrens
16034445fffbSMatthew Ahrens /* The history must be logged as part of the export */
16044445fffbSMatthew Ahrens log_history = B_FALSE;
16054445fffbSMatthew Ahrens
1606394ab0cbSGeorge Wilson if (hardforce) {
16074445fffbSMatthew Ahrens if (zpool_export_force(zhp, history_str) != 0)
1608fa9e4066Sahrens ret = 1;
16094445fffbSMatthew Ahrens } else if (zpool_export(zhp, force, history_str) != 0) {
1610394ab0cbSGeorge Wilson ret = 1;
1611394ab0cbSGeorge Wilson }
1612fa9e4066Sahrens
1613fa9e4066Sahrens zpool_close(zhp);
1614fa9e4066Sahrens }
1615fa9e4066Sahrens
1616fa9e4066Sahrens return (ret);
1617fa9e4066Sahrens }
1618fa9e4066Sahrens
1619fa9e4066Sahrens /*
1620fa9e4066Sahrens * Given a vdev configuration, determine the maximum width needed for the device
1621fa9e4066Sahrens * name column.
1622fa9e4066Sahrens */
1623fa9e4066Sahrens static int
max_width(zpool_handle_t * zhp,nvlist_t * nv,int depth,int max,int name_flags)1624663207adSDon Brady max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1625663207adSDon Brady int name_flags)
1626fa9e4066Sahrens {
1627663207adSDon Brady char *name;
1628fa9e4066Sahrens nvlist_t **child;
1629fa9e4066Sahrens uint_t c, children;
1630fa9e4066Sahrens int ret;
1631fa9e4066Sahrens
1632663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID);
1633fa9e4066Sahrens if (strlen(name) + depth > max)
1634fa9e4066Sahrens max = strlen(name) + depth;
1635fa9e4066Sahrens
1636afefbcddSeschrock free(name);
1637afefbcddSeschrock
163899653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
163999653d4eSeschrock &child, &children) == 0) {
1640fa9e4066Sahrens for (c = 0; c < children; c++)
164199653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2,
1642663207adSDon Brady max, name_flags)) > max)
1643fa9e4066Sahrens max = ret;
164499653d4eSeschrock }
164599653d4eSeschrock
1646fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1647fa94a07fSbrendan &child, &children) == 0) {
1648fa94a07fSbrendan for (c = 0; c < children; c++)
1649fa94a07fSbrendan if ((ret = max_width(zhp, child[c], depth + 2,
1650663207adSDon Brady max, name_flags)) > max)
1651fa94a07fSbrendan max = ret;
1652fa94a07fSbrendan }
1653fa94a07fSbrendan
165499653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
165599653d4eSeschrock &child, &children) == 0) {
165699653d4eSeschrock for (c = 0; c < children; c++)
165799653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2,
1658663207adSDon Brady max, name_flags)) > max)
165999653d4eSeschrock max = ret;
166099653d4eSeschrock }
166199653d4eSeschrock
1662fa9e4066Sahrens return (max);
1663fa9e4066Sahrens }
1664fa9e4066Sahrens
1665e6ca193dSGeorge Wilson typedef struct spare_cbdata {
1666e6ca193dSGeorge Wilson uint64_t cb_guid;
1667e6ca193dSGeorge Wilson zpool_handle_t *cb_zhp;
1668e6ca193dSGeorge Wilson } spare_cbdata_t;
1669e6ca193dSGeorge Wilson
1670e6ca193dSGeorge Wilson static boolean_t
find_vdev(nvlist_t * nv,uint64_t search)1671e6ca193dSGeorge Wilson find_vdev(nvlist_t *nv, uint64_t search)
1672e6ca193dSGeorge Wilson {
1673e6ca193dSGeorge Wilson uint64_t guid;
1674e6ca193dSGeorge Wilson nvlist_t **child;
1675e6ca193dSGeorge Wilson uint_t c, children;
1676e6ca193dSGeorge Wilson
1677e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1678e6ca193dSGeorge Wilson search == guid)
1679e6ca193dSGeorge Wilson return (B_TRUE);
1680e6ca193dSGeorge Wilson
1681e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1682e6ca193dSGeorge Wilson &child, &children) == 0) {
1683e6ca193dSGeorge Wilson for (c = 0; c < children; c++)
1684e6ca193dSGeorge Wilson if (find_vdev(child[c], search))
1685e6ca193dSGeorge Wilson return (B_TRUE);
1686e6ca193dSGeorge Wilson }
1687e6ca193dSGeorge Wilson
1688e6ca193dSGeorge Wilson return (B_FALSE);
1689e6ca193dSGeorge Wilson }
1690e6ca193dSGeorge Wilson
1691e6ca193dSGeorge Wilson static int
find_spare(zpool_handle_t * zhp,void * data)1692e6ca193dSGeorge Wilson find_spare(zpool_handle_t *zhp, void *data)
1693e6ca193dSGeorge Wilson {
1694e6ca193dSGeorge Wilson spare_cbdata_t *cbp = data;
1695e6ca193dSGeorge Wilson nvlist_t *config, *nvroot;
1696e6ca193dSGeorge Wilson
1697e6ca193dSGeorge Wilson config = zpool_get_config(zhp, NULL);
1698e6ca193dSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1699e6ca193dSGeorge Wilson &nvroot) == 0);
1700e6ca193dSGeorge Wilson
1701e6ca193dSGeorge Wilson if (find_vdev(nvroot, cbp->cb_guid)) {
1702e6ca193dSGeorge Wilson cbp->cb_zhp = zhp;
1703e6ca193dSGeorge Wilson return (1);
1704e6ca193dSGeorge Wilson }
1705e6ca193dSGeorge Wilson
1706e6ca193dSGeorge Wilson zpool_close(zhp);
1707e6ca193dSGeorge Wilson return (0);
1708e6ca193dSGeorge Wilson }
1709e6ca193dSGeorge Wilson
1710663207adSDon Brady typedef struct status_cbdata {
1711663207adSDon Brady int cb_count;
1712663207adSDon Brady int cb_name_flags;
1713663207adSDon Brady int cb_namewidth;
1714663207adSDon Brady boolean_t cb_allpools;
1715663207adSDon Brady boolean_t cb_verbose;
1716dd50e0ccSTony Hutter boolean_t cb_literal;
1717663207adSDon Brady boolean_t cb_explain;
1718663207adSDon Brady boolean_t cb_first;
1719663207adSDon Brady boolean_t cb_dedup_stats;
1720663207adSDon Brady boolean_t cb_print_status;
1721dd50e0ccSTony Hutter boolean_t cb_print_slow_ios;
1722084fd14fSBrian Behlendorf boolean_t cb_print_vdev_init;
1723084fd14fSBrian Behlendorf boolean_t cb_print_vdev_trim;
1724663207adSDon Brady } status_cbdata_t;
1725663207adSDon Brady
1726e6ca193dSGeorge Wilson /*
1727084fd14fSBrian Behlendorf * Print vdev initialization status for leaves
1728084fd14fSBrian Behlendorf */
1729084fd14fSBrian Behlendorf static void
print_status_initialize(vdev_stat_t * vs,boolean_t verbose)1730084fd14fSBrian Behlendorf print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
1731084fd14fSBrian Behlendorf {
1732084fd14fSBrian Behlendorf if (verbose) {
1733084fd14fSBrian Behlendorf if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
1734084fd14fSBrian Behlendorf vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
1735084fd14fSBrian Behlendorf vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
1736084fd14fSBrian Behlendorf !vs->vs_scan_removing) {
1737084fd14fSBrian Behlendorf char zbuf[1024];
1738084fd14fSBrian Behlendorf char tbuf[256];
1739084fd14fSBrian Behlendorf struct tm zaction_ts;
1740084fd14fSBrian Behlendorf
1741084fd14fSBrian Behlendorf time_t t = vs->vs_initialize_action_time;
1742084fd14fSBrian Behlendorf int initialize_pct = 100;
1743084fd14fSBrian Behlendorf if (vs->vs_initialize_state !=
1744084fd14fSBrian Behlendorf VDEV_INITIALIZE_COMPLETE) {
1745084fd14fSBrian Behlendorf initialize_pct = (vs->vs_initialize_bytes_done *
1746084fd14fSBrian Behlendorf 100 / (vs->vs_initialize_bytes_est + 1));
1747084fd14fSBrian Behlendorf }
1748084fd14fSBrian Behlendorf
1749084fd14fSBrian Behlendorf (void) localtime_r(&t, &zaction_ts);
1750084fd14fSBrian Behlendorf (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1751084fd14fSBrian Behlendorf
1752084fd14fSBrian Behlendorf switch (vs->vs_initialize_state) {
1753084fd14fSBrian Behlendorf case VDEV_INITIALIZE_SUSPENDED:
1754084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1755084fd14fSBrian Behlendorf gettext("suspended, started at"), tbuf);
1756084fd14fSBrian Behlendorf break;
1757084fd14fSBrian Behlendorf case VDEV_INITIALIZE_ACTIVE:
1758084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1759084fd14fSBrian Behlendorf gettext("started at"), tbuf);
1760084fd14fSBrian Behlendorf break;
1761084fd14fSBrian Behlendorf case VDEV_INITIALIZE_COMPLETE:
1762084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1763084fd14fSBrian Behlendorf gettext("completed at"), tbuf);
1764084fd14fSBrian Behlendorf break;
1765084fd14fSBrian Behlendorf }
1766084fd14fSBrian Behlendorf
1767084fd14fSBrian Behlendorf (void) printf(gettext(" (%d%% initialized%s)"),
1768084fd14fSBrian Behlendorf initialize_pct, zbuf);
1769084fd14fSBrian Behlendorf } else {
1770084fd14fSBrian Behlendorf (void) printf(gettext(" (uninitialized)"));
1771084fd14fSBrian Behlendorf }
1772084fd14fSBrian Behlendorf } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) {
1773084fd14fSBrian Behlendorf (void) printf(gettext(" (initializing)"));
1774084fd14fSBrian Behlendorf }
1775084fd14fSBrian Behlendorf }
1776084fd14fSBrian Behlendorf
1777084fd14fSBrian Behlendorf /*
1778084fd14fSBrian Behlendorf * Print vdev TRIM status for leaves
1779084fd14fSBrian Behlendorf */
1780084fd14fSBrian Behlendorf static void
print_status_trim(vdev_stat_t * vs,boolean_t verbose)1781084fd14fSBrian Behlendorf print_status_trim(vdev_stat_t *vs, boolean_t verbose)
1782084fd14fSBrian Behlendorf {
1783084fd14fSBrian Behlendorf if (verbose) {
1784084fd14fSBrian Behlendorf if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE ||
1785084fd14fSBrian Behlendorf vs->vs_trim_state == VDEV_TRIM_SUSPENDED ||
1786084fd14fSBrian Behlendorf vs->vs_trim_state == VDEV_TRIM_COMPLETE) &&
1787084fd14fSBrian Behlendorf !vs->vs_scan_removing) {
1788084fd14fSBrian Behlendorf char zbuf[1024];
1789084fd14fSBrian Behlendorf char tbuf[256];
1790084fd14fSBrian Behlendorf struct tm zaction_ts;
1791084fd14fSBrian Behlendorf
1792084fd14fSBrian Behlendorf time_t t = vs->vs_trim_action_time;
1793084fd14fSBrian Behlendorf int trim_pct = 100;
1794084fd14fSBrian Behlendorf if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) {
1795084fd14fSBrian Behlendorf trim_pct = (vs->vs_trim_bytes_done *
1796084fd14fSBrian Behlendorf 100 / (vs->vs_trim_bytes_est + 1));
1797084fd14fSBrian Behlendorf }
1798084fd14fSBrian Behlendorf
1799084fd14fSBrian Behlendorf (void) localtime_r(&t, &zaction_ts);
1800084fd14fSBrian Behlendorf (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1801084fd14fSBrian Behlendorf
1802084fd14fSBrian Behlendorf switch (vs->vs_trim_state) {
1803084fd14fSBrian Behlendorf case VDEV_TRIM_SUSPENDED:
1804084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1805084fd14fSBrian Behlendorf gettext("suspended, started at"), tbuf);
1806084fd14fSBrian Behlendorf break;
1807084fd14fSBrian Behlendorf case VDEV_TRIM_ACTIVE:
1808084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1809084fd14fSBrian Behlendorf gettext("started at"), tbuf);
1810084fd14fSBrian Behlendorf break;
1811084fd14fSBrian Behlendorf case VDEV_TRIM_COMPLETE:
1812084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1813084fd14fSBrian Behlendorf gettext("completed at"), tbuf);
1814084fd14fSBrian Behlendorf break;
1815084fd14fSBrian Behlendorf }
1816084fd14fSBrian Behlendorf
1817084fd14fSBrian Behlendorf (void) printf(gettext(" (%d%% trimmed%s)"),
1818084fd14fSBrian Behlendorf trim_pct, zbuf);
1819084fd14fSBrian Behlendorf } else if (vs->vs_trim_notsup) {
1820084fd14fSBrian Behlendorf (void) printf(gettext(" (trim unsupported)"));
1821084fd14fSBrian Behlendorf } else {
1822084fd14fSBrian Behlendorf (void) printf(gettext(" (untrimmed)"));
1823084fd14fSBrian Behlendorf }
1824084fd14fSBrian Behlendorf } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) {
1825084fd14fSBrian Behlendorf (void) printf(gettext(" (trimming)"));
1826084fd14fSBrian Behlendorf }
1827084fd14fSBrian Behlendorf }
1828084fd14fSBrian Behlendorf
1829084fd14fSBrian Behlendorf /*
1830e6ca193dSGeorge Wilson * Print out configuration state as requested by status_callback.
1831e6ca193dSGeorge Wilson */
1832663207adSDon Brady static void
print_status_config(zpool_handle_t * zhp,status_cbdata_t * cb,const char * name,nvlist_t * nv,int depth,boolean_t isspare)1833663207adSDon Brady print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
1834663207adSDon Brady nvlist_t *nv, int depth, boolean_t isspare)
1835e6ca193dSGeorge Wilson {
183664dee23eSTony Hutter nvlist_t **child, *root;
1837e6ca193dSGeorge Wilson uint_t c, children;
18383f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL;
1839e6ca193dSGeorge Wilson vdev_stat_t *vs;
18403f9d6ad7SLin Ling char rbuf[6], wbuf[6], cbuf[6];
1841e6ca193dSGeorge Wilson char *vname;
1842e6ca193dSGeorge Wilson uint64_t notpresent;
1843663207adSDon Brady spare_cbdata_t spare_cb;
18446401734dSWill Andrews const char *state;
18455cabbc6bSPrashanth Sreenivasa char *type;
1846e6ca193dSGeorge Wilson
1847e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1848e6ca193dSGeorge Wilson &child, &children) != 0)
1849e6ca193dSGeorge Wilson children = 0;
1850e6ca193dSGeorge Wilson
18513f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
18523f9d6ad7SLin Ling (uint64_t **)&vs, &c) == 0);
18533f9d6ad7SLin Ling
18545cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
18555cabbc6bSPrashanth Sreenivasa
18565cabbc6bSPrashanth Sreenivasa if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
18575cabbc6bSPrashanth Sreenivasa return;
18585cabbc6bSPrashanth Sreenivasa
1859e6ca193dSGeorge Wilson state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1860e6ca193dSGeorge Wilson if (isspare) {
1861e6ca193dSGeorge Wilson /*
1862e6ca193dSGeorge Wilson * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1863e6ca193dSGeorge Wilson * online drives.
1864e6ca193dSGeorge Wilson */
1865e6ca193dSGeorge Wilson if (vs->vs_aux == VDEV_AUX_SPARED)
1866e6ca193dSGeorge Wilson state = "INUSE";
1867e6ca193dSGeorge Wilson else if (vs->vs_state == VDEV_STATE_HEALTHY)
1868e6ca193dSGeorge Wilson state = "AVAIL";
1869e6ca193dSGeorge Wilson }
1870e6ca193dSGeorge Wilson
1871663207adSDon Brady (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
1872e6ca193dSGeorge Wilson name, state);
1873e6ca193dSGeorge Wilson
1874e6ca193dSGeorge Wilson if (!isspare) {
1875dd50e0ccSTony Hutter if (cb->cb_literal) {
1876dd50e0ccSTony Hutter printf(" %5llu %5llu %5llu",
1877dd50e0ccSTony Hutter (u_longlong_t)vs->vs_read_errors,
1878dd50e0ccSTony Hutter (u_longlong_t)vs->vs_write_errors,
1879dd50e0ccSTony Hutter (u_longlong_t)vs->vs_checksum_errors);
1880dd50e0ccSTony Hutter } else {
1881e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1882e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1883dd50e0ccSTony Hutter zfs_nicenum(vs->vs_checksum_errors, cbuf,
1884dd50e0ccSTony Hutter sizeof (cbuf));
1885dd50e0ccSTony Hutter printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1886dd50e0ccSTony Hutter }
1887dd50e0ccSTony Hutter
1888dd50e0ccSTony Hutter if (cb->cb_print_slow_ios) {
1889dd50e0ccSTony Hutter if (children == 0) {
1890dd50e0ccSTony Hutter /* Only leafs vdevs have slow IOs */
1891dd50e0ccSTony Hutter zfs_nicenum(vs->vs_slow_ios, rbuf,
1892dd50e0ccSTony Hutter sizeof (rbuf));
1893dd50e0ccSTony Hutter } else {
1894dd50e0ccSTony Hutter (void) snprintf(rbuf, sizeof (rbuf), "-");
1895dd50e0ccSTony Hutter }
1896dd50e0ccSTony Hutter
1897dd50e0ccSTony Hutter if (cb->cb_literal)
1898dd50e0ccSTony Hutter printf(" %5llu", (u_longlong_t)vs->vs_slow_ios);
1899dd50e0ccSTony Hutter else
1900dd50e0ccSTony Hutter printf(" %5s", rbuf);
1901dd50e0ccSTony Hutter }
1902dd50e0ccSTony Hutter
1903e6ca193dSGeorge Wilson }
1904e6ca193dSGeorge Wilson
1905e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1906e6ca193dSGeorge Wilson ¬present) == 0) {
1907e6ca193dSGeorge Wilson char *path;
1908e6ca193dSGeorge Wilson verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1909e6ca193dSGeorge Wilson (void) printf(" was %s", path);
1910e6ca193dSGeorge Wilson } else if (vs->vs_aux != 0) {
1911e6ca193dSGeorge Wilson (void) printf(" ");
1912e6ca193dSGeorge Wilson
1913e6ca193dSGeorge Wilson switch (vs->vs_aux) {
1914e6ca193dSGeorge Wilson case VDEV_AUX_OPEN_FAILED:
1915e6ca193dSGeorge Wilson (void) printf(gettext("cannot open"));
1916e6ca193dSGeorge Wilson break;
1917e6ca193dSGeorge Wilson
1918e6ca193dSGeorge Wilson case VDEV_AUX_BAD_GUID_SUM:
1919e6ca193dSGeorge Wilson (void) printf(gettext("missing device"));
1920e6ca193dSGeorge Wilson break;
1921e6ca193dSGeorge Wilson
1922e6ca193dSGeorge Wilson case VDEV_AUX_NO_REPLICAS:
1923e6ca193dSGeorge Wilson (void) printf(gettext("insufficient replicas"));
1924e6ca193dSGeorge Wilson break;
1925e6ca193dSGeorge Wilson
1926e6ca193dSGeorge Wilson case VDEV_AUX_VERSION_NEWER:
1927e6ca193dSGeorge Wilson (void) printf(gettext("newer version"));
1928e6ca193dSGeorge Wilson break;
1929e6ca193dSGeorge Wilson
1930ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT:
1931ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)"));
1932ad135b5dSChristopher Siden break;
1933ad135b5dSChristopher Siden
1934e6ca193dSGeorge Wilson case VDEV_AUX_SPARED:
1935e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1936663207adSDon Brady &spare_cb.cb_guid) == 0);
1937663207adSDon Brady if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
1938663207adSDon Brady if (strcmp(zpool_get_name(spare_cb.cb_zhp),
1939e6ca193dSGeorge Wilson zpool_get_name(zhp)) == 0)
1940e6ca193dSGeorge Wilson (void) printf(gettext("currently in "
1941e6ca193dSGeorge Wilson "use"));
1942e6ca193dSGeorge Wilson else
1943e6ca193dSGeorge Wilson (void) printf(gettext("in use by "
1944e6ca193dSGeorge Wilson "pool '%s'"),
1945663207adSDon Brady zpool_get_name(spare_cb.cb_zhp));
1946663207adSDon Brady zpool_close(spare_cb.cb_zhp);
1947e6ca193dSGeorge Wilson } else {
1948e6ca193dSGeorge Wilson (void) printf(gettext("currently in use"));
1949e6ca193dSGeorge Wilson }
1950e6ca193dSGeorge Wilson break;
1951e6ca193dSGeorge Wilson
1952e6ca193dSGeorge Wilson case VDEV_AUX_ERR_EXCEEDED:
1953e6ca193dSGeorge Wilson (void) printf(gettext("too many errors"));
1954e6ca193dSGeorge Wilson break;
1955e6ca193dSGeorge Wilson
1956e6ca193dSGeorge Wilson case VDEV_AUX_IO_FAILURE:
1957e6ca193dSGeorge Wilson (void) printf(gettext("experienced I/O failures"));
1958e6ca193dSGeorge Wilson break;
1959e6ca193dSGeorge Wilson
1960e6ca193dSGeorge Wilson case VDEV_AUX_BAD_LOG:
1961e6ca193dSGeorge Wilson (void) printf(gettext("bad intent log"));
1962e6ca193dSGeorge Wilson break;
1963e6ca193dSGeorge Wilson
1964069f55e2SEric Schrock case VDEV_AUX_EXTERNAL:
1965069f55e2SEric Schrock (void) printf(gettext("external device fault"));
1966069f55e2SEric Schrock break;
1967069f55e2SEric Schrock
19681195e687SMark J Musante case VDEV_AUX_SPLIT_POOL:
19691195e687SMark J Musante (void) printf(gettext("split into new pool"));
19701195e687SMark J Musante break;
19711195e687SMark J Musante
1972e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE:
1973e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use"));
1974e0f1c0afSOlaf Faaland break;
1975e0f1c0afSOlaf Faaland
19766f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE:
19776f793812SPavel Zakharov (void) printf(gettext("all children offline"));
19786f793812SPavel Zakharov break;
19796f793812SPavel Zakharov
1980e6ca193dSGeorge Wilson default:
1981e6ca193dSGeorge Wilson (void) printf(gettext("corrupted data"));
1982e6ca193dSGeorge Wilson break;
1983e6ca193dSGeorge Wilson }
19843f9d6ad7SLin Ling }
19853f9d6ad7SLin Ling
198664dee23eSTony Hutter /* The root vdev has the scrub/resilver stats */
198764dee23eSTony Hutter root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
198864dee23eSTony Hutter ZPOOL_CONFIG_VDEV_TREE);
198964dee23eSTony Hutter (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
19903f9d6ad7SLin Ling (uint64_t **)&ps, &c);
19913f9d6ad7SLin Ling
1992e4c795beSTom Caputi if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) {
1993e4c795beSTom Caputi if (vs->vs_scan_processed != 0) {
19943f9d6ad7SLin Ling (void) printf(gettext(" (%s)"),
19953f9d6ad7SLin Ling (ps->pss_func == POOL_SCAN_RESILVER) ?
19963f9d6ad7SLin Ling "resilvering" : "repairing");
1997e4c795beSTom Caputi } else if (vs->vs_resilver_deferred) {
1998e4c795beSTom Caputi (void) printf(gettext(" (awaiting resilver)"));
1999e4c795beSTom Caputi }
2000e6ca193dSGeorge Wilson }
2001e6ca193dSGeorge Wilson
2002084fd14fSBrian Behlendorf /* Display vdev initialization and trim status for leaves */
2003084fd14fSBrian Behlendorf if (children == 0) {
2004084fd14fSBrian Behlendorf print_status_initialize(vs, cb->cb_print_vdev_init);
2005084fd14fSBrian Behlendorf print_status_trim(vs, cb->cb_print_vdev_trim);
2006094e47e9SGeorge Wilson }
2007094e47e9SGeorge Wilson
2008e6ca193dSGeorge Wilson (void) printf("\n");
2009e6ca193dSGeorge Wilson
2010e6ca193dSGeorge Wilson for (c = 0; c < children; c++) {
201188ecc943SGeorge Wilson uint64_t islog = B_FALSE, ishole = B_FALSE;
2012e6ca193dSGeorge Wilson
201388ecc943SGeorge Wilson /* Don't print logs or holes here */
2014e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
201588ecc943SGeorge Wilson &islog);
201688ecc943SGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
201788ecc943SGeorge Wilson &ishole);
201888ecc943SGeorge Wilson if (islog || ishole)
2019e6ca193dSGeorge Wilson continue;
2020663207adSDon Brady /* Only print normal classes here */
2021663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2022663207adSDon Brady continue;
2023663207adSDon Brady
2024663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c],
2025663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID);
202664dee23eSTony Hutter
2027663207adSDon Brady print_status_config(zhp, cb, vname, child[c], depth + 2,
2028663207adSDon Brady isspare);
2029e6ca193dSGeorge Wilson free(vname);
2030e6ca193dSGeorge Wilson }
2031e6ca193dSGeorge Wilson }
2032e6ca193dSGeorge Wilson
2033fa9e4066Sahrens /*
2034fa9e4066Sahrens * Print the configuration of an exported pool. Iterate over all vdevs in the
2035fa9e4066Sahrens * pool, printing out the name and status for each one.
2036fa9e4066Sahrens */
2037663207adSDon Brady static void
print_import_config(status_cbdata_t * cb,const char * name,nvlist_t * nv,int depth)2038663207adSDon Brady print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
2039663207adSDon Brady int depth)
2040fa9e4066Sahrens {
2041fa9e4066Sahrens nvlist_t **child;
2042fa9e4066Sahrens uint_t c, children;
2043fa9e4066Sahrens vdev_stat_t *vs;
2044afefbcddSeschrock char *type, *vname;
2045fa9e4066Sahrens
2046fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
204788ecc943SGeorge Wilson if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
204888ecc943SGeorge Wilson strcmp(type, VDEV_TYPE_HOLE) == 0)
2049fa9e4066Sahrens return;
2050fa9e4066Sahrens
20513f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2052fa9e4066Sahrens (uint64_t **)&vs, &c) == 0);
2053fa9e4066Sahrens
2054663207adSDon Brady (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
2055990b4856Slling (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
2056fa9e4066Sahrens
2057fa9e4066Sahrens if (vs->vs_aux != 0) {
20583d7072f8Seschrock (void) printf(" ");
2059fa9e4066Sahrens
2060fa9e4066Sahrens switch (vs->vs_aux) {
2061fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED:
2062fa9e4066Sahrens (void) printf(gettext("cannot open"));
2063fa9e4066Sahrens break;
2064fa9e4066Sahrens
2065fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM:
2066fa9e4066Sahrens (void) printf(gettext("missing device"));
2067fa9e4066Sahrens break;
2068fa9e4066Sahrens
2069fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS:
2070fa9e4066Sahrens (void) printf(gettext("insufficient replicas"));
2071fa9e4066Sahrens break;
2072fa9e4066Sahrens
2073eaca9bbdSeschrock case VDEV_AUX_VERSION_NEWER:
2074eaca9bbdSeschrock (void) printf(gettext("newer version"));
2075eaca9bbdSeschrock break;
2076eaca9bbdSeschrock
2077ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT:
2078ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)"));
2079ad135b5dSChristopher Siden break;
2080ad135b5dSChristopher Siden
20813d7072f8Seschrock case VDEV_AUX_ERR_EXCEEDED:
20823d7072f8Seschrock (void) printf(gettext("too many errors"));
20833d7072f8Seschrock break;
20843d7072f8Seschrock
2085e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE:
2086e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use"));
2087e0f1c0afSOlaf Faaland break;
2088e0f1c0afSOlaf Faaland
20896f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE:
20906f793812SPavel Zakharov (void) printf(gettext("all children offline"));
20916f793812SPavel Zakharov break;
20926f793812SPavel Zakharov
2093fa9e4066Sahrens default:
2094fa9e4066Sahrens (void) printf(gettext("corrupted data"));
2095fa9e4066Sahrens break;
2096fa9e4066Sahrens }
2097fa9e4066Sahrens }
2098fa9e4066Sahrens (void) printf("\n");
2099fa9e4066Sahrens
2100fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2101fa9e4066Sahrens &child, &children) != 0)
2102fa9e4066Sahrens return;
2103fa9e4066Sahrens
2104afefbcddSeschrock for (c = 0; c < children; c++) {
21058654d025Sperrin uint64_t is_log = B_FALSE;
21068654d025Sperrin
21078654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
21088654d025Sperrin &is_log);
2109e6ca193dSGeorge Wilson if (is_log)
21108654d025Sperrin continue;
2111663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2112663207adSDon Brady continue;
21138654d025Sperrin
2114663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c],
2115663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2116663207adSDon Brady print_import_config(cb, vname, child[c], depth + 2);
2117afefbcddSeschrock free(vname);
2118afefbcddSeschrock }
211999653d4eSeschrock
2120fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2121fa94a07fSbrendan &child, &children) == 0) {
2122fa94a07fSbrendan (void) printf(gettext("\tcache\n"));
2123fa94a07fSbrendan for (c = 0; c < children; c++) {
2124663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c],
2125663207adSDon Brady cb->cb_name_flags);
2126fa94a07fSbrendan (void) printf("\t %s\n", vname);
2127fa94a07fSbrendan free(vname);
2128fa94a07fSbrendan }
2129fa94a07fSbrendan }
213099653d4eSeschrock
2131fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2132fa94a07fSbrendan &child, &children) == 0) {
213399653d4eSeschrock (void) printf(gettext("\tspares\n"));
213499653d4eSeschrock for (c = 0; c < children; c++) {
2135663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c],
2136663207adSDon Brady cb->cb_name_flags);
213799653d4eSeschrock (void) printf("\t %s\n", vname);
213899653d4eSeschrock free(vname);
213999653d4eSeschrock }
2140fa9e4066Sahrens }
2141fa94a07fSbrendan }
2142fa9e4066Sahrens
2143fa9e4066Sahrens /*
2144663207adSDon Brady * Print specialized class vdevs.
2145663207adSDon Brady *
2146663207adSDon Brady * These are recorded as top level vdevs in the main pool child array
2147663207adSDon Brady * but with "is_log" set to 1 or an "alloc_bias" string. We use either
2148663207adSDon Brady * print_status_config() or print_import_config() to print the top level
2149663207adSDon Brady * class vdevs then any of their children (eg mirrored slogs) are printed
2150663207adSDon Brady * recursively - which works because only the top level vdev is marked.
2151e6ca193dSGeorge Wilson */
2152e6ca193dSGeorge Wilson static void
print_class_vdevs(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t * nv,const char * class)2153663207adSDon Brady print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
2154663207adSDon Brady const char *class)
2155e6ca193dSGeorge Wilson {
2156e6ca193dSGeorge Wilson uint_t c, children;
2157e6ca193dSGeorge Wilson nvlist_t **child;
2158663207adSDon Brady boolean_t printed = B_FALSE;
2159663207adSDon Brady
2160663207adSDon Brady assert(zhp != NULL || !cb->cb_verbose);
2161e6ca193dSGeorge Wilson
2162e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
2163e6ca193dSGeorge Wilson &children) != 0)
2164e6ca193dSGeorge Wilson return;
2165e6ca193dSGeorge Wilson
2166e6ca193dSGeorge Wilson for (c = 0; c < children; c++) {
2167e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE;
2168663207adSDon Brady char *bias = NULL;
2169663207adSDon Brady char *type = NULL;
2170e6ca193dSGeorge Wilson
2171e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2172e6ca193dSGeorge Wilson &is_log);
2173663207adSDon Brady
2174663207adSDon Brady if (is_log) {
2175663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS;
2176663207adSDon Brady } else {
2177663207adSDon Brady (void) nvlist_lookup_string(child[c],
2178663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
2179663207adSDon Brady (void) nvlist_lookup_string(child[c],
2180663207adSDon Brady ZPOOL_CONFIG_TYPE, &type);
2181663207adSDon Brady }
2182663207adSDon Brady
2183663207adSDon Brady if (bias == NULL || strcmp(bias, class) != 0)
2184e6ca193dSGeorge Wilson continue;
2185663207adSDon Brady if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
2186663207adSDon Brady continue;
2187663207adSDon Brady
2188663207adSDon Brady if (!printed) {
2189663207adSDon Brady (void) printf("\t%s\t\n", gettext(class));
2190663207adSDon Brady printed = B_TRUE;
2191663207adSDon Brady }
2192663207adSDon Brady
2193663207adSDon Brady char *name = zpool_vdev_name(g_zfs, zhp, child[c],
2194663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2195663207adSDon Brady if (cb->cb_print_status)
2196663207adSDon Brady print_status_config(zhp, cb, name, child[c], 2,
2197663207adSDon Brady B_FALSE);
2198e6ca193dSGeorge Wilson else
2199663207adSDon Brady print_import_config(cb, name, child[c], 2);
2200e6ca193dSGeorge Wilson free(name);
2201e6ca193dSGeorge Wilson }
2202e6ca193dSGeorge Wilson }
2203468c413aSTim Haley
2204e6ca193dSGeorge Wilson /*
2205fa9e4066Sahrens * Display the status for the given pool.
2206fa9e4066Sahrens */
2207fa9e4066Sahrens static void
show_import(nvlist_t * config)2208fa9e4066Sahrens show_import(nvlist_t *config)
2209fa9e4066Sahrens {
2210fa9e4066Sahrens uint64_t pool_state;
2211fa9e4066Sahrens vdev_stat_t *vs;
2212fa9e4066Sahrens char *name;
2213fa9e4066Sahrens uint64_t guid;
2214e0f1c0afSOlaf Faaland uint64_t hostid = 0;
2215fa9e4066Sahrens char *msgid;
2216e0f1c0afSOlaf Faaland char *hostname = "unknown";
2217e0f1c0afSOlaf Faaland nvlist_t *nvroot, *nvinfo;
2218fa9e4066Sahrens int reason;
2219eb633035STom Caputi zpool_errata_t errata;
222046657f8dSmmusante const char *health;
2221fa9e4066Sahrens uint_t vsc;
22228704186eSDan McDonald char *comment;
2223663207adSDon Brady status_cbdata_t cb = { 0 };
2224fa9e4066Sahrens
2225fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2226fa9e4066Sahrens &name) == 0);
2227fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2228fa9e4066Sahrens &guid) == 0);
2229fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2230fa9e4066Sahrens &pool_state) == 0);
2231fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2232fa9e4066Sahrens &nvroot) == 0);
2233fa9e4066Sahrens
22343f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
2235fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0);
2236990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2237fa9e4066Sahrens
2238eb633035STom Caputi reason = zpool_import_status(config, &msgid, &errata);
2239fa9e4066Sahrens
224046657f8dSmmusante (void) printf(gettext(" pool: %s\n"), name);
224146657f8dSmmusante (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
224246657f8dSmmusante (void) printf(gettext(" state: %s"), health);
22434c58d714Sdarrenm if (pool_state == POOL_STATE_DESTROYED)
224446657f8dSmmusante (void) printf(gettext(" (DESTROYED)"));
22454c58d714Sdarrenm (void) printf("\n");
2246fa9e4066Sahrens
2247fa9e4066Sahrens switch (reason) {
2248fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R:
2249fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR:
2250fa9e4066Sahrens case ZPOOL_STATUS_BAD_GUID_SUM:
22518704186eSDan McDonald (void) printf(gettext(" status: One or more devices are "
22528704186eSDan McDonald "missing from the system.\n"));
2253fa9e4066Sahrens break;
2254fa9e4066Sahrens
2255fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R:
2256fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2257fa9e4066Sahrens (void) printf(gettext(" status: One or more devices contains "
2258fa9e4066Sahrens "corrupted data.\n"));
2259fa9e4066Sahrens break;
2260fa9e4066Sahrens
2261fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_DATA:
22628704186eSDan McDonald (void) printf(
22638704186eSDan McDonald gettext(" status: The pool data is corrupted.\n"));
2264fa9e4066Sahrens break;
2265fa9e4066Sahrens
2266441d80aaSlling case ZPOOL_STATUS_OFFLINE_DEV:
2267441d80aaSlling (void) printf(gettext(" status: One or more devices "
2268441d80aaSlling "are offlined.\n"));
2269441d80aaSlling break;
2270441d80aaSlling
2271ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL:
2272ea8dc4b6Seschrock (void) printf(gettext(" status: The pool metadata is "
2273ea8dc4b6Seschrock "corrupted.\n"));
2274ea8dc4b6Seschrock break;
2275ea8dc4b6Seschrock
2276eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER:
227757221772SChristopher Siden (void) printf(gettext(" status: The pool is formatted using a "
227857221772SChristopher Siden "legacy on-disk version.\n"));
2279eaca9bbdSeschrock break;
2280eaca9bbdSeschrock
2281eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER:
2282eaca9bbdSeschrock (void) printf(gettext(" status: The pool is formatted using an "
2283eaca9bbdSeschrock "incompatible version.\n"));
2284eaca9bbdSeschrock break;
2285b87f3af3Sperrin
228657221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED:
228757221772SChristopher Siden (void) printf(gettext(" status: Some supported features are "
228857221772SChristopher Siden "not enabled on the pool.\n"));
228957221772SChristopher Siden break;
229057221772SChristopher Siden
2291ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ:
2292ad135b5dSChristopher Siden (void) printf(gettext("status: The pool uses the following "
2293edc8ef7dSToomas Soome "feature(s) not supported on this system:\n"));
2294ad135b5dSChristopher Siden zpool_print_unsup_feat(config);
2295ad135b5dSChristopher Siden break;
2296ad135b5dSChristopher Siden
2297ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2298ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed "
2299ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be "
2300ad135b5dSChristopher Siden "accessed in read-write mode because it uses the "
2301ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n"));
2302ad135b5dSChristopher Siden zpool_print_unsup_feat(config);
2303ad135b5dSChristopher Siden break;
2304ad135b5dSChristopher Siden
2305e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE:
2306e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool is currently "
2307e0f1c0afSOlaf Faaland "imported by another system.\n"));
2308e0f1c0afSOlaf Faaland break;
2309e0f1c0afSOlaf Faaland
2310e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED:
2311e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool has the "
2312e0f1c0afSOlaf Faaland "multihost property on. It cannot\n\tbe safely imported "
2313e0f1c0afSOlaf Faaland "when the system hostid is not set.\n"));
2314e0f1c0afSOlaf Faaland break;
2315e0f1c0afSOlaf Faaland
231695173954Sek110237 case ZPOOL_STATUS_HOSTID_MISMATCH:
231795173954Sek110237 (void) printf(gettext(" status: The pool was last accessed by "
231895173954Sek110237 "another system.\n"));
231995173954Sek110237 break;
2320b87f3af3Sperrin
23213d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R:
23223d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR:
23233d7072f8Seschrock (void) printf(gettext(" status: One or more devices are "
23243d7072f8Seschrock "faulted.\n"));
23253d7072f8Seschrock break;
23263d7072f8Seschrock
2327b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG:
2328b87f3af3Sperrin (void) printf(gettext(" status: An intent log record cannot be "
2329b87f3af3Sperrin "read.\n"));
2330b87f3af3Sperrin break;
2331b87f3af3Sperrin
23323f9d6ad7SLin Ling case ZPOOL_STATUS_RESILVERING:
23333f9d6ad7SLin Ling (void) printf(gettext(" status: One or more devices were being "
23343f9d6ad7SLin Ling "resilvered.\n"));
23353f9d6ad7SLin Ling break;
23363f9d6ad7SLin Ling
2337eb633035STom Caputi case ZPOOL_STATUS_ERRATA:
2338eb633035STom Caputi (void) printf(gettext(" status: Errata #%d detected.\n"),
2339eb633035STom Caputi errata);
2340eb633035STom Caputi break;
2341eb633035STom Caputi
2342fa9e4066Sahrens default:
2343fa9e4066Sahrens /*
2344fa9e4066Sahrens * No other status can be seen when importing pools.
2345fa9e4066Sahrens */
2346fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK);
2347fa9e4066Sahrens }
2348fa9e4066Sahrens
2349fa9e4066Sahrens /*
2350fa9e4066Sahrens * Print out an action according to the overall state of the pool.
2351fa9e4066Sahrens */
235246657f8dSmmusante if (vs->vs_state == VDEV_STATE_HEALTHY) {
235357221772SChristopher Siden if (reason == ZPOOL_STATUS_VERSION_OLDER ||
235457221772SChristopher Siden reason == ZPOOL_STATUS_FEAT_DISABLED) {
2355eaca9bbdSeschrock (void) printf(gettext(" action: The pool can be "
2356eaca9bbdSeschrock "imported using its name or numeric identifier, "
2357eaca9bbdSeschrock "though\n\tsome features will not be available "
2358eaca9bbdSeschrock "without an explicit 'zpool upgrade'.\n"));
235957221772SChristopher Siden } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
236095173954Sek110237 (void) printf(gettext(" action: The pool can be "
236195173954Sek110237 "imported using its name or numeric "
236295173954Sek110237 "identifier and\n\tthe '-f' flag.\n"));
2363eb633035STom Caputi } else if (reason == ZPOOL_STATUS_ERRATA) {
2364eb633035STom Caputi switch (errata) {
2365eb633035STom Caputi case ZPOOL_ERRATA_NONE:
2366eb633035STom Caputi break;
2367eb633035STom Caputi
2368eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB:
2369eb633035STom Caputi (void) printf(gettext(" action: The pool can "
2370eb633035STom Caputi "be imported using its name or numeric "
2371eb633035STom Caputi "identifier,\n\thowever there is a compat"
2372eb633035STom Caputi "ibility issue which should be corrected"
2373eb633035STom Caputi "\n\tby running 'zpool scrub'\n"));
2374eb633035STom Caputi break;
2375eb633035STom Caputi
2376eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
2377eb633035STom Caputi (void) printf(gettext(" action: The pool can"
2378eb633035STom Caputi "not be imported with this version of ZFS "
2379eb633035STom Caputi "due to\n\tan active asynchronous destroy. "
2380eb633035STom Caputi "Revert to an earlier version\n\tand "
2381eb633035STom Caputi "allow the destroy to complete before "
2382eb633035STom Caputi "updating.\n"));
2383eb633035STom Caputi break;
2384eb633035STom Caputi
2385eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
2386eb633035STom Caputi (void) printf(gettext(" action: Existing "
2387eb633035STom Caputi "encrypted datasets contain an on-disk "
2388eb633035STom Caputi "incompatibility, which\n\tneeds to be "
2389eb633035STom Caputi "corrected. Backup these datasets to new "
2390eb633035STom Caputi "encrypted datasets\n\tand destroy the "
2391eb633035STom Caputi "old ones.\n"));
2392eb633035STom Caputi break;
2393eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
2394eb633035STom Caputi (void) printf(gettext(" action: Any existing "
2395eb633035STom Caputi "encrypted datasets contain an on-disk "
2396eb633035STom Caputi "incompatibility which\n\tmay cause "
2397eb633035STom Caputi "on-disk corruption with 'zfs recv' and "
2398eb633035STom Caputi "which needs to be\n\tcorrected. Enable "
2399eb633035STom Caputi "the bookmark_v2 feature and backup "
2400eb633035STom Caputi "these datasets to new encrypted "
2401eb633035STom Caputi "datasets and\n\tdestroy the old ones. "
2402eb633035STom Caputi "If this pool does not contain any "
2403eb633035STom Caputi "encrypted datasets, simply enable\n\t"
2404eb633035STom Caputi "the bookmark_v2 feature.\n"));
2405eb633035STom Caputi break;
2406eb633035STom Caputi default:
2407eb633035STom Caputi /*
2408eb633035STom Caputi * All errata must contain an action message.
2409eb633035STom Caputi */
2410eb633035STom Caputi assert(0);
2411eb633035STom Caputi }
241257221772SChristopher Siden } else {
2413eaca9bbdSeschrock (void) printf(gettext(" action: The pool can be "
2414eaca9bbdSeschrock "imported using its name or numeric "
2415eaca9bbdSeschrock "identifier.\n"));
241657221772SChristopher Siden }
241746657f8dSmmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2418fa9e4066Sahrens (void) printf(gettext(" action: The pool can be imported "
2419fa9e4066Sahrens "despite missing or damaged devices. The\n\tfault "
2420eaca9bbdSeschrock "tolerance of the pool may be compromised if imported.\n"));
2421fa9e4066Sahrens } else {
2422eaca9bbdSeschrock switch (reason) {
2423eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER:
2424eaca9bbdSeschrock (void) printf(gettext(" action: The pool cannot be "
2425eaca9bbdSeschrock "imported. Access the pool on a system running "
2426eaca9bbdSeschrock "newer\n\tsoftware, or recreate the pool from "
2427eaca9bbdSeschrock "backup.\n"));
2428eaca9bbdSeschrock break;
2429ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ:
2430ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be "
2431ad135b5dSChristopher Siden "imported. Access the pool on a system that "
2432ad135b5dSChristopher Siden "supports\n\tthe required feature(s), or recreate "
2433ad135b5dSChristopher Siden "the pool from backup.\n"));
2434ad135b5dSChristopher Siden break;
2435ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2436ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be "
2437ad135b5dSChristopher Siden "imported in read-write mode. Import the pool "
2438ad135b5dSChristopher Siden "with\n"
2439ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool on a system "
2440ad135b5dSChristopher Siden "that supports the\n\trequired feature(s), or "
2441ad135b5dSChristopher Siden "recreate the pool from backup.\n"));
2442ad135b5dSChristopher Siden break;
2443eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_R:
2444eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_NR:
2445eaca9bbdSeschrock case ZPOOL_STATUS_BAD_GUID_SUM:
2446fa9e4066Sahrens (void) printf(gettext(" action: The pool cannot be "
2447fa9e4066Sahrens "imported. Attach the missing\n\tdevices and try "
2448fa9e4066Sahrens "again.\n"));
2449eaca9bbdSeschrock break;
2450e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE:
2451e0f1c0afSOlaf Faaland VERIFY0(nvlist_lookup_nvlist(config,
2452e0f1c0afSOlaf Faaland ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
2453e0f1c0afSOlaf Faaland
2454e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2455e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo,
2456e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME);
2457e0f1c0afSOlaf Faaland
2458e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2459e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo,
2460e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID);
2461e0f1c0afSOlaf Faaland
2462e0f1c0afSOlaf Faaland (void) printf(gettext(" action: The pool must be "
2463e0f1c0afSOlaf Faaland "exported from %s (hostid=%lx)\n\tbefore it "
2464e0f1c0afSOlaf Faaland "can be safely imported.\n"), hostname,
2465e0f1c0afSOlaf Faaland (unsigned long) hostid);
2466e0f1c0afSOlaf Faaland break;
2467e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED:
2468e0f1c0afSOlaf Faaland (void) printf(gettext(" action: Check the SMF "
2469e0f1c0afSOlaf Faaland "svc:/system/hostid service.\n"));
2470e0f1c0afSOlaf Faaland break;
2471eaca9bbdSeschrock default:
2472fa9e4066Sahrens (void) printf(gettext(" action: The pool cannot be "
2473fa9e4066Sahrens "imported due to damaged devices or data.\n"));
2474fa9e4066Sahrens }
2475eaca9bbdSeschrock }
2476eaca9bbdSeschrock
24778704186eSDan McDonald /* Print the comment attached to the pool. */
24788704186eSDan McDonald if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
24798704186eSDan McDonald (void) printf(gettext("comment: %s\n"), comment);
24808704186eSDan McDonald
248146657f8dSmmusante /*
248246657f8dSmmusante * If the state is "closed" or "can't open", and the aux state
248346657f8dSmmusante * is "corrupt data":
248446657f8dSmmusante */
248546657f8dSmmusante if (((vs->vs_state == VDEV_STATE_CLOSED) ||
248646657f8dSmmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
248746657f8dSmmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2488eaca9bbdSeschrock if (pool_state == POOL_STATE_DESTROYED)
2489eaca9bbdSeschrock (void) printf(gettext("\tThe pool was destroyed, "
2490eaca9bbdSeschrock "but can be imported using the '-Df' flags.\n"));
2491eaca9bbdSeschrock else if (pool_state != POOL_STATE_EXPORTED)
2492eaca9bbdSeschrock (void) printf(gettext("\tThe pool may be active on "
249318ce54dfSek110237 "another system, but can be imported using\n\t"
2494eaca9bbdSeschrock "the '-f' flag.\n"));
2495eaca9bbdSeschrock }
2496fa9e4066Sahrens
2497fa9e4066Sahrens if (msgid != NULL)
2498654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
2499fa9e4066Sahrens msgid);
2500fa9e4066Sahrens
2501fa9e4066Sahrens (void) printf(gettext(" config:\n\n"));
2502fa9e4066Sahrens
2503dd50e0ccSTony Hutter cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
2504dd50e0ccSTony Hutter VDEV_NAME_TYPE_ID);
2505663207adSDon Brady if (cb.cb_namewidth < 10)
2506663207adSDon Brady cb.cb_namewidth = 10;
25078654d025Sperrin
2508663207adSDon Brady print_import_config(&cb, name, nvroot, 0);
2509663207adSDon Brady
2510663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
2511663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
2512663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
2513fa9e4066Sahrens
2514fa9e4066Sahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
251546657f8dSmmusante (void) printf(gettext("\n\tAdditional devices are known to "
2516fa9e4066Sahrens "be part of this pool, though their\n\texact "
251746657f8dSmmusante "configuration cannot be determined.\n"));
2518fa9e4066Sahrens }
2519fa9e4066Sahrens }
2520fa9e4066Sahrens
2521e0f1c0afSOlaf Faaland static boolean_t
zfs_force_import_required(nvlist_t * config)2522e0f1c0afSOlaf Faaland zfs_force_import_required(nvlist_t *config)
2523e0f1c0afSOlaf Faaland {
2524e0f1c0afSOlaf Faaland uint64_t state;
2525e0f1c0afSOlaf Faaland uint64_t hostid = 0;
2526e0f1c0afSOlaf Faaland nvlist_t *nvinfo;
2527e0f1c0afSOlaf Faaland
2528e0f1c0afSOlaf Faaland state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
2529e0f1c0afSOlaf Faaland (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
2530e0f1c0afSOlaf Faaland
2531e0f1c0afSOlaf Faaland if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
2532e0f1c0afSOlaf Faaland return (B_TRUE);
2533e0f1c0afSOlaf Faaland
2534e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2535e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
2536e0f1c0afSOlaf Faaland mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
2537e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE);
2538e0f1c0afSOlaf Faaland
2539e0f1c0afSOlaf Faaland if (mmp_state != MMP_STATE_INACTIVE)
2540e0f1c0afSOlaf Faaland return (B_TRUE);
2541e0f1c0afSOlaf Faaland }
2542e0f1c0afSOlaf Faaland
2543e0f1c0afSOlaf Faaland return (B_FALSE);
2544e0f1c0afSOlaf Faaland }
2545e0f1c0afSOlaf Faaland
2546fa9e4066Sahrens /*
2547fa9e4066Sahrens * Perform the import for the given configuration. This passes the heavy
2548990b4856Slling * lifting off to zpool_import_props(), and then mounts the datasets contained
2549990b4856Slling * within the pool.
2550fa9e4066Sahrens */
2551fa9e4066Sahrens static int
do_import(nvlist_t * config,const char * newname,const char * mntopts,nvlist_t * props,int flags)2552fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts,
25534b964adaSGeorge Wilson nvlist_t *props, int flags)
2554fa9e4066Sahrens {
2555eb633035STom Caputi int ret = 0;
2556fa9e4066Sahrens zpool_handle_t *zhp;
2557fa9e4066Sahrens char *name;
2558eaca9bbdSeschrock uint64_t version;
2559fa9e4066Sahrens
2560e0f1c0afSOlaf Faaland name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
2561e0f1c0afSOlaf Faaland version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
2562fa9e4066Sahrens
2563ad135b5dSChristopher Siden if (!SPA_VERSION_IS_SUPPORTED(version)) {
2564eaca9bbdSeschrock (void) fprintf(stderr, gettext("cannot import '%s': pool "
2565ad135b5dSChristopher Siden "is formatted using an unsupported ZFS version\n"), name);
2566eaca9bbdSeschrock return (1);
2567e0f1c0afSOlaf Faaland } else if (zfs_force_import_required(config) &&
25684b964adaSGeorge Wilson !(flags & ZFS_IMPORT_ANY_HOST)) {
2569e0f1c0afSOlaf Faaland mmp_state_t mmp_state = MMP_STATE_INACTIVE;
2570e0f1c0afSOlaf Faaland nvlist_t *nvinfo;
257195173954Sek110237
2572e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2573e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
2574e0f1c0afSOlaf Faaland mmp_state = fnvlist_lookup_uint64(nvinfo,
2575e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE);
257695173954Sek110237
2577e0f1c0afSOlaf Faaland if (mmp_state == MMP_STATE_ACTIVE) {
2578e0f1c0afSOlaf Faaland char *hostname = "<unknown>";
2579e0f1c0afSOlaf Faaland uint64_t hostid = 0;
2580e0f1c0afSOlaf Faaland
2581e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2582e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo,
2583e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME);
2584e0f1c0afSOlaf Faaland
2585e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2586e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo,
2587e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID);
2588e0f1c0afSOlaf Faaland
258995173954Sek110237 (void) fprintf(stderr, gettext("cannot import '%s': "
2590e0f1c0afSOlaf Faaland "pool is imported on %s (hostid: "
2591e0f1c0afSOlaf Faaland "0x%lx)\nExport the pool on the other system, "
2592e0f1c0afSOlaf Faaland "then run 'zpool import'.\n"),
2593e0f1c0afSOlaf Faaland name, hostname, (unsigned long) hostid);
2594e0f1c0afSOlaf Faaland } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2595e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("Cannot import '%s': "
2596e0f1c0afSOlaf Faaland "pool has the multihost property on and the\n"
2597e0f1c0afSOlaf Faaland "system's hostid is not set.\n"), name);
2598e0f1c0afSOlaf Faaland } else {
2599e0f1c0afSOlaf Faaland char *hostname = "<unknown>";
2600e0f1c0afSOlaf Faaland uint64_t timestamp = 0;
2601e0f1c0afSOlaf Faaland uint64_t hostid = 0;
2602e0f1c0afSOlaf Faaland
2603e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
2604e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(config,
2605e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTNAME);
2606e0f1c0afSOlaf Faaland
2607e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
2608e0f1c0afSOlaf Faaland timestamp = fnvlist_lookup_uint64(config,
2609e0f1c0afSOlaf Faaland ZPOOL_CONFIG_TIMESTAMP);
2610e0f1c0afSOlaf Faaland
2611e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
2612e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(config,
2613e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTID);
2614e0f1c0afSOlaf Faaland
2615e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("cannot import '%s': "
2616e0f1c0afSOlaf Faaland "pool was previously in use from another system.\n"
2617e0f1c0afSOlaf Faaland "Last accessed by %s (hostid=%lx) at %s"
2618e0f1c0afSOlaf Faaland "The pool can be imported, use 'zpool import -f' "
2619e0f1c0afSOlaf Faaland "to import the pool.\n"), name, hostname,
2620e0f1c0afSOlaf Faaland (unsigned long)hostid, ctime((time_t *)×tamp));
2621e0f1c0afSOlaf Faaland
262295173954Sek110237 }
2623e0f1c0afSOlaf Faaland
2624e0f1c0afSOlaf Faaland return (1);
262595173954Sek110237 }
2626fa9e4066Sahrens
26274b964adaSGeorge Wilson if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2628fa9e4066Sahrens return (1);
2629fa9e4066Sahrens
2630fa9e4066Sahrens if (newname != NULL)
2631fa9e4066Sahrens name = (char *)newname;
2632fa9e4066Sahrens
26334f0f5e5bSVictor Latushkin if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
26344f0f5e5bSVictor Latushkin return (1);
2635fa9e4066Sahrens
2636eb633035STom Caputi /*
2637eb633035STom Caputi * Loading keys is best effort. We don't want to return immediately
2638eb633035STom Caputi * if it fails but we do want to give the error to the caller.
2639eb633035STom Caputi */
2640eb633035STom Caputi if (flags & ZFS_IMPORT_LOAD_KEYS) {
2641eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, name);
2642eb633035STom Caputi if (ret != 0)
2643eb633035STom Caputi ret = 1;
2644eb633035STom Caputi }
2645eb633035STom Caputi
2646379c004dSEric Schrock if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2647f9af39baSGeorge Wilson !(flags & ZFS_IMPORT_ONLY) &&
2648379c004dSEric Schrock zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2649fa9e4066Sahrens zpool_close(zhp);
2650fa9e4066Sahrens return (1);
2651fa9e4066Sahrens }
2652fa9e4066Sahrens
2653fa9e4066Sahrens zpool_close(zhp);
2654eb633035STom Caputi return (ret);
2655fa9e4066Sahrens }
2656fa9e4066Sahrens
2657d8ab6e12SDon Brady typedef struct target_exists_args {
2658d8ab6e12SDon Brady const char *poolname;
2659d8ab6e12SDon Brady uint64_t poolguid;
2660d8ab6e12SDon Brady } target_exists_args_t;
2661d8ab6e12SDon Brady
2662d8ab6e12SDon Brady static int
name_or_guid_exists(zpool_handle_t * zhp,void * data)2663d8ab6e12SDon Brady name_or_guid_exists(zpool_handle_t *zhp, void *data)
2664d8ab6e12SDon Brady {
2665d8ab6e12SDon Brady target_exists_args_t *args = data;
2666d8ab6e12SDon Brady nvlist_t *config = zpool_get_config(zhp, NULL);
2667d8ab6e12SDon Brady int found = 0;
2668d8ab6e12SDon Brady
2669d8ab6e12SDon Brady if (config == NULL)
2670d8ab6e12SDon Brady return (0);
2671d8ab6e12SDon Brady
2672d8ab6e12SDon Brady if (args->poolname != NULL) {
2673d8ab6e12SDon Brady char *pool_name;
2674d8ab6e12SDon Brady
2675d8ab6e12SDon Brady verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2676d8ab6e12SDon Brady &pool_name) == 0);
2677d8ab6e12SDon Brady if (strcmp(pool_name, args->poolname) == 0)
2678d8ab6e12SDon Brady found = 1;
2679d8ab6e12SDon Brady } else {
2680d8ab6e12SDon Brady uint64_t pool_guid;
2681d8ab6e12SDon Brady
2682d8ab6e12SDon Brady verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2683d8ab6e12SDon Brady &pool_guid) == 0);
2684d8ab6e12SDon Brady if (pool_guid == args->poolguid)
2685d8ab6e12SDon Brady found = 1;
2686d8ab6e12SDon Brady }
2687d8ab6e12SDon Brady zpool_close(zhp);
2688d8ab6e12SDon Brady
2689d8ab6e12SDon Brady return (found);
2690d8ab6e12SDon Brady }
2691fa9e4066Sahrens /*
269286714001SSerapheim Dimitropoulos * zpool checkpoint <pool>
269386714001SSerapheim Dimitropoulos * checkpoint --discard <pool>
269486714001SSerapheim Dimitropoulos *
269586714001SSerapheim Dimitropoulos * -d Discard the checkpoint from a checkpointed
269686714001SSerapheim Dimitropoulos * --discard pool.
269786714001SSerapheim Dimitropoulos *
269886714001SSerapheim Dimitropoulos * Checkpoints the specified pool, by taking a "snapshot" of its
269986714001SSerapheim Dimitropoulos * current state. A pool can only have one checkpoint at a time.
270086714001SSerapheim Dimitropoulos */
270186714001SSerapheim Dimitropoulos int
zpool_do_checkpoint(int argc,char ** argv)270286714001SSerapheim Dimitropoulos zpool_do_checkpoint(int argc, char **argv)
270386714001SSerapheim Dimitropoulos {
270486714001SSerapheim Dimitropoulos boolean_t discard;
270586714001SSerapheim Dimitropoulos char *pool;
270686714001SSerapheim Dimitropoulos zpool_handle_t *zhp;
270786714001SSerapheim Dimitropoulos int c, err;
270886714001SSerapheim Dimitropoulos
270986714001SSerapheim Dimitropoulos struct option long_options[] = {
271086714001SSerapheim Dimitropoulos {"discard", no_argument, NULL, 'd'},
271186714001SSerapheim Dimitropoulos {0, 0, 0, 0}
271286714001SSerapheim Dimitropoulos };
271386714001SSerapheim Dimitropoulos
271486714001SSerapheim Dimitropoulos discard = B_FALSE;
271586714001SSerapheim Dimitropoulos while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
271686714001SSerapheim Dimitropoulos switch (c) {
271786714001SSerapheim Dimitropoulos case 'd':
271886714001SSerapheim Dimitropoulos discard = B_TRUE;
271986714001SSerapheim Dimitropoulos break;
272086714001SSerapheim Dimitropoulos case '?':
272186714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("invalid option '%c'\n"),
272286714001SSerapheim Dimitropoulos optopt);
272386714001SSerapheim Dimitropoulos usage(B_FALSE);
272486714001SSerapheim Dimitropoulos }
272586714001SSerapheim Dimitropoulos }
272686714001SSerapheim Dimitropoulos
272786714001SSerapheim Dimitropoulos argc -= optind;
272886714001SSerapheim Dimitropoulos argv += optind;
272986714001SSerapheim Dimitropoulos
273086714001SSerapheim Dimitropoulos if (argc < 1) {
273186714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("missing pool argument\n"));
273286714001SSerapheim Dimitropoulos usage(B_FALSE);
273386714001SSerapheim Dimitropoulos }
273486714001SSerapheim Dimitropoulos
273586714001SSerapheim Dimitropoulos if (argc > 1) {
273686714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("too many arguments\n"));
273786714001SSerapheim Dimitropoulos usage(B_FALSE);
273886714001SSerapheim Dimitropoulos }
273986714001SSerapheim Dimitropoulos
274086714001SSerapheim Dimitropoulos pool = argv[0];
274186714001SSerapheim Dimitropoulos
274286714001SSerapheim Dimitropoulos if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
274386714001SSerapheim Dimitropoulos /* As a special case, check for use of '/' in the name */
274486714001SSerapheim Dimitropoulos if (strchr(pool, '/') != NULL)
274586714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("'zpool checkpoint' "
274686714001SSerapheim Dimitropoulos "doesn't work on datasets. To save the state "
274786714001SSerapheim Dimitropoulos "of a dataset from a specific point in time "
274886714001SSerapheim Dimitropoulos "please use 'zfs snapshot'\n"));
274986714001SSerapheim Dimitropoulos return (1);
275086714001SSerapheim Dimitropoulos }
275186714001SSerapheim Dimitropoulos
275286714001SSerapheim Dimitropoulos if (discard)
275386714001SSerapheim Dimitropoulos err = (zpool_discard_checkpoint(zhp) != 0);
275486714001SSerapheim Dimitropoulos else
275586714001SSerapheim Dimitropoulos err = (zpool_checkpoint(zhp) != 0);
275686714001SSerapheim Dimitropoulos
275786714001SSerapheim Dimitropoulos zpool_close(zhp);
275886714001SSerapheim Dimitropoulos
275986714001SSerapheim Dimitropoulos return (err);
276086714001SSerapheim Dimitropoulos }
276186714001SSerapheim Dimitropoulos
276286714001SSerapheim Dimitropoulos #define CHECKPOINT_OPT 1024
276386714001SSerapheim Dimitropoulos
276486714001SSerapheim Dimitropoulos /*
27654c58d714Sdarrenm * zpool import [-d dir] [-D]
2766eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
27672f8aaab3Seschrock * [-d dir | -c cachefile] [-f] -a
2768eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
276904e56356SAndriy Gapon * [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
277004e56356SAndriy Gapon * <pool | id> [newpool]
27712f8aaab3Seschrock *
27722f8aaab3Seschrock * -c Read pool information from a cachefile instead of searching
27732f8aaab3Seschrock * devices.
2774fa9e4066Sahrens *
2775fa9e4066Sahrens * -d Scan in a specific directory, other than /dev/dsk. More than
2776fa9e4066Sahrens * one directory can be specified using multiple '-d' options.
2777fa9e4066Sahrens *
27784c58d714Sdarrenm * -D Scan for previously destroyed pools or import all or only
27794c58d714Sdarrenm * specified destroyed pools.
27804c58d714Sdarrenm *
2781fa9e4066Sahrens * -R Temporarily import the pool, with all mountpoints relative to
2782fa9e4066Sahrens * the given root. The pool will remain exported when the machine
2783fa9e4066Sahrens * is rebooted.
2784fa9e4066Sahrens *
2785468c413aSTim Haley * -V Import even in the presence of faulted vdevs. This is an
2786c5904d13Seschrock * intentionally undocumented option for testing purposes, and
2787c5904d13Seschrock * treats the pool configuration as complete, leaving any bad
27884f0f5e5bSVictor Latushkin * vdevs in the FAULTED state. In other words, it does verbatim
27894f0f5e5bSVictor Latushkin * import.
2790c5904d13Seschrock *
2791468c413aSTim Haley * -f Force import, even if it appears that the pool is active.
2792468c413aSTim Haley *
2793468c413aSTim Haley * -F Attempt rewind if necessary.
2794468c413aSTim Haley *
2795468c413aSTim Haley * -n See if rewind would work, but don't actually rewind.
2796468c413aSTim Haley *
2797f9af39baSGeorge Wilson * -N Import the pool but don't mount datasets.
2798f9af39baSGeorge Wilson *
279904e56356SAndriy Gapon * -t Use newpool as a temporary pool name instead of renaming
280004e56356SAndriy Gapon * the pool.
280104e56356SAndriy Gapon *
2802f9af39baSGeorge Wilson * -T Specify a starting txg to use for import. This option is
2803f9af39baSGeorge Wilson * intentionally undocumented option for testing purposes.
2804f9af39baSGeorge Wilson *
2805fa9e4066Sahrens * -a Import all pools found.
2806fa9e4066Sahrens *
2807990b4856Slling * -o Set property=value and/or temporary mount options (without '=').
2808eb633035STom Caputi * -l Load encryption keys while importing.
2809ecd6cf80Smarks *
281086714001SSerapheim Dimitropoulos * --rewind-to-checkpoint
281186714001SSerapheim Dimitropoulos * Import the pool and revert back to the checkpoint.
281286714001SSerapheim Dimitropoulos *
2813fa9e4066Sahrens * The import command scans for pools to import, and import pools based on pool
2814fa9e4066Sahrens * name and GUID. The pool can also be renamed as part of the import process.
2815fa9e4066Sahrens */
2816fa9e4066Sahrens int
zpool_do_import(int argc,char ** argv)2817fa9e4066Sahrens zpool_do_import(int argc, char **argv)
2818fa9e4066Sahrens {
2819fa9e4066Sahrens char **searchdirs = NULL;
2820fa9e4066Sahrens int nsearch = 0;
2821fa9e4066Sahrens int c;
2822d41c4376SMark J Musante int err = 0;
28232f8aaab3Seschrock nvlist_t *pools = NULL;
282499653d4eSeschrock boolean_t do_all = B_FALSE;
282599653d4eSeschrock boolean_t do_destroyed = B_FALSE;
2826fa9e4066Sahrens char *mntopts = NULL;
2827fa9e4066Sahrens nvpair_t *elem;
2828fa9e4066Sahrens nvlist_t *config;
282924e697d4Sck153898 uint64_t searchguid = 0;
283024e697d4Sck153898 char *searchname = NULL;
2831990b4856Slling char *propval;
2832fa9e4066Sahrens nvlist_t *found_config;
2833468c413aSTim Haley nvlist_t *policy = NULL;
2834ecd6cf80Smarks nvlist_t *props = NULL;
283599653d4eSeschrock boolean_t first;
28364b964adaSGeorge Wilson int flags = ZFS_IMPORT_NORMAL;
2837468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND;
2838468c413aSTim Haley boolean_t dryrun = B_FALSE;
2839468c413aSTim Haley boolean_t do_rewind = B_FALSE;
2840468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE;
2841d8ab6e12SDon Brady boolean_t pool_exists = B_FALSE;
2842f9af39baSGeorge Wilson uint64_t pool_state, txg = -1ULL;
28432f8aaab3Seschrock char *cachefile = NULL;
2844d41c4376SMark J Musante importargs_t idata = { 0 };
2845f9af39baSGeorge Wilson char *endptr;
2846fa9e4066Sahrens
284786714001SSerapheim Dimitropoulos
284886714001SSerapheim Dimitropoulos struct option long_options[] = {
284986714001SSerapheim Dimitropoulos {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
285086714001SSerapheim Dimitropoulos {0, 0, 0, 0}
285186714001SSerapheim Dimitropoulos };
285286714001SSerapheim Dimitropoulos
2853fa9e4066Sahrens /* check options */
2854eb633035STom Caputi while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX",
285586714001SSerapheim Dimitropoulos long_options, NULL)) != -1) {
2856fa9e4066Sahrens switch (c) {
2857fa9e4066Sahrens case 'a':
285899653d4eSeschrock do_all = B_TRUE;
2859fa9e4066Sahrens break;
28602f8aaab3Seschrock case 'c':
28612f8aaab3Seschrock cachefile = optarg;
28622f8aaab3Seschrock break;
2863fa9e4066Sahrens case 'd':
2864fa9e4066Sahrens if (searchdirs == NULL) {
2865fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *));
2866fa9e4066Sahrens } else {
2867fa9e4066Sahrens char **tmp = safe_malloc((nsearch + 1) *
2868fa9e4066Sahrens sizeof (char *));
2869fa9e4066Sahrens bcopy(searchdirs, tmp, nsearch *
2870fa9e4066Sahrens sizeof (char *));
2871fa9e4066Sahrens free(searchdirs);
2872fa9e4066Sahrens searchdirs = tmp;
2873fa9e4066Sahrens }
2874fa9e4066Sahrens searchdirs[nsearch++] = optarg;
2875fa9e4066Sahrens break;
28764c58d714Sdarrenm case 'D':
287799653d4eSeschrock do_destroyed = B_TRUE;
28784c58d714Sdarrenm break;
2879fa9e4066Sahrens case 'f':
28804b964adaSGeorge Wilson flags |= ZFS_IMPORT_ANY_HOST;
2881fa9e4066Sahrens break;
2882c5904d13Seschrock case 'F':
2883468c413aSTim Haley do_rewind = B_TRUE;
2884468c413aSTim Haley break;
2885eb633035STom Caputi case 'l':
2886eb633035STom Caputi flags |= ZFS_IMPORT_LOAD_KEYS;
2887eb633035STom Caputi break;
28884b964adaSGeorge Wilson case 'm':
28894b964adaSGeorge Wilson flags |= ZFS_IMPORT_MISSING_LOG;
28904b964adaSGeorge Wilson break;
2891468c413aSTim Haley case 'n':
2892468c413aSTim Haley dryrun = B_TRUE;
2893c5904d13Seschrock break;
2894f9af39baSGeorge Wilson case 'N':
2895f9af39baSGeorge Wilson flags |= ZFS_IMPORT_ONLY;
2896f9af39baSGeorge Wilson break;
2897fa9e4066Sahrens case 'o':
2898990b4856Slling if ((propval = strchr(optarg, '=')) != NULL) {
2899990b4856Slling *propval = '\0';
2900990b4856Slling propval++;
29010a48a24eStimh if (add_prop_list(optarg, propval,
29020a48a24eStimh &props, B_TRUE))
2903990b4856Slling goto error;
2904990b4856Slling } else {
2905fa9e4066Sahrens mntopts = optarg;
2906990b4856Slling }
2907fa9e4066Sahrens break;
2908fa9e4066Sahrens case 'R':
2909990b4856Slling if (add_prop_list(zpool_prop_to_name(
29100a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2911990b4856Slling goto error;
291204e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name(
291304e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
291404e56356SAndriy Gapon goto error;
29152f8aaab3Seschrock break;
291604e56356SAndriy Gapon case 't':
291704e56356SAndriy Gapon flags |= ZFS_IMPORT_TEMP_NAME;
291804e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name(
29190a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2920990b4856Slling goto error;
2921fa9e4066Sahrens break;
2922f9af39baSGeorge Wilson case 'T':
2923f9af39baSGeorge Wilson errno = 0;
2924e42d2059SMatthew Ahrens txg = strtoull(optarg, &endptr, 0);
2925f9af39baSGeorge Wilson if (errno != 0 || *endptr != '\0') {
2926f9af39baSGeorge Wilson (void) fprintf(stderr,
2927f9af39baSGeorge Wilson gettext("invalid txg value\n"));
2928f9af39baSGeorge Wilson usage(B_FALSE);
2929f9af39baSGeorge Wilson }
2930f9af39baSGeorge Wilson rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2931f9af39baSGeorge Wilson break;
2932468c413aSTim Haley case 'V':
29334b964adaSGeorge Wilson flags |= ZFS_IMPORT_VERBATIM;
2934468c413aSTim Haley break;
2935468c413aSTim Haley case 'X':
2936468c413aSTim Haley xtreme_rewind = B_TRUE;
2937468c413aSTim Haley break;
293886714001SSerapheim Dimitropoulos case CHECKPOINT_OPT:
293986714001SSerapheim Dimitropoulos flags |= ZFS_IMPORT_CHECKPOINT;
294086714001SSerapheim Dimitropoulos break;
2941fa9e4066Sahrens case ':':
2942fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for "
2943fa9e4066Sahrens "'%c' option\n"), optopt);
294499653d4eSeschrock usage(B_FALSE);
2945fa9e4066Sahrens break;
2946fa9e4066Sahrens case '?':
2947fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2948fa9e4066Sahrens optopt);
294999653d4eSeschrock usage(B_FALSE);
2950fa9e4066Sahrens }
2951fa9e4066Sahrens }
2952fa9e4066Sahrens
2953fa9e4066Sahrens argc -= optind;
2954fa9e4066Sahrens argv += optind;
2955fa9e4066Sahrens
29562f8aaab3Seschrock if (cachefile && nsearch != 0) {
29572f8aaab3Seschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
29582f8aaab3Seschrock usage(B_FALSE);
29592f8aaab3Seschrock }
29602f8aaab3Seschrock
2961eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
2962eb633035STom Caputi (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
2963eb633035STom Caputi usage(B_FALSE);
2964eb633035STom Caputi }
2965eb633035STom Caputi
2966eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
2967eb633035STom Caputi (void) fprintf(stderr, gettext("-l is only meaningful during "
2968eb633035STom Caputi "an import\n"));
2969eb633035STom Caputi usage(B_FALSE);
2970eb633035STom Caputi }
2971eb633035STom Caputi
2972468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) {
2973468c413aSTim Haley (void) fprintf(stderr,
2974468c413aSTim Haley gettext("-n or -X only meaningful with -F\n"));
2975468c413aSTim Haley usage(B_FALSE);
2976468c413aSTim Haley }
2977468c413aSTim Haley if (dryrun)
2978468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND;
2979468c413aSTim Haley else if (do_rewind)
2980468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND;
2981468c413aSTim Haley if (xtreme_rewind)
2982468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND;
2983468c413aSTim Haley
2984468c413aSTim Haley /* In the future, we can capture further policy and include it here */
2985468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
29865dafeea3SPavel Zakharov nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
29875dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
29885dafeea3SPavel Zakharov rewind_policy) != 0)
2989468c413aSTim Haley goto error;
2990468c413aSTim Haley
2991fa9e4066Sahrens if (searchdirs == NULL) {
2992fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *));
29936401734dSWill Andrews searchdirs[0] = ZFS_DISK_ROOT;
2994fa9e4066Sahrens nsearch = 1;
2995fa9e4066Sahrens }
2996fa9e4066Sahrens
2997fa9e4066Sahrens /* check argument count */
2998fa9e4066Sahrens if (do_all) {
2999fa9e4066Sahrens if (argc != 0) {
3000fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n"));
300199653d4eSeschrock usage(B_FALSE);
3002fa9e4066Sahrens }
3003fa9e4066Sahrens } else {
3004fa9e4066Sahrens if (argc > 2) {
3005fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n"));
300699653d4eSeschrock usage(B_FALSE);
3007fa9e4066Sahrens }
3008fa9e4066Sahrens
3009fa9e4066Sahrens /*
3010fa9e4066Sahrens * Check for the SYS_CONFIG privilege. We do this explicitly
3011fa9e4066Sahrens * here because otherwise any attempt to discover pools will
3012fa9e4066Sahrens * silently fail.
3013fa9e4066Sahrens */
3014fa9e4066Sahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
3015fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot "
3016fa9e4066Sahrens "discover pools: permission denied\n"));
301799653d4eSeschrock free(searchdirs);
3018468c413aSTim Haley nvlist_free(policy);
3019fa9e4066Sahrens return (1);
3020fa9e4066Sahrens }
3021fa9e4066Sahrens }
3022fa9e4066Sahrens
3023fa9e4066Sahrens /*
3024fa9e4066Sahrens * Depending on the arguments given, we do one of the following:
3025fa9e4066Sahrens *
3026fa9e4066Sahrens * <none> Iterate through all pools and display information about
3027fa9e4066Sahrens * each one.
3028fa9e4066Sahrens *
3029fa9e4066Sahrens * -a Iterate through all pools and try to import each one.
3030fa9e4066Sahrens *
3031fa9e4066Sahrens * <id> Find the pool that corresponds to the given GUID/pool
3032fa9e4066Sahrens * name and import that one.
30334c58d714Sdarrenm *
30344c58d714Sdarrenm * -D Above options applies only to destroyed pools.
3035fa9e4066Sahrens */
3036fa9e4066Sahrens if (argc != 0) {
3037fa9e4066Sahrens char *endptr;
3038fa9e4066Sahrens
3039fa9e4066Sahrens errno = 0;
3040fa9e4066Sahrens searchguid = strtoull(argv[0], &endptr, 10);
30419edf9ebdSPrasad Joshi if (errno != 0 || *endptr != '\0') {
3042fa9e4066Sahrens searchname = argv[0];
30439edf9ebdSPrasad Joshi searchguid = 0;
30449edf9ebdSPrasad Joshi }
3045fa9e4066Sahrens found_config = NULL;
3046fa9e4066Sahrens
304724e697d4Sck153898 /*
3048d41c4376SMark J Musante * User specified a name or guid. Ensure it's unique.
304924e697d4Sck153898 */
3050d8ab6e12SDon Brady target_exists_args_t search = {searchname, searchguid};
3051d8ab6e12SDon Brady pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search);
305224e697d4Sck153898 }
305324e697d4Sck153898
3054d41c4376SMark J Musante idata.path = searchdirs;
3055d41c4376SMark J Musante idata.paths = nsearch;
3056d41c4376SMark J Musante idata.poolname = searchname;
3057d41c4376SMark J Musante idata.guid = searchguid;
3058d41c4376SMark J Musante idata.cachefile = cachefile;
30596f793812SPavel Zakharov idata.policy = policy;
3060d41c4376SMark J Musante
3061d8ab6e12SDon Brady pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
3062d41c4376SMark J Musante
3063d8ab6e12SDon Brady if (pools != NULL && pool_exists &&
3064d41c4376SMark J Musante (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
3065d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': "
3066d41c4376SMark J Musante "a pool with that name already exists\n"),
3067d41c4376SMark J Musante argv[0]);
306804e56356SAndriy Gapon (void) fprintf(stderr, gettext("use the form 'zpool import "
306904e56356SAndriy Gapon "[-t] <pool | id> <newpool>' to give it a new temporary "
307004e56356SAndriy Gapon "or permanent name\n"));
3071d41c4376SMark J Musante err = 1;
3072d8ab6e12SDon Brady } else if (pools == NULL && pool_exists) {
3073d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': "
3074d41c4376SMark J Musante "a pool with that name is already created/imported,\n"),
3075d41c4376SMark J Musante argv[0]);
3076d41c4376SMark J Musante (void) fprintf(stderr, gettext("and no additional pools "
3077d41c4376SMark J Musante "with that name were found\n"));
3078d41c4376SMark J Musante err = 1;
3079d41c4376SMark J Musante } else if (pools == NULL) {
308024e697d4Sck153898 if (argc != 0) {
308124e697d4Sck153898 (void) fprintf(stderr, gettext("cannot import '%s': "
308224e697d4Sck153898 "no such pool available\n"), argv[0]);
308324e697d4Sck153898 }
3084d41c4376SMark J Musante err = 1;
3085d41c4376SMark J Musante }
3086d41c4376SMark J Musante
3087d41c4376SMark J Musante if (err == 1) {
308824e697d4Sck153898 free(searchdirs);
3089468c413aSTim Haley nvlist_free(policy);
309024e697d4Sck153898 return (1);
309124e697d4Sck153898 }
309224e697d4Sck153898
309324e697d4Sck153898 /*
309424e697d4Sck153898 * At this point we have a list of import candidate configs. Even if
309524e697d4Sck153898 * we were searching by pool name or guid, we still need to
309624e697d4Sck153898 * post-process the list to deal with pool state and possible
309724e697d4Sck153898 * duplicate names.
309824e697d4Sck153898 */
3099fa9e4066Sahrens err = 0;
3100fa9e4066Sahrens elem = NULL;
310199653d4eSeschrock first = B_TRUE;
3102fa9e4066Sahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
3103fa9e4066Sahrens
3104fa9e4066Sahrens verify(nvpair_value_nvlist(elem, &config) == 0);
3105fa9e4066Sahrens
31064c58d714Sdarrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
31074c58d714Sdarrenm &pool_state) == 0);
31084c58d714Sdarrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
31094c58d714Sdarrenm continue;
31104c58d714Sdarrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
31114c58d714Sdarrenm continue;
31124c58d714Sdarrenm
31135dafeea3SPavel Zakharov verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
3114468c413aSTim Haley policy) == 0);
3115468c413aSTim Haley
3116fa9e4066Sahrens if (argc == 0) {
3117fa9e4066Sahrens if (first)
311899653d4eSeschrock first = B_FALSE;
31193bb79becSeschrock else if (!do_all)
3120fa9e4066Sahrens (void) printf("\n");
3121fa9e4066Sahrens
3122468c413aSTim Haley if (do_all) {
3123fa9e4066Sahrens err |= do_import(config, NULL, mntopts,
31244b964adaSGeorge Wilson props, flags);
3125468c413aSTim Haley } else {
3126fa9e4066Sahrens show_import(config);
3127468c413aSTim Haley }
3128fa9e4066Sahrens } else if (searchname != NULL) {
3129fa9e4066Sahrens char *name;
3130fa9e4066Sahrens
3131fa9e4066Sahrens /*
3132fa9e4066Sahrens * We are searching for a pool based on name.
3133fa9e4066Sahrens */
3134fa9e4066Sahrens verify(nvlist_lookup_string(config,
3135fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0);
3136fa9e4066Sahrens
3137fa9e4066Sahrens if (strcmp(name, searchname) == 0) {
3138fa9e4066Sahrens if (found_config != NULL) {
3139fa9e4066Sahrens (void) fprintf(stderr, gettext(
3140fa9e4066Sahrens "cannot import '%s': more than "
3141fa9e4066Sahrens "one matching pool\n"), searchname);
3142fa9e4066Sahrens (void) fprintf(stderr, gettext(
3143fa9e4066Sahrens "import by numeric ID instead\n"));
314499653d4eSeschrock err = B_TRUE;
3145fa9e4066Sahrens }
3146fa9e4066Sahrens found_config = config;
3147fa9e4066Sahrens }
3148fa9e4066Sahrens } else {
3149fa9e4066Sahrens uint64_t guid;
3150fa9e4066Sahrens
3151fa9e4066Sahrens /*
3152fa9e4066Sahrens * Search for a pool by guid.
3153fa9e4066Sahrens */
3154fa9e4066Sahrens verify(nvlist_lookup_uint64(config,
3155fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
3156fa9e4066Sahrens
3157fa9e4066Sahrens if (guid == searchguid)
3158fa9e4066Sahrens found_config = config;
3159fa9e4066Sahrens }
3160fa9e4066Sahrens }
3161fa9e4066Sahrens
3162fa9e4066Sahrens /*
3163fa9e4066Sahrens * If we were searching for a specific pool, verify that we found a
3164fa9e4066Sahrens * pool, and then do the import.
3165fa9e4066Sahrens */
3166fa9e4066Sahrens if (argc != 0 && err == 0) {
3167fa9e4066Sahrens if (found_config == NULL) {
3168fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot import '%s': "
3169fa9e4066Sahrens "no such pool available\n"), argv[0]);
317099653d4eSeschrock err = B_TRUE;
3171fa9e4066Sahrens } else {
3172fa9e4066Sahrens err |= do_import(found_config, argc == 1 ? NULL :
31734b964adaSGeorge Wilson argv[1], mntopts, props, flags);
3174fa9e4066Sahrens }
3175fa9e4066Sahrens }
3176fa9e4066Sahrens
3177fa9e4066Sahrens /*
3178fa9e4066Sahrens * If we were just looking for pools, report an error if none were
3179fa9e4066Sahrens * found.
3180fa9e4066Sahrens */
3181fa9e4066Sahrens if (argc == 0 && first)
3182fa9e4066Sahrens (void) fprintf(stderr,
3183fa9e4066Sahrens gettext("no pools available to import\n"));
3184fa9e4066Sahrens
3185ecd6cf80Smarks error:
3186ecd6cf80Smarks nvlist_free(props);
3187fa9e4066Sahrens nvlist_free(pools);
3188468c413aSTim Haley nvlist_free(policy);
318999653d4eSeschrock free(searchdirs);
3190fa9e4066Sahrens
3191fa9e4066Sahrens return (err ? 1 : 0);
3192fa9e4066Sahrens }
3193fa9e4066Sahrens
31949c2acf00SAlek Pinchuk /*
31959c2acf00SAlek Pinchuk * zpool sync [-f] [pool] ...
31969c2acf00SAlek Pinchuk *
31979c2acf00SAlek Pinchuk * -f (undocumented) force uberblock (and config including zpool cache file)
31989c2acf00SAlek Pinchuk * update.
31999c2acf00SAlek Pinchuk *
32009c2acf00SAlek Pinchuk * Sync the specified pool(s).
32019c2acf00SAlek Pinchuk * Without arguments "zpool sync" will sync all pools.
32029c2acf00SAlek Pinchuk * This command initiates TXG sync(s) and will return after the TXG(s) commit.
32039c2acf00SAlek Pinchuk *
32049c2acf00SAlek Pinchuk */
32059c2acf00SAlek Pinchuk static int
zpool_do_sync(int argc,char ** argv)32069c2acf00SAlek Pinchuk zpool_do_sync(int argc, char **argv)
32079c2acf00SAlek Pinchuk {
32089c2acf00SAlek Pinchuk int ret;
32099c2acf00SAlek Pinchuk boolean_t force = B_FALSE;
32109c2acf00SAlek Pinchuk
32119c2acf00SAlek Pinchuk /* check options */
32129c2acf00SAlek Pinchuk while ((ret = getopt(argc, argv, "f")) != -1) {
32139c2acf00SAlek Pinchuk switch (ret) {
32149c2acf00SAlek Pinchuk case 'f':
32159c2acf00SAlek Pinchuk force = B_TRUE;
32169c2acf00SAlek Pinchuk break;
32179c2acf00SAlek Pinchuk case '?':
32189c2acf00SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option '%c'\n"),
32199c2acf00SAlek Pinchuk optopt);
32209c2acf00SAlek Pinchuk usage(B_FALSE);
32219c2acf00SAlek Pinchuk }
32229c2acf00SAlek Pinchuk }
32239c2acf00SAlek Pinchuk
32249c2acf00SAlek Pinchuk argc -= optind;
32259c2acf00SAlek Pinchuk argv += optind;
32269c2acf00SAlek Pinchuk
32279c2acf00SAlek Pinchuk /* if argc == 0 we will execute zpool_sync_one on all pools */
32289c2acf00SAlek Pinchuk ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);
32299c2acf00SAlek Pinchuk
32309c2acf00SAlek Pinchuk return (ret);
32319c2acf00SAlek Pinchuk }
32329c2acf00SAlek Pinchuk
3233fa9e4066Sahrens typedef struct iostat_cbdata {
3234dd50e0ccSTony Hutter uint64_t cb_flags;
3235663207adSDon Brady int cb_name_flags;
3236fa9e4066Sahrens int cb_namewidth;
32374263d13fSGeorge Wilson int cb_iteration;
3238dd50e0ccSTony Hutter char **cb_vdev_names; /* Only show these vdevs */
3239dd50e0ccSTony Hutter unsigned int cb_vdev_names_count;
3240dd50e0ccSTony Hutter boolean_t cb_verbose;
3241dd50e0ccSTony Hutter boolean_t cb_literal;
3242663207adSDon Brady boolean_t cb_scripted;
32434263d13fSGeorge Wilson zpool_list_t *cb_list;
3244fa9e4066Sahrens } iostat_cbdata_t;
3245fa9e4066Sahrens
3246dd50e0ccSTony Hutter /* iostat labels */
3247dd50e0ccSTony Hutter typedef struct name_and_columns {
3248dd50e0ccSTony Hutter const char *name; /* Column name */
3249dd50e0ccSTony Hutter unsigned int columns; /* Center name to this number of columns */
3250dd50e0ccSTony Hutter } name_and_columns_t;
3251dd50e0ccSTony Hutter
3252dd50e0ccSTony Hutter #define IOSTAT_MAX_LABELS 13 /* Max number of labels on one line */
3253dd50e0ccSTony Hutter
3254dd50e0ccSTony Hutter static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
3255dd50e0ccSTony Hutter {
3256dd50e0ccSTony Hutter [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2},
3257dd50e0ccSTony Hutter {NULL}},
3258dd50e0ccSTony Hutter [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3259dd50e0ccSTony Hutter {"asyncq_wait", 2}, {"scrub"}, {"trim", 1}, {NULL}},
3260dd50e0ccSTony Hutter [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
3261dd50e0ccSTony Hutter {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
3262dd50e0ccSTony Hutter {"trimq_write", 2}, {NULL}},
3263dd50e0ccSTony Hutter [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3264dd50e0ccSTony Hutter {"asyncq_wait", 2}, {NULL}},
3265dd50e0ccSTony Hutter [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
3266dd50e0ccSTony Hutter {"async_read", 2}, {"async_write", 2}, {"scrub", 2},
3267dd50e0ccSTony Hutter {"trim", 2}, {NULL}},
3268dd50e0ccSTony Hutter
3269dd50e0ccSTony Hutter };
3270dd50e0ccSTony Hutter
3271dd50e0ccSTony Hutter /* Shorthand - if "columns" field not set, default to 1 column */
3272dd50e0ccSTony Hutter static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
3273dd50e0ccSTony Hutter {
3274dd50e0ccSTony Hutter [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"},
3275dd50e0ccSTony Hutter {"write"}, {NULL}},
3276dd50e0ccSTony Hutter [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3277dd50e0ccSTony Hutter {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {NULL}},
3278dd50e0ccSTony Hutter [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
3279dd50e0ccSTony Hutter {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"},
3280dd50e0ccSTony Hutter {"pend"}, {"activ"}, {NULL}},
3281dd50e0ccSTony Hutter [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3282dd50e0ccSTony Hutter {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {NULL}},
3283dd50e0ccSTony Hutter [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
3284dd50e0ccSTony Hutter {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, {NULL}},
3285dd50e0ccSTony Hutter };
3286dd50e0ccSTony Hutter
3287dd50e0ccSTony Hutter static const char *histo_to_title[] = {
3288dd50e0ccSTony Hutter [IOS_L_HISTO] = "latency",
3289dd50e0ccSTony Hutter [IOS_RQ_HISTO] = "req_size",
3290dd50e0ccSTony Hutter };
3291dd50e0ccSTony Hutter
3292dd50e0ccSTony Hutter /*
3293dd50e0ccSTony Hutter * Return the number of labels in a null-terminated name_and_columns_t
3294dd50e0ccSTony Hutter * array.
3295dd50e0ccSTony Hutter *
3296dd50e0ccSTony Hutter */
3297dd50e0ccSTony Hutter static unsigned int
label_array_len(const name_and_columns_t * labels)3298dd50e0ccSTony Hutter label_array_len(const name_and_columns_t *labels)
3299fa9e4066Sahrens {
3300fa9e4066Sahrens int i = 0;
3301fa9e4066Sahrens
3302dd50e0ccSTony Hutter while (labels[i].name)
3303dd50e0ccSTony Hutter i++;
3304dd50e0ccSTony Hutter
3305dd50e0ccSTony Hutter return (i);
3306dd50e0ccSTony Hutter }
3307dd50e0ccSTony Hutter
3308dd50e0ccSTony Hutter /*
3309dd50e0ccSTony Hutter * Return the number of strings in a null-terminated string array.
3310dd50e0ccSTony Hutter * For example:
3311dd50e0ccSTony Hutter *
3312dd50e0ccSTony Hutter * const char foo[] = {"bar", "baz", NULL}
3313dd50e0ccSTony Hutter *
3314dd50e0ccSTony Hutter * returns 2
3315dd50e0ccSTony Hutter */
3316dd50e0ccSTony Hutter static uint64_t
str_array_len(const char * array[])3317dd50e0ccSTony Hutter str_array_len(const char *array[])
3318dd50e0ccSTony Hutter {
3319dd50e0ccSTony Hutter uint64_t i = 0;
3320dd50e0ccSTony Hutter while (array[i])
3321dd50e0ccSTony Hutter i++;
3322dd50e0ccSTony Hutter
3323dd50e0ccSTony Hutter return (i);
3324dd50e0ccSTony Hutter }
3325dd50e0ccSTony Hutter
3326dd50e0ccSTony Hutter
3327dd50e0ccSTony Hutter /*
3328dd50e0ccSTony Hutter * Return a default column width for default/latency/queue columns. This does
3329dd50e0ccSTony Hutter * not include histograms, which have their columns autosized.
3330dd50e0ccSTony Hutter */
3331dd50e0ccSTony Hutter static unsigned int
default_column_width(iostat_cbdata_t * cb,enum iostat_type type)3332dd50e0ccSTony Hutter default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
3333dd50e0ccSTony Hutter {
3334dd50e0ccSTony Hutter unsigned long column_width = 5; /* Normal niceprint */
3335dd50e0ccSTony Hutter static unsigned long widths[] = {
3336dd50e0ccSTony Hutter /*
3337dd50e0ccSTony Hutter * Choose some sane default column sizes for printing the
3338dd50e0ccSTony Hutter * raw numbers.
3339dd50e0ccSTony Hutter */
3340dd50e0ccSTony Hutter [IOS_DEFAULT] = 15, /* 1PB capacity */
3341dd50e0ccSTony Hutter [IOS_LATENCY] = 10, /* 1B ns = 10sec */
3342dd50e0ccSTony Hutter [IOS_QUEUES] = 6, /* 1M queue entries */
3343dd50e0ccSTony Hutter [IOS_L_HISTO] = 10, /* 1B ns = 10sec */
3344dd50e0ccSTony Hutter [IOS_RQ_HISTO] = 6, /* 1M queue entries */
3345dd50e0ccSTony Hutter };
3346dd50e0ccSTony Hutter
3347dd50e0ccSTony Hutter if (cb->cb_literal)
3348dd50e0ccSTony Hutter column_width = widths[type];
3349dd50e0ccSTony Hutter
3350dd50e0ccSTony Hutter return (column_width);
3351dd50e0ccSTony Hutter }
3352dd50e0ccSTony Hutter
3353dd50e0ccSTony Hutter /*
3354dd50e0ccSTony Hutter * Print the column labels, i.e:
3355dd50e0ccSTony Hutter *
3356dd50e0ccSTony Hutter * capacity operations bandwidth
3357dd50e0ccSTony Hutter * alloc free read write read write ...
3358dd50e0ccSTony Hutter *
3359dd50e0ccSTony Hutter * If force_column_width is set, use it for the column width. If not set, use
3360dd50e0ccSTony Hutter * the default column width.
3361dd50e0ccSTony Hutter */
3362dd50e0ccSTony Hutter void
print_iostat_labels(iostat_cbdata_t * cb,unsigned int force_column_width,const name_and_columns_t labels[][IOSTAT_MAX_LABELS])3363dd50e0ccSTony Hutter print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width,
3364dd50e0ccSTony Hutter const name_and_columns_t labels[][IOSTAT_MAX_LABELS])
3365dd50e0ccSTony Hutter {
3366dd50e0ccSTony Hutter int i, idx, s;
3367dd50e0ccSTony Hutter int text_start, rw_column_width, spaces_to_end;
3368dd50e0ccSTony Hutter uint64_t flags = cb->cb_flags;
3369dd50e0ccSTony Hutter uint64_t f;
3370dd50e0ccSTony Hutter unsigned int column_width = force_column_width;
3371dd50e0ccSTony Hutter
3372dd50e0ccSTony Hutter /* For each bit set in flags */
3373dd50e0ccSTony Hutter for (f = flags; f; f &= ~(1ULL << idx)) {
3374dd50e0ccSTony Hutter idx = lowbit64(f) - 1;
3375dd50e0ccSTony Hutter if (!force_column_width)
3376dd50e0ccSTony Hutter column_width = default_column_width(cb, idx);
3377dd50e0ccSTony Hutter /* Print our top labels centered over "read write" label. */
3378dd50e0ccSTony Hutter for (i = 0; i < label_array_len(labels[idx]); i++) {
3379dd50e0ccSTony Hutter const char *name = labels[idx][i].name;
3380dd50e0ccSTony Hutter /*
3381dd50e0ccSTony Hutter * We treat labels[][].columns == 0 as shorthand
3382dd50e0ccSTony Hutter * for one column. It makes writing out the label
3383dd50e0ccSTony Hutter * tables more concise.
3384dd50e0ccSTony Hutter */
3385dd50e0ccSTony Hutter unsigned int columns = MAX(1, labels[idx][i].columns);
3386dd50e0ccSTony Hutter unsigned int slen = strlen(name);
3387dd50e0ccSTony Hutter
3388dd50e0ccSTony Hutter rw_column_width = (column_width * columns) +
3389dd50e0ccSTony Hutter (2 * (columns - 1));
3390dd50e0ccSTony Hutter
3391dd50e0ccSTony Hutter text_start = (int)((rw_column_width) / columns -
3392dd50e0ccSTony Hutter slen / columns);
3393dd50e0ccSTony Hutter if (text_start < 0)
3394dd50e0ccSTony Hutter text_start = 0;
3395dd50e0ccSTony Hutter
3396dd50e0ccSTony Hutter printf(" "); /* Two spaces between columns */
3397dd50e0ccSTony Hutter
3398dd50e0ccSTony Hutter /* Space from beginning of column to label */
3399dd50e0ccSTony Hutter for (s = 0; s < text_start; s++)
3400dd50e0ccSTony Hutter printf(" ");
3401dd50e0ccSTony Hutter
3402dd50e0ccSTony Hutter printf("%s", name);
3403dd50e0ccSTony Hutter
3404dd50e0ccSTony Hutter /* Print space after label to end of column */
3405dd50e0ccSTony Hutter spaces_to_end = rw_column_width - text_start - slen;
3406dd50e0ccSTony Hutter if (spaces_to_end < 0)
3407dd50e0ccSTony Hutter spaces_to_end = 0;
3408dd50e0ccSTony Hutter
3409dd50e0ccSTony Hutter for (s = 0; s < spaces_to_end; s++)
3410dd50e0ccSTony Hutter printf(" ");
3411dd50e0ccSTony Hutter }
3412dd50e0ccSTony Hutter }
3413dd50e0ccSTony Hutter }
3414dd50e0ccSTony Hutter
3415dd50e0ccSTony Hutter /*
3416dd50e0ccSTony Hutter * Utility function to print out a line of dashes like:
3417dd50e0ccSTony Hutter *
3418dd50e0ccSTony Hutter * -------------------------------- ----- ----- ----- ----- -----
3419dd50e0ccSTony Hutter *
3420dd50e0ccSTony Hutter * ...or a dashed named-row line like:
3421dd50e0ccSTony Hutter *
3422dd50e0ccSTony Hutter * logs - - - - -
3423dd50e0ccSTony Hutter *
3424dd50e0ccSTony Hutter * @cb: iostat data
3425dd50e0ccSTony Hutter *
3426dd50e0ccSTony Hutter * @force_column_width If non-zero, use the value as the column width.
3427dd50e0ccSTony Hutter * Otherwise use the default column widths.
3428dd50e0ccSTony Hutter *
3429dd50e0ccSTony Hutter * @name: Print a dashed named-row line starting
3430dd50e0ccSTony Hutter * with @name. Otherwise, print a regular
3431dd50e0ccSTony Hutter * dashed line.
3432dd50e0ccSTony Hutter */
3433dd50e0ccSTony Hutter static void
print_iostat_dashes(iostat_cbdata_t * cb,unsigned int force_column_width,const char * name)3434dd50e0ccSTony Hutter print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width,
3435dd50e0ccSTony Hutter const char *name)
3436dd50e0ccSTony Hutter {
3437dd50e0ccSTony Hutter int i;
3438dd50e0ccSTony Hutter unsigned int namewidth;
3439dd50e0ccSTony Hutter uint64_t flags = cb->cb_flags;
3440dd50e0ccSTony Hutter uint64_t f;
3441dd50e0ccSTony Hutter int idx;
3442dd50e0ccSTony Hutter const name_and_columns_t *labels;
3443dd50e0ccSTony Hutter const char *title;
3444dd50e0ccSTony Hutter
3445dd50e0ccSTony Hutter
3446dd50e0ccSTony Hutter if (cb->cb_flags & IOS_ANYHISTO_M) {
3447dd50e0ccSTony Hutter title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3448dd50e0ccSTony Hutter } else if (cb->cb_vdev_names_count) {
3449dd50e0ccSTony Hutter title = "vdev";
3450dd50e0ccSTony Hutter } else {
3451dd50e0ccSTony Hutter title = "pool";
3452dd50e0ccSTony Hutter }
3453dd50e0ccSTony Hutter
3454dd50e0ccSTony Hutter namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3455dd50e0ccSTony Hutter name ? strlen(name) : 0);
3456dd50e0ccSTony Hutter
3457dd50e0ccSTony Hutter
3458dd50e0ccSTony Hutter if (name) {
3459dd50e0ccSTony Hutter printf("%-*s", namewidth, name);
3460dd50e0ccSTony Hutter } else {
3461dd50e0ccSTony Hutter for (i = 0; i < namewidth; i++)
3462fa9e4066Sahrens (void) printf("-");
3463dd50e0ccSTony Hutter }
3464dd50e0ccSTony Hutter
3465dd50e0ccSTony Hutter /* For each bit in flags */
3466dd50e0ccSTony Hutter for (f = flags; f; f &= ~(1ULL << idx)) {
3467dd50e0ccSTony Hutter unsigned int column_width;
3468dd50e0ccSTony Hutter idx = lowbit64(f) - 1;
3469dd50e0ccSTony Hutter if (force_column_width)
3470dd50e0ccSTony Hutter column_width = force_column_width;
3471dd50e0ccSTony Hutter else
3472dd50e0ccSTony Hutter column_width = default_column_width(cb, idx);
3473dd50e0ccSTony Hutter
3474dd50e0ccSTony Hutter labels = iostat_bottom_labels[idx];
3475dd50e0ccSTony Hutter for (i = 0; i < label_array_len(labels); i++) {
3476dd50e0ccSTony Hutter if (name)
3477dd50e0ccSTony Hutter printf(" %*s-", column_width - 1, " ");
3478dd50e0ccSTony Hutter else
3479dd50e0ccSTony Hutter printf(" %.*s", column_width,
3480dd50e0ccSTony Hutter "--------------------");
3481dd50e0ccSTony Hutter }
3482dd50e0ccSTony Hutter }
3483dd50e0ccSTony Hutter }
3484dd50e0ccSTony Hutter
3485dd50e0ccSTony Hutter
3486dd50e0ccSTony Hutter static void
print_iostat_separator_impl(iostat_cbdata_t * cb,unsigned int force_column_width)3487dd50e0ccSTony Hutter print_iostat_separator_impl(iostat_cbdata_t *cb,
3488dd50e0ccSTony Hutter unsigned int force_column_width)
3489dd50e0ccSTony Hutter {
3490dd50e0ccSTony Hutter print_iostat_dashes(cb, force_column_width, NULL);
3491dd50e0ccSTony Hutter }
3492dd50e0ccSTony Hutter
3493dd50e0ccSTony Hutter static void
print_iostat_separator(iostat_cbdata_t * cb)3494dd50e0ccSTony Hutter print_iostat_separator(iostat_cbdata_t *cb)
3495dd50e0ccSTony Hutter {
3496dd50e0ccSTony Hutter print_iostat_separator_impl(cb, 0);
3497dd50e0ccSTony Hutter }
3498dd50e0ccSTony Hutter
3499dd50e0ccSTony Hutter static void
print_iostat_header_impl(iostat_cbdata_t * cb,unsigned int force_column_width,const char * histo_vdev_name)3500dd50e0ccSTony Hutter print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
3501dd50e0ccSTony Hutter const char *histo_vdev_name)
3502dd50e0ccSTony Hutter {
3503dd50e0ccSTony Hutter unsigned int namewidth;
3504dd50e0ccSTony Hutter const char *title;
3505dd50e0ccSTony Hutter
3506dd50e0ccSTony Hutter if (cb->cb_flags & IOS_ANYHISTO_M) {
3507dd50e0ccSTony Hutter title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3508dd50e0ccSTony Hutter } else if (cb->cb_vdev_names_count) {
3509dd50e0ccSTony Hutter title = "vdev";
3510dd50e0ccSTony Hutter } else {
3511dd50e0ccSTony Hutter title = "pool";
3512dd50e0ccSTony Hutter }
3513dd50e0ccSTony Hutter
3514dd50e0ccSTony Hutter namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3515dd50e0ccSTony Hutter histo_vdev_name ? strlen(histo_vdev_name) : 0);
3516dd50e0ccSTony Hutter
3517dd50e0ccSTony Hutter if (histo_vdev_name)
3518dd50e0ccSTony Hutter printf("%-*s", namewidth, histo_vdev_name);
3519dd50e0ccSTony Hutter else
3520dd50e0ccSTony Hutter printf("%*s", namewidth, "");
3521dd50e0ccSTony Hutter
3522dd50e0ccSTony Hutter
3523dd50e0ccSTony Hutter print_iostat_labels(cb, force_column_width, iostat_top_labels);
3524dd50e0ccSTony Hutter printf("\n");
3525dd50e0ccSTony Hutter
3526dd50e0ccSTony Hutter printf("%-*s", namewidth, title);
3527dd50e0ccSTony Hutter
3528dd50e0ccSTony Hutter print_iostat_labels(cb, force_column_width, iostat_bottom_labels);
3529dd50e0ccSTony Hutter
3530dd50e0ccSTony Hutter printf("\n");
3531dd50e0ccSTony Hutter
3532dd50e0ccSTony Hutter print_iostat_separator_impl(cb, force_column_width);
3533dd50e0ccSTony Hutter
3534dd50e0ccSTony Hutter printf("\n");
3535fa9e4066Sahrens }
3536fa9e4066Sahrens
3537fa9e4066Sahrens static void
print_iostat_header(iostat_cbdata_t * cb)3538fa9e4066Sahrens print_iostat_header(iostat_cbdata_t *cb)
3539fa9e4066Sahrens {
3540dd50e0ccSTony Hutter print_iostat_header_impl(cb, 0, NULL);
3541fa9e4066Sahrens }
3542fa9e4066Sahrens
3543fa9e4066Sahrens /*
3544fa9e4066Sahrens * Display a single statistic.
3545fa9e4066Sahrens */
3546990b4856Slling static void
print_one_stat(uint64_t value,enum zfs_nicenum_format format,unsigned int column_size,boolean_t scripted)3547dd50e0ccSTony Hutter print_one_stat(uint64_t value, enum zfs_nicenum_format format,
3548dd50e0ccSTony Hutter unsigned int column_size, boolean_t scripted)
3549fa9e4066Sahrens {
3550fa9e4066Sahrens char buf[64];
3551fa9e4066Sahrens
3552dd50e0ccSTony Hutter zfs_nicenum_format(value, buf, sizeof (buf), format);
3553dd50e0ccSTony Hutter
3554dd50e0ccSTony Hutter if (scripted)
3555dd50e0ccSTony Hutter printf("\t%s", buf);
3556dd50e0ccSTony Hutter else
3557dd50e0ccSTony Hutter printf(" %*s", column_size, buf);
3558dd50e0ccSTony Hutter }
3559dd50e0ccSTony Hutter
3560dd50e0ccSTony Hutter /*
3561dd50e0ccSTony Hutter * Calculate the default vdev stats
3562dd50e0ccSTony Hutter *
3563dd50e0ccSTony Hutter * Subtract oldvs from newvs, apply a scaling factor, and save the resulting
3564dd50e0ccSTony Hutter * stats into calcvs.
3565dd50e0ccSTony Hutter */
3566dd50e0ccSTony Hutter static void
calc_default_iostats(vdev_stat_t * oldvs,vdev_stat_t * newvs,vdev_stat_t * calcvs)3567dd50e0ccSTony Hutter calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs,
3568dd50e0ccSTony Hutter vdev_stat_t *calcvs)
3569dd50e0ccSTony Hutter {
3570dd50e0ccSTony Hutter int i;
3571dd50e0ccSTony Hutter
3572dd50e0ccSTony Hutter memcpy(calcvs, newvs, sizeof (*calcvs));
3573dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++)
3574dd50e0ccSTony Hutter calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]);
3575dd50e0ccSTony Hutter
3576dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++)
3577dd50e0ccSTony Hutter calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]);
3578dd50e0ccSTony Hutter }
3579dd50e0ccSTony Hutter
3580dd50e0ccSTony Hutter /*
3581dd50e0ccSTony Hutter * Internal representation of the extended iostats data.
3582dd50e0ccSTony Hutter *
3583dd50e0ccSTony Hutter * The extended iostat stats are exported in nvlists as either uint64_t arrays
3584dd50e0ccSTony Hutter * or single uint64_t's. We make both look like arrays to make them easier
3585dd50e0ccSTony Hutter * to process. In order to make single uint64_t's look like arrays, we set
3586dd50e0ccSTony Hutter * __data to the stat data, and then set *data = &__data with count = 1. Then,
3587dd50e0ccSTony Hutter * we can just use *data and count.
3588dd50e0ccSTony Hutter */
3589dd50e0ccSTony Hutter struct stat_array {
3590dd50e0ccSTony Hutter uint64_t *data;
3591dd50e0ccSTony Hutter uint_t count; /* Number of entries in data[] */
3592dd50e0ccSTony Hutter uint64_t __data; /* Only used when data is a single uint64_t */
3593dd50e0ccSTony Hutter };
3594dd50e0ccSTony Hutter
3595dd50e0ccSTony Hutter static uint64_t
stat_histo_max(struct stat_array * nva,unsigned int len)3596dd50e0ccSTony Hutter stat_histo_max(struct stat_array *nva, unsigned int len)
3597dd50e0ccSTony Hutter {
3598dd50e0ccSTony Hutter uint64_t max = 0;
3599dd50e0ccSTony Hutter int i;
3600dd50e0ccSTony Hutter for (i = 0; i < len; i++)
3601dd50e0ccSTony Hutter max = MAX(max, array64_max(nva[i].data, nva[i].count));
3602dd50e0ccSTony Hutter
3603dd50e0ccSTony Hutter return (max);
3604dd50e0ccSTony Hutter }
3605dd50e0ccSTony Hutter
3606dd50e0ccSTony Hutter /*
3607dd50e0ccSTony Hutter * Helper function to lookup a uint64_t array or uint64_t value and store its
3608dd50e0ccSTony Hutter * data as a stat_array. If the nvpair is a single uint64_t value, then we make
3609dd50e0ccSTony Hutter * it look like a one element array to make it easier to process.
3610dd50e0ccSTony Hutter */
3611dd50e0ccSTony Hutter static int
nvpair64_to_stat_array(nvlist_t * nvl,const char * name,struct stat_array * nva)3612dd50e0ccSTony Hutter nvpair64_to_stat_array(nvlist_t *nvl, const char *name,
3613dd50e0ccSTony Hutter struct stat_array *nva)
3614dd50e0ccSTony Hutter {
3615dd50e0ccSTony Hutter nvpair_t *tmp;
3616dd50e0ccSTony Hutter int ret;
3617dd50e0ccSTony Hutter
3618dd50e0ccSTony Hutter verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0);
3619dd50e0ccSTony Hutter switch (nvpair_type(tmp)) {
3620dd50e0ccSTony Hutter case DATA_TYPE_UINT64_ARRAY:
3621dd50e0ccSTony Hutter ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count);
3622dd50e0ccSTony Hutter break;
3623dd50e0ccSTony Hutter case DATA_TYPE_UINT64:
3624dd50e0ccSTony Hutter ret = nvpair_value_uint64(tmp, &nva->__data);
3625dd50e0ccSTony Hutter nva->data = &nva->__data;
3626dd50e0ccSTony Hutter nva->count = 1;
3627dd50e0ccSTony Hutter break;
3628dd50e0ccSTony Hutter default:
3629dd50e0ccSTony Hutter /* Not a uint64_t */
3630dd50e0ccSTony Hutter ret = EINVAL;
3631dd50e0ccSTony Hutter break;
3632dd50e0ccSTony Hutter }
3633dd50e0ccSTony Hutter
3634dd50e0ccSTony Hutter return (ret);
3635dd50e0ccSTony Hutter }
3636dd50e0ccSTony Hutter
3637dd50e0ccSTony Hutter /*
3638dd50e0ccSTony Hutter * Given a list of nvlist names, look up the extended stats in newnv and oldnv,
3639dd50e0ccSTony Hutter * subtract them, and return the results in a newly allocated stat_array.
3640dd50e0ccSTony Hutter * You must free the returned array after you are done with it with
3641dd50e0ccSTony Hutter * free_calc_stats().
3642dd50e0ccSTony Hutter *
3643dd50e0ccSTony Hutter * Additionally, you can set "oldnv" to NULL if you simply want the newnv
3644dd50e0ccSTony Hutter * values.
3645dd50e0ccSTony Hutter */
3646dd50e0ccSTony Hutter static struct stat_array *
calc_and_alloc_stats_ex(const char ** names,unsigned int len,nvlist_t * oldnv,nvlist_t * newnv)3647dd50e0ccSTony Hutter calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv,
3648dd50e0ccSTony Hutter nvlist_t *newnv)
3649dd50e0ccSTony Hutter {
3650dd50e0ccSTony Hutter nvlist_t *oldnvx = NULL, *newnvx;
3651dd50e0ccSTony Hutter struct stat_array *oldnva, *newnva, *calcnva;
3652dd50e0ccSTony Hutter int i, j;
3653dd50e0ccSTony Hutter unsigned int alloc_size = (sizeof (struct stat_array)) * len;
3654dd50e0ccSTony Hutter
3655dd50e0ccSTony Hutter /* Extract our extended stats nvlist from the main list */
3656dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3657dd50e0ccSTony Hutter &newnvx) == 0);
3658dd50e0ccSTony Hutter if (oldnv) {
3659dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3660dd50e0ccSTony Hutter &oldnvx) == 0);
3661dd50e0ccSTony Hutter }
3662dd50e0ccSTony Hutter
3663dd50e0ccSTony Hutter newnva = safe_malloc(alloc_size);
3664dd50e0ccSTony Hutter oldnva = safe_malloc(alloc_size);
3665dd50e0ccSTony Hutter calcnva = safe_malloc(alloc_size);
3666dd50e0ccSTony Hutter
3667dd50e0ccSTony Hutter for (j = 0; j < len; j++) {
3668dd50e0ccSTony Hutter verify(nvpair64_to_stat_array(newnvx, names[j],
3669dd50e0ccSTony Hutter &newnva[j]) == 0);
3670dd50e0ccSTony Hutter calcnva[j].count = newnva[j].count;
3671dd50e0ccSTony Hutter alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]);
3672dd50e0ccSTony Hutter calcnva[j].data = safe_malloc(alloc_size);
3673dd50e0ccSTony Hutter memcpy(calcnva[j].data, newnva[j].data, alloc_size);
3674dd50e0ccSTony Hutter
3675dd50e0ccSTony Hutter if (oldnvx) {
3676dd50e0ccSTony Hutter verify(nvpair64_to_stat_array(oldnvx, names[j],
3677dd50e0ccSTony Hutter &oldnva[j]) == 0);
3678dd50e0ccSTony Hutter for (i = 0; i < oldnva[j].count; i++)
3679dd50e0ccSTony Hutter calcnva[j].data[i] -= oldnva[j].data[i];
3680dd50e0ccSTony Hutter }
3681dd50e0ccSTony Hutter }
3682dd50e0ccSTony Hutter free(newnva);
3683dd50e0ccSTony Hutter free(oldnva);
3684dd50e0ccSTony Hutter return (calcnva);
3685dd50e0ccSTony Hutter }
3686dd50e0ccSTony Hutter
3687dd50e0ccSTony Hutter static void
free_calc_stats(struct stat_array * nva,unsigned int len)3688dd50e0ccSTony Hutter free_calc_stats(struct stat_array *nva, unsigned int len)
3689dd50e0ccSTony Hutter {
3690dd50e0ccSTony Hutter int i;
3691dd50e0ccSTony Hutter for (i = 0; i < len; i++)
3692dd50e0ccSTony Hutter free(nva[i].data);
3693dd50e0ccSTony Hutter
3694dd50e0ccSTony Hutter free(nva);
3695dd50e0ccSTony Hutter }
3696dd50e0ccSTony Hutter
3697dd50e0ccSTony Hutter static void
print_iostat_histo(struct stat_array * nva,unsigned int len,iostat_cbdata_t * cb,unsigned int column_width,unsigned int namewidth,double scale)3698dd50e0ccSTony Hutter print_iostat_histo(struct stat_array *nva, unsigned int len,
3699dd50e0ccSTony Hutter iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth,
3700dd50e0ccSTony Hutter double scale)
3701dd50e0ccSTony Hutter {
3702dd50e0ccSTony Hutter int i, j;
3703dd50e0ccSTony Hutter char buf[6];
3704dd50e0ccSTony Hutter uint64_t val;
3705dd50e0ccSTony Hutter enum zfs_nicenum_format format;
3706dd50e0ccSTony Hutter unsigned int buckets;
3707dd50e0ccSTony Hutter unsigned int start_bucket;
3708dd50e0ccSTony Hutter
3709dd50e0ccSTony Hutter if (cb->cb_literal)
3710dd50e0ccSTony Hutter format = ZFS_NICENUM_RAW;
3711dd50e0ccSTony Hutter else
3712dd50e0ccSTony Hutter format = ZFS_NICENUM_1024;
3713dd50e0ccSTony Hutter
3714dd50e0ccSTony Hutter /* All these histos are the same size, so just use nva[0].count */
3715dd50e0ccSTony Hutter buckets = nva[0].count;
3716dd50e0ccSTony Hutter
3717dd50e0ccSTony Hutter if (cb->cb_flags & IOS_RQ_HISTO_M) {
3718dd50e0ccSTony Hutter /* Start at 512 - req size should never be lower than this */
3719dd50e0ccSTony Hutter start_bucket = 9;
3720dd50e0ccSTony Hutter } else {
3721dd50e0ccSTony Hutter start_bucket = 0;
3722dd50e0ccSTony Hutter }
3723dd50e0ccSTony Hutter
3724dd50e0ccSTony Hutter for (j = start_bucket; j < buckets; j++) {
3725dd50e0ccSTony Hutter /* Print histogram bucket label */
3726dd50e0ccSTony Hutter if (cb->cb_flags & IOS_L_HISTO_M) {
3727dd50e0ccSTony Hutter /* Ending range of this bucket */
3728dd50e0ccSTony Hutter val = (1ULL << (j + 1)) - 1;
3729dd50e0ccSTony Hutter zfs_nicetime(val, buf, sizeof (buf));
3730dd50e0ccSTony Hutter } else {
3731dd50e0ccSTony Hutter /* Request size (starting range of bucket) */
3732dd50e0ccSTony Hutter val = (1UL << j);
3733dd50e0ccSTony Hutter zfs_nicenum(val, buf, sizeof (buf));
3734dd50e0ccSTony Hutter }
3735dd50e0ccSTony Hutter
3736dd50e0ccSTony Hutter if (cb->cb_scripted)
3737dd50e0ccSTony Hutter printf("%llu", (u_longlong_t)val);
3738dd50e0ccSTony Hutter else
3739dd50e0ccSTony Hutter printf("%-*s", namewidth, buf);
3740dd50e0ccSTony Hutter
3741dd50e0ccSTony Hutter /* Print the values on the line */
3742dd50e0ccSTony Hutter for (i = 0; i < len; i++) {
3743dd50e0ccSTony Hutter print_one_stat(nva[i].data[j] * scale, format,
3744dd50e0ccSTony Hutter column_width, cb->cb_scripted);
3745dd50e0ccSTony Hutter }
3746dd50e0ccSTony Hutter printf("\n");
3747dd50e0ccSTony Hutter }
3748dd50e0ccSTony Hutter }
3749dd50e0ccSTony Hutter
3750dd50e0ccSTony Hutter static void
print_solid_separator(unsigned int length)3751dd50e0ccSTony Hutter print_solid_separator(unsigned int length)
3752dd50e0ccSTony Hutter {
3753dd50e0ccSTony Hutter while (length--)
3754dd50e0ccSTony Hutter printf("-");
3755dd50e0ccSTony Hutter printf("\n");
3756dd50e0ccSTony Hutter }
3757dd50e0ccSTony Hutter
3758dd50e0ccSTony Hutter static void
print_iostat_histos(iostat_cbdata_t * cb,nvlist_t * oldnv,nvlist_t * newnv,double scale,const char * name)3759dd50e0ccSTony Hutter print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv,
3760dd50e0ccSTony Hutter nvlist_t *newnv, double scale, const char *name)
3761dd50e0ccSTony Hutter {
3762dd50e0ccSTony Hutter unsigned int column_width;
3763dd50e0ccSTony Hutter unsigned int namewidth;
3764dd50e0ccSTony Hutter unsigned int entire_width;
3765dd50e0ccSTony Hutter enum iostat_type type;
3766dd50e0ccSTony Hutter struct stat_array *nva;
3767dd50e0ccSTony Hutter const char **names;
3768dd50e0ccSTony Hutter unsigned int names_len;
3769dd50e0ccSTony Hutter
3770dd50e0ccSTony Hutter /* What type of histo are we? */
3771dd50e0ccSTony Hutter type = IOS_HISTO_IDX(cb->cb_flags);
3772dd50e0ccSTony Hutter
3773dd50e0ccSTony Hutter /* Get NULL-terminated array of nvlist names for our histo */
3774dd50e0ccSTony Hutter names = vsx_type_to_nvlist[type];
3775dd50e0ccSTony Hutter names_len = str_array_len(names); /* num of names */
3776dd50e0ccSTony Hutter
3777dd50e0ccSTony Hutter nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv);
3778dd50e0ccSTony Hutter
3779dd50e0ccSTony Hutter if (cb->cb_literal) {
3780dd50e0ccSTony Hutter column_width = MAX(5,
3781dd50e0ccSTony Hutter (unsigned int) log10(stat_histo_max(nva, names_len)) + 1);
3782dd50e0ccSTony Hutter } else {
3783dd50e0ccSTony Hutter column_width = 5;
3784dd50e0ccSTony Hutter }
3785dd50e0ccSTony Hutter
3786dd50e0ccSTony Hutter namewidth = MAX(cb->cb_namewidth,
3787dd50e0ccSTony Hutter strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]));
3788dd50e0ccSTony Hutter
3789dd50e0ccSTony Hutter /*
3790dd50e0ccSTony Hutter * Calculate the entire line width of what we're printing. The
3791dd50e0ccSTony Hutter * +2 is for the two spaces between columns:
3792dd50e0ccSTony Hutter */
3793dd50e0ccSTony Hutter /* read write */
3794dd50e0ccSTony Hutter /* ----- ----- */
3795dd50e0ccSTony Hutter /* |___| <---------- column_width */
3796dd50e0ccSTony Hutter /* */
3797dd50e0ccSTony Hutter /* |__________| <--- entire_width */
3798dd50e0ccSTony Hutter /* */
3799dd50e0ccSTony Hutter entire_width = namewidth + (column_width + 2) *
3800dd50e0ccSTony Hutter label_array_len(iostat_bottom_labels[type]);
3801dd50e0ccSTony Hutter
3802dd50e0ccSTony Hutter if (cb->cb_scripted)
3803dd50e0ccSTony Hutter printf("%s\n", name);
3804dd50e0ccSTony Hutter else
3805dd50e0ccSTony Hutter print_iostat_header_impl(cb, column_width, name);
3806dd50e0ccSTony Hutter
3807dd50e0ccSTony Hutter print_iostat_histo(nva, names_len, cb, column_width,
3808dd50e0ccSTony Hutter namewidth, scale);
3809dd50e0ccSTony Hutter
3810dd50e0ccSTony Hutter free_calc_stats(nva, names_len);
3811dd50e0ccSTony Hutter if (!cb->cb_scripted)
3812dd50e0ccSTony Hutter print_solid_separator(entire_width);
3813dd50e0ccSTony Hutter }
3814dd50e0ccSTony Hutter
3815dd50e0ccSTony Hutter /*
3816dd50e0ccSTony Hutter * Calculate the average latency of a power-of-two latency histogram
3817dd50e0ccSTony Hutter */
3818dd50e0ccSTony Hutter static uint64_t
single_histo_average(uint64_t * histo,unsigned int buckets)3819dd50e0ccSTony Hutter single_histo_average(uint64_t *histo, unsigned int buckets)
3820dd50e0ccSTony Hutter {
3821dd50e0ccSTony Hutter int i;
3822dd50e0ccSTony Hutter uint64_t count = 0, total = 0;
3823dd50e0ccSTony Hutter
3824dd50e0ccSTony Hutter for (i = 0; i < buckets; i++) {
3825dd50e0ccSTony Hutter /*
3826dd50e0ccSTony Hutter * Our buckets are power-of-two latency ranges. Use the
3827dd50e0ccSTony Hutter * midpoint latency of each bucket to calculate the average.
3828dd50e0ccSTony Hutter * For example:
3829dd50e0ccSTony Hutter *
3830dd50e0ccSTony Hutter * Bucket Midpoint
3831dd50e0ccSTony Hutter * 8ns-15ns: 12ns
3832dd50e0ccSTony Hutter * 16ns-31ns: 24ns
3833dd50e0ccSTony Hutter * ...
3834dd50e0ccSTony Hutter */
3835dd50e0ccSTony Hutter if (histo[i] != 0) {
3836dd50e0ccSTony Hutter total += histo[i] * (((1UL << i) + ((1UL << i)/2)));
3837dd50e0ccSTony Hutter count += histo[i];
3838dd50e0ccSTony Hutter }
3839dd50e0ccSTony Hutter }
3840dd50e0ccSTony Hutter
3841dd50e0ccSTony Hutter /* Prevent divide by zero */
3842dd50e0ccSTony Hutter return (count == 0 ? 0 : total / count);
3843dd50e0ccSTony Hutter }
3844dd50e0ccSTony Hutter
3845dd50e0ccSTony Hutter static void
print_iostat_queues(iostat_cbdata_t * cb,nvlist_t * oldnv,nvlist_t * newnv)3846dd50e0ccSTony Hutter print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *oldnv,
3847dd50e0ccSTony Hutter nvlist_t *newnv)
3848dd50e0ccSTony Hutter {
3849dd50e0ccSTony Hutter int i;
3850dd50e0ccSTony Hutter uint64_t val;
3851dd50e0ccSTony Hutter const char *names[] = {
3852dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE,
3853dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
3854dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE,
3855dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
3856dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE,
3857dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
3858dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE,
3859dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
3860dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE,
3861dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
3862dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE,
3863dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
3864dd50e0ccSTony Hutter };
3865dd50e0ccSTony Hutter
3866dd50e0ccSTony Hutter struct stat_array *nva;
3867dd50e0ccSTony Hutter
3868dd50e0ccSTony Hutter unsigned int column_width = default_column_width(cb, IOS_QUEUES);
3869dd50e0ccSTony Hutter enum zfs_nicenum_format format;
3870dd50e0ccSTony Hutter
3871dd50e0ccSTony Hutter nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv);
3872dd50e0ccSTony Hutter
3873dd50e0ccSTony Hutter if (cb->cb_literal)
3874dd50e0ccSTony Hutter format = ZFS_NICENUM_RAW;
3875dd50e0ccSTony Hutter else
3876dd50e0ccSTony Hutter format = ZFS_NICENUM_1024;
3877dd50e0ccSTony Hutter
3878dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(names); i++) {
3879dd50e0ccSTony Hutter val = nva[i].data[0];
3880dd50e0ccSTony Hutter print_one_stat(val, format, column_width, cb->cb_scripted);
3881dd50e0ccSTony Hutter }
3882dd50e0ccSTony Hutter
3883dd50e0ccSTony Hutter free_calc_stats(nva, ARRAY_SIZE(names));
3884dd50e0ccSTony Hutter }
3885dd50e0ccSTony Hutter
3886dd50e0ccSTony Hutter static void
print_iostat_latency(iostat_cbdata_t * cb,nvlist_t * oldnv,nvlist_t * newnv)3887dd50e0ccSTony Hutter print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv,
3888dd50e0ccSTony Hutter nvlist_t *newnv)
3889dd50e0ccSTony Hutter {
3890dd50e0ccSTony Hutter int i;
3891dd50e0ccSTony Hutter uint64_t val;
3892dd50e0ccSTony Hutter const char *names[] = {
3893dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
3894dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
3895dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
3896dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
3897dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
3898dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
3899dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
3900dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
3901dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
3902dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
3903dd50e0ccSTony Hutter };
3904dd50e0ccSTony Hutter struct stat_array *nva;
3905dd50e0ccSTony Hutter
3906dd50e0ccSTony Hutter unsigned int column_width = default_column_width(cb, IOS_LATENCY);
3907dd50e0ccSTony Hutter enum zfs_nicenum_format format;
3908dd50e0ccSTony Hutter
3909dd50e0ccSTony Hutter nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv);
3910dd50e0ccSTony Hutter
3911dd50e0ccSTony Hutter if (cb->cb_literal)
3912dd50e0ccSTony Hutter format = ZFS_NICENUM_RAWTIME;
3913dd50e0ccSTony Hutter else
3914dd50e0ccSTony Hutter format = ZFS_NICENUM_TIME;
3915dd50e0ccSTony Hutter
3916dd50e0ccSTony Hutter /* Print our avg latencies on the line */
3917dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(names); i++) {
3918dd50e0ccSTony Hutter /* Compute average latency for a latency histo */
3919dd50e0ccSTony Hutter val = single_histo_average(nva[i].data, nva[i].count);
3920dd50e0ccSTony Hutter print_one_stat(val, format, column_width, cb->cb_scripted);
3921dd50e0ccSTony Hutter }
3922dd50e0ccSTony Hutter free_calc_stats(nva, ARRAY_SIZE(names));
3923dd50e0ccSTony Hutter }
3924dd50e0ccSTony Hutter
3925dd50e0ccSTony Hutter /*
3926dd50e0ccSTony Hutter * Print default statistics (capacity/operations/bandwidth)
3927dd50e0ccSTony Hutter */
3928dd50e0ccSTony Hutter static void
print_iostat_default(vdev_stat_t * vs,iostat_cbdata_t * cb,double scale)3929dd50e0ccSTony Hutter print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale)
3930dd50e0ccSTony Hutter {
3931dd50e0ccSTony Hutter unsigned int column_width = default_column_width(cb, IOS_DEFAULT);
3932dd50e0ccSTony Hutter enum zfs_nicenum_format format;
3933dd50e0ccSTony Hutter char na; /* char to print for "not applicable" values */
3934dd50e0ccSTony Hutter
3935dd50e0ccSTony Hutter if (cb->cb_literal) {
3936dd50e0ccSTony Hutter format = ZFS_NICENUM_RAW;
3937dd50e0ccSTony Hutter na = '0';
3938dd50e0ccSTony Hutter } else {
3939dd50e0ccSTony Hutter format = ZFS_NICENUM_1024;
3940dd50e0ccSTony Hutter na = '-';
3941dd50e0ccSTony Hutter }
3942dd50e0ccSTony Hutter
3943dd50e0ccSTony Hutter /* only toplevel vdevs have capacity stats */
3944dd50e0ccSTony Hutter if (vs->vs_space == 0) {
3945dd50e0ccSTony Hutter if (cb->cb_scripted)
3946dd50e0ccSTony Hutter printf("\t%c\t%c", na, na);
3947dd50e0ccSTony Hutter else
3948dd50e0ccSTony Hutter printf(" %*c %*c", column_width, na, column_width,
3949dd50e0ccSTony Hutter na);
3950dd50e0ccSTony Hutter } else {
3951dd50e0ccSTony Hutter print_one_stat(vs->vs_alloc, format, column_width,
3952dd50e0ccSTony Hutter cb->cb_scripted);
3953dd50e0ccSTony Hutter print_one_stat(vs->vs_space - vs->vs_alloc, format,
3954dd50e0ccSTony Hutter column_width, cb->cb_scripted);
3955dd50e0ccSTony Hutter }
3956dd50e0ccSTony Hutter
3957dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale),
3958dd50e0ccSTony Hutter format, column_width, cb->cb_scripted);
3959dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale),
3960dd50e0ccSTony Hutter format, column_width, cb->cb_scripted);
3961dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale),
3962dd50e0ccSTony Hutter format, column_width, cb->cb_scripted);
3963dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale),
3964dd50e0ccSTony Hutter format, column_width, cb->cb_scripted);
3965fa9e4066Sahrens }
3966fa9e4066Sahrens
3967663207adSDon Brady static const char *class_name[] = {
3968663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP,
3969663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL,
3970663207adSDon Brady VDEV_ALLOC_CLASS_LOGS
3971663207adSDon Brady };
3972663207adSDon Brady
3973fa9e4066Sahrens /*
3974fa9e4066Sahrens * Print out all the statistics for the given vdev. This can either be the
3975fa9e4066Sahrens * toplevel configuration, or called recursively. If 'name' is NULL, then this
3976fa9e4066Sahrens * is a verbose output, and we don't want to display the toplevel pool stats.
3977dd50e0ccSTony Hutter *
3978dd50e0ccSTony Hutter * Returns the number of stat lines printed.
3979fa9e4066Sahrens */
3980dd50e0ccSTony Hutter unsigned int
print_vdev_stats(zpool_handle_t * zhp,const char * name,nvlist_t * oldnv,nvlist_t * newnv,iostat_cbdata_t * cb,int depth)3981c67d9675Seschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
3982c67d9675Seschrock nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
3983fa9e4066Sahrens {
3984fa9e4066Sahrens nvlist_t **oldchild, **newchild;
3985dd50e0ccSTony Hutter uint_t c, children, oldchildren;
3986dd50e0ccSTony Hutter vdev_stat_t *oldvs, *newvs, *calcvs;
3987fa9e4066Sahrens vdev_stat_t zerovs = { 0 };
3988663207adSDon Brady char *vname;
3989dd50e0ccSTony Hutter int i;
3990dd50e0ccSTony Hutter int ret = 0;
3991fa9e4066Sahrens uint64_t tdelta;
3992fa9e4066Sahrens double scale;
3993fa9e4066Sahrens
39945cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3995dd50e0ccSTony Hutter return (0);
3996dd50e0ccSTony Hutter
3997dd50e0ccSTony Hutter calcvs = safe_malloc(sizeof (*calcvs));
39985cabbc6bSPrashanth Sreenivasa
3999fa9e4066Sahrens if (oldnv != NULL) {
40003f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(oldnv,
40013f9d6ad7SLin Ling ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
4002fa9e4066Sahrens } else {
4003fa9e4066Sahrens oldvs = &zerovs;
4004fa9e4066Sahrens }
4005fa9e4066Sahrens
4006dd50e0ccSTony Hutter /* Do we only want to see a specific vdev? */
4007dd50e0ccSTony Hutter for (i = 0; i < cb->cb_vdev_names_count; i++) {
4008dd50e0ccSTony Hutter /* Yes we do. Is this the vdev? */
4009dd50e0ccSTony Hutter if (strcmp(name, cb->cb_vdev_names[i]) == 0) {
4010dd50e0ccSTony Hutter /*
4011dd50e0ccSTony Hutter * This is our vdev. Since it is the only vdev we
4012dd50e0ccSTony Hutter * will be displaying, make depth = 0 so that it
4013dd50e0ccSTony Hutter * doesn't get indented.
4014dd50e0ccSTony Hutter */
4015dd50e0ccSTony Hutter depth = 0;
4016dd50e0ccSTony Hutter break;
4017dd50e0ccSTony Hutter }
4018dd50e0ccSTony Hutter }
4019dd50e0ccSTony Hutter
4020dd50e0ccSTony Hutter if (cb->cb_vdev_names_count && (i == cb->cb_vdev_names_count)) {
4021dd50e0ccSTony Hutter /* Couldn't match the name */
4022dd50e0ccSTony Hutter goto children;
4023dd50e0ccSTony Hutter }
4024dd50e0ccSTony Hutter
4025dd50e0ccSTony Hutter
40263f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
4027fa9e4066Sahrens (uint64_t **)&newvs, &c) == 0);
4028fa9e4066Sahrens
4029dd50e0ccSTony Hutter /*
4030dd50e0ccSTony Hutter * Print the vdev name unless it's is a histogram. Histograms
4031dd50e0ccSTony Hutter * display the vdev name in the header itself.
4032dd50e0ccSTony Hutter */
4033dd50e0ccSTony Hutter if (!(cb->cb_flags & IOS_ANYHISTO_M)) {
4034dd50e0ccSTony Hutter if (cb->cb_scripted) {
4035dd50e0ccSTony Hutter printf("%s", name);
4036dd50e0ccSTony Hutter } else {
4037fa9e4066Sahrens if (strlen(name) + depth > cb->cb_namewidth)
4038fa9e4066Sahrens (void) printf("%*s%s", depth, "", name);
4039fa9e4066Sahrens else
4040fa9e4066Sahrens (void) printf("%*s%s%*s", depth, "", name,
4041dd50e0ccSTony Hutter (int)(cb->cb_namewidth - strlen(name) -
4042dd50e0ccSTony Hutter depth), "");
4043dd50e0ccSTony Hutter }
4044dd50e0ccSTony Hutter }
4045fa9e4066Sahrens
4046dd50e0ccSTony Hutter /* Calculate our scaling factor */
4047fa9e4066Sahrens tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
4048dd50e0ccSTony Hutter if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) {
4049dd50e0ccSTony Hutter /*
4050dd50e0ccSTony Hutter * If we specify printing histograms with no time interval, then
4051dd50e0ccSTony Hutter * print the histogram numbers over the entire lifetime of the
4052dd50e0ccSTony Hutter * vdev.
4053dd50e0ccSTony Hutter */
4054dd50e0ccSTony Hutter scale = 1;
4055dd50e0ccSTony Hutter } else {
4056fa9e4066Sahrens if (tdelta == 0)
4057fa9e4066Sahrens scale = 1.0;
4058fa9e4066Sahrens else
4059fa9e4066Sahrens scale = (double)NANOSEC / tdelta;
4060fa9e4066Sahrens }
4061fa9e4066Sahrens
4062dd50e0ccSTony Hutter if (cb->cb_flags & IOS_DEFAULT_M) {
4063dd50e0ccSTony Hutter calc_default_iostats(oldvs, newvs, calcvs);
4064dd50e0ccSTony Hutter print_iostat_default(calcvs, cb, scale);
4065dd50e0ccSTony Hutter }
4066dd50e0ccSTony Hutter if (cb->cb_flags & IOS_LATENCY_M)
4067dd50e0ccSTony Hutter print_iostat_latency(cb, oldnv, newnv);
4068dd50e0ccSTony Hutter if (cb->cb_flags & IOS_QUEUES_M)
4069dd50e0ccSTony Hutter print_iostat_queues(cb, oldnv, newnv);
4070dd50e0ccSTony Hutter if (cb->cb_flags & IOS_ANYHISTO_M) {
4071dd50e0ccSTony Hutter printf("\n");
4072dd50e0ccSTony Hutter print_iostat_histos(cb, oldnv, newnv, scale, name);
4073dd50e0ccSTony Hutter }
4074fa9e4066Sahrens
4075dd50e0ccSTony Hutter if (!(cb->cb_flags & IOS_ANYHISTO_M))
4076dd50e0ccSTony Hutter printf("\n");
4077fa9e4066Sahrens
4078dd50e0ccSTony Hutter ret++;
4079fa9e4066Sahrens
4080dd50e0ccSTony Hutter children:
4081fa9e4066Sahrens
4082dd50e0ccSTony Hutter free(calcvs);
4083fa9e4066Sahrens
4084fa9e4066Sahrens if (!cb->cb_verbose)
4085dd50e0ccSTony Hutter return (ret);
4086fa9e4066Sahrens
4087fa9e4066Sahrens if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
4088fa9e4066Sahrens &newchild, &children) != 0)
4089dd50e0ccSTony Hutter return (ret);
4090fa9e4066Sahrens
4091dd50e0ccSTony Hutter if (oldnv) {
4092dd50e0ccSTony Hutter if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
4093dd50e0ccSTony Hutter &oldchild, &oldchildren) != 0)
4094dd50e0ccSTony Hutter return (ret);
4095dd50e0ccSTony Hutter
4096dd50e0ccSTony Hutter children = MIN(oldchildren, children);
4097dd50e0ccSTony Hutter }
4098fa9e4066Sahrens
4099663207adSDon Brady /*
4100663207adSDon Brady * print normal top-level devices
4101663207adSDon Brady */
4102afefbcddSeschrock for (c = 0; c < children; c++) {
41039d439f90SMike Harsch uint64_t ishole = B_FALSE, islog = B_FALSE;
41043f9d6ad7SLin Ling
41059d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
41069d439f90SMike Harsch &ishole);
41079d439f90SMike Harsch
41089d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
41099d439f90SMike Harsch &islog);
41109d439f90SMike Harsch
41119d439f90SMike Harsch if (ishole || islog)
41123f9d6ad7SLin Ling continue;
41133f9d6ad7SLin Ling
4114663207adSDon Brady if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
4115663207adSDon Brady continue;
4116663207adSDon Brady
4117663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4118663207adSDon Brady cb->cb_name_flags);
4119dd50e0ccSTony Hutter ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
4120afefbcddSeschrock newchild[c], cb, depth + 2);
4121afefbcddSeschrock free(vname);
4122afefbcddSeschrock }
4123fa94a07fSbrendan
4124fa94a07fSbrendan /*
4125663207adSDon Brady * print all other top-level devices
41269d439f90SMike Harsch */
4127663207adSDon Brady for (uint_t n = 0; n < 3; n++) {
4128c4e4d410SAndy Fiddaman boolean_t printed = B_FALSE;
4129dd50e0ccSTony Hutter
41309d439f90SMike Harsch for (c = 0; c < children; c++) {
41319d439f90SMike Harsch uint64_t islog = B_FALSE;
4132663207adSDon Brady char *bias = NULL;
4133663207adSDon Brady char *type = NULL;
4134663207adSDon Brady
41359d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c],
41369d439f90SMike Harsch ZPOOL_CONFIG_IS_LOG, &islog);
41379d439f90SMike Harsch if (islog) {
4138663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS;
4139663207adSDon Brady } else {
4140663207adSDon Brady (void) nvlist_lookup_string(newchild[c],
4141663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
4142663207adSDon Brady (void) nvlist_lookup_string(newchild[c],
4143663207adSDon Brady ZPOOL_CONFIG_TYPE, &type);
41449d439f90SMike Harsch }
4145663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0)
4146663207adSDon Brady continue;
4147663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
4148663207adSDon Brady continue;
4149663207adSDon Brady
4150c4e4d410SAndy Fiddaman if (!printed) {
4151dd50e0ccSTony Hutter if ((!(cb->cb_flags & IOS_ANYHISTO_M)) &&
4152dd50e0ccSTony Hutter !cb->cb_scripted && !cb->cb_vdev_names) {
4153dd50e0ccSTony Hutter print_iostat_dashes(cb, 0,
4154dd50e0ccSTony Hutter class_name[n]);
4155c4e4d410SAndy Fiddaman }
4156c4e4d410SAndy Fiddaman printf("\n");
4157c4e4d410SAndy Fiddaman printed = B_TRUE;
4158c4e4d410SAndy Fiddaman }
4159c4e4d410SAndy Fiddaman
4160663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4161663207adSDon Brady cb->cb_name_flags);
4162dd50e0ccSTony Hutter ret += print_vdev_stats(zhp, vname, oldnv ?
4163663207adSDon Brady oldchild[c] : NULL, newchild[c], cb, depth + 2);
4164663207adSDon Brady free(vname);
41659d439f90SMike Harsch }
41669d439f90SMike Harsch
41679d439f90SMike Harsch }
41689d439f90SMike Harsch
41699d439f90SMike Harsch /*
4170fa94a07fSbrendan * Include level 2 ARC devices in iostat output
4171fa94a07fSbrendan */
4172fa94a07fSbrendan if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
4173fa94a07fSbrendan &newchild, &children) != 0)
4174dd50e0ccSTony Hutter return (ret);
4175fa94a07fSbrendan
4176dd50e0ccSTony Hutter if (oldnv) {
4177dd50e0ccSTony Hutter if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
4178dd50e0ccSTony Hutter &oldchild, &oldchildren) != 0)
4179dd50e0ccSTony Hutter return (ret);
4180dd50e0ccSTony Hutter
4181dd50e0ccSTony Hutter children = MIN(oldchildren, children);
4182dd50e0ccSTony Hutter }
4183fa94a07fSbrendan
4184fa94a07fSbrendan if (children > 0) {
4185dd50e0ccSTony Hutter if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted &&
4186dd50e0ccSTony Hutter !cb->cb_vdev_names) {
4187dd50e0ccSTony Hutter print_iostat_dashes(cb, 0, "cache");
4188dd50e0ccSTony Hutter }
4189dd50e0ccSTony Hutter printf("\n");
4190dd50e0ccSTony Hutter
4191fa94a07fSbrendan for (c = 0; c < children; c++) {
419288ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
4193663207adSDon Brady cb->cb_name_flags);
4194dd50e0ccSTony Hutter ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c]
4195dd50e0ccSTony Hutter : NULL, newchild[c], cb, depth + 2);
4196fa94a07fSbrendan free(vname);
4197fa94a07fSbrendan }
4198fa94a07fSbrendan }
4199dd50e0ccSTony Hutter
4200dd50e0ccSTony Hutter return (ret);
4201fa9e4066Sahrens }
4202fa9e4066Sahrens
4203088e9d47Seschrock static int
refresh_iostat(zpool_handle_t * zhp,void * data)4204088e9d47Seschrock refresh_iostat(zpool_handle_t *zhp, void *data)
4205088e9d47Seschrock {
4206088e9d47Seschrock iostat_cbdata_t *cb = data;
420794de1d4cSeschrock boolean_t missing;
4208088e9d47Seschrock
4209088e9d47Seschrock /*
4210088e9d47Seschrock * If the pool has disappeared, remove it from the list and continue.
4211088e9d47Seschrock */
421294de1d4cSeschrock if (zpool_refresh_stats(zhp, &missing) != 0)
421394de1d4cSeschrock return (-1);
421494de1d4cSeschrock
421594de1d4cSeschrock if (missing)
4216088e9d47Seschrock pool_list_remove(cb->cb_list, zhp);
4217088e9d47Seschrock
4218088e9d47Seschrock return (0);
4219088e9d47Seschrock }
4220088e9d47Seschrock
4221fa9e4066Sahrens /*
4222fa9e4066Sahrens * Callback to print out the iostats for the given pool.
4223fa9e4066Sahrens */
4224fa9e4066Sahrens int
print_iostat(zpool_handle_t * zhp,void * data)4225fa9e4066Sahrens print_iostat(zpool_handle_t *zhp, void *data)
4226fa9e4066Sahrens {
4227fa9e4066Sahrens iostat_cbdata_t *cb = data;
4228fa9e4066Sahrens nvlist_t *oldconfig, *newconfig;
4229fa9e4066Sahrens nvlist_t *oldnvroot, *newnvroot;
4230dd50e0ccSTony Hutter int ret;
4231fa9e4066Sahrens
4232088e9d47Seschrock newconfig = zpool_get_config(zhp, &oldconfig);
4233fa9e4066Sahrens
4234088e9d47Seschrock if (cb->cb_iteration == 1)
4235fa9e4066Sahrens oldconfig = NULL;
4236fa9e4066Sahrens
4237fa9e4066Sahrens verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
4238fa9e4066Sahrens &newnvroot) == 0);
4239fa9e4066Sahrens
4240088e9d47Seschrock if (oldconfig == NULL)
4241fa9e4066Sahrens oldnvroot = NULL;
4242088e9d47Seschrock else
4243088e9d47Seschrock verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
4244088e9d47Seschrock &oldnvroot) == 0);
4245fa9e4066Sahrens
4246dd50e0ccSTony Hutter ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot,
4247dd50e0ccSTony Hutter cb, 0);
4248dd50e0ccSTony Hutter if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) &&
4249dd50e0ccSTony Hutter !cb->cb_scripted && cb->cb_verbose && !cb->cb_vdev_names_count) {
4250fa9e4066Sahrens print_iostat_separator(cb);
4251dd50e0ccSTony Hutter printf("\n");
4252fa9e4066Sahrens }
4253fa9e4066Sahrens
4254dd50e0ccSTony Hutter return (ret);
4255dd50e0ccSTony Hutter }
4256dd50e0ccSTony Hutter
4257dd50e0ccSTony Hutter static int
get_columns(void)4258dd50e0ccSTony Hutter get_columns(void)
4259fa9e4066Sahrens {
4260dd50e0ccSTony Hutter struct winsize ws;
4261dd50e0ccSTony Hutter int columns = 80;
4262dd50e0ccSTony Hutter int error;
4263dd50e0ccSTony Hutter
4264dd50e0ccSTony Hutter if (isatty(STDOUT_FILENO)) {
4265dd50e0ccSTony Hutter error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
4266dd50e0ccSTony Hutter if (error == 0)
4267dd50e0ccSTony Hutter columns = ws.ws_col;
4268dd50e0ccSTony Hutter } else {
4269dd50e0ccSTony Hutter columns = 999;
4270dd50e0ccSTony Hutter }
4271dd50e0ccSTony Hutter
4272dd50e0ccSTony Hutter return (columns);
4273dd50e0ccSTony Hutter }
4274dd50e0ccSTony Hutter
4275dd50e0ccSTony Hutter /*
4276dd50e0ccSTony Hutter * Return the required length of the pool/vdev name column. The minimum
4277dd50e0ccSTony Hutter * allowed width and output formatting flags must be provided.
4278dd50e0ccSTony Hutter */
4279dd50e0ccSTony Hutter static int
get_namewidth(zpool_handle_t * zhp,int min_width,int flags,boolean_t verbose)4280dd50e0ccSTony Hutter get_namewidth(zpool_handle_t *zhp, int min_width, int flags, boolean_t verbose)
4281dd50e0ccSTony Hutter {
4282fa9e4066Sahrens nvlist_t *config, *nvroot;
4283dd50e0ccSTony Hutter int width = min_width;
4284fa9e4066Sahrens
4285088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) != NULL) {
4286fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4287fa9e4066Sahrens &nvroot) == 0);
4288dd50e0ccSTony Hutter unsigned int poolname_len = strlen(zpool_get_name(zhp));
4289dd50e0ccSTony Hutter if (verbose == B_FALSE) {
4290dd50e0ccSTony Hutter width = MAX(poolname_len, min_width);
4291dd50e0ccSTony Hutter } else {
4292dd50e0ccSTony Hutter width = MAX(poolname_len,
4293dd50e0ccSTony Hutter max_width(zhp, nvroot, 0, min_width, flags));
4294dd50e0ccSTony Hutter }
4295fa9e4066Sahrens }
4296fa9e4066Sahrens
4297dd50e0ccSTony Hutter return (width);
4298fa9e4066Sahrens }
4299fa9e4066Sahrens
4300fa9e4066Sahrens /*
43013f9d6ad7SLin Ling * Parse the input string, get the 'interval' and 'count' value if there is one.
4302fa9e4066Sahrens */
43033f9d6ad7SLin Ling static void
get_interval_count(int * argcp,char ** argv,float * iv,unsigned long * cnt)4304dd50e0ccSTony Hutter get_interval_count(int *argcp, char **argv, float *iv,
43053f9d6ad7SLin Ling unsigned long *cnt)
4306fa9e4066Sahrens {
4307dd50e0ccSTony Hutter float interval = 0;
4308dd50e0ccSTony Hutter unsigned long count = 0;
43093f9d6ad7SLin Ling int argc = *argcp, errno;
4310fa9e4066Sahrens
4311fa9e4066Sahrens /*
4312fa9e4066Sahrens * Determine if the last argument is an integer or a pool name
4313fa9e4066Sahrens */
4314dd50e0ccSTony Hutter if (argc > 0 && isnumber(argv[argc - 1])) {
4315fa9e4066Sahrens char *end;
4316fa9e4066Sahrens
4317fa9e4066Sahrens errno = 0;
4318dd50e0ccSTony Hutter interval = strtof(argv[argc - 1], &end);
4319fa9e4066Sahrens
4320fa9e4066Sahrens if (*end == '\0' && errno == 0) {
4321fa9e4066Sahrens if (interval == 0) {
4322fa9e4066Sahrens (void) fprintf(stderr, gettext("interval "
4323fa9e4066Sahrens "cannot be zero\n"));
432499653d4eSeschrock usage(B_FALSE);
4325fa9e4066Sahrens }
4326fa9e4066Sahrens /*
4327fa9e4066Sahrens * Ignore the last parameter
4328fa9e4066Sahrens */
4329fa9e4066Sahrens argc--;
4330fa9e4066Sahrens } else {
4331fa9e4066Sahrens /*
4332fa9e4066Sahrens * If this is not a valid number, just plow on. The
4333fa9e4066Sahrens * user will get a more informative error message later
4334fa9e4066Sahrens * on.
4335fa9e4066Sahrens */
4336fa9e4066Sahrens interval = 0;
4337fa9e4066Sahrens }
4338fa9e4066Sahrens }
4339fa9e4066Sahrens
4340fa9e4066Sahrens /*
4341fa9e4066Sahrens * If the last argument is also an integer, then we have both a count
43423f9d6ad7SLin Ling * and an interval.
4343fa9e4066Sahrens */
4344dd50e0ccSTony Hutter if (argc > 0 && isnumber(argv[argc - 1])) {
4345fa9e4066Sahrens char *end;
4346fa9e4066Sahrens
4347fa9e4066Sahrens errno = 0;
4348fa9e4066Sahrens count = interval;
4349dd50e0ccSTony Hutter interval = strtof(argv[argc - 1], &end);
4350fa9e4066Sahrens
4351fa9e4066Sahrens if (*end == '\0' && errno == 0) {
4352fa9e4066Sahrens if (interval == 0) {
4353fa9e4066Sahrens (void) fprintf(stderr, gettext("interval "
4354fa9e4066Sahrens "cannot be zero\n"));
435599653d4eSeschrock usage(B_FALSE);
4356fa9e4066Sahrens }
4357fa9e4066Sahrens
4358fa9e4066Sahrens /*
4359fa9e4066Sahrens * Ignore the last parameter
4360fa9e4066Sahrens */
4361fa9e4066Sahrens argc--;
4362fa9e4066Sahrens } else {
4363fa9e4066Sahrens interval = 0;
4364fa9e4066Sahrens }
4365fa9e4066Sahrens }
4366fa9e4066Sahrens
43673f9d6ad7SLin Ling *iv = interval;
43683f9d6ad7SLin Ling *cnt = count;
43693f9d6ad7SLin Ling *argcp = argc;
43703f9d6ad7SLin Ling }
43713f9d6ad7SLin Ling
43723f9d6ad7SLin Ling static void
get_timestamp_arg(char c)43733f9d6ad7SLin Ling get_timestamp_arg(char c)
43743f9d6ad7SLin Ling {
43753f9d6ad7SLin Ling if (c == 'u')
43763f9d6ad7SLin Ling timestamp_fmt = UDATE;
43773f9d6ad7SLin Ling else if (c == 'd')
43783f9d6ad7SLin Ling timestamp_fmt = DDATE;
43793f9d6ad7SLin Ling else
43803f9d6ad7SLin Ling usage(B_FALSE);
43813f9d6ad7SLin Ling }
43823f9d6ad7SLin Ling
43833f9d6ad7SLin Ling /*
4384dd50e0ccSTony Hutter * Return stat flags that are supported by all pools by both the module and
4385dd50e0ccSTony Hutter * zpool iostat. "*data" should be initialized to all 0xFFs before running.
4386dd50e0ccSTony Hutter * It will get ANDed down until only the flags that are supported on all pools
4387dd50e0ccSTony Hutter * remain.
4388dd50e0ccSTony Hutter */
4389dd50e0ccSTony Hutter static int
get_stat_flags_cb(zpool_handle_t * zhp,void * data)4390dd50e0ccSTony Hutter get_stat_flags_cb(zpool_handle_t *zhp, void *data)
4391dd50e0ccSTony Hutter {
4392dd50e0ccSTony Hutter uint64_t *mask = data;
4393dd50e0ccSTony Hutter nvlist_t *config, *nvroot, *nvx;
4394dd50e0ccSTony Hutter uint64_t flags = 0;
4395dd50e0ccSTony Hutter int i, j;
4396dd50e0ccSTony Hutter
4397dd50e0ccSTony Hutter config = zpool_get_config(zhp, NULL);
4398dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4399dd50e0ccSTony Hutter &nvroot) == 0);
4400dd50e0ccSTony Hutter
4401dd50e0ccSTony Hutter /* Default stats are always supported, but for completeness.. */
4402dd50e0ccSTony Hutter if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS))
4403dd50e0ccSTony Hutter flags |= IOS_DEFAULT_M;
4404dd50e0ccSTony Hutter
4405dd50e0ccSTony Hutter /* Get our extended stats nvlist from the main list */
4406dd50e0ccSTony Hutter if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX,
4407dd50e0ccSTony Hutter &nvx) != 0) {
4408dd50e0ccSTony Hutter /*
4409dd50e0ccSTony Hutter * No extended stats; they're probably running an older
4410dd50e0ccSTony Hutter * module. No big deal, we support that too.
4411dd50e0ccSTony Hutter */
4412dd50e0ccSTony Hutter goto end;
4413dd50e0ccSTony Hutter }
4414dd50e0ccSTony Hutter
4415dd50e0ccSTony Hutter /* For each extended stat, make sure all its nvpairs are supported */
4416dd50e0ccSTony Hutter for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) {
4417dd50e0ccSTony Hutter if (!vsx_type_to_nvlist[j][0])
4418dd50e0ccSTony Hutter continue;
4419dd50e0ccSTony Hutter
4420dd50e0ccSTony Hutter /* Start off by assuming the flag is supported, then check */
4421dd50e0ccSTony Hutter flags |= (1ULL << j);
4422dd50e0ccSTony Hutter for (i = 0; vsx_type_to_nvlist[j][i]; i++) {
4423dd50e0ccSTony Hutter if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) {
4424dd50e0ccSTony Hutter /* flag isn't supported */
4425dd50e0ccSTony Hutter flags = flags & ~(1ULL << j);
4426dd50e0ccSTony Hutter break;
4427dd50e0ccSTony Hutter }
4428dd50e0ccSTony Hutter }
4429dd50e0ccSTony Hutter }
4430dd50e0ccSTony Hutter end:
4431dd50e0ccSTony Hutter *mask = *mask & flags;
4432dd50e0ccSTony Hutter return (0);
4433dd50e0ccSTony Hutter }
4434dd50e0ccSTony Hutter
4435dd50e0ccSTony Hutter /*
4436dd50e0ccSTony Hutter * Return a bitmask of stats that are supported on all pools by both the module
4437dd50e0ccSTony Hutter * and zpool iostat.
4438dd50e0ccSTony Hutter */
4439dd50e0ccSTony Hutter static uint64_t
get_stat_flags(zpool_list_t * list)4440dd50e0ccSTony Hutter get_stat_flags(zpool_list_t *list)
4441dd50e0ccSTony Hutter {
4442dd50e0ccSTony Hutter uint64_t mask = -1;
4443dd50e0ccSTony Hutter
4444dd50e0ccSTony Hutter /*
4445dd50e0ccSTony Hutter * get_stat_flags_cb() will lop off bits from "mask" until only the
4446dd50e0ccSTony Hutter * flags that are supported on all pools remain.
4447dd50e0ccSTony Hutter */
4448dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask);
4449dd50e0ccSTony Hutter return (mask);
4450dd50e0ccSTony Hutter }
4451dd50e0ccSTony Hutter
4452dd50e0ccSTony Hutter /*
4453dd50e0ccSTony Hutter * Return 1 if cb_data->cb_vdev_names[0] is this vdev's name, 0 otherwise.
4454dd50e0ccSTony Hutter */
4455dd50e0ccSTony Hutter static int
is_vdev_cb(zpool_handle_t * zhp,nvlist_t * nv,void * cb_data)4456dd50e0ccSTony Hutter is_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_data)
4457dd50e0ccSTony Hutter {
4458dd50e0ccSTony Hutter iostat_cbdata_t *cb = cb_data;
4459dd50e0ccSTony Hutter char *name;
4460dd50e0ccSTony Hutter
4461dd50e0ccSTony Hutter name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags);
4462dd50e0ccSTony Hutter
4463dd50e0ccSTony Hutter if (strcmp(name, cb->cb_vdev_names[0]) == 0)
4464dd50e0ccSTony Hutter return (1); /* match */
4465dd50e0ccSTony Hutter
4466dd50e0ccSTony Hutter return (0);
4467dd50e0ccSTony Hutter }
4468dd50e0ccSTony Hutter
4469dd50e0ccSTony Hutter /*
4470dd50e0ccSTony Hutter * Returns 1 if cb_data->cb_vdev_names[0] is a vdev name, 0 otherwise.
4471dd50e0ccSTony Hutter */
4472dd50e0ccSTony Hutter static int
is_vdev(zpool_handle_t * zhp,void * cb_data)4473dd50e0ccSTony Hutter is_vdev(zpool_handle_t *zhp, void *cb_data)
4474dd50e0ccSTony Hutter {
4475dd50e0ccSTony Hutter return (for_each_vdev(zhp, is_vdev_cb, cb_data));
4476dd50e0ccSTony Hutter }
4477dd50e0ccSTony Hutter
4478dd50e0ccSTony Hutter /*
4479dd50e0ccSTony Hutter * Check if vdevs are in a pool
4480dd50e0ccSTony Hutter *
4481dd50e0ccSTony Hutter * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise
4482dd50e0ccSTony Hutter * return 0. If pool_name is NULL, then search all pools.
4483dd50e0ccSTony Hutter */
4484dd50e0ccSTony Hutter static int
are_vdevs_in_pool(int argc,char ** argv,char * pool_name,iostat_cbdata_t * cb)4485dd50e0ccSTony Hutter are_vdevs_in_pool(int argc, char **argv, char *pool_name,
4486dd50e0ccSTony Hutter iostat_cbdata_t *cb)
4487dd50e0ccSTony Hutter {
4488dd50e0ccSTony Hutter char **tmp_name;
4489dd50e0ccSTony Hutter int ret = 0;
4490dd50e0ccSTony Hutter int i;
4491dd50e0ccSTony Hutter int pool_count = 0;
4492dd50e0ccSTony Hutter
4493dd50e0ccSTony Hutter if ((argc == 0) || !*argv)
4494dd50e0ccSTony Hutter return (0);
4495dd50e0ccSTony Hutter
4496dd50e0ccSTony Hutter if (pool_name)
4497dd50e0ccSTony Hutter pool_count = 1;
4498dd50e0ccSTony Hutter
4499dd50e0ccSTony Hutter /* Temporarily hijack cb_vdev_names for a second... */
4500dd50e0ccSTony Hutter tmp_name = cb->cb_vdev_names;
4501dd50e0ccSTony Hutter
4502dd50e0ccSTony Hutter /* Go though our list of prospective vdev names */
4503dd50e0ccSTony Hutter for (i = 0; i < argc; i++) {
4504dd50e0ccSTony Hutter cb->cb_vdev_names = argv + i;
4505dd50e0ccSTony Hutter
4506dd50e0ccSTony Hutter /* Is this name a vdev in our pools? */
4507dd50e0ccSTony Hutter ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL,
4508dd50e0ccSTony Hutter is_vdev, cb);
4509dd50e0ccSTony Hutter if (!ret) {
4510dd50e0ccSTony Hutter /* No match */
4511dd50e0ccSTony Hutter break;
4512dd50e0ccSTony Hutter }
4513dd50e0ccSTony Hutter }
4514dd50e0ccSTony Hutter
4515dd50e0ccSTony Hutter cb->cb_vdev_names = tmp_name;
4516dd50e0ccSTony Hutter
4517dd50e0ccSTony Hutter return (ret);
4518dd50e0ccSTony Hutter }
4519dd50e0ccSTony Hutter
4520dd50e0ccSTony Hutter static int
is_pool_cb(zpool_handle_t * zhp,void * data)4521dd50e0ccSTony Hutter is_pool_cb(zpool_handle_t *zhp, void *data)
4522dd50e0ccSTony Hutter {
4523dd50e0ccSTony Hutter char *name = data;
4524dd50e0ccSTony Hutter if (strcmp(name, zpool_get_name(zhp)) == 0)
4525dd50e0ccSTony Hutter return (1);
4526dd50e0ccSTony Hutter
4527dd50e0ccSTony Hutter return (0);
4528dd50e0ccSTony Hutter }
4529dd50e0ccSTony Hutter
4530dd50e0ccSTony Hutter /*
4531dd50e0ccSTony Hutter * Do we have a pool named *name? If so, return 1, otherwise 0.
4532dd50e0ccSTony Hutter */
4533dd50e0ccSTony Hutter static int
is_pool(char * name)4534dd50e0ccSTony Hutter is_pool(char *name)
4535dd50e0ccSTony Hutter {
4536dd50e0ccSTony Hutter return (for_each_pool(0, NULL, B_TRUE, NULL, is_pool_cb, name));
4537dd50e0ccSTony Hutter }
4538dd50e0ccSTony Hutter
4539dd50e0ccSTony Hutter /* Are all our argv[] strings pool names? If so return 1, 0 otherwise. */
4540dd50e0ccSTony Hutter static int
are_all_pools(int argc,char ** argv)4541dd50e0ccSTony Hutter are_all_pools(int argc, char **argv)
4542dd50e0ccSTony Hutter {
4543dd50e0ccSTony Hutter if ((argc == 0) || !*argv)
4544dd50e0ccSTony Hutter return (0);
4545dd50e0ccSTony Hutter
4546dd50e0ccSTony Hutter while (--argc >= 0)
4547dd50e0ccSTony Hutter if (!is_pool(argv[argc]))
4548dd50e0ccSTony Hutter return (0);
4549dd50e0ccSTony Hutter
4550dd50e0ccSTony Hutter return (1);
4551dd50e0ccSTony Hutter }
4552dd50e0ccSTony Hutter
4553dd50e0ccSTony Hutter /*
4554dd50e0ccSTony Hutter * Helper function to print out vdev/pool names we can't resolve. Used for an
4555dd50e0ccSTony Hutter * error message.
4556dd50e0ccSTony Hutter */
4557dd50e0ccSTony Hutter static void
error_list_unresolved_vdevs(int argc,char ** argv,char * pool_name,iostat_cbdata_t * cb)4558dd50e0ccSTony Hutter error_list_unresolved_vdevs(int argc, char **argv, char *pool_name,
4559dd50e0ccSTony Hutter iostat_cbdata_t *cb)
4560dd50e0ccSTony Hutter {
4561dd50e0ccSTony Hutter int i;
4562dd50e0ccSTony Hutter char *name;
4563dd50e0ccSTony Hutter char *str;
4564dd50e0ccSTony Hutter for (i = 0; i < argc; i++) {
4565dd50e0ccSTony Hutter name = argv[i];
4566dd50e0ccSTony Hutter
4567dd50e0ccSTony Hutter if (is_pool(name))
4568dd50e0ccSTony Hutter str = gettext("pool");
4569dd50e0ccSTony Hutter else if (are_vdevs_in_pool(1, &name, pool_name, cb))
4570dd50e0ccSTony Hutter str = gettext("vdev in this pool");
4571dd50e0ccSTony Hutter else if (are_vdevs_in_pool(1, &name, NULL, cb))
4572dd50e0ccSTony Hutter str = gettext("vdev in another pool");
4573dd50e0ccSTony Hutter else
4574dd50e0ccSTony Hutter str = gettext("unknown");
4575dd50e0ccSTony Hutter
4576dd50e0ccSTony Hutter fprintf(stderr, "\t%s (%s)\n", name, str);
4577dd50e0ccSTony Hutter }
4578dd50e0ccSTony Hutter }
4579dd50e0ccSTony Hutter
4580dd50e0ccSTony Hutter /*
4581dd50e0ccSTony Hutter * Same as get_interval_count(), but with additional checks to not misinterpret
4582dd50e0ccSTony Hutter * guids as interval/count values. Assumes VDEV_NAME_GUID is set in
4583dd50e0ccSTony Hutter * cb.cb_name_flags.
4584dd50e0ccSTony Hutter */
4585dd50e0ccSTony Hutter static void
get_interval_count_filter_guids(int * argc,char ** argv,float * interval,unsigned long * count,iostat_cbdata_t * cb)4586dd50e0ccSTony Hutter get_interval_count_filter_guids(int *argc, char **argv, float *interval,
4587dd50e0ccSTony Hutter unsigned long *count, iostat_cbdata_t *cb)
4588dd50e0ccSTony Hutter {
4589dd50e0ccSTony Hutter char **tmpargv = argv;
4590dd50e0ccSTony Hutter int argc_for_interval = 0;
4591dd50e0ccSTony Hutter
4592dd50e0ccSTony Hutter /* Is the last arg an interval value? Or a guid? */
4593dd50e0ccSTony Hutter if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL, cb)) {
4594dd50e0ccSTony Hutter /*
4595dd50e0ccSTony Hutter * The last arg is not a guid, so it's probably an
4596dd50e0ccSTony Hutter * interval value.
4597dd50e0ccSTony Hutter */
4598dd50e0ccSTony Hutter argc_for_interval++;
4599dd50e0ccSTony Hutter
4600dd50e0ccSTony Hutter if (*argc >= 2 &&
4601dd50e0ccSTony Hutter !are_vdevs_in_pool(1, &argv[*argc - 2], NULL, cb)) {
4602dd50e0ccSTony Hutter /*
4603dd50e0ccSTony Hutter * The 2nd to last arg is not a guid, so it's probably
4604dd50e0ccSTony Hutter * an interval value.
4605dd50e0ccSTony Hutter */
4606dd50e0ccSTony Hutter argc_for_interval++;
4607dd50e0ccSTony Hutter }
4608dd50e0ccSTony Hutter }
4609dd50e0ccSTony Hutter
4610dd50e0ccSTony Hutter /* Point to our list of possible intervals */
4611dd50e0ccSTony Hutter tmpargv = &argv[*argc - argc_for_interval];
4612dd50e0ccSTony Hutter
4613dd50e0ccSTony Hutter *argc = *argc - argc_for_interval;
4614dd50e0ccSTony Hutter get_interval_count(&argc_for_interval, tmpargv,
4615dd50e0ccSTony Hutter interval, count);
4616dd50e0ccSTony Hutter }
4617dd50e0ccSTony Hutter
4618dd50e0ccSTony Hutter /*
4619dd50e0ccSTony Hutter * Floating point sleep(). Allows you to pass in a floating point value for
4620dd50e0ccSTony Hutter * seconds.
4621dd50e0ccSTony Hutter */
4622dd50e0ccSTony Hutter static void
fsleep(float sec)4623dd50e0ccSTony Hutter fsleep(float sec)
4624dd50e0ccSTony Hutter {
4625dd50e0ccSTony Hutter struct timespec req;
4626dd50e0ccSTony Hutter req.tv_sec = floor(sec);
4627dd50e0ccSTony Hutter req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
4628dd50e0ccSTony Hutter (void) nanosleep(&req, NULL);
4629dd50e0ccSTony Hutter }
4630dd50e0ccSTony Hutter
4631dd50e0ccSTony Hutter /*
4632dd50e0ccSTony Hutter * Set the minimum pool/vdev name column width. The width must be at least 10,
4633dd50e0ccSTony Hutter * but may be as large as the column width - 42 so it still fits on one line.
4634dd50e0ccSTony Hutter */
4635dd50e0ccSTony Hutter static int
get_namewidth_iostat(zpool_handle_t * zhp,void * data)4636dd50e0ccSTony Hutter get_namewidth_iostat(zpool_handle_t *zhp, void *data)
4637dd50e0ccSTony Hutter {
4638dd50e0ccSTony Hutter iostat_cbdata_t *cb = data;
4639dd50e0ccSTony Hutter int width, columns;
4640dd50e0ccSTony Hutter
4641dd50e0ccSTony Hutter width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
4642dd50e0ccSTony Hutter cb->cb_verbose);
4643dd50e0ccSTony Hutter columns = get_columns();
4644dd50e0ccSTony Hutter
4645dd50e0ccSTony Hutter if (width < 10)
4646dd50e0ccSTony Hutter width = 10;
4647dd50e0ccSTony Hutter if (width > columns - 42)
4648dd50e0ccSTony Hutter width = columns - 42;
4649dd50e0ccSTony Hutter
4650dd50e0ccSTony Hutter cb->cb_namewidth = width;
4651dd50e0ccSTony Hutter
4652dd50e0ccSTony Hutter return (0);
4653dd50e0ccSTony Hutter }
4654dd50e0ccSTony Hutter
4655dd50e0ccSTony Hutter /*
4656dd50e0ccSTony Hutter * zpool iostat [-ghHLpPvy] [[-lq]|[-r|-w]] [-n name] [-T d|u]
4657dd50e0ccSTony Hutter * [[ pool ...]|[pool vdev ...]|[vdev ...]]
4658dd50e0ccSTony Hutter * [interval [count]]
46593f9d6ad7SLin Ling *
4660663207adSDon Brady * -g Display guid for individual vdev name.
4661663207adSDon Brady * -L Follow links when resolving vdev path name.
4662663207adSDon Brady * -P Display full path for vdev name.
46633f9d6ad7SLin Ling * -v Display statistics for individual vdevs
4664dd50e0ccSTony Hutter * -h Display help
4665dd50e0ccSTony Hutter * -p Display values in parsable (exact) format.
4666dd50e0ccSTony Hutter * -H Scripted mode. Don't display headers, and separate properties
4667dd50e0ccSTony Hutter * by a single tab.
4668dd50e0ccSTony Hutter * -l Display average latency
4669dd50e0ccSTony Hutter * -q Display queue depths
4670dd50e0ccSTony Hutter * -w Display latency histograms
4671dd50e0ccSTony Hutter * -r Display request size histogram
46723f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format
4673dd50e0ccSTony Hutter * -n Only print headers once
46743f9d6ad7SLin Ling *
46753f9d6ad7SLin Ling * This command can be tricky because we want to be able to deal with pool
46763f9d6ad7SLin Ling * creation/destruction as well as vdev configuration changes. The bulk of this
46773f9d6ad7SLin Ling * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
46783f9d6ad7SLin Ling * on pool_list_update() to detect the addition of new pools. Configuration
46793f9d6ad7SLin Ling * changes are all handled within libzfs.
46803f9d6ad7SLin Ling */
46813f9d6ad7SLin Ling int
zpool_do_iostat(int argc,char ** argv)46823f9d6ad7SLin Ling zpool_do_iostat(int argc, char **argv)
46833f9d6ad7SLin Ling {
46843f9d6ad7SLin Ling int c;
46853f9d6ad7SLin Ling int ret;
46863f9d6ad7SLin Ling int npools;
4687dd50e0ccSTony Hutter float interval = 0;
4688dd50e0ccSTony Hutter unsigned long count = 0;
4689dd50e0ccSTony Hutter int winheight = 24;
4690dd50e0ccSTony Hutter struct winsize win;
46913f9d6ad7SLin Ling zpool_list_t *list;
46923f9d6ad7SLin Ling boolean_t verbose = B_FALSE;
4693dd50e0ccSTony Hutter boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
4694dd50e0ccSTony Hutter boolean_t queues = B_FALSE, parseable = B_FALSE, scripted = B_FALSE;
4695dd50e0ccSTony Hutter boolean_t omit_since_boot = B_FALSE;
4696663207adSDon Brady boolean_t guid = B_FALSE;
4697663207adSDon Brady boolean_t follow_links = B_FALSE;
4698663207adSDon Brady boolean_t full_name = B_FALSE;
4699dd50e0ccSTony Hutter boolean_t headers_once = B_FALSE;
4700663207adSDon Brady iostat_cbdata_t cb = { 0 };
47013f9d6ad7SLin Ling
4702dd50e0ccSTony Hutter /* Used for printing error message */
4703dd50e0ccSTony Hutter const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q',
4704dd50e0ccSTony Hutter [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'};
4705dd50e0ccSTony Hutter
4706dd50e0ccSTony Hutter uint64_t unsupported_flags;
4707dd50e0ccSTony Hutter
47083f9d6ad7SLin Ling /* check options */
4709dd50e0ccSTony Hutter while ((c = getopt(argc, argv, "gLPT:vyhplqrwnH")) != -1) {
47103f9d6ad7SLin Ling switch (c) {
4711663207adSDon Brady case 'g':
4712663207adSDon Brady guid = B_TRUE;
4713663207adSDon Brady break;
4714663207adSDon Brady case 'L':
4715663207adSDon Brady follow_links = B_TRUE;
4716663207adSDon Brady break;
4717663207adSDon Brady case 'P':
4718663207adSDon Brady full_name = B_TRUE;
4719663207adSDon Brady break;
47203f9d6ad7SLin Ling case 'T':
47213f9d6ad7SLin Ling get_timestamp_arg(*optarg);
47223f9d6ad7SLin Ling break;
47233f9d6ad7SLin Ling case 'v':
47243f9d6ad7SLin Ling verbose = B_TRUE;
47253f9d6ad7SLin Ling break;
4726dd50e0ccSTony Hutter case 'p':
4727dd50e0ccSTony Hutter parseable = B_TRUE;
4728dd50e0ccSTony Hutter break;
4729dd50e0ccSTony Hutter case 'l':
4730dd50e0ccSTony Hutter latency = B_TRUE;
4731dd50e0ccSTony Hutter break;
4732dd50e0ccSTony Hutter case 'q':
4733dd50e0ccSTony Hutter queues = B_TRUE;
4734dd50e0ccSTony Hutter break;
4735dd50e0ccSTony Hutter case 'H':
4736dd50e0ccSTony Hutter scripted = B_TRUE;
4737dd50e0ccSTony Hutter break;
4738dd50e0ccSTony Hutter case 'w':
4739dd50e0ccSTony Hutter l_histo = B_TRUE;
4740dd50e0ccSTony Hutter break;
4741dd50e0ccSTony Hutter case 'r':
4742dd50e0ccSTony Hutter rq_histo = B_TRUE;
4743dd50e0ccSTony Hutter break;
4744dd50e0ccSTony Hutter case 'y':
4745dd50e0ccSTony Hutter omit_since_boot = B_TRUE;
4746dd50e0ccSTony Hutter break;
4747dd50e0ccSTony Hutter case 'n':
4748dd50e0ccSTony Hutter headers_once = B_TRUE;
4749dd50e0ccSTony Hutter break;
4750dd50e0ccSTony Hutter case 'h':
4751dd50e0ccSTony Hutter usage(B_FALSE);
4752dd50e0ccSTony Hutter break;
47533f9d6ad7SLin Ling case '?':
47543f9d6ad7SLin Ling (void) fprintf(stderr, gettext("invalid option '%c'\n"),
47553f9d6ad7SLin Ling optopt);
47563f9d6ad7SLin Ling usage(B_FALSE);
47573f9d6ad7SLin Ling }
47583f9d6ad7SLin Ling }
47593f9d6ad7SLin Ling
47603f9d6ad7SLin Ling argc -= optind;
47613f9d6ad7SLin Ling argv += optind;
47623f9d6ad7SLin Ling
4763dd50e0ccSTony Hutter cb.cb_literal = parseable;
4764dd50e0ccSTony Hutter cb.cb_scripted = scripted;
4765dd50e0ccSTony Hutter
4766dd50e0ccSTony Hutter if (guid)
4767dd50e0ccSTony Hutter cb.cb_name_flags |= VDEV_NAME_GUID;
4768dd50e0ccSTony Hutter if (follow_links)
4769dd50e0ccSTony Hutter cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
4770dd50e0ccSTony Hutter if (full_name)
4771dd50e0ccSTony Hutter cb.cb_name_flags |= VDEV_NAME_PATH;
4772dd50e0ccSTony Hutter cb.cb_iteration = 0;
4773dd50e0ccSTony Hutter cb.cb_namewidth = 0;
4774dd50e0ccSTony Hutter cb.cb_verbose = verbose;
4775dd50e0ccSTony Hutter
4776dd50e0ccSTony Hutter /* Get our interval and count values (if any) */
4777dd50e0ccSTony Hutter if (guid) {
4778dd50e0ccSTony Hutter get_interval_count_filter_guids(&argc, argv, &interval,
4779dd50e0ccSTony Hutter &count, &cb);
4780dd50e0ccSTony Hutter } else {
47813f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count);
4782dd50e0ccSTony Hutter }
4783dd50e0ccSTony Hutter
4784dd50e0ccSTony Hutter if (argc == 0) {
4785dd50e0ccSTony Hutter /* No args, so just print the defaults. */
4786dd50e0ccSTony Hutter } else if (are_all_pools(argc, argv)) {
4787dd50e0ccSTony Hutter /* All the args are pool names */
4788dd50e0ccSTony Hutter } else if (are_vdevs_in_pool(argc, argv, NULL, &cb)) {
4789dd50e0ccSTony Hutter /* All the args are vdevs */
4790dd50e0ccSTony Hutter cb.cb_vdev_names = argv;
4791dd50e0ccSTony Hutter cb.cb_vdev_names_count = argc;
4792dd50e0ccSTony Hutter argc = 0; /* No pools to process */
4793dd50e0ccSTony Hutter } else if (are_all_pools(1, argv)) {
4794dd50e0ccSTony Hutter /* The first arg is a pool name */
4795dd50e0ccSTony Hutter if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb)) {
4796dd50e0ccSTony Hutter /* ...and the rest are vdev names */
4797dd50e0ccSTony Hutter cb.cb_vdev_names = argv + 1;
4798dd50e0ccSTony Hutter cb.cb_vdev_names_count = argc - 1;
4799dd50e0ccSTony Hutter argc = 1; /* One pool to process */
4800dd50e0ccSTony Hutter } else {
4801dd50e0ccSTony Hutter fprintf(stderr, gettext("Expected either a list of "));
4802dd50e0ccSTony Hutter fprintf(stderr, gettext("pools, or list of vdevs in"));
4803dd50e0ccSTony Hutter fprintf(stderr, " \"%s\", ", argv[0]);
4804dd50e0ccSTony Hutter fprintf(stderr, gettext("but got:\n"));
4805dd50e0ccSTony Hutter error_list_unresolved_vdevs(argc - 1, argv + 1,
4806dd50e0ccSTony Hutter argv[0], &cb);
4807dd50e0ccSTony Hutter fprintf(stderr, "\n");
4808dd50e0ccSTony Hutter usage(B_FALSE);
4809dd50e0ccSTony Hutter return (1);
4810dd50e0ccSTony Hutter }
4811dd50e0ccSTony Hutter } else {
4812dd50e0ccSTony Hutter /*
4813dd50e0ccSTony Hutter * The args don't make sense. The first arg isn't a pool name,
4814dd50e0ccSTony Hutter * nor are all the args vdevs.
4815dd50e0ccSTony Hutter */
4816dd50e0ccSTony Hutter fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n"));
4817dd50e0ccSTony Hutter fprintf(stderr, "\n");
4818dd50e0ccSTony Hutter return (1);
4819dd50e0ccSTony Hutter }
4820dd50e0ccSTony Hutter
4821dd50e0ccSTony Hutter if (cb.cb_vdev_names_count != 0) {
4822dd50e0ccSTony Hutter /*
4823dd50e0ccSTony Hutter * If user specified vdevs, it implies verbose.
4824dd50e0ccSTony Hutter */
4825dd50e0ccSTony Hutter cb.cb_verbose = B_TRUE;
4826dd50e0ccSTony Hutter }
48273f9d6ad7SLin Ling
4828fa9e4066Sahrens /*
4829fa9e4066Sahrens * Construct the list of all interesting pools.
4830fa9e4066Sahrens */
4831fa9e4066Sahrens ret = 0;
4832b1b8ab34Slling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
4833fa9e4066Sahrens return (1);
4834fa9e4066Sahrens
483599653d4eSeschrock if (pool_list_count(list) == 0 && argc != 0) {
483699653d4eSeschrock pool_list_free(list);
4837fa9e4066Sahrens return (1);
483899653d4eSeschrock }
4839fa9e4066Sahrens
4840fa9e4066Sahrens if (pool_list_count(list) == 0 && interval == 0) {
484199653d4eSeschrock pool_list_free(list);
4842fa9e4066Sahrens (void) fprintf(stderr, gettext("no pools available\n"));
4843fa9e4066Sahrens return (1);
4844fa9e4066Sahrens }
4845fa9e4066Sahrens
4846dd50e0ccSTony Hutter if ((l_histo || rq_histo) && (queues || latency)) {
4847dd50e0ccSTony Hutter pool_list_free(list);
4848dd50e0ccSTony Hutter (void) fprintf(stderr,
4849dd50e0ccSTony Hutter gettext("[-r|-w] isn't allowed with [-q|-l]\n"));
4850dd50e0ccSTony Hutter usage(B_FALSE);
4851dd50e0ccSTony Hutter return (1);
4852dd50e0ccSTony Hutter }
4853dd50e0ccSTony Hutter
4854dd50e0ccSTony Hutter if (l_histo && rq_histo) {
4855dd50e0ccSTony Hutter pool_list_free(list);
4856dd50e0ccSTony Hutter (void) fprintf(stderr,
4857dd50e0ccSTony Hutter gettext("Only one of [-r|-w] can be passed at a time\n"));
4858dd50e0ccSTony Hutter usage(B_FALSE);
4859dd50e0ccSTony Hutter return (1);
4860dd50e0ccSTony Hutter }
4861dd50e0ccSTony Hutter
4862fa9e4066Sahrens /*
4863fa9e4066Sahrens * Enter the main iostat loop.
4864fa9e4066Sahrens */
4865fa9e4066Sahrens cb.cb_list = list;
4866fa9e4066Sahrens
4867dd50e0ccSTony Hutter if (l_histo) {
4868dd50e0ccSTony Hutter /*
4869dd50e0ccSTony Hutter * Histograms tables look out of place when you try to display
4870dd50e0ccSTony Hutter * them with the other stats, so make a rule that you can only
4871dd50e0ccSTony Hutter * print histograms by themselves.
4872dd50e0ccSTony Hutter */
4873dd50e0ccSTony Hutter cb.cb_flags = IOS_L_HISTO_M;
4874dd50e0ccSTony Hutter } else if (rq_histo) {
4875dd50e0ccSTony Hutter cb.cb_flags = IOS_RQ_HISTO_M;
4876dd50e0ccSTony Hutter } else {
4877dd50e0ccSTony Hutter cb.cb_flags = IOS_DEFAULT_M;
4878dd50e0ccSTony Hutter if (latency)
4879dd50e0ccSTony Hutter cb.cb_flags |= IOS_LATENCY_M;
4880dd50e0ccSTony Hutter if (queues)
4881dd50e0ccSTony Hutter cb.cb_flags |= IOS_QUEUES_M;
4882dd50e0ccSTony Hutter }
4883fa9e4066Sahrens
4884fa9e4066Sahrens /*
4885dd50e0ccSTony Hutter * See if the module supports all the stats we want to display.
4886088e9d47Seschrock */
4887dd50e0ccSTony Hutter unsupported_flags = cb.cb_flags & ~get_stat_flags(list);
4888dd50e0ccSTony Hutter if (unsupported_flags) {
4889dd50e0ccSTony Hutter uint64_t f;
4890dd50e0ccSTony Hutter int idx;
4891dd50e0ccSTony Hutter fprintf(stderr,
4892dd50e0ccSTony Hutter gettext("The loaded zfs module doesn't support:"));
4893dd50e0ccSTony Hutter
4894dd50e0ccSTony Hutter /* for each bit set in unsupported_flags */
4895dd50e0ccSTony Hutter for (f = unsupported_flags; f; f &= ~(1ULL << idx)) {
4896dd50e0ccSTony Hutter idx = lowbit64(f) - 1;
4897dd50e0ccSTony Hutter fprintf(stderr, " -%c", flag_to_arg[idx]);
4898dd50e0ccSTony Hutter }
4899dd50e0ccSTony Hutter
4900dd50e0ccSTony Hutter fprintf(stderr, ". Try running a newer module.\n"),
4901dd50e0ccSTony Hutter pool_list_free(list);
4902dd50e0ccSTony Hutter
4903dd50e0ccSTony Hutter return (1);
4904dd50e0ccSTony Hutter }
4905dd50e0ccSTony Hutter
4906dd50e0ccSTony Hutter for (;;) {
4907dd50e0ccSTony Hutter if ((npools = pool_list_count(list)) == 0)
4908dd50e0ccSTony Hutter (void) fprintf(stderr, gettext("no pools available\n"));
4909dd50e0ccSTony Hutter else {
4910dd50e0ccSTony Hutter /*
4911dd50e0ccSTony Hutter * If this is the first iteration and -y was supplied
4912dd50e0ccSTony Hutter * we skip any printing.
4913dd50e0ccSTony Hutter */
4914dd50e0ccSTony Hutter boolean_t skip = (omit_since_boot &&
4915dd50e0ccSTony Hutter cb.cb_iteration == 0);
4916dd50e0ccSTony Hutter
4917dd50e0ccSTony Hutter /*
4918dd50e0ccSTony Hutter * Refresh all statistics. This is done as an
4919dd50e0ccSTony Hutter * explicit step before calculating the maximum name
4920dd50e0ccSTony Hutter * width, so that any configuration changes are
4921dd50e0ccSTony Hutter * properly accounted for.
4922dd50e0ccSTony Hutter */
4923dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, refresh_iostat,
4924dd50e0ccSTony Hutter &cb);
4925088e9d47Seschrock
4926088e9d47Seschrock /*
4927fa9e4066Sahrens * Iterate over all pools to determine the maximum width
4928fa9e4066Sahrens * for the pool / device name column across all pools.
4929fa9e4066Sahrens */
4930fa9e4066Sahrens cb.cb_namewidth = 0;
4931dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE,
4932dd50e0ccSTony Hutter get_namewidth_iostat, &cb);
4933fa9e4066Sahrens
493426fd7700SKrishnendu Sadhukhan - Sun Microsystems if (timestamp_fmt != NODATE)
493526fd7700SKrishnendu Sadhukhan - Sun Microsystems print_timestamp(timestamp_fmt);
493626fd7700SKrishnendu Sadhukhan - Sun Microsystems
4937fa9e4066Sahrens /*
4938dd50e0ccSTony Hutter * Check terminal size so we can print headers
4939dd50e0ccSTony Hutter * even when terminal window has its height
4940dd50e0ccSTony Hutter * changed.
4941fa9e4066Sahrens */
4942dd50e0ccSTony Hutter if (headers_once == B_FALSE) {
4943dd50e0ccSTony Hutter if (ioctl(1, TIOCGWINSZ, &win) != -1) {
4944dd50e0ccSTony Hutter if (win.ws_row <= 0) {
4945dd50e0ccSTony Hutter headers_once = B_TRUE;
4946dd50e0ccSTony Hutter } else {
4947dd50e0ccSTony Hutter winheight = win.ws_row;
4948dd50e0ccSTony Hutter }
4949dd50e0ccSTony Hutter }
4950dd50e0ccSTony Hutter }
4951dd50e0ccSTony Hutter /*
4952dd50e0ccSTony Hutter * Are we connected to TTY? If not, headers_once
4953dd50e0ccSTony Hutter * should be true, to avoid breaking scripts.
4954dd50e0ccSTony Hutter */
4955dd50e0ccSTony Hutter if (isatty(fileno(stdout)) == 0)
4956dd50e0ccSTony Hutter headers_once = B_TRUE;
4957dd50e0ccSTony Hutter
4958dd50e0ccSTony Hutter /*
4959dd50e0ccSTony Hutter * If it's the first time and we're not skipping it,
4960dd50e0ccSTony Hutter * or either skip or verbose mode, print the header.
4961dd50e0ccSTony Hutter *
4962dd50e0ccSTony Hutter * The histogram code explicitly prints its header on
4963dd50e0ccSTony Hutter * every vdev, so skip this for histograms.
4964dd50e0ccSTony Hutter */
4965dd50e0ccSTony Hutter if (((++cb.cb_iteration == 1 && !skip) ||
4966dd50e0ccSTony Hutter (skip != verbose) ||
4967dd50e0ccSTony Hutter (!headers_once &&
4968dd50e0ccSTony Hutter (cb.cb_iteration % winheight) == 0)) &&
4969dd50e0ccSTony Hutter (!(cb.cb_flags & IOS_ANYHISTO_M)) &&
4970dd50e0ccSTony Hutter !cb.cb_scripted)
4971fa9e4066Sahrens print_iostat_header(&cb);
4972fa9e4066Sahrens
4973dd50e0ccSTony Hutter if (skip) {
4974dd50e0ccSTony Hutter (void) fsleep(interval);
4975dd50e0ccSTony Hutter continue;
4976dd50e0ccSTony Hutter }
4977dd50e0ccSTony Hutter
497899653d4eSeschrock (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
4979fa9e4066Sahrens
4980fa9e4066Sahrens /*
4981dd50e0ccSTony Hutter * If there's more than one pool, and we're not in
4982dd50e0ccSTony Hutter * verbose mode (which prints a separator for us),
4983dd50e0ccSTony Hutter * then print a separator.
4984dd50e0ccSTony Hutter *
4985dd50e0ccSTony Hutter * In addition, if we're printing specific vdevs then
4986dd50e0ccSTony Hutter * we also want an ending separator.
4987fa9e4066Sahrens */
4988dd50e0ccSTony Hutter if (((npools > 1 && !verbose &&
4989dd50e0ccSTony Hutter !(cb.cb_flags & IOS_ANYHISTO_M)) ||
4990dd50e0ccSTony Hutter (!(cb.cb_flags & IOS_ANYHISTO_M) &&
4991dd50e0ccSTony Hutter cb.cb_vdev_names_count)) &&
4992dd50e0ccSTony Hutter !cb.cb_scripted) {
4993fa9e4066Sahrens print_iostat_separator(&cb);
499420f5062bSJerry Jelinek printf("\n");
4995dd50e0ccSTony Hutter }
4996dd50e0ccSTony Hutter }
4997fa9e4066Sahrens
499839c23413Seschrock /*
499939c23413Seschrock * Flush the output so that redirection to a file isn't buffered
500039c23413Seschrock * indefinitely.
500139c23413Seschrock */
500239c23413Seschrock (void) fflush(stdout);
500339c23413Seschrock
5004fa9e4066Sahrens if (interval == 0)
5005fa9e4066Sahrens break;
5006fa9e4066Sahrens
5007fa9e4066Sahrens if (count != 0 && --count == 0)
5008fa9e4066Sahrens break;
5009fa9e4066Sahrens
5010dd50e0ccSTony Hutter (void) fsleep(interval);
5011fa9e4066Sahrens }
5012fa9e4066Sahrens
5013fa9e4066Sahrens pool_list_free(list);
5014fa9e4066Sahrens
5015fa9e4066Sahrens return (ret);
5016fa9e4066Sahrens }
5017fa9e4066Sahrens
5018fa9e4066Sahrens typedef struct list_cbdata {
50194263d13fSGeorge Wilson boolean_t cb_verbose;
5020663207adSDon Brady int cb_name_flags;
50214263d13fSGeorge Wilson int cb_namewidth;
502299653d4eSeschrock boolean_t cb_scripted;
5023990b4856Slling zprop_list_t *cb_proplist;
5024c58b3526SAdam Stevko boolean_t cb_literal;
5025fa9e4066Sahrens } list_cbdata_t;
5026fa9e4066Sahrens
5027663207adSDon Brady
5028fa9e4066Sahrens /*
5029fa9e4066Sahrens * Given a list of columns to display, output appropriate headers for each one.
5030fa9e4066Sahrens */
5031990b4856Slling static void
print_header(list_cbdata_t * cb)50324263d13fSGeorge Wilson print_header(list_cbdata_t *cb)
5033fa9e4066Sahrens {
50344263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist;
5035ad135b5dSChristopher Siden char headerbuf[ZPOOL_MAXPROPLEN];
5036990b4856Slling const char *header;
5037990b4856Slling boolean_t first = B_TRUE;
5038990b4856Slling boolean_t right_justify;
50394263d13fSGeorge Wilson size_t width = 0;
5040fa9e4066Sahrens
5041990b4856Slling for (; pl != NULL; pl = pl->pl_next) {
50424263d13fSGeorge Wilson width = pl->pl_width;
50434263d13fSGeorge Wilson if (first && cb->cb_verbose) {
50444263d13fSGeorge Wilson /*
50454263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing
50464263d13fSGeorge Wilson * of devices.
50474263d13fSGeorge Wilson */
50484263d13fSGeorge Wilson width = cb->cb_namewidth;
50494263d13fSGeorge Wilson }
50504263d13fSGeorge Wilson
5051990b4856Slling if (!first)
5052fa9e4066Sahrens (void) printf(" ");
5053fa9e4066Sahrens else
5054990b4856Slling first = B_FALSE;
5055fa9e4066Sahrens
5056ad135b5dSChristopher Siden right_justify = B_FALSE;
5057ad135b5dSChristopher Siden if (pl->pl_prop != ZPROP_INVAL) {
5058990b4856Slling header = zpool_prop_column_name(pl->pl_prop);
5059990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop);
5060ad135b5dSChristopher Siden } else {
5061ad135b5dSChristopher Siden int i;
5062ad135b5dSChristopher Siden
5063ad135b5dSChristopher Siden for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
5064ad135b5dSChristopher Siden headerbuf[i] = toupper(pl->pl_user_prop[i]);
5065ad135b5dSChristopher Siden headerbuf[i] = '\0';
5066ad135b5dSChristopher Siden header = headerbuf;
5067ad135b5dSChristopher Siden }
5068990b4856Slling
5069990b4856Slling if (pl->pl_next == NULL && !right_justify)
5070990b4856Slling (void) printf("%s", header);
5071990b4856Slling else if (right_justify)
50724263d13fSGeorge Wilson (void) printf("%*s", width, header);
5073990b4856Slling else
50744263d13fSGeorge Wilson (void) printf("%-*s", width, header);
50754263d13fSGeorge Wilson
5076fa9e4066Sahrens }
5077fa9e4066Sahrens
5078fa9e4066Sahrens (void) printf("\n");
5079fa9e4066Sahrens }
5080fa9e4066Sahrens
5081990b4856Slling /*
5082990b4856Slling * Given a pool and a list of properties, print out all the properties according
5083663207adSDon Brady * to the described layout. Used by zpool_do_list().
5084990b4856Slling */
5085990b4856Slling static void
print_pool(zpool_handle_t * zhp,list_cbdata_t * cb)50864263d13fSGeorge Wilson print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
5087990b4856Slling {
50884263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist;
5089990b4856Slling boolean_t first = B_TRUE;
5090990b4856Slling char property[ZPOOL_MAXPROPLEN];
5091990b4856Slling char *propstr;
5092990b4856Slling boolean_t right_justify;
50934263d13fSGeorge Wilson size_t width;
5094990b4856Slling
5095990b4856Slling for (; pl != NULL; pl = pl->pl_next) {
50964263d13fSGeorge Wilson
50974263d13fSGeorge Wilson width = pl->pl_width;
50984263d13fSGeorge Wilson if (first && cb->cb_verbose) {
50994263d13fSGeorge Wilson /*
51004263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing
51014263d13fSGeorge Wilson * of devices.
51024263d13fSGeorge Wilson */
51034263d13fSGeorge Wilson width = cb->cb_namewidth;
51044263d13fSGeorge Wilson }
51054263d13fSGeorge Wilson
5106990b4856Slling if (!first) {
51074263d13fSGeorge Wilson if (cb->cb_scripted)
5108990b4856Slling (void) printf("\t");
5109990b4856Slling else
5110990b4856Slling (void) printf(" ");
5111990b4856Slling } else {
5112990b4856Slling first = B_FALSE;
5113990b4856Slling }
5114990b4856Slling
5115990b4856Slling right_justify = B_FALSE;
5116990b4856Slling if (pl->pl_prop != ZPROP_INVAL) {
51177a09f97bSGeorge Wilson if (zpool_get_prop(zhp, pl->pl_prop, property,
5118c58b3526SAdam Stevko sizeof (property), NULL, cb->cb_literal) != 0)
5119990b4856Slling propstr = "-";
5120990b4856Slling else
5121990b4856Slling propstr = property;
5122990b4856Slling
5123990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop);
5124ad135b5dSChristopher Siden } else if ((zpool_prop_feature(pl->pl_user_prop) ||
5125ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop)) &&
5126ad135b5dSChristopher Siden zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
5127ad135b5dSChristopher Siden sizeof (property)) == 0) {
5128ad135b5dSChristopher Siden propstr = property;
5129990b4856Slling } else {
5130990b4856Slling propstr = "-";
5131990b4856Slling }
5132990b4856Slling
5133990b4856Slling
5134990b4856Slling /*
5135990b4856Slling * If this is being called in scripted mode, or if this is the
5136990b4856Slling * last column and it is left-justified, don't include a width
5137990b4856Slling * format specifier.
5138990b4856Slling */
51394263d13fSGeorge Wilson if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
5140990b4856Slling (void) printf("%s", propstr);
5141990b4856Slling else if (right_justify)
5142990b4856Slling (void) printf("%*s", width, propstr);
5143990b4856Slling else
5144990b4856Slling (void) printf("%-*s", width, propstr);
5145990b4856Slling }
5146990b4856Slling
5147990b4856Slling (void) printf("\n");
5148990b4856Slling }
5149990b4856Slling
51504263d13fSGeorge Wilson static void
print_one_column(zpool_prop_t prop,uint64_t value,const char * str,boolean_t scripted,boolean_t valid,enum zfs_nicenum_format format)5151609febc9SBrian Behlendorf print_one_column(zpool_prop_t prop, uint64_t value, const char *str,
5152609febc9SBrian Behlendorf boolean_t scripted, boolean_t valid, enum zfs_nicenum_format format)
51534263d13fSGeorge Wilson {
51544263d13fSGeorge Wilson char propval[64];
51554263d13fSGeorge Wilson boolean_t fixed;
51564263d13fSGeorge Wilson size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
51574263d13fSGeorge Wilson
51587a09f97bSGeorge Wilson switch (prop) {
51597a09f97bSGeorge Wilson case ZPOOL_PROP_EXPANDSZ:
516086714001SSerapheim Dimitropoulos case ZPOOL_PROP_CHECKPOINT:
5161609febc9SBrian Behlendorf case ZPOOL_PROP_DEDUPRATIO:
51627a09f97bSGeorge Wilson if (value == 0)
51634263d13fSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval));
51642e4c9986SGeorge Wilson else
51653dfe8017SChrister Ekholm zfs_nicenum_format(value, propval, sizeof (propval),
51663dfe8017SChrister Ekholm format);
51677a09f97bSGeorge Wilson break;
51687a09f97bSGeorge Wilson case ZPOOL_PROP_FRAGMENTATION:
51697a09f97bSGeorge Wilson if (value == ZFS_FRAG_INVALID) {
51707a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval));
51713dfe8017SChrister Ekholm } else if (format == ZFS_NICENUM_RAW) {
51723dfe8017SChrister Ekholm (void) snprintf(propval, sizeof (propval), "%llu",
51733dfe8017SChrister Ekholm (unsigned long long)value);
51747a09f97bSGeorge Wilson } else {
51757a09f97bSGeorge Wilson (void) snprintf(propval, sizeof (propval), "%llu%%",
51763dfe8017SChrister Ekholm (unsigned long long)value);
51777a09f97bSGeorge Wilson }
51787a09f97bSGeorge Wilson break;
51797a09f97bSGeorge Wilson case ZPOOL_PROP_CAPACITY:
51803dfe8017SChrister Ekholm if (format == ZFS_NICENUM_RAW)
51813dfe8017SChrister Ekholm (void) snprintf(propval, sizeof (propval), "%llu",
51823dfe8017SChrister Ekholm (unsigned long long)value / 100);
51833dfe8017SChrister Ekholm
51843dfe8017SChrister Ekholm else
5185663207adSDon Brady (void) snprintf(propval, sizeof (propval),
5186663207adSDon Brady value < 1000 ? "%1.2f%%" : value < 10000 ?
5187663207adSDon Brady "%2.1f%%" : "%3.0f%%", value / 100.0);
51887a09f97bSGeorge Wilson break;
5189609febc9SBrian Behlendorf case ZPOOL_PROP_HEALTH:
5190609febc9SBrian Behlendorf width = 8;
5191609febc9SBrian Behlendorf (void) strlcpy(propval, str, sizeof (propval));
5192609febc9SBrian Behlendorf break;
51937a09f97bSGeorge Wilson default:
51943dfe8017SChrister Ekholm zfs_nicenum_format(value, propval, sizeof (propval), format);
51957a09f97bSGeorge Wilson }
51967a09f97bSGeorge Wilson
51977a09f97bSGeorge Wilson if (!valid)
51987a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval));
51994263d13fSGeorge Wilson
52004263d13fSGeorge Wilson if (scripted)
52014263d13fSGeorge Wilson (void) printf("\t%s", propval);
52024263d13fSGeorge Wilson else
52034263d13fSGeorge Wilson (void) printf(" %*s", width, propval);
52044263d13fSGeorge Wilson }
52054263d13fSGeorge Wilson
5206663207adSDon Brady /*
5207663207adSDon Brady * print static default line per vdev
5208663207adSDon Brady */
52094263d13fSGeorge Wilson void
print_list_stats(zpool_handle_t * zhp,const char * name,nvlist_t * nv,list_cbdata_t * cb,int depth,boolean_t isspare)52104263d13fSGeorge Wilson print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
5211609febc9SBrian Behlendorf list_cbdata_t *cb, int depth, boolean_t isspare)
52124263d13fSGeorge Wilson {
52134263d13fSGeorge Wilson nvlist_t **child;
52144263d13fSGeorge Wilson vdev_stat_t *vs;
52154263d13fSGeorge Wilson uint_t c, children;
52164263d13fSGeorge Wilson char *vname;
52174263d13fSGeorge Wilson boolean_t scripted = cb->cb_scripted;
521852244c09SJohn Wren Kennedy uint64_t islog = B_FALSE;
5219609febc9SBrian Behlendorf char *dashes = " %-*s - - - - "
5220609febc9SBrian Behlendorf "- - - - -\n";
52214263d13fSGeorge Wilson
52224263d13fSGeorge Wilson verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
52234263d13fSGeorge Wilson (uint64_t **)&vs, &c) == 0);
52244263d13fSGeorge Wilson
52254263d13fSGeorge Wilson if (name != NULL) {
52267a09f97bSGeorge Wilson boolean_t toplevel = (vs->vs_space != 0);
52277a09f97bSGeorge Wilson uint64_t cap;
52283dfe8017SChrister Ekholm enum zfs_nicenum_format format;
5229609febc9SBrian Behlendorf const char *state;
52303dfe8017SChrister Ekholm
52313dfe8017SChrister Ekholm if (cb->cb_literal)
52323dfe8017SChrister Ekholm format = ZFS_NICENUM_RAW;
52333dfe8017SChrister Ekholm else
52343dfe8017SChrister Ekholm format = ZFS_NICENUM_1024;
52357a09f97bSGeorge Wilson
52365cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
52375cabbc6bSPrashanth Sreenivasa return;
52385cabbc6bSPrashanth Sreenivasa
52394263d13fSGeorge Wilson if (scripted)
52404263d13fSGeorge Wilson (void) printf("\t%s", name);
52414263d13fSGeorge Wilson else if (strlen(name) + depth > cb->cb_namewidth)
52424263d13fSGeorge Wilson (void) printf("%*s%s", depth, "", name);
52434263d13fSGeorge Wilson else
52444263d13fSGeorge Wilson (void) printf("%*s%s%*s", depth, "", name,
52454263d13fSGeorge Wilson (int)(cb->cb_namewidth - strlen(name) - depth), "");
52464263d13fSGeorge Wilson
52477a09f97bSGeorge Wilson /*
52487a09f97bSGeorge Wilson * Print the properties for the individual vdevs. Some
52497a09f97bSGeorge Wilson * properties are only applicable to toplevel vdevs. The
52507a09f97bSGeorge Wilson * 'toplevel' boolean value is passed to the print_one_column()
52517a09f97bSGeorge Wilson * to indicate that the value is valid.
52527a09f97bSGeorge Wilson */
5253609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, NULL, scripted,
52543dfe8017SChrister Ekholm toplevel, format);
5255609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, NULL,
52563dfe8017SChrister Ekholm scripted, toplevel, format);
5257609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
5258609febc9SBrian Behlendorf NULL, scripted, toplevel, format);
525986714001SSerapheim Dimitropoulos print_one_column(ZPOOL_PROP_CHECKPOINT,
5260609febc9SBrian Behlendorf vs->vs_checkpoint_space, NULL, scripted, toplevel, format);
5261609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, NULL,
5262609febc9SBrian Behlendorf scripted, B_TRUE, format);
52632e4c9986SGeorge Wilson print_one_column(ZPOOL_PROP_FRAGMENTATION,
5264609febc9SBrian Behlendorf vs->vs_fragmentation, NULL, scripted,
52653dfe8017SChrister Ekholm (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel),
52663dfe8017SChrister Ekholm format);
52677a09f97bSGeorge Wilson cap = (vs->vs_space == 0) ? 0 :
5268663207adSDon Brady (vs->vs_alloc * 10000 / vs->vs_space);
5269609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_CAPACITY, cap, NULL,
5270609febc9SBrian Behlendorf scripted, toplevel, format);
5271609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_DEDUPRATIO, 0, NULL,
5272609febc9SBrian Behlendorf scripted, toplevel, format);
5273609febc9SBrian Behlendorf state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
5274609febc9SBrian Behlendorf if (isspare) {
5275609febc9SBrian Behlendorf if (vs->vs_aux == VDEV_AUX_SPARED)
5276609febc9SBrian Behlendorf state = "INUSE";
5277609febc9SBrian Behlendorf else if (vs->vs_state == VDEV_STATE_HEALTHY)
5278609febc9SBrian Behlendorf state = "AVAIL";
5279609febc9SBrian Behlendorf }
5280609febc9SBrian Behlendorf print_one_column(ZPOOL_PROP_HEALTH, 0, state, scripted,
5281609febc9SBrian Behlendorf B_TRUE, format);
52824263d13fSGeorge Wilson (void) printf("\n");
52834263d13fSGeorge Wilson }
52844263d13fSGeorge Wilson
52854263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
52864263d13fSGeorge Wilson &child, &children) != 0)
52874263d13fSGeorge Wilson return;
52884263d13fSGeorge Wilson
5289663207adSDon Brady /* list the normal vdevs first */
52904263d13fSGeorge Wilson for (c = 0; c < children; c++) {
52914263d13fSGeorge Wilson uint64_t ishole = B_FALSE;
52924263d13fSGeorge Wilson
52934263d13fSGeorge Wilson if (nvlist_lookup_uint64(child[c],
52944263d13fSGeorge Wilson ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
52954263d13fSGeorge Wilson continue;
52964263d13fSGeorge Wilson
529752244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c],
5298663207adSDon Brady ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog)
529952244c09SJohn Wren Kennedy continue;
530052244c09SJohn Wren Kennedy
5301663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
5302663207adSDon Brady continue;
5303663207adSDon Brady
5304663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c],
5305663207adSDon Brady cb->cb_name_flags);
5306609febc9SBrian Behlendorf print_list_stats(zhp, vname, child[c], cb, depth + 1, B_FALSE);
53074263d13fSGeorge Wilson free(vname);
53084263d13fSGeorge Wilson }
53094263d13fSGeorge Wilson
5310663207adSDon Brady /* list the classes: 'logs', 'dedup', and 'special' */
5311663207adSDon Brady for (uint_t n = 0; n < 3; n++) {
5312663207adSDon Brady boolean_t printed = B_FALSE;
5313663207adSDon Brady
53144263d13fSGeorge Wilson for (c = 0; c < children; c++) {
5315663207adSDon Brady char *bias = NULL;
5316663207adSDon Brady char *type = NULL;
5317663207adSDon Brady
531852244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
5319663207adSDon Brady &islog) == 0 && islog) {
5320663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS;
5321663207adSDon Brady } else {
5322663207adSDon Brady (void) nvlist_lookup_string(child[c],
5323663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
5324663207adSDon Brady (void) nvlist_lookup_string(child[c],
5325663207adSDon Brady ZPOOL_CONFIG_TYPE, &type);
5326663207adSDon Brady }
5327663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0)
532852244c09SJohn Wren Kennedy continue;
5329663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
5330663207adSDon Brady continue;
5331663207adSDon Brady
5332663207adSDon Brady if (!printed) {
5333663207adSDon Brady (void) printf(dashes, cb->cb_namewidth,
5334663207adSDon Brady class_name[n]);
5335663207adSDon Brady printed = B_TRUE;
5336663207adSDon Brady }
5337663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c],
5338663207adSDon Brady cb->cb_name_flags);
5339609febc9SBrian Behlendorf print_list_stats(zhp, vname, child[c], cb, depth + 2,
5340609febc9SBrian Behlendorf B_FALSE);
534152244c09SJohn Wren Kennedy free(vname);
534252244c09SJohn Wren Kennedy }
534352244c09SJohn Wren Kennedy }
534452244c09SJohn Wren Kennedy
534552244c09SJohn Wren Kennedy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
534652244c09SJohn Wren Kennedy &child, &children) == 0 && children > 0) {
534752244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "cache");
534852244c09SJohn Wren Kennedy for (c = 0; c < children; c++) {
5349663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c],
5350663207adSDon Brady cb->cb_name_flags);
5351609febc9SBrian Behlendorf print_list_stats(zhp, vname, child[c], cb, depth + 2,
5352609febc9SBrian Behlendorf B_FALSE);
535352244c09SJohn Wren Kennedy free(vname);
535452244c09SJohn Wren Kennedy }
535552244c09SJohn Wren Kennedy }
535652244c09SJohn Wren Kennedy
535752244c09SJohn Wren Kennedy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
535852244c09SJohn Wren Kennedy &children) == 0 && children > 0) {
535952244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "spare");
536052244c09SJohn Wren Kennedy for (c = 0; c < children; c++) {
5361663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c],
5362663207adSDon Brady cb->cb_name_flags);
5363609febc9SBrian Behlendorf print_list_stats(zhp, vname, child[c], cb, depth + 2,
5364609febc9SBrian Behlendorf B_TRUE);
53654263d13fSGeorge Wilson free(vname);
53664263d13fSGeorge Wilson }
53674263d13fSGeorge Wilson }
53684263d13fSGeorge Wilson }
53694263d13fSGeorge Wilson
5370990b4856Slling /*
5371990b4856Slling * Generic callback function to list a pool.
5372990b4856Slling */
5373fa9e4066Sahrens int
list_callback(zpool_handle_t * zhp,void * data)5374fa9e4066Sahrens list_callback(zpool_handle_t *zhp, void *data)
5375fa9e4066Sahrens {
5376fa9e4066Sahrens list_cbdata_t *cbp = data;
5377663207adSDon Brady
5378663207adSDon Brady print_pool(zhp, cbp);
5379663207adSDon Brady
5380609febc9SBrian Behlendorf if (cbp->cb_verbose) {
5381609febc9SBrian Behlendorf nvlist_t *config, *nvroot;
5382609febc9SBrian Behlendorf
5383609febc9SBrian Behlendorf config = zpool_get_config(zhp, NULL);
5384609febc9SBrian Behlendorf verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5385609febc9SBrian Behlendorf &nvroot) == 0);
5386609febc9SBrian Behlendorf print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE);
5387609febc9SBrian Behlendorf }
5388fa9e4066Sahrens
5389fa9e4066Sahrens return (0);
5390fa9e4066Sahrens }
5391fa9e4066Sahrens
5392fa9e4066Sahrens /*
5393dd50e0ccSTony Hutter * Set the minimum pool/vdev name column width. The width must be at least 9,
5394dd50e0ccSTony Hutter * but may be as large as needed.
5395dd50e0ccSTony Hutter */
5396dd50e0ccSTony Hutter static int
get_namewidth_list(zpool_handle_t * zhp,void * data)5397dd50e0ccSTony Hutter get_namewidth_list(zpool_handle_t *zhp, void *data)
5398dd50e0ccSTony Hutter {
5399dd50e0ccSTony Hutter list_cbdata_t *cb = data;
5400dd50e0ccSTony Hutter int width;
5401dd50e0ccSTony Hutter
5402dd50e0ccSTony Hutter width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
5403dd50e0ccSTony Hutter cb->cb_verbose);
5404dd50e0ccSTony Hutter
5405dd50e0ccSTony Hutter if (width < 9)
5406dd50e0ccSTony Hutter width = 9;
5407dd50e0ccSTony Hutter
5408dd50e0ccSTony Hutter cb->cb_namewidth = width;
5409dd50e0ccSTony Hutter
5410dd50e0ccSTony Hutter return (0);
5411dd50e0ccSTony Hutter }
5412dd50e0ccSTony Hutter
5413dd50e0ccSTony Hutter /*
5414663207adSDon Brady * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
5415fa9e4066Sahrens *
5416663207adSDon Brady * -g Display guid for individual vdev name.
5417990b4856Slling * -H Scripted mode. Don't display headers, and separate properties
5418990b4856Slling * by a single tab.
5419663207adSDon Brady * -L Follow links when resolving vdev path name.
5420990b4856Slling * -o List of properties to display. Defaults to
54217a09f97bSGeorge Wilson * "name,size,allocated,free,expandsize,fragmentation,capacity,"
54227a09f97bSGeorge Wilson * "dedupratio,health,altroot"
5423c58b3526SAdam Stevko * -p Diplay values in parsable (exact) format.
5424663207adSDon Brady * -P Display full path for vdev name.
54253f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format
5426fa9e4066Sahrens *
5427fa9e4066Sahrens * List all pools in the system, whether or not they're healthy. Output space
5428fa9e4066Sahrens * statistics for each one, as well as health status summary.
5429fa9e4066Sahrens */
5430fa9e4066Sahrens int
zpool_do_list(int argc,char ** argv)5431fa9e4066Sahrens zpool_do_list(int argc, char **argv)
5432fa9e4066Sahrens {
5433fa9e4066Sahrens int c;
5434fa9e4066Sahrens int ret;
5435fa9e4066Sahrens list_cbdata_t cb = { 0 };
5436990b4856Slling static char default_props[] =
543786714001SSerapheim Dimitropoulos "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
543886714001SSerapheim Dimitropoulos "capacity,dedupratio,health,altroot";
5439990b4856Slling char *props = default_props;
5440dd50e0ccSTony Hutter float interval = 0;
5441dd50e0ccSTony Hutter unsigned long count = 0;
54424263d13fSGeorge Wilson zpool_list_t *list;
54434263d13fSGeorge Wilson boolean_t first = B_TRUE;
5444fa9e4066Sahrens
5445fa9e4066Sahrens /* check options */
5446663207adSDon Brady while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
5447fa9e4066Sahrens switch (c) {
5448663207adSDon Brady case 'g':
5449663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID;
5450663207adSDon Brady break;
5451fa9e4066Sahrens case 'H':
545299653d4eSeschrock cb.cb_scripted = B_TRUE;
5453fa9e4066Sahrens break;
5454663207adSDon Brady case 'L':
5455663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
5456663207adSDon Brady break;
5457fa9e4066Sahrens case 'o':
5458990b4856Slling props = optarg;
5459fa9e4066Sahrens break;
5460663207adSDon Brady case 'P':
5461663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH;
5462663207adSDon Brady break;
5463c58b3526SAdam Stevko case 'p':
5464c58b3526SAdam Stevko cb.cb_literal = B_TRUE;
5465c58b3526SAdam Stevko break;
54663f9d6ad7SLin Ling case 'T':
54673f9d6ad7SLin Ling get_timestamp_arg(*optarg);
54683f9d6ad7SLin Ling break;
54694263d13fSGeorge Wilson case 'v':
54704263d13fSGeorge Wilson cb.cb_verbose = B_TRUE;
5471663207adSDon Brady cb.cb_namewidth = 8; /* 8 until precalc is avail */
54724263d13fSGeorge Wilson break;
5473fa9e4066Sahrens case ':':
5474fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for "
5475fa9e4066Sahrens "'%c' option\n"), optopt);
547699653d4eSeschrock usage(B_FALSE);
5477fa9e4066Sahrens break;
5478fa9e4066Sahrens case '?':
5479fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5480fa9e4066Sahrens optopt);
548199653d4eSeschrock usage(B_FALSE);
5482fa9e4066Sahrens }
5483fa9e4066Sahrens }
5484fa9e4066Sahrens
5485fa9e4066Sahrens argc -= optind;
5486fa9e4066Sahrens argv += optind;
5487fa9e4066Sahrens
54883f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count);
54893f9d6ad7SLin Ling
5490990b4856Slling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
549199653d4eSeschrock usage(B_FALSE);
5492fa9e4066Sahrens
54934263d13fSGeorge Wilson for (;;) {
5494cd67d23dSGeorge Wilson if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
5495cd67d23dSGeorge Wilson &ret)) == NULL)
5496cd67d23dSGeorge Wilson return (1);
54974263d13fSGeorge Wilson
54984263d13fSGeorge Wilson if (pool_list_count(list) == 0)
54994263d13fSGeorge Wilson break;
55004263d13fSGeorge Wilson
55014263d13fSGeorge Wilson cb.cb_namewidth = 0;
5502dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, get_namewidth_list, &cb);
55034263d13fSGeorge Wilson
55044263d13fSGeorge Wilson if (timestamp_fmt != NODATE)
55054263d13fSGeorge Wilson print_timestamp(timestamp_fmt);
55064263d13fSGeorge Wilson
55074263d13fSGeorge Wilson if (!cb.cb_scripted && (first || cb.cb_verbose)) {
55084263d13fSGeorge Wilson print_header(&cb);
55094263d13fSGeorge Wilson first = B_FALSE;
55104263d13fSGeorge Wilson }
55114263d13fSGeorge Wilson ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
55124263d13fSGeorge Wilson
55133f9d6ad7SLin Ling if (interval == 0)
55143f9d6ad7SLin Ling break;
55153f9d6ad7SLin Ling
55163f9d6ad7SLin Ling if (count != 0 && --count == 0)
55173f9d6ad7SLin Ling break;
55183f9d6ad7SLin Ling
5519cd67d23dSGeorge Wilson pool_list_free(list);
5520dd50e0ccSTony Hutter (void) fsleep(interval);
55213f9d6ad7SLin Ling }
55223f9d6ad7SLin Ling
5523cd67d23dSGeorge Wilson if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
5524cd67d23dSGeorge Wilson (void) printf(gettext("no pools available\n"));
5525cd67d23dSGeorge Wilson ret = 0;
5526cd67d23dSGeorge Wilson }
5527cd67d23dSGeorge Wilson
5528cd67d23dSGeorge Wilson pool_list_free(list);
55293f9d6ad7SLin Ling zprop_free_list(cb.cb_proplist);
5530fa9e4066Sahrens return (ret);
5531fa9e4066Sahrens }
5532fa9e4066Sahrens
5533fa9e4066Sahrens static int
zpool_do_attach_or_replace(int argc,char ** argv,int replacing)5534fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing)
5535fa9e4066Sahrens {
553699653d4eSeschrock boolean_t force = B_FALSE;
5537fa9e4066Sahrens int c;
5538fa9e4066Sahrens nvlist_t *nvroot;
5539fa9e4066Sahrens char *poolname, *old_disk, *new_disk;
5540fa9e4066Sahrens zpool_handle_t *zhp;
55417855d95bSToomas Soome zpool_boot_label_t boot_type;
55427855d95bSToomas Soome uint64_t boot_size;
55435711d393Sloli10K nvlist_t *props = NULL;
55445711d393Sloli10K char *propval;
554599653d4eSeschrock int ret;
5546fa9e4066Sahrens
5547fa9e4066Sahrens /* check options */
55485711d393Sloli10K while ((c = getopt(argc, argv, "fo:")) != -1) {
5549fa9e4066Sahrens switch (c) {
5550fa9e4066Sahrens case 'f':
555199653d4eSeschrock force = B_TRUE;
5552fa9e4066Sahrens break;
55535711d393Sloli10K case 'o':
55545711d393Sloli10K if ((propval = strchr(optarg, '=')) == NULL) {
55555711d393Sloli10K (void) fprintf(stderr, gettext("missing "
55565711d393Sloli10K "'=' for -o option\n"));
55575711d393Sloli10K usage(B_FALSE);
55585711d393Sloli10K }
55595711d393Sloli10K *propval = '\0';
55605711d393Sloli10K propval++;
55615711d393Sloli10K
55625711d393Sloli10K if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
55635711d393Sloli10K (add_prop_list(optarg, propval, &props, B_TRUE)))
55645711d393Sloli10K usage(B_FALSE);
55655711d393Sloli10K break;
5566fa9e4066Sahrens case '?':
5567fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5568fa9e4066Sahrens optopt);
556999653d4eSeschrock usage(B_FALSE);
5570fa9e4066Sahrens }
5571fa9e4066Sahrens }
5572fa9e4066Sahrens
5573fa9e4066Sahrens argc -= optind;
5574fa9e4066Sahrens argv += optind;
5575fa9e4066Sahrens
5576fa9e4066Sahrens /* get pool name and check number of arguments */
5577fa9e4066Sahrens if (argc < 1) {
5578fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n"));
557999653d4eSeschrock usage(B_FALSE);
5580fa9e4066Sahrens }
5581fa9e4066Sahrens
5582fa9e4066Sahrens poolname = argv[0];
5583fa9e4066Sahrens
5584fa9e4066Sahrens if (argc < 2) {
5585fa9e4066Sahrens (void) fprintf(stderr,
5586fa9e4066Sahrens gettext("missing <device> specification\n"));
558799653d4eSeschrock usage(B_FALSE);
5588fa9e4066Sahrens }
5589fa9e4066Sahrens
5590fa9e4066Sahrens old_disk = argv[1];
5591fa9e4066Sahrens
5592fa9e4066Sahrens if (argc < 3) {
5593fa9e4066Sahrens if (!replacing) {
5594fa9e4066Sahrens (void) fprintf(stderr,
5595fa9e4066Sahrens gettext("missing <new_device> specification\n"));
559699653d4eSeschrock usage(B_FALSE);
5597fa9e4066Sahrens }
5598fa9e4066Sahrens new_disk = old_disk;
5599fa9e4066Sahrens argc -= 1;
5600fa9e4066Sahrens argv += 1;
5601fa9e4066Sahrens } else {
5602fa9e4066Sahrens new_disk = argv[2];
5603fa9e4066Sahrens argc -= 2;
5604fa9e4066Sahrens argv += 2;
5605fa9e4066Sahrens }
5606fa9e4066Sahrens
5607fa9e4066Sahrens if (argc > 1) {
5608fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n"));
560999653d4eSeschrock usage(B_FALSE);
5610fa9e4066Sahrens }
5611fa9e4066Sahrens
561299653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5613fa9e4066Sahrens return (1);
5614fa9e4066Sahrens
56158488aeb5Staylor if (zpool_get_config(zhp, NULL) == NULL) {
5616fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
5617fa9e4066Sahrens poolname);
5618fa9e4066Sahrens zpool_close(zhp);
5619fa9e4066Sahrens return (1);
5620fa9e4066Sahrens }
5621fa9e4066Sahrens
56227855d95bSToomas Soome if (zpool_is_bootable(zhp))
56237855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL;
56247855d95bSToomas Soome else
56257855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL;
56267855d95bSToomas Soome
56277855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
56285711d393Sloli10K
56295711d393Sloli10K /* unless manually specified use "ashift" pool property (if set) */
56305711d393Sloli10K if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
56315711d393Sloli10K int intval;
56325711d393Sloli10K zprop_source_t src;
56335711d393Sloli10K char strval[ZPOOL_MAXPROPLEN];
56345711d393Sloli10K
56355711d393Sloli10K intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
56365711d393Sloli10K if (src != ZPROP_SRC_DEFAULT) {
56375711d393Sloli10K (void) sprintf(strval, "%" PRId32, intval);
56385711d393Sloli10K verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
56395711d393Sloli10K &props, B_TRUE) == 0);
56405711d393Sloli10K }
56415711d393Sloli10K }
56425711d393Sloli10K
56435711d393Sloli10K nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
56447855d95bSToomas Soome boot_type, boot_size, argc, argv);
5645fa9e4066Sahrens if (nvroot == NULL) {
5646fa9e4066Sahrens zpool_close(zhp);
5647fa9e4066Sahrens return (1);
5648fa9e4066Sahrens }
5649fa9e4066Sahrens
565099653d4eSeschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
565199653d4eSeschrock
565299653d4eSeschrock nvlist_free(nvroot);
565399653d4eSeschrock zpool_close(zhp);
565499653d4eSeschrock
565599653d4eSeschrock return (ret);
5656fa9e4066Sahrens }
5657fa9e4066Sahrens
5658fa9e4066Sahrens /*
5659fa9e4066Sahrens * zpool replace [-f] <pool> <device> <new_device>
5660fa9e4066Sahrens *
5661fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use.
5662fa9e4066Sahrens *
5663fa9e4066Sahrens * Replace <device> with <new_device>.
5664fa9e4066Sahrens */
5665fa9e4066Sahrens /* ARGSUSED */
5666fa9e4066Sahrens int
zpool_do_replace(int argc,char ** argv)5667fa9e4066Sahrens zpool_do_replace(int argc, char **argv)
5668fa9e4066Sahrens {
5669fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
5670fa9e4066Sahrens }
5671fa9e4066Sahrens
5672fa9e4066Sahrens /*
56735711d393Sloli10K * zpool attach [-f] [-o property=value] <pool> <device> <new_device>
5674fa9e4066Sahrens *
5675fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use.
56765711d393Sloli10K * -o Set property=value.
5677fa9e4066Sahrens *
5678fa9e4066Sahrens * Attach <new_device> to the mirror containing <device>. If <device> is not
5679fa9e4066Sahrens * part of a mirror, then <device> will be transformed into a mirror of
5680fa9e4066Sahrens * <device> and <new_device>. In either case, <new_device> will begin life
5681fa9e4066Sahrens * with a DTL of [0, now], and will immediately begin to resilver itself.
5682fa9e4066Sahrens */
5683fa9e4066Sahrens int
zpool_do_attach(int argc,char ** argv)5684fa9e4066Sahrens zpool_do_attach(int argc, char **argv)
5685fa9e4066Sahrens {
5686fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
5687fa9e4066Sahrens }
5688fa9e4066Sahrens
5689fa9e4066Sahrens /*
5690fa9e4066Sahrens * zpool detach [-f] <pool> <device>
5691fa9e4066Sahrens *
5692fa9e4066Sahrens * -f Force detach of <device>, even if DTLs argue against it
5693fa9e4066Sahrens * (not supported yet)
5694fa9e4066Sahrens *
5695fa9e4066Sahrens * Detach a device from a mirror. The operation will be refused if <device>
5696fa9e4066Sahrens * is the last device in the mirror, or if the DTLs indicate that this device
5697fa9e4066Sahrens * has the only valid copy of some data.
5698fa9e4066Sahrens */
5699fa9e4066Sahrens /* ARGSUSED */
5700fa9e4066Sahrens int
zpool_do_detach(int argc,char ** argv)5701fa9e4066Sahrens zpool_do_detach(int argc, char **argv)
5702fa9e4066Sahrens {
5703fa9e4066Sahrens int c;
5704fa9e4066Sahrens char *poolname, *path;
5705fa9e4066Sahrens zpool_handle_t *zhp;
570699653d4eSeschrock int ret;
5707fa9e4066Sahrens
5708fa9e4066Sahrens /* check options */
5709fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) {
5710fa9e4066Sahrens switch (c) {
5711fa9e4066Sahrens case 'f':
5712fa9e4066Sahrens case '?':
5713fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5714fa9e4066Sahrens optopt);
571599653d4eSeschrock usage(B_FALSE);
5716fa9e4066Sahrens }
5717fa9e4066Sahrens }
5718fa9e4066Sahrens
5719fa9e4066Sahrens argc -= optind;
5720fa9e4066Sahrens argv += optind;
5721fa9e4066Sahrens
5722fa9e4066Sahrens /* get pool name and check number of arguments */
5723fa9e4066Sahrens if (argc < 1) {
5724fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n"));
572599653d4eSeschrock usage(B_FALSE);
5726fa9e4066Sahrens }
5727fa9e4066Sahrens
5728fa9e4066Sahrens if (argc < 2) {
5729fa9e4066Sahrens (void) fprintf(stderr,
5730fa9e4066Sahrens gettext("missing <device> specification\n"));
573199653d4eSeschrock usage(B_FALSE);
5732fa9e4066Sahrens }
5733fa9e4066Sahrens
5734fa9e4066Sahrens poolname = argv[0];
5735fa9e4066Sahrens path = argv[1];
5736fa9e4066Sahrens
573799653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5738fa9e4066Sahrens return (1);
5739fa9e4066Sahrens
574099653d4eSeschrock ret = zpool_vdev_detach(zhp, path);
574199653d4eSeschrock
574299653d4eSeschrock zpool_close(zhp);
574399653d4eSeschrock
574499653d4eSeschrock return (ret);
5745fa9e4066Sahrens }
5746fa9e4066Sahrens
5747fa9e4066Sahrens /*
5748663207adSDon Brady * zpool split [-gLnP] [-o prop=val] ...
57491195e687SMark J Musante * [-o mntopt] ...
57501195e687SMark J Musante * [-R altroot] <pool> <newpool> [<device> ...]
57511195e687SMark J Musante *
5752663207adSDon Brady * -g Display guid for individual vdev name.
5753663207adSDon Brady * -L Follow links when resolving vdev path name.
57541195e687SMark J Musante * -n Do not split the pool, but display the resulting layout if
57551195e687SMark J Musante * it were to be split.
57561195e687SMark J Musante * -o Set property=value, or set mount options.
5757663207adSDon Brady * -P Display full path for vdev name.
57581195e687SMark J Musante * -R Mount the split-off pool under an alternate root.
5759eb633035STom Caputi * -l Load encryption keys while importing.
57601195e687SMark J Musante *
57611195e687SMark J Musante * Splits the named pool and gives it the new pool name. Devices to be split
57621195e687SMark J Musante * off may be listed, provided that no more than one device is specified
57631195e687SMark J Musante * per top-level vdev mirror. The newly split pool is left in an exported
57641195e687SMark J Musante * state unless -R is specified.
57651195e687SMark J Musante *
57661195e687SMark J Musante * Restrictions: the top-level of the pool pool must only be made up of
57671195e687SMark J Musante * mirrors; all devices in the pool must be healthy; no device may be
57681195e687SMark J Musante * undergoing a resilvering operation.
57691195e687SMark J Musante */
57701195e687SMark J Musante int
zpool_do_split(int argc,char ** argv)57711195e687SMark J Musante zpool_do_split(int argc, char **argv)
57721195e687SMark J Musante {
57731195e687SMark J Musante char *srcpool, *newpool, *propval;
57741195e687SMark J Musante char *mntopts = NULL;
57751195e687SMark J Musante splitflags_t flags;
57761195e687SMark J Musante int c, ret = 0;
5777eb633035STom Caputi boolean_t loadkeys = B_FALSE;
57781195e687SMark J Musante zpool_handle_t *zhp;
57791195e687SMark J Musante nvlist_t *config, *props = NULL;
57801195e687SMark J Musante
57811195e687SMark J Musante flags.dryrun = B_FALSE;
57821195e687SMark J Musante flags.import = B_FALSE;
5783663207adSDon Brady flags.name_flags = 0;
57841195e687SMark J Musante
57851195e687SMark J Musante /* check options */
5786eb633035STom Caputi while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) {
57871195e687SMark J Musante switch (c) {
5788663207adSDon Brady case 'g':
5789663207adSDon Brady flags.name_flags |= VDEV_NAME_GUID;
5790663207adSDon Brady break;
5791663207adSDon Brady case 'L':
5792663207adSDon Brady flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
5793663207adSDon Brady break;
57941195e687SMark J Musante case 'R':
57951195e687SMark J Musante flags.import = B_TRUE;
57961195e687SMark J Musante if (add_prop_list(
57971195e687SMark J Musante zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
57981195e687SMark J Musante &props, B_TRUE) != 0) {
57991195e687SMark J Musante nvlist_free(props);
58001195e687SMark J Musante usage(B_FALSE);
58011195e687SMark J Musante }
58021195e687SMark J Musante break;
5803eb633035STom Caputi case 'l':
5804eb633035STom Caputi loadkeys = B_TRUE;
5805eb633035STom Caputi break;
58061195e687SMark J Musante case 'n':
58071195e687SMark J Musante flags.dryrun = B_TRUE;
58081195e687SMark J Musante break;
58091195e687SMark J Musante case 'o':
58101195e687SMark J Musante if ((propval = strchr(optarg, '=')) != NULL) {
58111195e687SMark J Musante *propval = '\0';
58121195e687SMark J Musante propval++;
58131195e687SMark J Musante if (add_prop_list(optarg, propval,
58141195e687SMark J Musante &props, B_TRUE) != 0) {
58151195e687SMark J Musante nvlist_free(props);
58161195e687SMark J Musante usage(B_FALSE);
58171195e687SMark J Musante }
58181195e687SMark J Musante } else {
58191195e687SMark J Musante mntopts = optarg;
58201195e687SMark J Musante }
58211195e687SMark J Musante break;
5822663207adSDon Brady case 'P':
5823663207adSDon Brady flags.name_flags |= VDEV_NAME_PATH;
5824663207adSDon Brady break;
58251195e687SMark J Musante case ':':
58261195e687SMark J Musante (void) fprintf(stderr, gettext("missing argument for "
58271195e687SMark J Musante "'%c' option\n"), optopt);
58281195e687SMark J Musante usage(B_FALSE);
58291195e687SMark J Musante break;
58301195e687SMark J Musante case '?':
58311195e687SMark J Musante (void) fprintf(stderr, gettext("invalid option '%c'\n"),
58321195e687SMark J Musante optopt);
58331195e687SMark J Musante usage(B_FALSE);
58341195e687SMark J Musante break;
58351195e687SMark J Musante }
58361195e687SMark J Musante }
58371195e687SMark J Musante
58381195e687SMark J Musante if (!flags.import && mntopts != NULL) {
58391195e687SMark J Musante (void) fprintf(stderr, gettext("setting mntopts is only "
58401195e687SMark J Musante "valid when importing the pool\n"));
58411195e687SMark J Musante usage(B_FALSE);
58421195e687SMark J Musante }
58431195e687SMark J Musante
5844eb633035STom Caputi if (!flags.import && loadkeys) {
5845eb633035STom Caputi (void) fprintf(stderr, gettext("loading keys is only "
5846eb633035STom Caputi "valid when importing the pool\n"));
5847eb633035STom Caputi usage(B_FALSE);
5848eb633035STom Caputi }
5849eb633035STom Caputi
58501195e687SMark J Musante argc -= optind;
58511195e687SMark J Musante argv += optind;
58521195e687SMark J Musante
58531195e687SMark J Musante if (argc < 1) {
58541195e687SMark J Musante (void) fprintf(stderr, gettext("Missing pool name\n"));
58551195e687SMark J Musante usage(B_FALSE);
58561195e687SMark J Musante }
58571195e687SMark J Musante if (argc < 2) {
58581195e687SMark J Musante (void) fprintf(stderr, gettext("Missing new pool name\n"));
58591195e687SMark J Musante usage(B_FALSE);
58601195e687SMark J Musante }
58611195e687SMark J Musante
58621195e687SMark J Musante srcpool = argv[0];
58631195e687SMark J Musante newpool = argv[1];
58641195e687SMark J Musante
58651195e687SMark J Musante argc -= 2;
58661195e687SMark J Musante argv += 2;
58671195e687SMark J Musante
58681195e687SMark J Musante if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
58691195e687SMark J Musante return (1);
58701195e687SMark J Musante
58711195e687SMark J Musante config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
58721195e687SMark J Musante if (config == NULL) {
58731195e687SMark J Musante ret = 1;
58741195e687SMark J Musante } else {
58751195e687SMark J Musante if (flags.dryrun) {
58761195e687SMark J Musante (void) printf(gettext("would create '%s' with the "
58771195e687SMark J Musante "following layout:\n\n"), newpool);
5878663207adSDon Brady print_vdev_tree(NULL, newpool, config, 0, "",
5879663207adSDon Brady flags.name_flags);
58801195e687SMark J Musante }
58811195e687SMark J Musante nvlist_free(config);
58821195e687SMark J Musante }
58831195e687SMark J Musante
58841195e687SMark J Musante zpool_close(zhp);
58851195e687SMark J Musante
58861195e687SMark J Musante if (ret != 0 || flags.dryrun || !flags.import)
58871195e687SMark J Musante return (ret);
58881195e687SMark J Musante
58891195e687SMark J Musante /*
58901195e687SMark J Musante * The split was successful. Now we need to open the new
58911195e687SMark J Musante * pool and import it.
58921195e687SMark J Musante */
58931195e687SMark J Musante if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
58941195e687SMark J Musante return (1);
5895eb633035STom Caputi
5896eb633035STom Caputi if (loadkeys) {
5897eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, newpool);
5898eb633035STom Caputi if (ret != 0)
5899eb633035STom Caputi ret = 1;
5900eb633035STom Caputi }
5901eb633035STom Caputi
59021195e687SMark J Musante if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
59031195e687SMark J Musante zpool_enable_datasets(zhp, mntopts, 0) != 0) {
59041195e687SMark J Musante ret = 1;
5905fe7cd8aaSCyril Plisko (void) fprintf(stderr, gettext("Split was successful, but "
59061195e687SMark J Musante "the datasets could not all be mounted\n"));
59071195e687SMark J Musante (void) fprintf(stderr, gettext("Try doing '%s' with a "
59081195e687SMark J Musante "different altroot\n"), "zpool import");
59091195e687SMark J Musante }
59101195e687SMark J Musante zpool_close(zhp);
59111195e687SMark J Musante
59121195e687SMark J Musante return (ret);
59131195e687SMark J Musante }
59141195e687SMark J Musante
59151195e687SMark J Musante
59161195e687SMark J Musante
59171195e687SMark J Musante /*
5918441d80aaSlling * zpool online <pool> <device> ...
5919fa9e4066Sahrens */
5920fa9e4066Sahrens int
zpool_do_online(int argc,char ** argv)5921fa9e4066Sahrens zpool_do_online(int argc, char **argv)
5922fa9e4066Sahrens {
5923fa9e4066Sahrens int c, i;
5924fa9e4066Sahrens char *poolname;
5925fa9e4066Sahrens zpool_handle_t *zhp;
5926fa9e4066Sahrens int ret = 0;
59273d7072f8Seschrock vdev_state_t newstate;
5928573ca77eSGeorge Wilson int flags = 0;
5929fa9e4066Sahrens
5930fa9e4066Sahrens /* check options */
5931573ca77eSGeorge Wilson while ((c = getopt(argc, argv, "et")) != -1) {
5932fa9e4066Sahrens switch (c) {
5933573ca77eSGeorge Wilson case 'e':
5934573ca77eSGeorge Wilson flags |= ZFS_ONLINE_EXPAND;
5935573ca77eSGeorge Wilson break;
5936fa9e4066Sahrens case 't':
5937fa9e4066Sahrens case '?':
5938fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5939fa9e4066Sahrens optopt);
594099653d4eSeschrock usage(B_FALSE);
5941fa9e4066Sahrens }
5942fa9e4066Sahrens }
5943fa9e4066Sahrens
5944fa9e4066Sahrens argc -= optind;
5945fa9e4066Sahrens argv += optind;
5946fa9e4066Sahrens
5947fa9e4066Sahrens /* get pool name and check number of arguments */
5948fa9e4066Sahrens if (argc < 1) {
5949fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n"));
595099653d4eSeschrock usage(B_FALSE);
5951fa9e4066Sahrens }
5952fa9e4066Sahrens if (argc < 2) {
5953fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n"));
595499653d4eSeschrock usage(B_FALSE);
5955fa9e4066Sahrens }
5956fa9e4066Sahrens
5957fa9e4066Sahrens poolname = argv[0];
5958fa9e4066Sahrens
595999653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
5960fa9e4066Sahrens return (1);
5961fa9e4066Sahrens
59623d7072f8Seschrock for (i = 1; i < argc; i++) {
5963573ca77eSGeorge Wilson if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
59643d7072f8Seschrock if (newstate != VDEV_STATE_HEALTHY) {
59653d7072f8Seschrock (void) printf(gettext("warning: device '%s' "
59663d7072f8Seschrock "onlined, but remains in faulted state\n"),
5967fa9e4066Sahrens argv[i]);
59683d7072f8Seschrock if (newstate == VDEV_STATE_FAULTED)
59693d7072f8Seschrock (void) printf(gettext("use 'zpool "
59703d7072f8Seschrock "clear' to restore a faulted "
59713d7072f8Seschrock "device\n"));
5972fa9e4066Sahrens else
59733d7072f8Seschrock (void) printf(gettext("use 'zpool "
59743d7072f8Seschrock "replace' to replace devices "
59753d7072f8Seschrock "that are no longer present\n"));
59763d7072f8Seschrock }
59773d7072f8Seschrock } else {
5978fa9e4066Sahrens ret = 1;
59793d7072f8Seschrock }
59803d7072f8Seschrock }
5981fa9e4066Sahrens
598299653d4eSeschrock zpool_close(zhp);
598399653d4eSeschrock
5984fa9e4066Sahrens return (ret);
5985fa9e4066Sahrens }
5986fa9e4066Sahrens
5987fa9e4066Sahrens /*
5988441d80aaSlling * zpool offline [-ft] <pool> <device> ...
5989fa9e4066Sahrens *
5990fa9e4066Sahrens * -f Force the device into the offline state, even if doing
5991fa9e4066Sahrens * so would appear to compromise pool availability.
5992fa9e4066Sahrens * (not supported yet)
5993fa9e4066Sahrens *
5994fa9e4066Sahrens * -t Only take the device off-line temporarily. The offline
5995fa9e4066Sahrens * state will not be persistent across reboots.
5996fa9e4066Sahrens */
5997fa9e4066Sahrens /* ARGSUSED */
5998fa9e4066Sahrens int
zpool_do_offline(int argc,char ** argv)5999fa9e4066Sahrens zpool_do_offline(int argc, char **argv)
6000fa9e4066Sahrens {
6001fa9e4066Sahrens int c, i;
6002fa9e4066Sahrens char *poolname;
6003fa9e4066Sahrens zpool_handle_t *zhp;
600499653d4eSeschrock int ret = 0;
600599653d4eSeschrock boolean_t istmp = B_FALSE;
6006fa9e4066Sahrens
6007fa9e4066Sahrens /* check options */
6008fa9e4066Sahrens while ((c = getopt(argc, argv, "ft")) != -1) {
6009fa9e4066Sahrens switch (c) {
6010fa9e4066Sahrens case 't':
601199653d4eSeschrock istmp = B_TRUE;
6012441d80aaSlling break;
6013441d80aaSlling case 'f':
6014fa9e4066Sahrens case '?':
6015fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6016fa9e4066Sahrens optopt);
601799653d4eSeschrock usage(B_FALSE);
6018fa9e4066Sahrens }
6019fa9e4066Sahrens }
6020fa9e4066Sahrens
6021fa9e4066Sahrens argc -= optind;
6022fa9e4066Sahrens argv += optind;
6023fa9e4066Sahrens
6024fa9e4066Sahrens /* get pool name and check number of arguments */
6025fa9e4066Sahrens if (argc < 1) {
6026fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n"));
602799653d4eSeschrock usage(B_FALSE);
6028fa9e4066Sahrens }
6029fa9e4066Sahrens if (argc < 2) {
6030fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n"));
603199653d4eSeschrock usage(B_FALSE);
6032fa9e4066Sahrens }
6033fa9e4066Sahrens
6034fa9e4066Sahrens poolname = argv[0];
6035fa9e4066Sahrens
603699653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6037fa9e4066Sahrens return (1);
6038fa9e4066Sahrens
60393d7072f8Seschrock for (i = 1; i < argc; i++) {
60403d7072f8Seschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
6041fa9e4066Sahrens ret = 1;
60423d7072f8Seschrock }
6043fa9e4066Sahrens
604499653d4eSeschrock zpool_close(zhp);
604599653d4eSeschrock
6046fa9e4066Sahrens return (ret);
6047fa9e4066Sahrens }
6048fa9e4066Sahrens
6049ea8dc4b6Seschrock /*
6050ea8dc4b6Seschrock * zpool clear <pool> [device]
6051ea8dc4b6Seschrock *
6052ea8dc4b6Seschrock * Clear all errors associated with a pool or a particular device.
6053ea8dc4b6Seschrock */
6054ea8dc4b6Seschrock int
zpool_do_clear(int argc,char ** argv)6055ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv)
6056ea8dc4b6Seschrock {
6057468c413aSTim Haley int c;
6058ea8dc4b6Seschrock int ret = 0;
6059468c413aSTim Haley boolean_t dryrun = B_FALSE;
6060468c413aSTim Haley boolean_t do_rewind = B_FALSE;
6061468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE;
6062468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND;
6063468c413aSTim Haley nvlist_t *policy = NULL;
6064ea8dc4b6Seschrock zpool_handle_t *zhp;
6065ea8dc4b6Seschrock char *pool, *device;
6066ea8dc4b6Seschrock
6067468c413aSTim Haley /* check options */
6068468c413aSTim Haley while ((c = getopt(argc, argv, "FnX")) != -1) {
6069468c413aSTim Haley switch (c) {
6070468c413aSTim Haley case 'F':
6071468c413aSTim Haley do_rewind = B_TRUE;
6072468c413aSTim Haley break;
6073468c413aSTim Haley case 'n':
6074468c413aSTim Haley dryrun = B_TRUE;
6075468c413aSTim Haley break;
6076468c413aSTim Haley case 'X':
6077468c413aSTim Haley xtreme_rewind = B_TRUE;
6078468c413aSTim Haley break;
6079468c413aSTim Haley case '?':
6080468c413aSTim Haley (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6081468c413aSTim Haley optopt);
6082468c413aSTim Haley usage(B_FALSE);
6083468c413aSTim Haley }
6084468c413aSTim Haley }
6085468c413aSTim Haley
6086468c413aSTim Haley argc -= optind;
6087468c413aSTim Haley argv += optind;
6088468c413aSTim Haley
6089468c413aSTim Haley if (argc < 1) {
6090ea8dc4b6Seschrock (void) fprintf(stderr, gettext("missing pool name\n"));
609199653d4eSeschrock usage(B_FALSE);
6092ea8dc4b6Seschrock }
6093ea8dc4b6Seschrock
6094468c413aSTim Haley if (argc > 2) {
6095ea8dc4b6Seschrock (void) fprintf(stderr, gettext("too many arguments\n"));
609699653d4eSeschrock usage(B_FALSE);
6097ea8dc4b6Seschrock }
6098ea8dc4b6Seschrock
6099468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) {
6100468c413aSTim Haley (void) fprintf(stderr,
6101468c413aSTim Haley gettext("-n or -X only meaningful with -F\n"));
6102468c413aSTim Haley usage(B_FALSE);
6103468c413aSTim Haley }
6104468c413aSTim Haley if (dryrun)
6105468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND;
6106468c413aSTim Haley else if (do_rewind)
6107468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND;
6108468c413aSTim Haley if (xtreme_rewind)
6109468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND;
6110ea8dc4b6Seschrock
6111468c413aSTim Haley /* In future, further rewind policy choices can be passed along here */
6112468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
61135dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
61145dafeea3SPavel Zakharov rewind_policy) != 0) {
6115ea8dc4b6Seschrock return (1);
61165dafeea3SPavel Zakharov }
6117ea8dc4b6Seschrock
6118468c413aSTim Haley pool = argv[0];
6119468c413aSTim Haley device = argc == 2 ? argv[1] : NULL;
6120468c413aSTim Haley
6121468c413aSTim Haley if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
6122468c413aSTim Haley nvlist_free(policy);
6123468c413aSTim Haley return (1);
6124468c413aSTim Haley }
6125468c413aSTim Haley
6126468c413aSTim Haley if (zpool_clear(zhp, device, policy) != 0)
6127ea8dc4b6Seschrock ret = 1;
6128ea8dc4b6Seschrock
6129ea8dc4b6Seschrock zpool_close(zhp);
6130ea8dc4b6Seschrock
6131468c413aSTim Haley nvlist_free(policy);
6132468c413aSTim Haley
6133ea8dc4b6Seschrock return (ret);
6134ea8dc4b6Seschrock }
6135ea8dc4b6Seschrock
6136e9103aaeSGarrett D'Amore /*
6137e9103aaeSGarrett D'Amore * zpool reguid <pool>
6138e9103aaeSGarrett D'Amore */
6139e9103aaeSGarrett D'Amore int
zpool_do_reguid(int argc,char ** argv)6140e9103aaeSGarrett D'Amore zpool_do_reguid(int argc, char **argv)
6141e9103aaeSGarrett D'Amore {
6142e9103aaeSGarrett D'Amore int c;
6143e9103aaeSGarrett D'Amore char *poolname;
6144e9103aaeSGarrett D'Amore zpool_handle_t *zhp;
6145e9103aaeSGarrett D'Amore int ret = 0;
6146e9103aaeSGarrett D'Amore
6147e9103aaeSGarrett D'Amore /* check options */
6148e9103aaeSGarrett D'Amore while ((c = getopt(argc, argv, "")) != -1) {
6149e9103aaeSGarrett D'Amore switch (c) {
6150e9103aaeSGarrett D'Amore case '?':
6151e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6152e9103aaeSGarrett D'Amore optopt);
6153e9103aaeSGarrett D'Amore usage(B_FALSE);
6154e9103aaeSGarrett D'Amore }
6155e9103aaeSGarrett D'Amore }
6156e9103aaeSGarrett D'Amore
6157e9103aaeSGarrett D'Amore argc -= optind;
6158e9103aaeSGarrett D'Amore argv += optind;
6159e9103aaeSGarrett D'Amore
6160e9103aaeSGarrett D'Amore /* get pool name and check number of arguments */
6161e9103aaeSGarrett D'Amore if (argc < 1) {
6162e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("missing pool name\n"));
6163e9103aaeSGarrett D'Amore usage(B_FALSE);
6164e9103aaeSGarrett D'Amore }
6165e9103aaeSGarrett D'Amore
6166e9103aaeSGarrett D'Amore if (argc > 1) {
6167e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("too many arguments\n"));
6168e9103aaeSGarrett D'Amore usage(B_FALSE);
6169e9103aaeSGarrett D'Amore }
6170e9103aaeSGarrett D'Amore
6171e9103aaeSGarrett D'Amore poolname = argv[0];
6172e9103aaeSGarrett D'Amore if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6173e9103aaeSGarrett D'Amore return (1);
6174e9103aaeSGarrett D'Amore
6175e9103aaeSGarrett D'Amore ret = zpool_reguid(zhp);
6176e9103aaeSGarrett D'Amore
6177e9103aaeSGarrett D'Amore zpool_close(zhp);
6178e9103aaeSGarrett D'Amore return (ret);
6179e9103aaeSGarrett D'Amore }
6180e9103aaeSGarrett D'Amore
6181e9103aaeSGarrett D'Amore
61824263d13fSGeorge Wilson /*
61834263d13fSGeorge Wilson * zpool reopen <pool>
61844263d13fSGeorge Wilson *
61854263d13fSGeorge Wilson * Reopen the pool so that the kernel can update the sizes of all vdevs.
61864263d13fSGeorge Wilson */
61874263d13fSGeorge Wilson int
zpool_do_reopen(int argc,char ** argv)61884263d13fSGeorge Wilson zpool_do_reopen(int argc, char **argv)
61894263d13fSGeorge Wilson {
619031d7e8faSGeorge Wilson int c;
61914263d13fSGeorge Wilson int ret = 0;
61924263d13fSGeorge Wilson zpool_handle_t *zhp;
61934263d13fSGeorge Wilson char *pool;
61944263d13fSGeorge Wilson
619531d7e8faSGeorge Wilson /* check options */
619631d7e8faSGeorge Wilson while ((c = getopt(argc, argv, "")) != -1) {
619731d7e8faSGeorge Wilson switch (c) {
619831d7e8faSGeorge Wilson case '?':
619931d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("invalid option '%c'\n"),
620031d7e8faSGeorge Wilson optopt);
620131d7e8faSGeorge Wilson usage(B_FALSE);
620231d7e8faSGeorge Wilson }
620331d7e8faSGeorge Wilson }
620431d7e8faSGeorge Wilson
62054263d13fSGeorge Wilson argc--;
62064263d13fSGeorge Wilson argv++;
62074263d13fSGeorge Wilson
620831d7e8faSGeorge Wilson if (argc < 1) {
620931d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("missing pool name\n"));
621031d7e8faSGeorge Wilson usage(B_FALSE);
621131d7e8faSGeorge Wilson }
621231d7e8faSGeorge Wilson
621331d7e8faSGeorge Wilson if (argc > 1) {
621431d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("too many arguments\n"));
621531d7e8faSGeorge Wilson usage(B_FALSE);
621631d7e8faSGeorge Wilson }
62174263d13fSGeorge Wilson
62184263d13fSGeorge Wilson pool = argv[0];
62194263d13fSGeorge Wilson if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
62204263d13fSGeorge Wilson return (1);
62214263d13fSGeorge Wilson
62224263d13fSGeorge Wilson ret = zpool_reopen(zhp);
62234263d13fSGeorge Wilson zpool_close(zhp);
62244263d13fSGeorge Wilson return (ret);
62254263d13fSGeorge Wilson }
62264263d13fSGeorge Wilson
6227fa9e4066Sahrens typedef struct scrub_cbdata {
6228fa9e4066Sahrens int cb_type;
622906eeb2adSek110237 int cb_argc;
623006eeb2adSek110237 char **cb_argv;
62311702cce7SAlek Pinchuk pool_scrub_cmd_t cb_scrub_cmd;
6232fa9e4066Sahrens } scrub_cbdata_t;
6233fa9e4066Sahrens
623486714001SSerapheim Dimitropoulos static boolean_t
zpool_has_checkpoint(zpool_handle_t * zhp)623586714001SSerapheim Dimitropoulos zpool_has_checkpoint(zpool_handle_t *zhp)
623686714001SSerapheim Dimitropoulos {
623786714001SSerapheim Dimitropoulos nvlist_t *config, *nvroot;
623886714001SSerapheim Dimitropoulos
623986714001SSerapheim Dimitropoulos config = zpool_get_config(zhp, NULL);
624086714001SSerapheim Dimitropoulos
624186714001SSerapheim Dimitropoulos if (config != NULL) {
624286714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL;
624386714001SSerapheim Dimitropoulos uint_t c;
624486714001SSerapheim Dimitropoulos
624586714001SSerapheim Dimitropoulos nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
624686714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot,
624786714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
624886714001SSerapheim Dimitropoulos
624986714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE)
625086714001SSerapheim Dimitropoulos return (B_FALSE);
625186714001SSerapheim Dimitropoulos
625286714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
625386714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
625486714001SSerapheim Dimitropoulos return (B_TRUE);
625586714001SSerapheim Dimitropoulos }
625686714001SSerapheim Dimitropoulos
625786714001SSerapheim Dimitropoulos return (B_FALSE);
625886714001SSerapheim Dimitropoulos }
625986714001SSerapheim Dimitropoulos
6260fa9e4066Sahrens int
scrub_callback(zpool_handle_t * zhp,void * data)6261fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data)
6262fa9e4066Sahrens {
6263fa9e4066Sahrens scrub_cbdata_t *cb = data;
626406eeb2adSek110237 int err;
6265fa9e4066Sahrens
6266ea8dc4b6Seschrock /*
6267ea8dc4b6Seschrock * Ignore faulted pools.
6268ea8dc4b6Seschrock */
6269ea8dc4b6Seschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
6270e4c795beSTom Caputi (void) fprintf(stderr, gettext("cannot scan '%s': pool is "
6271ea8dc4b6Seschrock "currently unavailable\n"), zpool_get_name(zhp));
6272ea8dc4b6Seschrock return (1);
6273ea8dc4b6Seschrock }
6274ea8dc4b6Seschrock
62751702cce7SAlek Pinchuk err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
627606eeb2adSek110237
627786714001SSerapheim Dimitropoulos if (err == 0 && zpool_has_checkpoint(zhp) &&
627886714001SSerapheim Dimitropoulos cb->cb_type == POOL_SCAN_SCRUB) {
627986714001SSerapheim Dimitropoulos (void) printf(gettext("warning: will not scrub state that "
628086714001SSerapheim Dimitropoulos "belongs to the checkpoint of pool '%s'\n"),
628186714001SSerapheim Dimitropoulos zpool_get_name(zhp));
628286714001SSerapheim Dimitropoulos }
628386714001SSerapheim Dimitropoulos
628406eeb2adSek110237 return (err != 0);
6285fa9e4066Sahrens }
6286fa9e4066Sahrens
6287fa9e4066Sahrens /*
62881702cce7SAlek Pinchuk * zpool scrub [-s | -p] <pool> ...
6289fa9e4066Sahrens *
6290fa9e4066Sahrens * -s Stop. Stops any in-progress scrub.
62911702cce7SAlek Pinchuk * -p Pause. Pause in-progress scrub.
6292fa9e4066Sahrens */
6293fa9e4066Sahrens int
zpool_do_scrub(int argc,char ** argv)6294fa9e4066Sahrens zpool_do_scrub(int argc, char **argv)
6295fa9e4066Sahrens {
6296fa9e4066Sahrens int c;
6297fa9e4066Sahrens scrub_cbdata_t cb;
6298fa9e4066Sahrens
62993f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_SCRUB;
63001702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
6301fa9e4066Sahrens
6302fa9e4066Sahrens /* check options */
63031702cce7SAlek Pinchuk while ((c = getopt(argc, argv, "sp")) != -1) {
6304fa9e4066Sahrens switch (c) {
6305fa9e4066Sahrens case 's':
63063f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_NONE;
6307fa9e4066Sahrens break;
63081702cce7SAlek Pinchuk case 'p':
63091702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
63101702cce7SAlek Pinchuk break;
6311fa9e4066Sahrens case '?':
6312fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6313fa9e4066Sahrens optopt);
631499653d4eSeschrock usage(B_FALSE);
6315fa9e4066Sahrens }
6316fa9e4066Sahrens }
6317fa9e4066Sahrens
63181702cce7SAlek Pinchuk if (cb.cb_type == POOL_SCAN_NONE &&
63191702cce7SAlek Pinchuk cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
63201702cce7SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option combination: "
63211702cce7SAlek Pinchuk "-s and -p are mutually exclusive\n"));
63221702cce7SAlek Pinchuk usage(B_FALSE);
63231702cce7SAlek Pinchuk }
63241702cce7SAlek Pinchuk
632506eeb2adSek110237 cb.cb_argc = argc;
632606eeb2adSek110237 cb.cb_argv = argv;
6327fa9e4066Sahrens argc -= optind;
6328fa9e4066Sahrens argv += optind;
6329fa9e4066Sahrens
6330fa9e4066Sahrens if (argc < 1) {
6331fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n"));
633299653d4eSeschrock usage(B_FALSE);
6333fa9e4066Sahrens }
6334fa9e4066Sahrens
6335b1b8ab34Slling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
6336fa9e4066Sahrens }
6337fa9e4066Sahrens
6338e4c795beSTom Caputi /*
6339e4c795beSTom Caputi * zpool resilver <pool> ...
6340e4c795beSTom Caputi *
6341e4c795beSTom Caputi * Restarts any in-progress resilver
6342e4c795beSTom Caputi */
6343e4c795beSTom Caputi int
zpool_do_resilver(int argc,char ** argv)6344e4c795beSTom Caputi zpool_do_resilver(int argc, char **argv)
6345e4c795beSTom Caputi {
6346e4c795beSTom Caputi int c;
6347e4c795beSTom Caputi scrub_cbdata_t cb;
6348e4c795beSTom Caputi
6349e4c795beSTom Caputi cb.cb_type = POOL_SCAN_RESILVER;
6350e4c795beSTom Caputi cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
6351e4c795beSTom Caputi cb.cb_argc = argc;
6352e4c795beSTom Caputi cb.cb_argv = argv;
6353e4c795beSTom Caputi
6354e4c795beSTom Caputi /* check options */
6355e4c795beSTom Caputi while ((c = getopt(argc, argv, "")) != -1) {
6356e4c795beSTom Caputi switch (c) {
6357e4c795beSTom Caputi case '?':
6358e4c795beSTom Caputi (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6359e4c795beSTom Caputi optopt);
6360e4c795beSTom Caputi usage(B_FALSE);
6361e4c795beSTom Caputi }
6362e4c795beSTom Caputi }
6363e4c795beSTom Caputi
6364e4c795beSTom Caputi argc -= optind;
6365e4c795beSTom Caputi argv += optind;
6366e4c795beSTom Caputi
6367e4c795beSTom Caputi if (argc < 1) {
6368e4c795beSTom Caputi (void) fprintf(stderr, gettext("missing pool name argument\n"));
6369e4c795beSTom Caputi usage(B_FALSE);
6370e4c795beSTom Caputi }
6371e4c795beSTom Caputi
6372e4c795beSTom Caputi return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
6373e4c795beSTom Caputi }
6374e4c795beSTom Caputi
6375084fd14fSBrian Behlendorf /*
6376084fd14fSBrian Behlendorf * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...]
6377084fd14fSBrian Behlendorf *
6378084fd14fSBrian Behlendorf * -c Cancel. Ends any in-progress trim.
6379084fd14fSBrian Behlendorf * -d Secure trim. Requires kernel and device support.
6380084fd14fSBrian Behlendorf * -r <rate> Sets the TRIM rate in bytes (per second). Supports
6381084fd14fSBrian Behlendorf * adding a multiplier suffix such as 'k' or 'm'.
6382084fd14fSBrian Behlendorf * -s Suspend. TRIM can then be restarted with no flags.
6383084fd14fSBrian Behlendorf */
6384084fd14fSBrian Behlendorf int
zpool_do_trim(int argc,char ** argv)6385084fd14fSBrian Behlendorf zpool_do_trim(int argc, char **argv)
6386094e47e9SGeorge Wilson {
6387084fd14fSBrian Behlendorf struct option long_options[] = {
6388084fd14fSBrian Behlendorf {"cancel", no_argument, NULL, 'c'},
6389084fd14fSBrian Behlendorf {"secure", no_argument, NULL, 'd'},
6390084fd14fSBrian Behlendorf {"rate", required_argument, NULL, 'r'},
6391084fd14fSBrian Behlendorf {"suspend", no_argument, NULL, 's'},
6392084fd14fSBrian Behlendorf {0, 0, 0, 0}
6393084fd14fSBrian Behlendorf };
6394094e47e9SGeorge Wilson
6395084fd14fSBrian Behlendorf pool_trim_func_t cmd_type = POOL_TRIM_START;
6396084fd14fSBrian Behlendorf uint64_t rate = 0;
6397084fd14fSBrian Behlendorf boolean_t secure = B_FALSE;
6398094e47e9SGeorge Wilson
6399084fd14fSBrian Behlendorf int c;
6400084fd14fSBrian Behlendorf while ((c = getopt_long(argc, argv, "cdr:s", long_options, NULL))
6401084fd14fSBrian Behlendorf != -1) {
6402084fd14fSBrian Behlendorf switch (c) {
6403084fd14fSBrian Behlendorf case 'c':
6404084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START &&
6405084fd14fSBrian Behlendorf cmd_type != POOL_TRIM_CANCEL) {
6406084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-c cannot be "
6407084fd14fSBrian Behlendorf "combined with other options\n"));
6408084fd14fSBrian Behlendorf usage(B_FALSE);
6409084fd14fSBrian Behlendorf }
6410084fd14fSBrian Behlendorf cmd_type = POOL_TRIM_CANCEL;
6411084fd14fSBrian Behlendorf break;
6412084fd14fSBrian Behlendorf case 'd':
6413084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START) {
6414084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-d cannot be "
6415084fd14fSBrian Behlendorf "combined with the -c or -s options\n"));
6416084fd14fSBrian Behlendorf usage(B_FALSE);
6417084fd14fSBrian Behlendorf }
6418084fd14fSBrian Behlendorf secure = B_TRUE;
6419084fd14fSBrian Behlendorf break;
6420084fd14fSBrian Behlendorf case 'r':
6421084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START) {
6422084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-r cannot be "
6423084fd14fSBrian Behlendorf "combined with the -c or -s options\n"));
6424084fd14fSBrian Behlendorf usage(B_FALSE);
6425084fd14fSBrian Behlendorf }
642643a48c4aSToomas Soome if (zfs_nicestrtonum(g_zfs, optarg, &rate) == -1) {
642743a48c4aSToomas Soome (void) fprintf(stderr, "%s: %s\n",
642843a48c4aSToomas Soome gettext("invalid value for rate"),
642943a48c4aSToomas Soome libzfs_error_description(g_zfs));
6430084fd14fSBrian Behlendorf usage(B_FALSE);
6431084fd14fSBrian Behlendorf }
6432084fd14fSBrian Behlendorf break;
6433084fd14fSBrian Behlendorf case 's':
6434084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START &&
6435084fd14fSBrian Behlendorf cmd_type != POOL_TRIM_SUSPEND) {
6436084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-s cannot be "
6437084fd14fSBrian Behlendorf "combined with other options\n"));
6438084fd14fSBrian Behlendorf usage(B_FALSE);
6439084fd14fSBrian Behlendorf }
6440084fd14fSBrian Behlendorf cmd_type = POOL_TRIM_SUSPEND;
6441084fd14fSBrian Behlendorf break;
6442084fd14fSBrian Behlendorf case '?':
6443084fd14fSBrian Behlendorf if (optopt != 0) {
6444084fd14fSBrian Behlendorf (void) fprintf(stderr,
6445084fd14fSBrian Behlendorf gettext("invalid option '%c'\n"), optopt);
6446084fd14fSBrian Behlendorf } else {
6447084fd14fSBrian Behlendorf (void) fprintf(stderr,
6448084fd14fSBrian Behlendorf gettext("invalid option '%s'\n"),
6449084fd14fSBrian Behlendorf argv[optind - 1]);
6450084fd14fSBrian Behlendorf }
6451084fd14fSBrian Behlendorf usage(B_FALSE);
6452084fd14fSBrian Behlendorf }
6453094e47e9SGeorge Wilson }
6454094e47e9SGeorge Wilson
6455084fd14fSBrian Behlendorf argc -= optind;
6456084fd14fSBrian Behlendorf argv += optind;
6457084fd14fSBrian Behlendorf
6458084fd14fSBrian Behlendorf if (argc < 1) {
6459084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("missing pool name argument\n"));
6460084fd14fSBrian Behlendorf usage(B_FALSE);
6461084fd14fSBrian Behlendorf return (-1);
6462094e47e9SGeorge Wilson }
6463084fd14fSBrian Behlendorf
6464084fd14fSBrian Behlendorf char *poolname = argv[0];
6465084fd14fSBrian Behlendorf zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
6466084fd14fSBrian Behlendorf if (zhp == NULL)
6467084fd14fSBrian Behlendorf return (-1);
6468084fd14fSBrian Behlendorf
6469084fd14fSBrian Behlendorf trimflags_t trim_flags = {
6470084fd14fSBrian Behlendorf .secure = secure,
6471084fd14fSBrian Behlendorf .rate = rate,
6472084fd14fSBrian Behlendorf };
6473084fd14fSBrian Behlendorf
6474084fd14fSBrian Behlendorf nvlist_t *vdevs = fnvlist_alloc();
6475084fd14fSBrian Behlendorf if (argc == 1) {
6476084fd14fSBrian Behlendorf /* no individual leaf vdevs specified, so add them all */
6477084fd14fSBrian Behlendorf nvlist_t *config = zpool_get_config(zhp, NULL);
6478084fd14fSBrian Behlendorf nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
6479084fd14fSBrian Behlendorf ZPOOL_CONFIG_VDEV_TREE);
6480084fd14fSBrian Behlendorf zpool_collect_leaves(zhp, nvroot, vdevs);
6481084fd14fSBrian Behlendorf trim_flags.fullpool = B_TRUE;
6482084fd14fSBrian Behlendorf } else {
6483084fd14fSBrian Behlendorf trim_flags.fullpool = B_FALSE;
6484084fd14fSBrian Behlendorf for (int i = 1; i < argc; i++) {
6485084fd14fSBrian Behlendorf fnvlist_add_boolean(vdevs, argv[i]);
6486084fd14fSBrian Behlendorf }
6487084fd14fSBrian Behlendorf }
6488084fd14fSBrian Behlendorf
6489084fd14fSBrian Behlendorf int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
6490084fd14fSBrian Behlendorf
6491084fd14fSBrian Behlendorf fnvlist_free(vdevs);
6492084fd14fSBrian Behlendorf zpool_close(zhp);
6493084fd14fSBrian Behlendorf
6494084fd14fSBrian Behlendorf return (error);
6495094e47e9SGeorge Wilson }
6496094e47e9SGeorge Wilson
6497094e47e9SGeorge Wilson /*
6498084fd14fSBrian Behlendorf * zpool initialize [-c | -s] <pool> [<vdev> ...]
6499094e47e9SGeorge Wilson * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
6500094e47e9SGeorge Wilson * if none specified.
6501094e47e9SGeorge Wilson *
6502094e47e9SGeorge Wilson * -c Cancel. Ends active initializing.
6503094e47e9SGeorge Wilson * -s Suspend. Initializing can then be restarted with no flags.
6504094e47e9SGeorge Wilson */
6505094e47e9SGeorge Wilson int
zpool_do_initialize(int argc,char ** argv)6506094e47e9SGeorge Wilson zpool_do_initialize(int argc, char **argv)
6507094e47e9SGeorge Wilson {
6508094e47e9SGeorge Wilson int c;
6509094e47e9SGeorge Wilson char *poolname;
6510094e47e9SGeorge Wilson zpool_handle_t *zhp;
6511094e47e9SGeorge Wilson nvlist_t *vdevs;
6512094e47e9SGeorge Wilson int err = 0;
6513094e47e9SGeorge Wilson
6514094e47e9SGeorge Wilson struct option long_options[] = {
6515094e47e9SGeorge Wilson {"cancel", no_argument, NULL, 'c'},
6516094e47e9SGeorge Wilson {"suspend", no_argument, NULL, 's'},
6517094e47e9SGeorge Wilson {0, 0, 0, 0}
6518094e47e9SGeorge Wilson };
6519094e47e9SGeorge Wilson
6520084fd14fSBrian Behlendorf pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
6521094e47e9SGeorge Wilson while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) {
6522094e47e9SGeorge Wilson switch (c) {
6523094e47e9SGeorge Wilson case 'c':
6524084fd14fSBrian Behlendorf if (cmd_type != POOL_INITIALIZE_START &&
6525084fd14fSBrian Behlendorf cmd_type != POOL_INITIALIZE_CANCEL) {
6526094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-c cannot be "
6527094e47e9SGeorge Wilson "combined with other options\n"));
6528094e47e9SGeorge Wilson usage(B_FALSE);
6529094e47e9SGeorge Wilson }
6530094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_CANCEL;
6531094e47e9SGeorge Wilson break;
6532094e47e9SGeorge Wilson case 's':
6533084fd14fSBrian Behlendorf if (cmd_type != POOL_INITIALIZE_START &&
6534084fd14fSBrian Behlendorf cmd_type != POOL_INITIALIZE_SUSPEND) {
6535094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-s cannot be "
6536094e47e9SGeorge Wilson "combined with other options\n"));
6537094e47e9SGeorge Wilson usage(B_FALSE);
6538094e47e9SGeorge Wilson }
6539094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_SUSPEND;
6540094e47e9SGeorge Wilson break;
6541094e47e9SGeorge Wilson case '?':
6542094e47e9SGeorge Wilson if (optopt != 0) {
6543094e47e9SGeorge Wilson (void) fprintf(stderr,
6544094e47e9SGeorge Wilson gettext("invalid option '%c'\n"), optopt);
6545094e47e9SGeorge Wilson } else {
6546094e47e9SGeorge Wilson (void) fprintf(stderr,
6547094e47e9SGeorge Wilson gettext("invalid option '%s'\n"),
6548094e47e9SGeorge Wilson argv[optind - 1]);
6549094e47e9SGeorge Wilson }
6550094e47e9SGeorge Wilson usage(B_FALSE);
6551094e47e9SGeorge Wilson }
6552094e47e9SGeorge Wilson }
6553094e47e9SGeorge Wilson
6554094e47e9SGeorge Wilson argc -= optind;
6555094e47e9SGeorge Wilson argv += optind;
6556094e47e9SGeorge Wilson
6557094e47e9SGeorge Wilson if (argc < 1) {
6558094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("missing pool name argument\n"));
6559094e47e9SGeorge Wilson usage(B_FALSE);
6560094e47e9SGeorge Wilson return (-1);
6561094e47e9SGeorge Wilson }
6562094e47e9SGeorge Wilson
6563094e47e9SGeorge Wilson poolname = argv[0];
6564094e47e9SGeorge Wilson zhp = zpool_open(g_zfs, poolname);
6565094e47e9SGeorge Wilson if (zhp == NULL)
6566094e47e9SGeorge Wilson return (-1);
6567094e47e9SGeorge Wilson
6568094e47e9SGeorge Wilson vdevs = fnvlist_alloc();
6569094e47e9SGeorge Wilson if (argc == 1) {
6570094e47e9SGeorge Wilson /* no individual leaf vdevs specified, so add them all */
6571094e47e9SGeorge Wilson nvlist_t *config = zpool_get_config(zhp, NULL);
6572094e47e9SGeorge Wilson nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
6573094e47e9SGeorge Wilson ZPOOL_CONFIG_VDEV_TREE);
6574094e47e9SGeorge Wilson zpool_collect_leaves(zhp, nvroot, vdevs);
6575094e47e9SGeorge Wilson } else {
6576084fd14fSBrian Behlendorf for (int i = 1; i < argc; i++) {
6577094e47e9SGeorge Wilson fnvlist_add_boolean(vdevs, argv[i]);
6578094e47e9SGeorge Wilson }
6579094e47e9SGeorge Wilson }
6580094e47e9SGeorge Wilson
6581094e47e9SGeorge Wilson err = zpool_initialize(zhp, cmd_type, vdevs);
6582094e47e9SGeorge Wilson
6583094e47e9SGeorge Wilson fnvlist_free(vdevs);
6584094e47e9SGeorge Wilson zpool_close(zhp);
6585094e47e9SGeorge Wilson
6586094e47e9SGeorge Wilson return (err);
6587094e47e9SGeorge Wilson }
6588094e47e9SGeorge Wilson
6589fa9e4066Sahrens /*
6590fa9e4066Sahrens * Print out detailed scrub status.
6591fa9e4066Sahrens */
65925cabbc6bSPrashanth Sreenivasa static void
print_scan_status(pool_scan_stat_t * ps)65933f9d6ad7SLin Ling print_scan_status(pool_scan_stat_t *ps)
6594fa9e4066Sahrens {
65951702cce7SAlek Pinchuk time_t start, end, pause;
6596a3874b8bSToomas Soome uint64_t total_secs_left;
6597a3874b8bSToomas Soome uint64_t elapsed, secs_left, mins_left, hours_left, days_left;
6598a3874b8bSToomas Soome uint64_t pass_scanned, scanned, pass_issued, issued, total;
6599a3874b8bSToomas Soome uint_t scan_rate, issue_rate;
6600fa9e4066Sahrens double fraction_done;
6601a3874b8bSToomas Soome char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
6602a3874b8bSToomas Soome char srate_buf[7], irate_buf[7];
6603fa9e4066Sahrens
66043f9d6ad7SLin Ling (void) printf(gettext(" scan: "));
6605fa9e4066Sahrens
66063f9d6ad7SLin Ling /* If there's never been a scan, there's not much to say. */
66073f9d6ad7SLin Ling if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
66083f9d6ad7SLin Ling ps->pss_func >= POOL_SCAN_FUNCS) {
6609fa9e4066Sahrens (void) printf(gettext("none requested\n"));
6610fa9e4066Sahrens return;
6611fa9e4066Sahrens }
6612fa9e4066Sahrens
66133f9d6ad7SLin Ling start = ps->pss_start_time;
66143f9d6ad7SLin Ling end = ps->pss_end_time;
66151702cce7SAlek Pinchuk pause = ps->pss_pass_scrub_pause;
6616a3874b8bSToomas Soome
66176520eed5SToomas Soome zfs_nicebytes(ps->pss_processed, processed_buf, sizeof (processed_buf));
6618fa9e4066Sahrens
66193f9d6ad7SLin Ling assert(ps->pss_func == POOL_SCAN_SCRUB ||
66203f9d6ad7SLin Ling ps->pss_func == POOL_SCAN_RESILVER);
6621a3874b8bSToomas Soome
66223f9d6ad7SLin Ling /*
66233f9d6ad7SLin Ling * Scan is finished or canceled.
66243f9d6ad7SLin Ling */
66253f9d6ad7SLin Ling if (ps->pss_state == DSS_FINISHED) {
6626a3874b8bSToomas Soome total_secs_left = end - start;
6627a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24;
6628a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24;
6629a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60;
6630a3874b8bSToomas Soome secs_left = (total_secs_left % 60);
6631fa9e4066Sahrens
66323f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) {
6633a3874b8bSToomas Soome (void) printf(gettext("scrub repaired %s "
6634a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu "
6635a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf,
6636a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left,
6637a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left,
6638a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end));
66393f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) {
6640a3874b8bSToomas Soome (void) printf(gettext("resilvered %s "
6641a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu "
6642a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf,
6643a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left,
6644a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left,
6645a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end));
66463f9d6ad7SLin Ling }
66473f9d6ad7SLin Ling return;
66483f9d6ad7SLin Ling } else if (ps->pss_state == DSS_CANCELED) {
66493f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) {
66503f9d6ad7SLin Ling (void) printf(gettext("scrub canceled on %s"),
66513f9d6ad7SLin Ling ctime(&end));
66523f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) {
66533f9d6ad7SLin Ling (void) printf(gettext("resilver canceled on %s"),
66543f9d6ad7SLin Ling ctime(&end));
66553f9d6ad7SLin Ling }
6656fa9e4066Sahrens return;
6657fa9e4066Sahrens }
6658fa9e4066Sahrens
66593f9d6ad7SLin Ling assert(ps->pss_state == DSS_SCANNING);
6660fa9e4066Sahrens
6661a3874b8bSToomas Soome /* Scan is in progress. Resilvers can't be paused. */
66623f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) {
66631702cce7SAlek Pinchuk if (pause == 0) {
66643f9d6ad7SLin Ling (void) printf(gettext("scrub in progress since %s"),
66653f9d6ad7SLin Ling ctime(&start));
66661702cce7SAlek Pinchuk } else {
6667a3874b8bSToomas Soome (void) printf(gettext("scrub paused since %s"),
6668a3874b8bSToomas Soome ctime(&pause));
66691702cce7SAlek Pinchuk (void) printf(gettext("\tscrub started on %s"),
66701702cce7SAlek Pinchuk ctime(&start));
66711702cce7SAlek Pinchuk }
66723f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) {
66733f9d6ad7SLin Ling (void) printf(gettext("resilver in progress since %s"),
66743f9d6ad7SLin Ling ctime(&start));
66753f9d6ad7SLin Ling }
66763f9d6ad7SLin Ling
6677a3874b8bSToomas Soome scanned = ps->pss_examined;
6678a3874b8bSToomas Soome pass_scanned = ps->pss_pass_exam;
6679a3874b8bSToomas Soome issued = ps->pss_issued;
6680a3874b8bSToomas Soome pass_issued = ps->pss_pass_issued;
66813f9d6ad7SLin Ling total = ps->pss_to_examine;
6682fa9e4066Sahrens
6683a3874b8bSToomas Soome /* we are only done with a block once we have issued the IO for it */
6684a3874b8bSToomas Soome fraction_done = (double)issued / total;
6685a3874b8bSToomas Soome
6686a3874b8bSToomas Soome /* elapsed time for this pass, rounding up to 1 if it's 0 */
66873f9d6ad7SLin Ling elapsed = time(NULL) - ps->pss_pass_start;
66881702cce7SAlek Pinchuk elapsed -= ps->pss_pass_scrub_spent_paused;
6689a3874b8bSToomas Soome elapsed = (elapsed != 0) ? elapsed : 1;
66903f9d6ad7SLin Ling
6691a3874b8bSToomas Soome scan_rate = pass_scanned / elapsed;
6692a3874b8bSToomas Soome issue_rate = pass_issued / elapsed;
66933db6627cSTom Caputi total_secs_left = (issue_rate != 0 && total >= issued) ?
6694a3874b8bSToomas Soome ((total - issued) / issue_rate) : UINT64_MAX;
6695a3874b8bSToomas Soome
6696a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24;
6697a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24;
6698a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60;
6699a3874b8bSToomas Soome secs_left = (total_secs_left % 60);
6700a3874b8bSToomas Soome
6701a3874b8bSToomas Soome /* format all of the numbers we will be reporting */
67026520eed5SToomas Soome zfs_nicebytes(scanned, scanned_buf, sizeof (scanned_buf));
67036520eed5SToomas Soome zfs_nicebytes(issued, issued_buf, sizeof (issued_buf));
67046520eed5SToomas Soome zfs_nicebytes(total, total_buf, sizeof (total_buf));
67056520eed5SToomas Soome zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf));
67066520eed5SToomas Soome zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf));
67073f9d6ad7SLin Ling
6708a3874b8bSToomas Soome /* do not print estimated time if we have a paused scrub */
67091702cce7SAlek Pinchuk if (pause == 0) {
6710a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned at %s/s, "
6711a3874b8bSToomas Soome "%s issued at %s/s, %s total\n"),
6712a3874b8bSToomas Soome scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
671373d314ceSLin Ling } else {
6714a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
6715a3874b8bSToomas Soome scanned_buf, issued_buf, total_buf);
67161702cce7SAlek Pinchuk }
67173f9d6ad7SLin Ling
67183f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_RESILVER) {
6719a3874b8bSToomas Soome (void) printf(gettext("\t%s resilvered, %.2f%% done"),
67203f9d6ad7SLin Ling processed_buf, 100 * fraction_done);
67213f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_SCRUB) {
6722a3874b8bSToomas Soome (void) printf(gettext("\t%s repaired, %.2f%% done"),
67233f9d6ad7SLin Ling processed_buf, 100 * fraction_done);
67243f9d6ad7SLin Ling }
6725a3874b8bSToomas Soome
6726a3874b8bSToomas Soome if (pause == 0) {
67273db6627cSTom Caputi if (total_secs_left != UINT64_MAX &&
67283db6627cSTom Caputi issue_rate >= 10 * 1024 * 1024) {
6729a3874b8bSToomas Soome (void) printf(gettext(", %llu days "
6730a3874b8bSToomas Soome "%02llu:%02llu:%02llu to go\n"),
6731a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left,
6732a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left);
6733a3874b8bSToomas Soome } else {
6734a3874b8bSToomas Soome (void) printf(gettext(", no estimated "
6735a3874b8bSToomas Soome "completion time\n"));
6736a3874b8bSToomas Soome }
6737a3874b8bSToomas Soome } else {
6738a3874b8bSToomas Soome (void) printf(gettext("\n"));
6739a3874b8bSToomas Soome }
6740fa9e4066Sahrens }
6741fa9e4066Sahrens
67425cabbc6bSPrashanth Sreenivasa /*
674386714001SSerapheim Dimitropoulos * As we don't scrub checkpointed blocks, we want to warn the
674486714001SSerapheim Dimitropoulos * user that we skipped scanning some blocks if a checkpoint exists
674586714001SSerapheim Dimitropoulos * or existed at any time during the scan.
674686714001SSerapheim Dimitropoulos */
674786714001SSerapheim Dimitropoulos static void
print_checkpoint_scan_warning(pool_scan_stat_t * ps,pool_checkpoint_stat_t * pcs)674886714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
674986714001SSerapheim Dimitropoulos {
675086714001SSerapheim Dimitropoulos if (ps == NULL || pcs == NULL)
675186714001SSerapheim Dimitropoulos return;
675286714001SSerapheim Dimitropoulos
675386714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_NONE ||
675486714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
675586714001SSerapheim Dimitropoulos return;
675686714001SSerapheim Dimitropoulos
675786714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
675886714001SSerapheim Dimitropoulos
675986714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_NONE)
676086714001SSerapheim Dimitropoulos return;
676186714001SSerapheim Dimitropoulos
676286714001SSerapheim Dimitropoulos if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
676386714001SSerapheim Dimitropoulos ps->pss_end_time < pcs->pcs_start_time)
676486714001SSerapheim Dimitropoulos return;
676586714001SSerapheim Dimitropoulos
676686714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
676786714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipped blocks "
676886714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n"));
676986714001SSerapheim Dimitropoulos } else {
677086714001SSerapheim Dimitropoulos assert(ps->pss_state == DSS_SCANNING);
677186714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipping blocks "
677286714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n"));
677386714001SSerapheim Dimitropoulos }
677486714001SSerapheim Dimitropoulos }
677586714001SSerapheim Dimitropoulos
677686714001SSerapheim Dimitropoulos /*
67775cabbc6bSPrashanth Sreenivasa * Print out detailed removal status.
67785cabbc6bSPrashanth Sreenivasa */
67795cabbc6bSPrashanth Sreenivasa static void
print_removal_status(zpool_handle_t * zhp,pool_removal_stat_t * prs)67805cabbc6bSPrashanth Sreenivasa print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
67815cabbc6bSPrashanth Sreenivasa {
67825cabbc6bSPrashanth Sreenivasa char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
67835cabbc6bSPrashanth Sreenivasa time_t start, end;
67845cabbc6bSPrashanth Sreenivasa nvlist_t *config, *nvroot;
67855cabbc6bSPrashanth Sreenivasa nvlist_t **child;
67865cabbc6bSPrashanth Sreenivasa uint_t children;
67875cabbc6bSPrashanth Sreenivasa char *vdev_name;
67885cabbc6bSPrashanth Sreenivasa
67895cabbc6bSPrashanth Sreenivasa if (prs == NULL || prs->prs_state == DSS_NONE)
67905cabbc6bSPrashanth Sreenivasa return;
67915cabbc6bSPrashanth Sreenivasa
67925cabbc6bSPrashanth Sreenivasa /*
67935cabbc6bSPrashanth Sreenivasa * Determine name of vdev.
67945cabbc6bSPrashanth Sreenivasa */
67955cabbc6bSPrashanth Sreenivasa config = zpool_get_config(zhp, NULL);
67965cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config,
67975cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_VDEV_TREE);
67985cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
67995cabbc6bSPrashanth Sreenivasa &child, &children) == 0);
68005cabbc6bSPrashanth Sreenivasa assert(prs->prs_removing_vdev < children);
68015cabbc6bSPrashanth Sreenivasa vdev_name = zpool_vdev_name(g_zfs, zhp,
68025cabbc6bSPrashanth Sreenivasa child[prs->prs_removing_vdev], B_TRUE);
68035cabbc6bSPrashanth Sreenivasa
68045cabbc6bSPrashanth Sreenivasa (void) printf(gettext("remove: "));
68055cabbc6bSPrashanth Sreenivasa
68065cabbc6bSPrashanth Sreenivasa start = prs->prs_start_time;
68075cabbc6bSPrashanth Sreenivasa end = prs->prs_end_time;
68085cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
68095cabbc6bSPrashanth Sreenivasa
68105cabbc6bSPrashanth Sreenivasa /*
68115cabbc6bSPrashanth Sreenivasa * Removal is finished or canceled.
68125cabbc6bSPrashanth Sreenivasa */
68135cabbc6bSPrashanth Sreenivasa if (prs->prs_state == DSS_FINISHED) {
68145cabbc6bSPrashanth Sreenivasa uint64_t minutes_taken = (end - start) / 60;
68155cabbc6bSPrashanth Sreenivasa
68165cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of vdev %llu copied %s "
68175cabbc6bSPrashanth Sreenivasa "in %lluh%um, completed on %s"),
68185cabbc6bSPrashanth Sreenivasa (longlong_t)prs->prs_removing_vdev,
68195cabbc6bSPrashanth Sreenivasa copied_buf,
68205cabbc6bSPrashanth Sreenivasa (u_longlong_t)(minutes_taken / 60),
68215cabbc6bSPrashanth Sreenivasa (uint_t)(minutes_taken % 60),
68225cabbc6bSPrashanth Sreenivasa ctime((time_t *)&end));
68235cabbc6bSPrashanth Sreenivasa } else if (prs->prs_state == DSS_CANCELED) {
68245cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of %s canceled on %s"),
68255cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&end));
68265cabbc6bSPrashanth Sreenivasa } else {
68275cabbc6bSPrashanth Sreenivasa uint64_t copied, total, elapsed, mins_left, hours_left;
68285cabbc6bSPrashanth Sreenivasa double fraction_done;
68295cabbc6bSPrashanth Sreenivasa uint_t rate;
68305cabbc6bSPrashanth Sreenivasa
68315cabbc6bSPrashanth Sreenivasa assert(prs->prs_state == DSS_SCANNING);
68325cabbc6bSPrashanth Sreenivasa
68335cabbc6bSPrashanth Sreenivasa /*
68345cabbc6bSPrashanth Sreenivasa * Removal is in progress.
68355cabbc6bSPrashanth Sreenivasa */
68365cabbc6bSPrashanth Sreenivasa (void) printf(gettext(
68375cabbc6bSPrashanth Sreenivasa "Evacuation of %s in progress since %s"),
68385cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&start));
68395cabbc6bSPrashanth Sreenivasa
68405cabbc6bSPrashanth Sreenivasa copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
68415cabbc6bSPrashanth Sreenivasa total = prs->prs_to_copy;
68425cabbc6bSPrashanth Sreenivasa fraction_done = (double)copied / total;
68435cabbc6bSPrashanth Sreenivasa
68445cabbc6bSPrashanth Sreenivasa /* elapsed time for this pass */
68455cabbc6bSPrashanth Sreenivasa elapsed = time(NULL) - prs->prs_start_time;
68465cabbc6bSPrashanth Sreenivasa elapsed = elapsed > 0 ? elapsed : 1;
68475cabbc6bSPrashanth Sreenivasa rate = copied / elapsed;
68485cabbc6bSPrashanth Sreenivasa rate = rate > 0 ? rate : 1;
68495cabbc6bSPrashanth Sreenivasa mins_left = ((total - copied) / rate) / 60;
68505cabbc6bSPrashanth Sreenivasa hours_left = mins_left / 60;
68515cabbc6bSPrashanth Sreenivasa
68525cabbc6bSPrashanth Sreenivasa zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
68535cabbc6bSPrashanth Sreenivasa zfs_nicenum(total, total_buf, sizeof (total_buf));
68545cabbc6bSPrashanth Sreenivasa zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
68555cabbc6bSPrashanth Sreenivasa
68565cabbc6bSPrashanth Sreenivasa /*
68575cabbc6bSPrashanth Sreenivasa * do not print estimated time if hours_left is more than
68585cabbc6bSPrashanth Sreenivasa * 30 days
68595cabbc6bSPrashanth Sreenivasa */
68605cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s copied out of %s at %s/s, "
68615cabbc6bSPrashanth Sreenivasa "%.2f%% done"),
68625cabbc6bSPrashanth Sreenivasa examined_buf, total_buf, rate_buf, 100 * fraction_done);
68635cabbc6bSPrashanth Sreenivasa if (hours_left < (30 * 24)) {
68645cabbc6bSPrashanth Sreenivasa (void) printf(gettext(", %lluh%um to go\n"),
68655cabbc6bSPrashanth Sreenivasa (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
68665cabbc6bSPrashanth Sreenivasa } else {
68675cabbc6bSPrashanth Sreenivasa (void) printf(gettext(
68685cabbc6bSPrashanth Sreenivasa ", (copy is slow, no estimated time)\n"));
68695cabbc6bSPrashanth Sreenivasa }
68705cabbc6bSPrashanth Sreenivasa }
68715cabbc6bSPrashanth Sreenivasa
68725cabbc6bSPrashanth Sreenivasa if (prs->prs_mapping_memory > 0) {
68735cabbc6bSPrashanth Sreenivasa char mem_buf[7];
68745cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
68755cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s memory used for "
68765cabbc6bSPrashanth Sreenivasa "removed device mappings\n"),
68775cabbc6bSPrashanth Sreenivasa mem_buf);
68785cabbc6bSPrashanth Sreenivasa }
68795cabbc6bSPrashanth Sreenivasa }
68805cabbc6bSPrashanth Sreenivasa
6881ea8dc4b6Seschrock static void
print_checkpoint_status(pool_checkpoint_stat_t * pcs)688286714001SSerapheim Dimitropoulos print_checkpoint_status(pool_checkpoint_stat_t *pcs)
688386714001SSerapheim Dimitropoulos {
688486714001SSerapheim Dimitropoulos time_t start;
688586714001SSerapheim Dimitropoulos char space_buf[7];
688686714001SSerapheim Dimitropoulos
688786714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE)
688886714001SSerapheim Dimitropoulos return;
688986714001SSerapheim Dimitropoulos
689086714001SSerapheim Dimitropoulos (void) printf(gettext("checkpoint: "));
689186714001SSerapheim Dimitropoulos
689286714001SSerapheim Dimitropoulos start = pcs->pcs_start_time;
689386714001SSerapheim Dimitropoulos zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
689486714001SSerapheim Dimitropoulos
689586714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
689686714001SSerapheim Dimitropoulos char *date = ctime(&start);
689786714001SSerapheim Dimitropoulos
689886714001SSerapheim Dimitropoulos /*
689986714001SSerapheim Dimitropoulos * ctime() adds a newline at the end of the generated
690086714001SSerapheim Dimitropoulos * string, thus the weird format specifier and the
690186714001SSerapheim Dimitropoulos * strlen() call used to chop it off from the output.
690286714001SSerapheim Dimitropoulos */
690386714001SSerapheim Dimitropoulos (void) printf(gettext("created %.*s, consumes %s\n"),
690486714001SSerapheim Dimitropoulos strlen(date) - 1, date, space_buf);
690586714001SSerapheim Dimitropoulos return;
690686714001SSerapheim Dimitropoulos }
690786714001SSerapheim Dimitropoulos
690886714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
690986714001SSerapheim Dimitropoulos
691086714001SSerapheim Dimitropoulos (void) printf(gettext("discarding, %s remaining.\n"),
691186714001SSerapheim Dimitropoulos space_buf);
691286714001SSerapheim Dimitropoulos }
691386714001SSerapheim Dimitropoulos
691486714001SSerapheim Dimitropoulos static void
print_error_log(zpool_handle_t * zhp)6915ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp)
6916ea8dc4b6Seschrock {
691775519f38Sek110237 nvlist_t *nverrlist = NULL;
691855434c77Sek110237 nvpair_t *elem;
691955434c77Sek110237 char *pathname;
692055434c77Sek110237 size_t len = MAXPATHLEN * 2;
6921ea8dc4b6Seschrock
692255434c77Sek110237 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
6923ea8dc4b6Seschrock (void) printf("errors: List of errors unavailable "
6924ea8dc4b6Seschrock "(insufficient privileges)\n");
6925ea8dc4b6Seschrock return;
6926ea8dc4b6Seschrock }
6927ea8dc4b6Seschrock
692855434c77Sek110237 (void) printf("errors: Permanent errors have been "
692955434c77Sek110237 "detected in the following files:\n\n");
6930ea8dc4b6Seschrock
693155434c77Sek110237 pathname = safe_malloc(len);
693255434c77Sek110237 elem = NULL;
693355434c77Sek110237 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
693455434c77Sek110237 nvlist_t *nv;
693555434c77Sek110237 uint64_t dsobj, obj;
6936ea8dc4b6Seschrock
693755434c77Sek110237 verify(nvpair_value_nvlist(elem, &nv) == 0);
693855434c77Sek110237 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
693955434c77Sek110237 &dsobj) == 0);
694055434c77Sek110237 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
694155434c77Sek110237 &obj) == 0);
694255434c77Sek110237 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
694355434c77Sek110237 (void) printf("%7s %s\n", "", pathname);
6944ea8dc4b6Seschrock }
694555434c77Sek110237 free(pathname);
694655434c77Sek110237 nvlist_free(nverrlist);
6947ea8dc4b6Seschrock }
6948ea8dc4b6Seschrock
694999653d4eSeschrock static void
print_spares(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t ** spares,uint_t nspares)6950663207adSDon Brady print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
6951663207adSDon Brady uint_t nspares)
695299653d4eSeschrock {
695399653d4eSeschrock uint_t i;
695499653d4eSeschrock char *name;
695599653d4eSeschrock
695699653d4eSeschrock if (nspares == 0)
695799653d4eSeschrock return;
695899653d4eSeschrock
695999653d4eSeschrock (void) printf(gettext("\tspares\n"));
696099653d4eSeschrock
696199653d4eSeschrock for (i = 0; i < nspares; i++) {
6962663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, spares[i],
6963663207adSDon Brady cb->cb_name_flags);
6964663207adSDon Brady print_status_config(zhp, cb, name, spares[i], 2, B_TRUE);
696599653d4eSeschrock free(name);
696699653d4eSeschrock }
696799653d4eSeschrock }
696899653d4eSeschrock
6969fa94a07fSbrendan static void
print_l2cache(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t ** l2cache,uint_t nl2cache)6970663207adSDon Brady print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
6971663207adSDon Brady uint_t nl2cache)
6972fa94a07fSbrendan {
6973fa94a07fSbrendan uint_t i;
6974fa94a07fSbrendan char *name;
6975fa94a07fSbrendan
6976fa94a07fSbrendan if (nl2cache == 0)
6977fa94a07fSbrendan return;
6978fa94a07fSbrendan
6979fa94a07fSbrendan (void) printf(gettext("\tcache\n"));
6980fa94a07fSbrendan
6981fa94a07fSbrendan for (i = 0; i < nl2cache; i++) {
6982663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
6983663207adSDon Brady cb->cb_name_flags);
6984663207adSDon Brady print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE);
6985aa8cf21aSNeil Perrin free(name);
6986aa8cf21aSNeil Perrin }
6987aa8cf21aSNeil Perrin }
6988aa8cf21aSNeil Perrin
69899eb19f4dSGeorge Wilson static void
print_dedup_stats(nvlist_t * config)69909eb19f4dSGeorge Wilson print_dedup_stats(nvlist_t *config)
69919eb19f4dSGeorge Wilson {
69929eb19f4dSGeorge Wilson ddt_histogram_t *ddh;
69939eb19f4dSGeorge Wilson ddt_stat_t *dds;
69949eb19f4dSGeorge Wilson ddt_object_t *ddo;
69959eb19f4dSGeorge Wilson uint_t c;
69966520eed5SToomas Soome char dspace[6], mspace[6];
69979eb19f4dSGeorge Wilson
69989eb19f4dSGeorge Wilson /*
69999eb19f4dSGeorge Wilson * If the pool was faulted then we may not have been able to
70002384d9f8SGeorge Wilson * obtain the config. Otherwise, if we have anything in the dedup
70019eb19f4dSGeorge Wilson * table continue processing the stats.
70029eb19f4dSGeorge Wilson */
70039eb19f4dSGeorge Wilson if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
7004ce72e614SYuri Pankov (uint64_t **)&ddo, &c) != 0)
70059eb19f4dSGeorge Wilson return;
70069eb19f4dSGeorge Wilson
70079eb19f4dSGeorge Wilson (void) printf("\n");
7008ce72e614SYuri Pankov (void) printf(gettext(" dedup: "));
7009ce72e614SYuri Pankov if (ddo->ddo_count == 0) {
7010ce72e614SYuri Pankov (void) printf(gettext("no DDT entries\n"));
7011ce72e614SYuri Pankov return;
7012ce72e614SYuri Pankov }
7013ce72e614SYuri Pankov
70146520eed5SToomas Soome zfs_nicebytes(ddo->ddo_dspace, dspace, sizeof (dspace));
70156520eed5SToomas Soome zfs_nicebytes(ddo->ddo_mspace, mspace, sizeof (mspace));
70166520eed5SToomas Soome (void) printf("DDT entries %llu, size %s on disk, %s in core\n",
70179eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_count,
70186520eed5SToomas Soome dspace,
70196520eed5SToomas Soome mspace);
70209eb19f4dSGeorge Wilson
70219eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
70229eb19f4dSGeorge Wilson (uint64_t **)&dds, &c) == 0);
70239eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
70249eb19f4dSGeorge Wilson (uint64_t **)&ddh, &c) == 0);
70259eb19f4dSGeorge Wilson zpool_dump_ddt(dds, ddh);
70269eb19f4dSGeorge Wilson }
70279eb19f4dSGeorge Wilson
7028aa8cf21aSNeil Perrin /*
7029fa9e4066Sahrens * Display a summary of pool status. Displays a summary such as:
7030fa9e4066Sahrens *
7031fa9e4066Sahrens * pool: tank
7032fa9e4066Sahrens * status: DEGRADED
7033fa9e4066Sahrens * reason: One or more devices ...
7034654b400cSJoshua M. Clulow * see: http://illumos.org/msg/ZFS-xxxx-01
7035fa9e4066Sahrens * config:
7036fa9e4066Sahrens * mirror DEGRADED
7037fa9e4066Sahrens * c1t0d0 OK
7038ea8dc4b6Seschrock * c2t0d0 UNAVAIL
7039fa9e4066Sahrens *
7040fa9e4066Sahrens * When given the '-v' option, we print out the complete config. If the '-e'
7041fa9e4066Sahrens * option is specified, then we print out error rate information as well.
7042fa9e4066Sahrens */
7043fa9e4066Sahrens int
status_callback(zpool_handle_t * zhp,void * data)7044fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data)
7045fa9e4066Sahrens {
7046fa9e4066Sahrens status_cbdata_t *cbp = data;
7047fa9e4066Sahrens nvlist_t *config, *nvroot;
7048fa9e4066Sahrens char *msgid;
7049fa9e4066Sahrens int reason;
7050eb633035STom Caputi zpool_errata_t errata;
705146657f8dSmmusante const char *health;
705246657f8dSmmusante uint_t c;
705346657f8dSmmusante vdev_stat_t *vs;
7054fa9e4066Sahrens
7055088e9d47Seschrock config = zpool_get_config(zhp, NULL);
7056eb633035STom Caputi reason = zpool_get_status(zhp, &msgid, &errata);
7057fa9e4066Sahrens
7058fa9e4066Sahrens cbp->cb_count++;
7059fa9e4066Sahrens
7060fa9e4066Sahrens /*
7061fa9e4066Sahrens * If we were given 'zpool status -x', only report those pools with
7062fa9e4066Sahrens * problems.
7063fa9e4066Sahrens */
7064b3a6f804STim Connors if (cbp->cb_explain &&
7065b3a6f804STim Connors (reason == ZPOOL_STATUS_OK ||
7066b3a6f804STim Connors reason == ZPOOL_STATUS_VERSION_OLDER ||
7067b3a6f804STim Connors reason == ZPOOL_STATUS_FEAT_DISABLED)) {
7068e9dbad6fSeschrock if (!cbp->cb_allpools) {
7069e9dbad6fSeschrock (void) printf(gettext("pool '%s' is healthy\n"),
7070e9dbad6fSeschrock zpool_get_name(zhp));
7071e9dbad6fSeschrock if (cbp->cb_first)
7072e9dbad6fSeschrock cbp->cb_first = B_FALSE;
7073e9dbad6fSeschrock }
7074fa9e4066Sahrens return (0);
7075e9dbad6fSeschrock }
7076fa9e4066Sahrens
7077fa9e4066Sahrens if (cbp->cb_first)
707899653d4eSeschrock cbp->cb_first = B_FALSE;
7079fa9e4066Sahrens else
7080fa9e4066Sahrens (void) printf("\n");
7081fa9e4066Sahrens
70825cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
70833f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
708446657f8dSmmusante (uint64_t **)&vs, &c) == 0);
7085990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
7086fa9e4066Sahrens
7087fa9e4066Sahrens (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
7088fa9e4066Sahrens (void) printf(gettext(" state: %s\n"), health);
7089fa9e4066Sahrens
7090fa9e4066Sahrens switch (reason) {
7091fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R:
7092fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not "
7093fa9e4066Sahrens "be opened. Sufficient replicas exist for\n\tthe pool to "
7094fa9e4066Sahrens "continue functioning in a degraded state.\n"));
7095fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and "
7096fa9e4066Sahrens "online it using 'zpool online'.\n"));
7097fa9e4066Sahrens break;
7098fa9e4066Sahrens
7099fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR:
7100fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not "
7101fa9e4066Sahrens "be opened. There are insufficient\n\treplicas for the "
7102fa9e4066Sahrens "pool to continue functioning.\n"));
7103fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and "
7104fa9e4066Sahrens "online it using 'zpool online'.\n"));
7105fa9e4066Sahrens break;
7106fa9e4066Sahrens
7107fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R:
7108fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not "
7109fa9e4066Sahrens "be used because the label is missing or\n\tinvalid. "
7110fa9e4066Sahrens "Sufficient replicas exist for the pool to continue\n\t"
7111fa9e4066Sahrens "functioning in a degraded state.\n"));
7112fa9e4066Sahrens (void) printf(gettext("action: Replace the device using "
7113fa9e4066Sahrens "'zpool replace'.\n"));
7114fa9e4066Sahrens break;
7115fa9e4066Sahrens
7116fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR:
7117fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not "
7118b1b8ab34Slling "be used because the label is missing \n\tor invalid. "
7119fa9e4066Sahrens "There are insufficient replicas for the pool to "
7120fa9e4066Sahrens "continue\n\tfunctioning.\n"));
7121468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp),
7122468c413aSTim Haley zpool_get_name(zhp), reason, config);
7123fa9e4066Sahrens break;
7124fa9e4066Sahrens
7125fa9e4066Sahrens case ZPOOL_STATUS_FAILING_DEV:
7126fa9e4066Sahrens (void) printf(gettext("status: One or more devices has "
7127fa9e4066Sahrens "experienced an unrecoverable error. An\n\tattempt was "
7128fa9e4066Sahrens "made to correct the error. Applications are "
7129fa9e4066Sahrens "unaffected.\n"));
7130fa9e4066Sahrens (void) printf(gettext("action: Determine if the device needs "
7131fa9e4066Sahrens "to be replaced, and clear the errors\n\tusing "
7132ea8dc4b6Seschrock "'zpool clear' or replace the device with 'zpool "
7133fa9e4066Sahrens "replace'.\n"));
7134fa9e4066Sahrens break;
7135fa9e4066Sahrens
7136fa9e4066Sahrens case ZPOOL_STATUS_OFFLINE_DEV:
7137fa9e4066Sahrens (void) printf(gettext("status: One or more devices has "
7138d7d4af51Smmusante "been taken offline by the administrator.\n\tSufficient "
7139fa9e4066Sahrens "replicas exist for the pool to continue functioning in "
7140fa9e4066Sahrens "a\n\tdegraded state.\n"));
7141fa9e4066Sahrens (void) printf(gettext("action: Online the device using "
7142fa9e4066Sahrens "'zpool online' or replace the device with\n\t'zpool "
7143fa9e4066Sahrens "replace'.\n"));
7144fa9e4066Sahrens break;
7145fa9e4066Sahrens
7146c25309d4SGeorge Wilson case ZPOOL_STATUS_REMOVED_DEV:
7147c25309d4SGeorge Wilson (void) printf(gettext("status: One or more devices has "
7148c25309d4SGeorge Wilson "been removed by the administrator.\n\tSufficient "
7149c25309d4SGeorge Wilson "replicas exist for the pool to continue functioning in "
7150c25309d4SGeorge Wilson "a\n\tdegraded state.\n"));
7151c25309d4SGeorge Wilson (void) printf(gettext("action: Online the device using "
7152c25309d4SGeorge Wilson "'zpool online' or replace the device with\n\t'zpool "
7153c25309d4SGeorge Wilson "replace'.\n"));
7154c25309d4SGeorge Wilson break;
7155c25309d4SGeorge Wilson
7156fa9e4066Sahrens case ZPOOL_STATUS_RESILVERING:
7157fa9e4066Sahrens (void) printf(gettext("status: One or more devices is "
7158fa9e4066Sahrens "currently being resilvered. The pool will\n\tcontinue "
7159fa9e4066Sahrens "to function, possibly in a degraded state.\n"));
7160fa9e4066Sahrens (void) printf(gettext("action: Wait for the resilver to "
7161fa9e4066Sahrens "complete.\n"));
7162fa9e4066Sahrens break;
7163fa9e4066Sahrens
7164ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_DATA:
7165ea8dc4b6Seschrock (void) printf(gettext("status: One or more devices has "
7166ea8dc4b6Seschrock "experienced an error resulting in data\n\tcorruption. "
7167ea8dc4b6Seschrock "Applications may be affected.\n"));
7168ea8dc4b6Seschrock (void) printf(gettext("action: Restore the file in question "
7169ea8dc4b6Seschrock "if possible. Otherwise restore the\n\tentire pool from "
7170ea8dc4b6Seschrock "backup.\n"));
7171ea8dc4b6Seschrock break;
7172ea8dc4b6Seschrock
7173ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL:
7174ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is corrupted "
7175ea8dc4b6Seschrock "and the pool cannot be opened.\n"));
7176468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp),
7177468c413aSTim Haley zpool_get_name(zhp), reason, config);
7178ea8dc4b6Seschrock break;
7179ea8dc4b6Seschrock
7180eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER:
718157221772SChristopher Siden (void) printf(gettext("status: The pool is formatted using a "
718257221772SChristopher Siden "legacy on-disk format. The pool can\n\tstill be used, "
718357221772SChristopher Siden "but some features are unavailable.\n"));
7184eaca9bbdSeschrock (void) printf(gettext("action: Upgrade the pool using 'zpool "
7185eaca9bbdSeschrock "upgrade'. Once this is done, the\n\tpool will no longer "
718657221772SChristopher Siden "be accessible on software that does not support feature\n"
718757221772SChristopher Siden "\tflags.\n"));
7188eaca9bbdSeschrock break;
7189eaca9bbdSeschrock
7190eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER:
7191eaca9bbdSeschrock (void) printf(gettext("status: The pool has been upgraded to a "
7192eaca9bbdSeschrock "newer, incompatible on-disk version.\n\tThe pool cannot "
7193eaca9bbdSeschrock "be accessed on this system.\n"));
7194eaca9bbdSeschrock (void) printf(gettext("action: Access the pool from a system "
7195eaca9bbdSeschrock "running more recent software, or\n\trestore the pool from "
7196eaca9bbdSeschrock "backup.\n"));
7197eaca9bbdSeschrock break;
7198eaca9bbdSeschrock
719957221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED:
720057221772SChristopher Siden (void) printf(gettext("status: Some supported features are not "
720157221772SChristopher Siden "enabled on the pool. The pool can\n\tstill be used, but "
720257221772SChristopher Siden "some features are unavailable.\n"));
720357221772SChristopher Siden (void) printf(gettext("action: Enable all features using "
720457221772SChristopher Siden "'zpool upgrade'. Once this is done,\n\tthe pool may no "
720557221772SChristopher Siden "longer be accessible by software that does not support\n\t"
7206bbf21555SRichard Lowe "the features. See zpool-features(7) for details.\n"));
720757221772SChristopher Siden break;
720857221772SChristopher Siden
7209ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ:
7210ad135b5dSChristopher Siden (void) printf(gettext("status: The pool cannot be accessed on "
7211ad135b5dSChristopher Siden "this system because it uses the\n\tfollowing feature(s) "
7212ad135b5dSChristopher Siden "not supported on this system:\n"));
7213ad135b5dSChristopher Siden zpool_print_unsup_feat(config);
7214ad135b5dSChristopher Siden (void) printf("\n");
7215ad135b5dSChristopher Siden (void) printf(gettext("action: Access the pool from a system "
7216ad135b5dSChristopher Siden "that supports the required feature(s),\n\tor restore the "
7217ad135b5dSChristopher Siden "pool from backup.\n"));
7218ad135b5dSChristopher Siden break;
7219ad135b5dSChristopher Siden
7220ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
7221ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed "
7222ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be "
7223ad135b5dSChristopher Siden "accessed in read-write mode because it uses the "
7224ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n"));
7225ad135b5dSChristopher Siden zpool_print_unsup_feat(config);
7226ad135b5dSChristopher Siden (void) printf("\n");
7227ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be accessed in "
7228ad135b5dSChristopher Siden "read-write mode. Import the pool with\n"
7229ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool from a system that "
7230ad135b5dSChristopher Siden "supports the\n\trequired feature(s), or restore the "
7231ad135b5dSChristopher Siden "pool from backup.\n"));
7232ad135b5dSChristopher Siden break;
7233ad135b5dSChristopher Siden
72343d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R:
72353d7072f8Seschrock (void) printf(gettext("status: One or more devices are "
72363d7072f8Seschrock "faulted in response to persistent errors.\n\tSufficient "
72373d7072f8Seschrock "replicas exist for the pool to continue functioning "
72383d7072f8Seschrock "in a\n\tdegraded state.\n"));
72393d7072f8Seschrock (void) printf(gettext("action: Replace the faulted device, "
72403d7072f8Seschrock "or use 'zpool clear' to mark the device\n\trepaired.\n"));
72413d7072f8Seschrock break;
72423d7072f8Seschrock
72433d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR:
72443d7072f8Seschrock (void) printf(gettext("status: One or more devices are "
72453d7072f8Seschrock "faulted in response to persistent errors. There are "
72463d7072f8Seschrock "insufficient replicas for the pool to\n\tcontinue "
72473d7072f8Seschrock "functioning.\n"));
72483d7072f8Seschrock (void) printf(gettext("action: Destroy and re-create the pool "
72493d7072f8Seschrock "from a backup source. Manually marking the device\n"
72503d7072f8Seschrock "\trepaired using 'zpool clear' may allow some data "
72513d7072f8Seschrock "to be recovered.\n"));
72523d7072f8Seschrock break;
72533d7072f8Seschrock
7254e0f1c0afSOlaf Faaland case ZPOOL_STATUS_IO_FAILURE_MMP:
7255e0f1c0afSOlaf Faaland (void) printf(gettext("status: The pool is suspended because "
7256e0f1c0afSOlaf Faaland "multihost writes failed or were delayed;\n\tanother "
7257e0f1c0afSOlaf Faaland "system could import the pool undetected.\n"));
7258e0f1c0afSOlaf Faaland (void) printf(gettext("action: Make sure the pool's devices "
7259e0f1c0afSOlaf Faaland "are connected, then reboot your system and\n\timport the "
7260e0f1c0afSOlaf Faaland "pool.\n"));
7261e0f1c0afSOlaf Faaland break;
7262e0f1c0afSOlaf Faaland
726332b87932Sek110237 case ZPOOL_STATUS_IO_FAILURE_WAIT:
726432b87932Sek110237 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
726532b87932Sek110237 (void) printf(gettext("status: One or more devices are "
72668a79c1b5Sek110237 "faulted in response to IO failures.\n"));
726732b87932Sek110237 (void) printf(gettext("action: Make sure the affected devices "
726832b87932Sek110237 "are connected, then run 'zpool clear'.\n"));
726932b87932Sek110237 break;
727032b87932Sek110237
7271b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG:
7272b87f3af3Sperrin (void) printf(gettext("status: An intent log record "
7273b87f3af3Sperrin "could not be read.\n"
7274b87f3af3Sperrin "\tWaiting for adminstrator intervention to fix the "
7275b87f3af3Sperrin "faulted pool.\n"));
7276b87f3af3Sperrin (void) printf(gettext("action: Either restore the affected "
7277b87f3af3Sperrin "device(s) and run 'zpool online',\n"
7278b87f3af3Sperrin "\tor ignore the intent log records by running "
7279b87f3af3Sperrin "'zpool clear'.\n"));
7280b87f3af3Sperrin break;
7281b87f3af3Sperrin
7282eb633035STom Caputi case ZPOOL_STATUS_ERRATA:
7283eb633035STom Caputi (void) printf(gettext("status: Errata #%d detected.\n"),
7284eb633035STom Caputi errata);
7285eb633035STom Caputi
7286eb633035STom Caputi switch (errata) {
7287eb633035STom Caputi case ZPOOL_ERRATA_NONE:
7288eb633035STom Caputi break;
7289eb633035STom Caputi
7290eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB:
7291eb633035STom Caputi (void) printf(gettext("action: To correct the issue "
7292eb633035STom Caputi "run 'zpool scrub'.\n"));
7293eb633035STom Caputi break;
7294eb633035STom Caputi
7295eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
7296eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets "
7297eb633035STom Caputi "contain an on-disk incompatibility\n\twhich "
7298eb633035STom Caputi "needs to be corrected.\n"));
7299eb633035STom Caputi (void) printf(gettext("action: To correct the issue "
7300eb633035STom Caputi "backup existing encrypted datasets to new\n\t"
7301eb633035STom Caputi "encrypted datasets and destroy the old ones. "
7302eb633035STom Caputi "'zfs mount -o ro' can\n\tbe used to temporarily "
7303eb633035STom Caputi "mount existing encrypted datasets readonly.\n"));
7304eb633035STom Caputi break;
7305eb633035STom Caputi
7306eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
7307eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets "
7308eb633035STom Caputi "contain an on-disk incompatibility\n\twhich "
7309eb633035STom Caputi "needs to be corrected.\n"));
7310eb633035STom Caputi (void) printf(gettext("action: To correct the issue "
7311eb633035STom Caputi "enable the bookmark_v2 feature and "
7312eb633035STom Caputi "backup\n\tany existing encrypted datasets to "
7313eb633035STom Caputi "new encrypted datasets and\n\tdestroy the old "
7314eb633035STom Caputi "ones. If this pool does not contain any\n\t"
7315eb633035STom Caputi "encrypted datasets, simply enable the "
7316eb633035STom Caputi "bookmark_v2 feature\n"));
7317eb633035STom Caputi break;
7318eb633035STom Caputi
7319eb633035STom Caputi default:
7320eb633035STom Caputi /*
7321eb633035STom Caputi * All errata which allow the pool to be imported
7322eb633035STom Caputi * must contain an action message.
7323eb633035STom Caputi */
7324eb633035STom Caputi assert(0);
7325eb633035STom Caputi }
7326eb633035STom Caputi break;
7327eb633035STom Caputi
7328fa9e4066Sahrens default:
7329fa9e4066Sahrens /*
7330fa9e4066Sahrens * The remaining errors can't actually be generated, yet.
7331fa9e4066Sahrens */
7332fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK);
7333fa9e4066Sahrens }
7334fa9e4066Sahrens
7335fa9e4066Sahrens if (msgid != NULL)
7336654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
7337fa9e4066Sahrens msgid);
7338fa9e4066Sahrens
7339fa9e4066Sahrens if (config != NULL) {
7340ea8dc4b6Seschrock uint64_t nerr;
7341fa94a07fSbrendan nvlist_t **spares, **l2cache;
7342fa94a07fSbrendan uint_t nspares, nl2cache;
734386714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL;
73443f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL;
73455cabbc6bSPrashanth Sreenivasa pool_removal_stat_t *prs = NULL;
7346fa9e4066Sahrens
73473f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nvroot,
734886714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
734986714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot,
73503f9d6ad7SLin Ling ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
73515cabbc6bSPrashanth Sreenivasa (void) nvlist_lookup_uint64_array(nvroot,
73525cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
735386714001SSerapheim Dimitropoulos
735486714001SSerapheim Dimitropoulos print_scan_status(ps);
735586714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(ps, pcs);
73565cabbc6bSPrashanth Sreenivasa print_removal_status(zhp, prs);
735786714001SSerapheim Dimitropoulos print_checkpoint_status(pcs);
73585cabbc6bSPrashanth Sreenivasa
7359663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
7360663207adSDon Brady cbp->cb_name_flags);
7361663207adSDon Brady if (cbp->cb_namewidth < 10)
7362663207adSDon Brady cbp->cb_namewidth = 10;
7363fa9e4066Sahrens
7364fa9e4066Sahrens (void) printf(gettext("config:\n\n"));
7365663207adSDon Brady (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"),
7366663207adSDon Brady cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
7367663207adSDon Brady "CKSUM");
736899653d4eSeschrock
7369dd50e0ccSTony Hutter if (cbp->cb_print_slow_ios)
7370dd50e0ccSTony Hutter (void) printf(" %5s", gettext("SLOW"));
7371dd50e0ccSTony Hutter
7372663207adSDon Brady print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
7373663207adSDon Brady B_FALSE);
7374663207adSDon Brady
7375663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
7376663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
7377663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
7378663207adSDon Brady
7379fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
7380fa94a07fSbrendan &l2cache, &nl2cache) == 0)
7381663207adSDon Brady print_l2cache(zhp, cbp, l2cache, nl2cache);
7382fa94a07fSbrendan
738399653d4eSeschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
738499653d4eSeschrock &spares, &nspares) == 0)
7385663207adSDon Brady print_spares(zhp, cbp, spares, nspares);
7386ea8dc4b6Seschrock
7387ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
7388ea8dc4b6Seschrock &nerr) == 0) {
738955434c77Sek110237 nvlist_t *nverrlist = NULL;
739055434c77Sek110237
7391ea8dc4b6Seschrock /*
7392ea8dc4b6Seschrock * If the approximate error count is small, get a
7393ea8dc4b6Seschrock * precise count by fetching the entire log and
7394ea8dc4b6Seschrock * uniquifying the results.
7395ea8dc4b6Seschrock */
739675519f38Sek110237 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
739755434c77Sek110237 zpool_get_errlog(zhp, &nverrlist) == 0) {
739855434c77Sek110237 nvpair_t *elem;
739955434c77Sek110237
740055434c77Sek110237 elem = NULL;
740155434c77Sek110237 nerr = 0;
740255434c77Sek110237 while ((elem = nvlist_next_nvpair(nverrlist,
740355434c77Sek110237 elem)) != NULL) {
740455434c77Sek110237 nerr++;
740555434c77Sek110237 }
740655434c77Sek110237 }
740755434c77Sek110237 nvlist_free(nverrlist);
7408ea8dc4b6Seschrock
7409ea8dc4b6Seschrock (void) printf("\n");
741099653d4eSeschrock
7411ea8dc4b6Seschrock if (nerr == 0)
7412ea8dc4b6Seschrock (void) printf(gettext("errors: No known data "
7413ea8dc4b6Seschrock "errors\n"));
7414ea8dc4b6Seschrock else if (!cbp->cb_verbose)
7415e9dbad6fSeschrock (void) printf(gettext("errors: %llu data "
74165ad82045Snd150628 "errors, use '-v' for a list\n"),
74175ad82045Snd150628 (u_longlong_t)nerr);
7418ea8dc4b6Seschrock else
7419ea8dc4b6Seschrock print_error_log(zhp);
7420ea8dc4b6Seschrock }
74219eb19f4dSGeorge Wilson
74229eb19f4dSGeorge Wilson if (cbp->cb_dedup_stats)
74239eb19f4dSGeorge Wilson print_dedup_stats(config);
7424fa9e4066Sahrens } else {
7425fa9e4066Sahrens (void) printf(gettext("config: The configuration cannot be "
7426fa9e4066Sahrens "determined.\n"));
7427fa9e4066Sahrens }
7428fa9e4066Sahrens
7429fa9e4066Sahrens return (0);
7430fa9e4066Sahrens }
7431fa9e4066Sahrens
7432fa9e4066Sahrens /*
7433dd50e0ccSTony Hutter * zpool status [-igLpPstvx] [-T d|u] [pool] ... [interval [count]]
7434fa9e4066Sahrens *
7435084fd14fSBrian Behlendorf * -i Display vdev initialization status.
7436663207adSDon Brady * -g Display guid for individual vdev name.
7437663207adSDon Brady * -L Follow links when resolving vdev path name.
7438dd50e0ccSTony Hutter * -p Display values in parsable (exact) format.
7439663207adSDon Brady * -P Display full path for vdev name.
7440dd50e0ccSTony Hutter * -s Display slow IOs column.
7441fa9e4066Sahrens * -v Display complete error logs
7442fa9e4066Sahrens * -x Display only pools with potential problems
74439eb19f4dSGeorge Wilson * -D Display dedup status (undocumented)
7444084fd14fSBrian Behlendorf * -t Display vdev TRIM status.
74453f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format
7446fa9e4066Sahrens *
7447fa9e4066Sahrens * Describes the health status of all pools or some subset.
7448fa9e4066Sahrens */
7449fa9e4066Sahrens int
zpool_do_status(int argc,char ** argv)7450fa9e4066Sahrens zpool_do_status(int argc, char **argv)
7451fa9e4066Sahrens {
7452fa9e4066Sahrens int c;
7453fa9e4066Sahrens int ret;
7454dd50e0ccSTony Hutter float interval = 0;
7455dd50e0ccSTony Hutter unsigned long count = 0;
7456fa9e4066Sahrens status_cbdata_t cb = { 0 };
7457fa9e4066Sahrens
7458fa9e4066Sahrens /* check options */
7459dd50e0ccSTony Hutter while ((c = getopt(argc, argv, "igLpPsvxDtT:")) != -1) {
7460fa9e4066Sahrens switch (c) {
7461084fd14fSBrian Behlendorf case 'i':
7462084fd14fSBrian Behlendorf cb.cb_print_vdev_init = B_TRUE;
7463084fd14fSBrian Behlendorf break;
7464663207adSDon Brady case 'g':
7465663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID;
7466663207adSDon Brady break;
7467663207adSDon Brady case 'L':
7468663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
7469663207adSDon Brady break;
7470dd50e0ccSTony Hutter case 'p':
7471dd50e0ccSTony Hutter cb.cb_literal = B_TRUE;
7472dd50e0ccSTony Hutter break;
7473663207adSDon Brady case 'P':
7474663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH;
7475663207adSDon Brady break;
7476dd50e0ccSTony Hutter case 's':
7477dd50e0ccSTony Hutter cb.cb_print_slow_ios = B_TRUE;
7478dd50e0ccSTony Hutter break;
7479fa9e4066Sahrens case 'v':
748099653d4eSeschrock cb.cb_verbose = B_TRUE;
7481fa9e4066Sahrens break;
7482fa9e4066Sahrens case 'x':
748399653d4eSeschrock cb.cb_explain = B_TRUE;
7484fa9e4066Sahrens break;
74859eb19f4dSGeorge Wilson case 'D':
74869eb19f4dSGeorge Wilson cb.cb_dedup_stats = B_TRUE;
74879eb19f4dSGeorge Wilson break;
7488084fd14fSBrian Behlendorf case 't':
7489084fd14fSBrian Behlendorf cb.cb_print_vdev_trim = B_TRUE;
7490084fd14fSBrian Behlendorf break;
74913f9d6ad7SLin Ling case 'T':
74923f9d6ad7SLin Ling get_timestamp_arg(*optarg);
74933f9d6ad7SLin Ling break;
7494fa9e4066Sahrens case '?':
7495fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7496fa9e4066Sahrens optopt);
749799653d4eSeschrock usage(B_FALSE);
7498fa9e4066Sahrens }
7499fa9e4066Sahrens }
7500fa9e4066Sahrens
7501fa9e4066Sahrens argc -= optind;
7502fa9e4066Sahrens argv += optind;
7503fa9e4066Sahrens
75043f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count);
7505fa9e4066Sahrens
7506e9dbad6fSeschrock if (argc == 0)
7507e9dbad6fSeschrock cb.cb_allpools = B_TRUE;
7508e9dbad6fSeschrock
75093f9d6ad7SLin Ling cb.cb_first = B_TRUE;
7510663207adSDon Brady cb.cb_print_status = B_TRUE;
75113f9d6ad7SLin Ling
75123f9d6ad7SLin Ling for (;;) {
75133f9d6ad7SLin Ling if (timestamp_fmt != NODATE)
75143f9d6ad7SLin Ling print_timestamp(timestamp_fmt);
75153f9d6ad7SLin Ling
75163f9d6ad7SLin Ling ret = for_each_pool(argc, argv, B_TRUE, NULL,
75173f9d6ad7SLin Ling status_callback, &cb);
7518fa9e4066Sahrens
7519fa9e4066Sahrens if (argc == 0 && cb.cb_count == 0)
7520fa9e4066Sahrens (void) printf(gettext("no pools available\n"));
7521e9dbad6fSeschrock else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
7522fa9e4066Sahrens (void) printf(gettext("all pools are healthy\n"));
7523fa9e4066Sahrens
75243f9d6ad7SLin Ling if (ret != 0)
7525fa9e4066Sahrens return (ret);
75263f9d6ad7SLin Ling
75273f9d6ad7SLin Ling if (interval == 0)
75283f9d6ad7SLin Ling break;
75293f9d6ad7SLin Ling
75303f9d6ad7SLin Ling if (count != 0 && --count == 0)
75313f9d6ad7SLin Ling break;
75323f9d6ad7SLin Ling
7533dd50e0ccSTony Hutter (void) fsleep(interval);
75343f9d6ad7SLin Ling }
75353f9d6ad7SLin Ling
75363f9d6ad7SLin Ling return (0);
7537fa9e4066Sahrens }
7538fa9e4066Sahrens
7539eaca9bbdSeschrock typedef struct upgrade_cbdata {
7540eaca9bbdSeschrock int cb_first;
754106eeb2adSek110237 int cb_argc;
7542990b4856Slling uint64_t cb_version;
754306eeb2adSek110237 char **cb_argv;
7544eaca9bbdSeschrock } upgrade_cbdata_t;
7545eaca9bbdSeschrock
7546eaca9bbdSeschrock static int
upgrade_version(zpool_handle_t * zhp,uint64_t version)754757221772SChristopher Siden upgrade_version(zpool_handle_t *zhp, uint64_t version)
754857221772SChristopher Siden {
754957221772SChristopher Siden int ret;
755057221772SChristopher Siden nvlist_t *config;
755157221772SChristopher Siden uint64_t oldversion;
755257221772SChristopher Siden
755357221772SChristopher Siden config = zpool_get_config(zhp, NULL);
755457221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
755557221772SChristopher Siden &oldversion) == 0);
755657221772SChristopher Siden
755757221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(oldversion));
755857221772SChristopher Siden assert(oldversion < version);
755957221772SChristopher Siden
756057221772SChristopher Siden ret = zpool_upgrade(zhp, version);
756157221772SChristopher Siden if (ret != 0)
756257221772SChristopher Siden return (ret);
756357221772SChristopher Siden
756457221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) {
756557221772SChristopher Siden (void) printf(gettext("Successfully upgraded "
756657221772SChristopher Siden "'%s' from version %llu to feature flags.\n"),
756757221772SChristopher Siden zpool_get_name(zhp), oldversion);
756857221772SChristopher Siden } else {
756957221772SChristopher Siden (void) printf(gettext("Successfully upgraded "
757057221772SChristopher Siden "'%s' from version %llu to version %llu.\n"),
757157221772SChristopher Siden zpool_get_name(zhp), oldversion, version);
757257221772SChristopher Siden }
757357221772SChristopher Siden
757457221772SChristopher Siden return (0);
757557221772SChristopher Siden }
757657221772SChristopher Siden
757757221772SChristopher Siden static int
upgrade_enable_all(zpool_handle_t * zhp,int * countp)757857221772SChristopher Siden upgrade_enable_all(zpool_handle_t *zhp, int *countp)
757957221772SChristopher Siden {
758057221772SChristopher Siden int i, ret, count;
758157221772SChristopher Siden boolean_t firstff = B_TRUE;
758257221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp);
758357221772SChristopher Siden
758457221772SChristopher Siden count = 0;
758557221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) {
758657221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname;
758757221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid;
758857221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) {
758957221772SChristopher Siden char *propname;
759057221772SChristopher Siden verify(-1 != asprintf(&propname, "feature@%s", fname));
759157221772SChristopher Siden ret = zpool_set_prop(zhp, propname,
759257221772SChristopher Siden ZFS_FEATURE_ENABLED);
759357221772SChristopher Siden if (ret != 0) {
759457221772SChristopher Siden free(propname);
759557221772SChristopher Siden return (ret);
759657221772SChristopher Siden }
759757221772SChristopher Siden count++;
759857221772SChristopher Siden
759957221772SChristopher Siden if (firstff) {
760057221772SChristopher Siden (void) printf(gettext("Enabled the "
760157221772SChristopher Siden "following features on '%s':\n"),
760257221772SChristopher Siden zpool_get_name(zhp));
760357221772SChristopher Siden firstff = B_FALSE;
760457221772SChristopher Siden }
760557221772SChristopher Siden (void) printf(gettext(" %s\n"), fname);
760657221772SChristopher Siden free(propname);
760757221772SChristopher Siden }
760857221772SChristopher Siden }
760957221772SChristopher Siden
761057221772SChristopher Siden if (countp != NULL)
761157221772SChristopher Siden *countp = count;
761257221772SChristopher Siden return (0);
761357221772SChristopher Siden }
761457221772SChristopher Siden
761557221772SChristopher Siden static int
upgrade_cb(zpool_handle_t * zhp,void * arg)7616eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg)
7617eaca9bbdSeschrock {
7618eaca9bbdSeschrock upgrade_cbdata_t *cbp = arg;
7619eaca9bbdSeschrock nvlist_t *config;
7620eaca9bbdSeschrock uint64_t version;
762157221772SChristopher Siden boolean_t printnl = B_FALSE;
762257221772SChristopher Siden int ret;
7623eaca9bbdSeschrock
7624eaca9bbdSeschrock config = zpool_get_config(zhp, NULL);
7625eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
7626eaca9bbdSeschrock &version) == 0);
7627eaca9bbdSeschrock
762857221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version));
7629eaca9bbdSeschrock
763057221772SChristopher Siden if (version < cbp->cb_version) {
763199653d4eSeschrock cbp->cb_first = B_FALSE;
763257221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version);
763357221772SChristopher Siden if (ret != 0)
763457221772SChristopher Siden return (ret);
763557221772SChristopher Siden printnl = B_TRUE;
763657221772SChristopher Siden
76374445fffbSMatthew Ahrens /*
76384445fffbSMatthew Ahrens * If they did "zpool upgrade -a", then we could
76394445fffbSMatthew Ahrens * be doing ioctls to different pools. We need
76404445fffbSMatthew Ahrens * to log this history once to each pool, and bypass
76414445fffbSMatthew Ahrens * the normal history logging that happens in main().
76424445fffbSMatthew Ahrens */
76434445fffbSMatthew Ahrens (void) zpool_log_history(g_zfs, history_str);
76444445fffbSMatthew Ahrens log_history = B_FALSE;
764506eeb2adSek110237 }
7646eaca9bbdSeschrock
764757221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) {
764857221772SChristopher Siden int count;
764957221772SChristopher Siden ret = upgrade_enable_all(zhp, &count);
765057221772SChristopher Siden if (ret != 0)
765157221772SChristopher Siden return (ret);
765257221772SChristopher Siden
765357221772SChristopher Siden if (count > 0) {
765457221772SChristopher Siden cbp->cb_first = B_FALSE;
765557221772SChristopher Siden printnl = B_TRUE;
765657221772SChristopher Siden }
765757221772SChristopher Siden }
765857221772SChristopher Siden
765957221772SChristopher Siden if (printnl) {
766057221772SChristopher Siden (void) printf(gettext("\n"));
766157221772SChristopher Siden }
766257221772SChristopher Siden
766357221772SChristopher Siden return (0);
766457221772SChristopher Siden }
766557221772SChristopher Siden
766657221772SChristopher Siden static int
upgrade_list_older_cb(zpool_handle_t * zhp,void * arg)766757221772SChristopher Siden upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
766857221772SChristopher Siden {
766957221772SChristopher Siden upgrade_cbdata_t *cbp = arg;
767057221772SChristopher Siden nvlist_t *config;
767157221772SChristopher Siden uint64_t version;
767257221772SChristopher Siden
767357221772SChristopher Siden config = zpool_get_config(zhp, NULL);
767457221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
767557221772SChristopher Siden &version) == 0);
767657221772SChristopher Siden
767757221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version));
767857221772SChristopher Siden
767957221772SChristopher Siden if (version < SPA_VERSION_FEATURES) {
7680eaca9bbdSeschrock if (cbp->cb_first) {
7681eaca9bbdSeschrock (void) printf(gettext("The following pools are "
768257221772SChristopher Siden "formatted with legacy version numbers and can\n"
768357221772SChristopher Siden "be upgraded to use feature flags. After "
768457221772SChristopher Siden "being upgraded, these pools\nwill no "
768557221772SChristopher Siden "longer be accessible by software that does not "
768657221772SChristopher Siden "support feature\nflags.\n\n"));
7687eaca9bbdSeschrock (void) printf(gettext("VER POOL\n"));
7688eaca9bbdSeschrock (void) printf(gettext("--- ------------\n"));
768999653d4eSeschrock cbp->cb_first = B_FALSE;
7690eaca9bbdSeschrock }
7691eaca9bbdSeschrock
76925ad82045Snd150628 (void) printf("%2llu %s\n", (u_longlong_t)version,
7693eaca9bbdSeschrock zpool_get_name(zhp));
7694eaca9bbdSeschrock }
7695eaca9bbdSeschrock
769657221772SChristopher Siden return (0);
769757221772SChristopher Siden }
769857221772SChristopher Siden
769957221772SChristopher Siden static int
upgrade_list_disabled_cb(zpool_handle_t * zhp,void * arg)770057221772SChristopher Siden upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
770157221772SChristopher Siden {
770257221772SChristopher Siden upgrade_cbdata_t *cbp = arg;
770357221772SChristopher Siden nvlist_t *config;
770457221772SChristopher Siden uint64_t version;
770557221772SChristopher Siden
770657221772SChristopher Siden config = zpool_get_config(zhp, NULL);
770757221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
770857221772SChristopher Siden &version) == 0);
770957221772SChristopher Siden
771057221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) {
771157221772SChristopher Siden int i;
771257221772SChristopher Siden boolean_t poolfirst = B_TRUE;
771357221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp);
771457221772SChristopher Siden
771557221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) {
771657221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid;
771757221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname;
771857221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) {
771957221772SChristopher Siden if (cbp->cb_first) {
772057221772SChristopher Siden (void) printf(gettext("\nSome "
772157221772SChristopher Siden "supported features are not "
772257221772SChristopher Siden "enabled on the following pools. "
772357221772SChristopher Siden "Once a\nfeature is enabled the "
772457221772SChristopher Siden "pool may become incompatible with "
772557221772SChristopher Siden "software\nthat does not support "
772657221772SChristopher Siden "the feature. See "
7727bbf21555SRichard Lowe "zpool-features(7) for "
772857221772SChristopher Siden "details.\n\n"));
772957221772SChristopher Siden (void) printf(gettext("POOL "
773057221772SChristopher Siden "FEATURE\n"));
773157221772SChristopher Siden (void) printf(gettext("------"
773257221772SChristopher Siden "---------\n"));
773357221772SChristopher Siden cbp->cb_first = B_FALSE;
773457221772SChristopher Siden }
773557221772SChristopher Siden
773657221772SChristopher Siden if (poolfirst) {
773757221772SChristopher Siden (void) printf(gettext("%s\n"),
773857221772SChristopher Siden zpool_get_name(zhp));
773957221772SChristopher Siden poolfirst = B_FALSE;
774057221772SChristopher Siden }
774157221772SChristopher Siden
774257221772SChristopher Siden (void) printf(gettext(" %s\n"), fname);
774357221772SChristopher Siden }
774457221772SChristopher Siden }
774557221772SChristopher Siden }
774657221772SChristopher Siden
774757221772SChristopher Siden return (0);
7748eaca9bbdSeschrock }
7749eaca9bbdSeschrock
7750eaca9bbdSeschrock /* ARGSUSED */
7751eaca9bbdSeschrock static int
upgrade_one(zpool_handle_t * zhp,void * data)775206eeb2adSek110237 upgrade_one(zpool_handle_t *zhp, void *data)
7753eaca9bbdSeschrock {
775457221772SChristopher Siden boolean_t printnl = B_FALSE;
7755990b4856Slling upgrade_cbdata_t *cbp = data;
7756990b4856Slling uint64_t cur_version;
7757eaca9bbdSeschrock int ret;
7758eaca9bbdSeschrock
77598654d025Sperrin if (strcmp("log", zpool_get_name(zhp)) == 0) {
77608654d025Sperrin (void) printf(gettext("'log' is now a reserved word\n"
77618654d025Sperrin "Pool 'log' must be renamed using export and import"
77628654d025Sperrin " to upgrade.\n"));
77638654d025Sperrin return (1);
77648654d025Sperrin }
7765990b4856Slling
7766990b4856Slling cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
7767e6c728e1Sbrendan if (cur_version > cbp->cb_version) {
7768eaca9bbdSeschrock (void) printf(gettext("Pool '%s' is already formatted "
776957221772SChristopher Siden "using more current version '%llu'.\n\n"),
7770e6c728e1Sbrendan zpool_get_name(zhp), cur_version);
7771e6c728e1Sbrendan return (0);
7772e6c728e1Sbrendan }
777357221772SChristopher Siden
777457221772SChristopher Siden if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
7775e6c728e1Sbrendan (void) printf(gettext("Pool '%s' is already formatted "
777657221772SChristopher Siden "using version %llu.\n\n"), zpool_get_name(zhp),
777757221772SChristopher Siden cbp->cb_version);
7778eaca9bbdSeschrock return (0);
7779eaca9bbdSeschrock }
7780eaca9bbdSeschrock
778157221772SChristopher Siden if (cur_version != cbp->cb_version) {
778257221772SChristopher Siden printnl = B_TRUE;
778357221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version);
778457221772SChristopher Siden if (ret != 0)
778557221772SChristopher Siden return (ret);
778606eeb2adSek110237 }
7787eaca9bbdSeschrock
778857221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) {
778957221772SChristopher Siden int count = 0;
779057221772SChristopher Siden ret = upgrade_enable_all(zhp, &count);
779157221772SChristopher Siden if (ret != 0)
779257221772SChristopher Siden return (ret);
779357221772SChristopher Siden
779457221772SChristopher Siden if (count != 0) {
779557221772SChristopher Siden printnl = B_TRUE;
779657221772SChristopher Siden } else if (cur_version == SPA_VERSION) {
779757221772SChristopher Siden (void) printf(gettext("Pool '%s' already has all "
779857221772SChristopher Siden "supported features enabled.\n"),
779957221772SChristopher Siden zpool_get_name(zhp));
780057221772SChristopher Siden }
780157221772SChristopher Siden }
780257221772SChristopher Siden
780357221772SChristopher Siden if (printnl) {
780457221772SChristopher Siden (void) printf(gettext("\n"));
780557221772SChristopher Siden }
780657221772SChristopher Siden
780757221772SChristopher Siden return (0);
7808eaca9bbdSeschrock }
7809eaca9bbdSeschrock
7810eaca9bbdSeschrock /*
7811eaca9bbdSeschrock * zpool upgrade
7812eaca9bbdSeschrock * zpool upgrade -v
7813990b4856Slling * zpool upgrade [-V version] <-a | pool ...>
7814eaca9bbdSeschrock *
7815eaca9bbdSeschrock * With no arguments, display downrev'd ZFS pool available for upgrade.
7816eaca9bbdSeschrock * Individual pools can be upgraded by specifying the pool, and '-a' will
7817eaca9bbdSeschrock * upgrade all pools.
7818eaca9bbdSeschrock */
7819eaca9bbdSeschrock int
zpool_do_upgrade(int argc,char ** argv)7820eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv)
7821eaca9bbdSeschrock {
7822eaca9bbdSeschrock int c;
7823eaca9bbdSeschrock upgrade_cbdata_t cb = { 0 };
7824eaca9bbdSeschrock int ret = 0;
7825eaca9bbdSeschrock boolean_t showversions = B_FALSE;
782657221772SChristopher Siden boolean_t upgradeall = B_FALSE;
7827990b4856Slling char *end;
7828990b4856Slling
7829eaca9bbdSeschrock
7830eaca9bbdSeschrock /* check options */
7831478ed9adSEric Taylor while ((c = getopt(argc, argv, ":avV:")) != -1) {
7832eaca9bbdSeschrock switch (c) {
7833eaca9bbdSeschrock case 'a':
783457221772SChristopher Siden upgradeall = B_TRUE;
7835eaca9bbdSeschrock break;
7836eaca9bbdSeschrock case 'v':
7837eaca9bbdSeschrock showversions = B_TRUE;
7838eaca9bbdSeschrock break;
7839990b4856Slling case 'V':
7840990b4856Slling cb.cb_version = strtoll(optarg, &end, 10);
7841ad135b5dSChristopher Siden if (*end != '\0' ||
7842ad135b5dSChristopher Siden !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
7843990b4856Slling (void) fprintf(stderr,
7844990b4856Slling gettext("invalid version '%s'\n"), optarg);
7845990b4856Slling usage(B_FALSE);
7846990b4856Slling }
7847990b4856Slling break;
7848478ed9adSEric Taylor case ':':
7849478ed9adSEric Taylor (void) fprintf(stderr, gettext("missing argument for "
7850478ed9adSEric Taylor "'%c' option\n"), optopt);
7851478ed9adSEric Taylor usage(B_FALSE);
7852478ed9adSEric Taylor break;
7853eaca9bbdSeschrock case '?':
7854eaca9bbdSeschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7855eaca9bbdSeschrock optopt);
785699653d4eSeschrock usage(B_FALSE);
7857eaca9bbdSeschrock }
7858eaca9bbdSeschrock }
7859eaca9bbdSeschrock
786006eeb2adSek110237 cb.cb_argc = argc;
786106eeb2adSek110237 cb.cb_argv = argv;
7862eaca9bbdSeschrock argc -= optind;
7863eaca9bbdSeschrock argv += optind;
7864eaca9bbdSeschrock
7865351420b3Slling if (cb.cb_version == 0) {
7866351420b3Slling cb.cb_version = SPA_VERSION;
786757221772SChristopher Siden } else if (!upgradeall && argc == 0) {
7868351420b3Slling (void) fprintf(stderr, gettext("-V option is "
7869351420b3Slling "incompatible with other arguments\n"));
7870351420b3Slling usage(B_FALSE);
7871351420b3Slling }
7872351420b3Slling
7873eaca9bbdSeschrock if (showversions) {
787457221772SChristopher Siden if (upgradeall || argc != 0) {
7875eaca9bbdSeschrock (void) fprintf(stderr, gettext("-v option is "
7876eaca9bbdSeschrock "incompatible with other arguments\n"));
787799653d4eSeschrock usage(B_FALSE);
7878eaca9bbdSeschrock }
787957221772SChristopher Siden } else if (upgradeall) {
7880eaca9bbdSeschrock if (argc != 0) {
7881351420b3Slling (void) fprintf(stderr, gettext("-a option should not "
7882351420b3Slling "be used along with a pool name\n"));
788399653d4eSeschrock usage(B_FALSE);
7884eaca9bbdSeschrock }
7885eaca9bbdSeschrock }
7886eaca9bbdSeschrock
7887ad135b5dSChristopher Siden (void) printf(gettext("This system supports ZFS pool feature "
7888ad135b5dSChristopher Siden "flags.\n\n"));
7889eaca9bbdSeschrock if (showversions) {
789057221772SChristopher Siden int i;
789157221772SChristopher Siden
789257221772SChristopher Siden (void) printf(gettext("The following features are "
789357221772SChristopher Siden "supported:\n\n"));
789457221772SChristopher Siden (void) printf(gettext("FEAT DESCRIPTION\n"));
789557221772SChristopher Siden (void) printf("----------------------------------------------"
789657221772SChristopher Siden "---------------\n");
789757221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) {
789857221772SChristopher Siden zfeature_info_t *fi = &spa_feature_table[i];
7899ca0cc391SMatthew Ahrens const char *ro =
7900ca0cc391SMatthew Ahrens (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
790157221772SChristopher Siden " (read-only compatible)" : "";
790257221772SChristopher Siden
790357221772SChristopher Siden (void) printf("%-37s%s\n", fi->fi_uname, ro);
790457221772SChristopher Siden (void) printf(" %s\n", fi->fi_desc);
790557221772SChristopher Siden }
790657221772SChristopher Siden (void) printf("\n");
790757221772SChristopher Siden
790857221772SChristopher Siden (void) printf(gettext("The following legacy versions are also "
7909d7d4af51Smmusante "supported:\n\n"));
7910eaca9bbdSeschrock (void) printf(gettext("VER DESCRIPTION\n"));
7911eaca9bbdSeschrock (void) printf("--- -----------------------------------------"
7912eaca9bbdSeschrock "---------------\n");
791399653d4eSeschrock (void) printf(gettext(" 1 Initial ZFS version\n"));
791444cd46caSbillm (void) printf(gettext(" 2 Ditto blocks "
791544cd46caSbillm "(replicated metadata)\n"));
791699653d4eSeschrock (void) printf(gettext(" 3 Hot spares and double parity "
791799653d4eSeschrock "RAID-Z\n"));
7918d7306b64Sek110237 (void) printf(gettext(" 4 zpool history\n"));
7919c9431fa1Sahl (void) printf(gettext(" 5 Compression using the gzip "
7920c9431fa1Sahl "algorithm\n"));
7921990b4856Slling (void) printf(gettext(" 6 bootfs pool property\n"));
79228654d025Sperrin (void) printf(gettext(" 7 Separate intent log devices\n"));
7923ecd6cf80Smarks (void) printf(gettext(" 8 Delegated administration\n"));
7924a9799022Sck153898 (void) printf(gettext(" 9 refquota and refreservation "
7925a9799022Sck153898 "properties\n"));
7926fa94a07fSbrendan (void) printf(gettext(" 10 Cache devices\n"));
7927088f3894Sahrens (void) printf(gettext(" 11 Improved scrub performance\n"));
7928bb0ade09Sahrens (void) printf(gettext(" 12 Snapshot properties\n"));
792974e7dc98SMatthew Ahrens (void) printf(gettext(" 13 snapused property\n"));
793014843421SMatthew Ahrens (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
793114843421SMatthew Ahrens (void) printf(gettext(" 15 user/group space accounting\n"));
7932478ed9adSEric Taylor (void) printf(gettext(" 16 stmf property support\n"));
79337aeab329SAdam Leventhal (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
7934b24ab676SJeff Bonwick (void) printf(gettext(" 18 Snapshot user holds\n"));
793588ecc943SGeorge Wilson (void) printf(gettext(" 19 Log device removal\n"));
7936b24ab676SJeff Bonwick (void) printf(gettext(" 20 Compression using zle "
7937b24ab676SJeff Bonwick "(zero-length encoding)\n"));
7938b24ab676SJeff Bonwick (void) printf(gettext(" 21 Deduplication\n"));
793992241e0bSTom Erickson (void) printf(gettext(" 22 Received properties\n"));
79406e1f5caaSNeil Perrin (void) printf(gettext(" 23 Slim ZIL\n"));
79410a586ceaSMark Shellenbaum (void) printf(gettext(" 24 System attributes\n"));
79423f9d6ad7SLin Ling (void) printf(gettext(" 25 Improved scrub stats\n"));
7943cde58dbcSMatthew Ahrens (void) printf(gettext(" 26 Improved snapshot deletion "
7944cde58dbcSMatthew Ahrens "performance\n"));
79456e0cbcaaSMatthew Ahrens (void) printf(gettext(" 27 Improved snapshot creation "
79466e0cbcaaSMatthew Ahrens "performance\n"));
7947cb04b873SMark J Musante (void) printf(gettext(" 28 Multiple vdev replacements\n"));
7948b24ab676SJeff Bonwick (void) printf(gettext("\nFor more information on a particular "
79499a8685acSstephanie scheffler "version, including supported releases,\n"));
79509a8685acSstephanie scheffler (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
795157221772SChristopher Siden } else if (argc == 0 && upgradeall) {
7952eaca9bbdSeschrock cb.cb_first = B_TRUE;
795399653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb);
795457221772SChristopher Siden if (ret == 0 && cb.cb_first) {
795557221772SChristopher Siden if (cb.cb_version == SPA_VERSION) {
795657221772SChristopher Siden (void) printf(gettext("All pools are already "
795757221772SChristopher Siden "formatted using feature flags.\n\n"));
795857221772SChristopher Siden (void) printf(gettext("Every feature flags "
795957221772SChristopher Siden "pool already has all supported features "
796057221772SChristopher Siden "enabled.\n"));
796157221772SChristopher Siden } else {
796257221772SChristopher Siden (void) printf(gettext("All pools are already "
796357221772SChristopher Siden "formatted with version %llu or higher.\n"),
796457221772SChristopher Siden cb.cb_version);
7965eaca9bbdSeschrock }
7966eaca9bbdSeschrock }
796757221772SChristopher Siden } else if (argc == 0) {
796857221772SChristopher Siden cb.cb_first = B_TRUE;
796957221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
797057221772SChristopher Siden assert(ret == 0);
797157221772SChristopher Siden
797257221772SChristopher Siden if (cb.cb_first) {
797357221772SChristopher Siden (void) printf(gettext("All pools are formatted "
797457221772SChristopher Siden "using feature flags.\n\n"));
797557221772SChristopher Siden } else {
797657221772SChristopher Siden (void) printf(gettext("\nUse 'zpool upgrade -v' "
797757221772SChristopher Siden "for a list of available legacy versions.\n"));
797857221772SChristopher Siden }
7979eaca9bbdSeschrock
798057221772SChristopher Siden cb.cb_first = B_TRUE;
798157221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
798257221772SChristopher Siden assert(ret == 0);
798357221772SChristopher Siden
798457221772SChristopher Siden if (cb.cb_first) {
798557221772SChristopher Siden (void) printf(gettext("Every feature flags pool has "
798657221772SChristopher Siden "all supported features enabled.\n"));
798757221772SChristopher Siden } else {
798857221772SChristopher Siden (void) printf(gettext("\n"));
7989eaca9bbdSeschrock }
7990eaca9bbdSeschrock } else {
7991b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL,
7992b1b8ab34Slling upgrade_one, &cb);
799306eeb2adSek110237 }
799406eeb2adSek110237
799506eeb2adSek110237 return (ret);
799606eeb2adSek110237 }
799706eeb2adSek110237
7998ecd6cf80Smarks typedef struct hist_cbdata {
7999ecd6cf80Smarks boolean_t first;
80004445fffbSMatthew Ahrens boolean_t longfmt;
80014445fffbSMatthew Ahrens boolean_t internal;
8002ecd6cf80Smarks } hist_cbdata_t;
8003ecd6cf80Smarks
8004a52121eaSChunwei Chen static void
print_history_records(nvlist_t * nvhis,hist_cbdata_t * cb)8005a52121eaSChunwei Chen print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
800606eeb2adSek110237 {
800706eeb2adSek110237 nvlist_t **records;
800806eeb2adSek110237 uint_t numrecords;
8009a52121eaSChunwei Chen int i;
801006eeb2adSek110237
801106eeb2adSek110237 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
801206eeb2adSek110237 &records, &numrecords) == 0);
801306eeb2adSek110237 for (i = 0; i < numrecords; i++) {
80144445fffbSMatthew Ahrens nvlist_t *rec = records[i];
80154445fffbSMatthew Ahrens char tbuf[30] = "";
8016ecd6cf80Smarks
80174445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
80184445fffbSMatthew Ahrens time_t tsec;
80194445fffbSMatthew Ahrens struct tm t;
8020ecd6cf80Smarks
80214445fffbSMatthew Ahrens tsec = fnvlist_lookup_uint64(records[i],
80224445fffbSMatthew Ahrens ZPOOL_HIST_TIME);
802306eeb2adSek110237 (void) localtime_r(&tsec, &t);
802406eeb2adSek110237 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
80254445fffbSMatthew Ahrens }
80264445fffbSMatthew Ahrens
80274445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
80284445fffbSMatthew Ahrens (void) printf("%s %s", tbuf,
80294445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
80304445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
80314445fffbSMatthew Ahrens int ievent =
80324445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
80334445fffbSMatthew Ahrens if (!cb->internal)
80344445fffbSMatthew Ahrens continue;
80354445fffbSMatthew Ahrens if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
80364445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n",
80374445fffbSMatthew Ahrens tbuf);
80384445fffbSMatthew Ahrens dump_nvlist(rec, 4);
80394445fffbSMatthew Ahrens continue;
80404445fffbSMatthew Ahrens }
80414445fffbSMatthew Ahrens (void) printf("%s [internal %s txg:%lld] %s", tbuf,
80424445fffbSMatthew Ahrens zfs_history_event_names[ievent],
80434445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
80444445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
80454445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
80464445fffbSMatthew Ahrens if (!cb->internal)
80474445fffbSMatthew Ahrens continue;
80484445fffbSMatthew Ahrens (void) printf("%s [txg:%lld] %s", tbuf,
80494445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
80504445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
80514445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
80524445fffbSMatthew Ahrens (void) printf(" %s (%llu)",
80534445fffbSMatthew Ahrens fnvlist_lookup_string(rec,
80544445fffbSMatthew Ahrens ZPOOL_HIST_DSNAME),
80554445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec,
80564445fffbSMatthew Ahrens ZPOOL_HIST_DSID));
80574445fffbSMatthew Ahrens }
80584445fffbSMatthew Ahrens (void) printf(" %s", fnvlist_lookup_string(rec,
80594445fffbSMatthew Ahrens ZPOOL_HIST_INT_STR));
80604445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
80614445fffbSMatthew Ahrens if (!cb->internal)
80624445fffbSMatthew Ahrens continue;
80634445fffbSMatthew Ahrens (void) printf("%s ioctl %s\n", tbuf,
80644445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
80654445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
80664445fffbSMatthew Ahrens (void) printf(" input:\n");
80674445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec,
80684445fffbSMatthew Ahrens ZPOOL_HIST_INPUT_NVL), 8);
80694445fffbSMatthew Ahrens }
80704445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
80714445fffbSMatthew Ahrens (void) printf(" output:\n");
80724445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec,
80734445fffbSMatthew Ahrens ZPOOL_HIST_OUTPUT_NVL), 8);
80744445fffbSMatthew Ahrens }
8075dfc11533SChris Williamson if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
8076dfc11533SChris Williamson (void) printf(" errno: %lld\n",
8077dfc11533SChris Williamson fnvlist_lookup_int64(rec,
8078dfc11533SChris Williamson ZPOOL_HIST_ERRNO));
8079dfc11533SChris Williamson }
80804445fffbSMatthew Ahrens } else {
80814445fffbSMatthew Ahrens if (!cb->internal)
80824445fffbSMatthew Ahrens continue;
80834445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", tbuf);
80844445fffbSMatthew Ahrens dump_nvlist(rec, 4);
80854445fffbSMatthew Ahrens }
8086ecd6cf80Smarks
8087ecd6cf80Smarks if (!cb->longfmt) {
8088ecd6cf80Smarks (void) printf("\n");
8089ecd6cf80Smarks continue;
809006eeb2adSek110237 }
8091ecd6cf80Smarks (void) printf(" [");
80924445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
80934445fffbSMatthew Ahrens uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
80944445fffbSMatthew Ahrens struct passwd *pwd = getpwuid(who);
80954445fffbSMatthew Ahrens (void) printf("user %d ", (int)who);
80964445fffbSMatthew Ahrens if (pwd != NULL)
80974445fffbSMatthew Ahrens (void) printf("(%s) ", pwd->pw_name);
8098ecd6cf80Smarks }
80994445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
81004445fffbSMatthew Ahrens (void) printf("on %s",
81014445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
8102ecd6cf80Smarks }
81034445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
81044445fffbSMatthew Ahrens (void) printf(":%s",
81054445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
8106ecd6cf80Smarks }
8107ecd6cf80Smarks (void) printf("]");
8108ecd6cf80Smarks (void) printf("\n");
810906eeb2adSek110237 }
8110a52121eaSChunwei Chen }
8111a52121eaSChunwei Chen
8112a52121eaSChunwei Chen /*
8113a52121eaSChunwei Chen * Print out the command history for a specific pool.
8114a52121eaSChunwei Chen */
8115a52121eaSChunwei Chen static int
get_history_one(zpool_handle_t * zhp,void * data)8116a52121eaSChunwei Chen get_history_one(zpool_handle_t *zhp, void *data)
8117a52121eaSChunwei Chen {
8118a52121eaSChunwei Chen nvlist_t *nvhis;
8119a52121eaSChunwei Chen int ret;
8120a52121eaSChunwei Chen hist_cbdata_t *cb = (hist_cbdata_t *)data;
8121a52121eaSChunwei Chen uint64_t off = 0;
8122a52121eaSChunwei Chen boolean_t eof = B_FALSE;
8123a52121eaSChunwei Chen
8124a52121eaSChunwei Chen cb->first = B_FALSE;
8125a52121eaSChunwei Chen
8126a52121eaSChunwei Chen (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
8127a52121eaSChunwei Chen
8128a52121eaSChunwei Chen while (!eof) {
8129a52121eaSChunwei Chen if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
8130a52121eaSChunwei Chen return (ret);
8131a52121eaSChunwei Chen
8132a52121eaSChunwei Chen print_history_records(nvhis, cb);
813306eeb2adSek110237 nvlist_free(nvhis);
8134a52121eaSChunwei Chen }
8135a52121eaSChunwei Chen (void) printf("\n");
813606eeb2adSek110237
813706eeb2adSek110237 return (ret);
813806eeb2adSek110237 }
813906eeb2adSek110237
814006eeb2adSek110237 /*
814106eeb2adSek110237 * zpool history <pool>
814206eeb2adSek110237 *
814306eeb2adSek110237 * Displays the history of commands that modified pools.
814406eeb2adSek110237 */
814506eeb2adSek110237 int
zpool_do_history(int argc,char ** argv)814606eeb2adSek110237 zpool_do_history(int argc, char **argv)
814706eeb2adSek110237 {
8148ecd6cf80Smarks hist_cbdata_t cbdata = { 0 };
814906eeb2adSek110237 int ret;
8150ecd6cf80Smarks int c;
815106eeb2adSek110237
8152ecd6cf80Smarks cbdata.first = B_TRUE;
8153ecd6cf80Smarks /* check options */
8154ecd6cf80Smarks while ((c = getopt(argc, argv, "li")) != -1) {
8155ecd6cf80Smarks switch (c) {
8156ecd6cf80Smarks case 'l':
81574445fffbSMatthew Ahrens cbdata.longfmt = B_TRUE;
8158ecd6cf80Smarks break;
8159ecd6cf80Smarks case 'i':
81604445fffbSMatthew Ahrens cbdata.internal = B_TRUE;
8161ecd6cf80Smarks break;
8162ecd6cf80Smarks case '?':
8163ecd6cf80Smarks (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8164ecd6cf80Smarks optopt);
8165ecd6cf80Smarks usage(B_FALSE);
8166ecd6cf80Smarks }
8167ecd6cf80Smarks }
816806eeb2adSek110237 argc -= optind;
816906eeb2adSek110237 argv += optind;
817006eeb2adSek110237
8171b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
8172ecd6cf80Smarks &cbdata);
817306eeb2adSek110237
8174ecd6cf80Smarks if (argc == 0 && cbdata.first == B_TRUE) {
817506eeb2adSek110237 (void) printf(gettext("no pools available\n"));
817606eeb2adSek110237 return (0);
8177eaca9bbdSeschrock }
8178eaca9bbdSeschrock
8179eaca9bbdSeschrock return (ret);
8180eaca9bbdSeschrock }
8181eaca9bbdSeschrock
8182b1b8ab34Slling static int
get_callback(zpool_handle_t * zhp,void * data)8183b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data)
8184b1b8ab34Slling {
8185990b4856Slling zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
8186b1b8ab34Slling char value[MAXNAMELEN];
8187990b4856Slling zprop_source_t srctype;
8188990b4856Slling zprop_list_t *pl;
8189b1b8ab34Slling
8190b1b8ab34Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
8191b1b8ab34Slling
8192b1b8ab34Slling /*
8193990b4856Slling * Skip the special fake placeholder. This will also skip
8194990b4856Slling * over the name property when 'all' is specified.
8195b1b8ab34Slling */
8196990b4856Slling if (pl->pl_prop == ZPOOL_PROP_NAME &&
8197b1b8ab34Slling pl == cbp->cb_proplist)
8198b1b8ab34Slling continue;
8199b1b8ab34Slling
8200ad135b5dSChristopher Siden if (pl->pl_prop == ZPROP_INVAL &&
8201ad135b5dSChristopher Siden (zpool_prop_feature(pl->pl_user_prop) ||
8202ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop))) {
8203ad135b5dSChristopher Siden srctype = ZPROP_SRC_LOCAL;
8204ad135b5dSChristopher Siden
8205ad135b5dSChristopher Siden if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
8206ad135b5dSChristopher Siden value, sizeof (value)) == 0) {
8207ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp),
8208ad135b5dSChristopher Siden cbp, pl->pl_user_prop, value, srctype,
8209ad135b5dSChristopher Siden NULL, NULL);
8210ad135b5dSChristopher Siden }
8211ad135b5dSChristopher Siden } else {
8212ad135b5dSChristopher Siden if (zpool_get_prop(zhp, pl->pl_prop, value,
8213c58b3526SAdam Stevko sizeof (value), &srctype, cbp->cb_literal) != 0)
8214b1b8ab34Slling continue;
8215b1b8ab34Slling
8216990b4856Slling zprop_print_one_property(zpool_get_name(zhp), cbp,
8217ad135b5dSChristopher Siden zpool_prop_to_name(pl->pl_prop), value, srctype,
8218ad135b5dSChristopher Siden NULL, NULL);
8219ad135b5dSChristopher Siden }
8220b1b8ab34Slling }
8221b1b8ab34Slling return (0);
8222b1b8ab34Slling }
8223b1b8ab34Slling
8224c58b3526SAdam Stevko /*
8225c58b3526SAdam Stevko * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
8226c58b3526SAdam Stevko *
8227c58b3526SAdam Stevko * -H Scripted mode. Don't display headers, and separate properties
8228c58b3526SAdam Stevko * by a single tab.
8229c58b3526SAdam Stevko * -o List of columns to display. Defaults to
8230c58b3526SAdam Stevko * "name,property,value,source".
8231c58b3526SAdam Stevko * -p Diplay values in parsable (exact) format.
8232c58b3526SAdam Stevko *
8233c58b3526SAdam Stevko * Get properties of pools in the system. Output space statistics
8234c58b3526SAdam Stevko * for each one as well as other attributes.
8235c58b3526SAdam Stevko */
8236b1b8ab34Slling int
zpool_do_get(int argc,char ** argv)8237b1b8ab34Slling zpool_do_get(int argc, char **argv)
8238b1b8ab34Slling {
8239990b4856Slling zprop_get_cbdata_t cb = { 0 };
8240990b4856Slling zprop_list_t fake_name = { 0 };
8241b1b8ab34Slling int ret;
8242c58b3526SAdam Stevko int c, i;
8243c58b3526SAdam Stevko char *value;
8244b1b8ab34Slling
8245b1b8ab34Slling cb.cb_first = B_TRUE;
8246c58b3526SAdam Stevko
8247c58b3526SAdam Stevko /*
8248c58b3526SAdam Stevko * Set up default columns and sources.
8249c58b3526SAdam Stevko */
8250990b4856Slling cb.cb_sources = ZPROP_SRC_ALL;
8251b1b8ab34Slling cb.cb_columns[0] = GET_COL_NAME;
8252b1b8ab34Slling cb.cb_columns[1] = GET_COL_PROPERTY;
8253b1b8ab34Slling cb.cb_columns[2] = GET_COL_VALUE;
8254b1b8ab34Slling cb.cb_columns[3] = GET_COL_SOURCE;
8255990b4856Slling cb.cb_type = ZFS_TYPE_POOL;
8256b1b8ab34Slling
8257c58b3526SAdam Stevko /* check options */
8258c58b3526SAdam Stevko while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
8259c58b3526SAdam Stevko switch (c) {
8260c58b3526SAdam Stevko case 'p':
8261c58b3526SAdam Stevko cb.cb_literal = B_TRUE;
8262c58b3526SAdam Stevko break;
8263c58b3526SAdam Stevko case 'H':
8264c58b3526SAdam Stevko cb.cb_scripted = B_TRUE;
8265c58b3526SAdam Stevko break;
8266c58b3526SAdam Stevko case 'o':
8267c58b3526SAdam Stevko bzero(&cb.cb_columns, sizeof (cb.cb_columns));
8268c58b3526SAdam Stevko i = 0;
8269c58b3526SAdam Stevko while (*optarg != '\0') {
8270c58b3526SAdam Stevko static char *col_subopts[] =
8271c58b3526SAdam Stevko { "name", "property", "value", "source",
8272c58b3526SAdam Stevko "all", NULL };
8273c58b3526SAdam Stevko
8274c58b3526SAdam Stevko if (i == ZFS_GET_NCOLS) {
8275c58b3526SAdam Stevko (void) fprintf(stderr, gettext("too "
8276c58b3526SAdam Stevko "many fields given to -o "
8277c58b3526SAdam Stevko "option\n"));
8278c58b3526SAdam Stevko usage(B_FALSE);
8279c58b3526SAdam Stevko }
8280c58b3526SAdam Stevko
8281c58b3526SAdam Stevko switch (getsubopt(&optarg, col_subopts,
8282c58b3526SAdam Stevko &value)) {
8283c58b3526SAdam Stevko case 0:
8284c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_NAME;
8285c58b3526SAdam Stevko break;
8286c58b3526SAdam Stevko case 1:
8287c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_PROPERTY;
8288c58b3526SAdam Stevko break;
8289c58b3526SAdam Stevko case 2:
8290c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_VALUE;
8291c58b3526SAdam Stevko break;
8292c58b3526SAdam Stevko case 3:
8293c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_SOURCE;
8294c58b3526SAdam Stevko break;
8295c58b3526SAdam Stevko case 4:
8296c58b3526SAdam Stevko if (i > 0) {
8297c58b3526SAdam Stevko (void) fprintf(stderr,
8298c58b3526SAdam Stevko gettext("\"all\" conflicts "
8299c58b3526SAdam Stevko "with specific fields "
8300c58b3526SAdam Stevko "given to -o option\n"));
8301c58b3526SAdam Stevko usage(B_FALSE);
8302c58b3526SAdam Stevko }
8303c58b3526SAdam Stevko cb.cb_columns[0] = GET_COL_NAME;
8304c58b3526SAdam Stevko cb.cb_columns[1] = GET_COL_PROPERTY;
8305c58b3526SAdam Stevko cb.cb_columns[2] = GET_COL_VALUE;
8306c58b3526SAdam Stevko cb.cb_columns[3] = GET_COL_SOURCE;
8307c58b3526SAdam Stevko i = ZFS_GET_NCOLS;
8308c58b3526SAdam Stevko break;
8309c58b3526SAdam Stevko default:
8310c58b3526SAdam Stevko (void) fprintf(stderr,
8311c58b3526SAdam Stevko gettext("invalid column name "
8312c58b3526SAdam Stevko "'%s'\n"), value);
8313c58b3526SAdam Stevko usage(B_FALSE);
8314c58b3526SAdam Stevko }
8315c58b3526SAdam Stevko }
8316c58b3526SAdam Stevko break;
8317c58b3526SAdam Stevko case '?':
8318c58b3526SAdam Stevko (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8319c58b3526SAdam Stevko optopt);
8320c58b3526SAdam Stevko usage(B_FALSE);
8321c58b3526SAdam Stevko }
8322c58b3526SAdam Stevko }
8323c58b3526SAdam Stevko
8324c58b3526SAdam Stevko argc -= optind;
8325c58b3526SAdam Stevko argv += optind;
8326c58b3526SAdam Stevko
8327c58b3526SAdam Stevko if (argc < 1) {
8328c58b3526SAdam Stevko (void) fprintf(stderr, gettext("missing property "
8329c58b3526SAdam Stevko "argument\n"));
8330c58b3526SAdam Stevko usage(B_FALSE);
8331c58b3526SAdam Stevko }
8332c58b3526SAdam Stevko
8333c58b3526SAdam Stevko if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
8334990b4856Slling ZFS_TYPE_POOL) != 0)
8335b1b8ab34Slling usage(B_FALSE);
8336b1b8ab34Slling
8337c58b3526SAdam Stevko argc--;
8338c58b3526SAdam Stevko argv++;
8339c58b3526SAdam Stevko
8340b1b8ab34Slling if (cb.cb_proplist != NULL) {
8341990b4856Slling fake_name.pl_prop = ZPOOL_PROP_NAME;
8342b1b8ab34Slling fake_name.pl_width = strlen(gettext("NAME"));
8343b1b8ab34Slling fake_name.pl_next = cb.cb_proplist;
8344b1b8ab34Slling cb.cb_proplist = &fake_name;
8345b1b8ab34Slling }
8346b1b8ab34Slling
8347c58b3526SAdam Stevko ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
8348b1b8ab34Slling get_callback, &cb);
8349b1b8ab34Slling
8350b1b8ab34Slling if (cb.cb_proplist == &fake_name)
8351990b4856Slling zprop_free_list(fake_name.pl_next);
8352b1b8ab34Slling else
8353990b4856Slling zprop_free_list(cb.cb_proplist);
8354b1b8ab34Slling
8355b1b8ab34Slling return (ret);
8356b1b8ab34Slling }
8357b1b8ab34Slling
8358b1b8ab34Slling typedef struct set_cbdata {
8359b1b8ab34Slling char *cb_propname;
8360b1b8ab34Slling char *cb_value;
8361b1b8ab34Slling boolean_t cb_any_successful;
8362b1b8ab34Slling } set_cbdata_t;
8363b1b8ab34Slling
8364b1b8ab34Slling int
set_callback(zpool_handle_t * zhp,void * data)8365b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data)
8366b1b8ab34Slling {
8367b1b8ab34Slling int error;
8368b1b8ab34Slling set_cbdata_t *cb = (set_cbdata_t *)data;
8369b1b8ab34Slling
8370b1b8ab34Slling error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
8371b1b8ab34Slling
8372b1b8ab34Slling if (!error)
8373b1b8ab34Slling cb->cb_any_successful = B_TRUE;
8374b1b8ab34Slling
8375b1b8ab34Slling return (error);
8376b1b8ab34Slling }
8377b1b8ab34Slling
8378b1b8ab34Slling int
zpool_do_set(int argc,char ** argv)8379b1b8ab34Slling zpool_do_set(int argc, char **argv)
8380b1b8ab34Slling {
8381b1b8ab34Slling set_cbdata_t cb = { 0 };
8382b1b8ab34Slling int error;
8383b1b8ab34Slling
8384b1b8ab34Slling if (argc > 1 && argv[1][0] == '-') {
8385b1b8ab34Slling (void) fprintf(stderr, gettext("invalid option '%c'\n"),
8386b1b8ab34Slling argv[1][1]);
8387b1b8ab34Slling usage(B_FALSE);
8388b1b8ab34Slling }
8389b1b8ab34Slling
8390b1b8ab34Slling if (argc < 2) {
8391b1b8ab34Slling (void) fprintf(stderr, gettext("missing property=value "
8392b1b8ab34Slling "argument\n"));
8393b1b8ab34Slling usage(B_FALSE);
8394b1b8ab34Slling }
8395b1b8ab34Slling
8396b1b8ab34Slling if (argc < 3) {
8397b1b8ab34Slling (void) fprintf(stderr, gettext("missing pool name\n"));
8398b1b8ab34Slling usage(B_FALSE);
8399b1b8ab34Slling }
8400b1b8ab34Slling
8401b1b8ab34Slling if (argc > 3) {
8402b1b8ab34Slling (void) fprintf(stderr, gettext("too many pool names\n"));
8403b1b8ab34Slling usage(B_FALSE);
8404b1b8ab34Slling }
8405b1b8ab34Slling
8406b1b8ab34Slling cb.cb_propname = argv[1];
8407b1b8ab34Slling cb.cb_value = strchr(cb.cb_propname, '=');
8408b1b8ab34Slling if (cb.cb_value == NULL) {
8409b1b8ab34Slling (void) fprintf(stderr, gettext("missing value in "
8410b1b8ab34Slling "property=value argument\n"));
8411b1b8ab34Slling usage(B_FALSE);
8412b1b8ab34Slling }
8413b1b8ab34Slling
8414b1b8ab34Slling *(cb.cb_value) = '\0';
8415b1b8ab34Slling cb.cb_value++;
8416b1b8ab34Slling
8417b1b8ab34Slling error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
8418b1b8ab34Slling set_callback, &cb);
8419b1b8ab34Slling
8420b1b8ab34Slling return (error);
8421b1b8ab34Slling }
8422b1b8ab34Slling
8423b1b8ab34Slling static int
find_command_idx(char * command,int * idx)8424b1b8ab34Slling find_command_idx(char *command, int *idx)
8425b1b8ab34Slling {
8426b1b8ab34Slling int i;
8427b1b8ab34Slling
8428b1b8ab34Slling for (i = 0; i < NCOMMAND; i++) {
8429b1b8ab34Slling if (command_table[i].name == NULL)
8430b1b8ab34Slling continue;
8431b1b8ab34Slling
8432b1b8ab34Slling if (strcmp(command, command_table[i].name) == 0) {
8433b1b8ab34Slling *idx = i;
8434b1b8ab34Slling return (0);
8435b1b8ab34Slling }
8436b1b8ab34Slling }
8437b1b8ab34Slling return (1);
8438b1b8ab34Slling }
8439b1b8ab34Slling
8440fa9e4066Sahrens int
main(int argc,char ** argv)8441fa9e4066Sahrens main(int argc, char **argv)
8442fa9e4066Sahrens {
8443b327cd3fSIgor Kozhukhov int ret = 0;
8444fa9e4066Sahrens int i;
8445fa9e4066Sahrens char *cmdname;
8446fa9e4066Sahrens
8447fa9e4066Sahrens (void) setlocale(LC_ALL, "");
8448fa9e4066Sahrens (void) textdomain(TEXT_DOMAIN);
8449fa9e4066Sahrens
845099653d4eSeschrock if ((g_zfs = libzfs_init()) == NULL) {
845199653d4eSeschrock (void) fprintf(stderr, gettext("internal error: failed to "
8452203a47d8Snd150628 "initialize ZFS library\n"));
845399653d4eSeschrock return (1);
845499653d4eSeschrock }
845599653d4eSeschrock
845699653d4eSeschrock libzfs_print_on_error(g_zfs, B_TRUE);
845799653d4eSeschrock
8458fa9e4066Sahrens opterr = 0;
8459fa9e4066Sahrens
8460fa9e4066Sahrens /*
8461fa9e4066Sahrens * Make sure the user has specified some command.
8462fa9e4066Sahrens */
8463fa9e4066Sahrens if (argc < 2) {
8464fa9e4066Sahrens (void) fprintf(stderr, gettext("missing command\n"));
846599653d4eSeschrock usage(B_FALSE);
8466fa9e4066Sahrens }
8467fa9e4066Sahrens
8468fa9e4066Sahrens cmdname = argv[1];
8469fa9e4066Sahrens
8470fa9e4066Sahrens /*
8471fa9e4066Sahrens * Special case '-?'
8472fa9e4066Sahrens */
8473fa9e4066Sahrens if (strcmp(cmdname, "-?") == 0)
847499653d4eSeschrock usage(B_TRUE);
8475fa9e4066Sahrens
84764445fffbSMatthew Ahrens zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
84772a6b87f0Sek110237
8478fa9e4066Sahrens /*
8479fa9e4066Sahrens * Run the appropriate command.
8480fa9e4066Sahrens */
8481b1b8ab34Slling if (find_command_idx(cmdname, &i) == 0) {
8482fa9e4066Sahrens current_command = &command_table[i];
8483fa9e4066Sahrens ret = command_table[i].func(argc - 1, argv + 1);
848491ebeef5Sahrens } else if (strchr(cmdname, '=')) {
848591ebeef5Sahrens verify(find_command_idx("set", &i) == 0);
848691ebeef5Sahrens current_command = &command_table[i];
848791ebeef5Sahrens ret = command_table[i].func(argc, argv);
848891ebeef5Sahrens } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
8489fa9e4066Sahrens /*
849091ebeef5Sahrens * 'freeze' is a vile debugging abomination, so we treat
849191ebeef5Sahrens * it as such.
8492fa9e4066Sahrens */
8493ea8dc4b6Seschrock char buf[16384];
8494ea8dc4b6Seschrock int fd = open(ZFS_DEV, O_RDWR);
8495fa9e4066Sahrens (void) strcpy((void *)buf, argv[2]);
8496fa9e4066Sahrens return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
849791ebeef5Sahrens } else {
8498fa9e4066Sahrens (void) fprintf(stderr, gettext("unrecognized "
8499fa9e4066Sahrens "command '%s'\n"), cmdname);
850099653d4eSeschrock usage(B_FALSE);
8501fa9e4066Sahrens }
8502fa9e4066Sahrens
85034445fffbSMatthew Ahrens if (ret == 0 && log_history)
85044445fffbSMatthew Ahrens (void) zpool_log_history(g_zfs, history_str);
85054445fffbSMatthew Ahrens
850699653d4eSeschrock libzfs_fini(g_zfs);
850799653d4eSeschrock
8508fa9e4066Sahrens /*
8509fa9e4066Sahrens * The 'ZFS_ABORT' environment variable causes us to dump core on exit
8510fa9e4066Sahrens * for the purposes of running ::findleaks.
8511fa9e4066Sahrens */
8512fa9e4066Sahrens if (getenv("ZFS_ABORT") != NULL) {
8513fa9e4066Sahrens (void) printf("dumping core by request\n");
8514fa9e4066Sahrens abort();
8515fa9e4066Sahrens }
8516fa9e4066Sahrens
8517fa9e4066Sahrens return (ret);
8518fa9e4066Sahrens }
8519