]> git.proxmox.com Git - mirror_zfs.git/blame - cmd/zpool/zpool_main.c
Add support for zpool user properties
[mirror_zfs.git] / cmd / zpool / zpool_main.c
CommitLineData
34dc7c2f
BB
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1d3ba0bf 9 * or https://opensource.org/licenses/CDDL-1.0.
34dc7c2f
BB
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
428870ff 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
95bcd51e 24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
c15d36c6 25 * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
95bcd51e 26 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
df831108 27 * Copyright (c) 2012 by Cyril Plisko. All rights reserved.
eaa52d32 28 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
8e896579 29 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
bec1067d 30 * Copyright (c) 2017 Datto Inc.
d3f2cd7e 31 * Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
cc99f275 32 * Copyright (c) 2017, Intel Corporation.
e55db32a 33 * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
658fb802 34 * Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
2a673e76 35 * Copyright (c) 2021, Klara Inc.
dce1bf99 36 * Copyright [2021] Hewlett Packard Enterprise Development LP
34dc7c2f
BB
37 */
38
34dc7c2f
BB
39#include <assert.h>
40#include <ctype.h>
41#include <dirent.h>
42#include <errno.h>
43#include <fcntl.h>
d2734cce 44#include <getopt.h>
34dc7c2f
BB
45#include <libgen.h>
46#include <libintl.h>
47#include <libuutil.h>
48#include <locale.h>
e60e158e 49#include <pthread.h>
34dc7c2f
BB
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
e60e158e 53#include <time.h>
34dc7c2f 54#include <unistd.h>
34dc7c2f
BB
55#include <pwd.h>
56#include <zone.h>
d6418de0 57#include <sys/wait.h>
1bd201e7 58#include <zfs_prop.h>
34dc7c2f 59#include <sys/fs/zfs.h>
34dc7c2f 60#include <sys/stat.h>
46364cb2 61#include <sys/systeminfo.h>
d02ca379 62#include <sys/fm/fs/zfs.h>
26685276
BB
63#include <sys/fm/util.h>
64#include <sys/fm/protocol.h>
8c7aa0cf 65#include <sys/zfs_ioctl.h>
b5256303 66#include <sys/mount.h>
d4a72f23
TC
67#include <sys/sysmacros.h>
68
193a37cb 69#include <math.h>
34dc7c2f
BB
70
71#include <libzfs.h>
e89f1295 72#include <libzutil.h>
34dc7c2f
BB
73
74#include "zpool_util.h"
75#include "zfs_comutil.h"
9ae529ec 76#include "zfeature_common.h"
34dc7c2f 77
428870ff
BB
78#include "statcommon.h"
79
af09c050
RD
80libzfs_handle_t *g_zfs;
81
34dc7c2f
BB
82static int zpool_do_create(int, char **);
83static int zpool_do_destroy(int, char **);
84
85static int zpool_do_add(int, char **);
86static int zpool_do_remove(int, char **);
131cc95c 87static int zpool_do_labelclear(int, char **);
34dc7c2f 88
d2734cce
SD
89static int zpool_do_checkpoint(int, char **);
90
34dc7c2f
BB
91static int zpool_do_list(int, char **);
92static int zpool_do_iostat(int, char **);
93static int zpool_do_status(int, char **);
94
95static int zpool_do_online(int, char **);
96static int zpool_do_offline(int, char **);
97static int zpool_do_clear(int, char **);
1bd201e7 98static int zpool_do_reopen(int, char **);
34dc7c2f 99
3541dc6d
GA
100static int zpool_do_reguid(int, char **);
101
34dc7c2f
BB
102static int zpool_do_attach(int, char **);
103static int zpool_do_detach(int, char **);
104static int zpool_do_replace(int, char **);
428870ff 105static int zpool_do_split(int, char **);
34dc7c2f 106
619f0976 107static int zpool_do_initialize(int, char **);
34dc7c2f 108static int zpool_do_scrub(int, char **);
80a91e74 109static int zpool_do_resilver(int, char **);
1b939560 110static int zpool_do_trim(int, char **);
34dc7c2f
BB
111
112static int zpool_do_import(int, char **);
113static int zpool_do_export(int, char **);
114
115static int zpool_do_upgrade(int, char **);
116
117static int zpool_do_history(int, char **);
26685276 118static int zpool_do_events(int, char **);
34dc7c2f
BB
119
120static int zpool_do_get(int, char **);
121static int zpool_do_set(int, char **);
122
bec1067d
AP
123static int zpool_do_sync(int, char **);
124
50478c6d
T
125static int zpool_do_version(int, char **);
126
e60e158e
JG
127static int zpool_do_wait(int, char **);
128
658fb802
CB
129static zpool_compat_status_t zpool_do_load_compat(
130 const char *, boolean_t *);
131
34dc7c2f
BB
132/*
133 * These libumem hooks provide a reasonable set of defaults for the allocator's
134 * debugging facilities.
135 */
b128c09f
BB
136
137#ifdef DEBUG
34dc7c2f
BB
138const char *
139_umem_debug_init(void)
140{
141 return ("default,verbose"); /* $UMEM_DEBUG setting */
142}
143
144const char *
145_umem_logging_init(void)
146{
147 return ("fail,contents"); /* $UMEM_LOGGING setting */
148}
b128c09f 149#endif
34dc7c2f
BB
150
151typedef enum {
152 HELP_ADD,
153 HELP_ATTACH,
154 HELP_CLEAR,
155 HELP_CREATE,
d2734cce 156 HELP_CHECKPOINT,
34dc7c2f
BB
157 HELP_DESTROY,
158 HELP_DETACH,
159 HELP_EXPORT,
160 HELP_HISTORY,
161 HELP_IMPORT,
162 HELP_IOSTAT,
131cc95c 163 HELP_LABELCLEAR,
34dc7c2f
BB
164 HELP_LIST,
165 HELP_OFFLINE,
166 HELP_ONLINE,
167 HELP_REPLACE,
168 HELP_REMOVE,
619f0976 169 HELP_INITIALIZE,
34dc7c2f 170 HELP_SCRUB,
80a91e74 171 HELP_RESILVER,
1b939560 172 HELP_TRIM,
34dc7c2f
BB
173 HELP_STATUS,
174 HELP_UPGRADE,
26685276 175 HELP_EVENTS,
34dc7c2f 176 HELP_GET,
428870ff 177 HELP_SET,
3541dc6d 178 HELP_SPLIT,
bec1067d 179 HELP_SYNC,
1bd201e7 180 HELP_REGUID,
50478c6d 181 HELP_REOPEN,
e60e158e
JG
182 HELP_VERSION,
183 HELP_WAIT
34dc7c2f
BB
184} zpool_help_t;
185
186
193a37cb
TH
187/*
188 * Flags for stats to display with "zpool iostats"
189 */
190enum iostat_type {
191 IOS_DEFAULT = 0,
192 IOS_LATENCY = 1,
193 IOS_QUEUES = 2,
194 IOS_L_HISTO = 3,
7e945072 195 IOS_RQ_HISTO = 4,
193a37cb
TH
196 IOS_COUNT, /* always last element */
197};
198
199/* iostat_type entries as bitmasks */
200#define IOS_DEFAULT_M (1ULL << IOS_DEFAULT)
201#define IOS_LATENCY_M (1ULL << IOS_LATENCY)
202#define IOS_QUEUES_M (1ULL << IOS_QUEUES)
203#define IOS_L_HISTO_M (1ULL << IOS_L_HISTO)
7e945072
TH
204#define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO)
205
206/* Mask of all the histo bits */
207#define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
208
209/*
210 * Lookup table for iostat flags to nvlist names. Basically a list
211 * of all the nvlists a flag requires. Also specifies the order in
212 * which data gets printed in zpool iostat.
213 */
00888c08 214static const char *vsx_type_to_nvlist[IOS_COUNT][15] = {
7e945072
TH
215 [IOS_L_HISTO] = {
216 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
217 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
218 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
219 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
220 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
221 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
222 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
223 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
224 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
1b939560 225 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
00888c08 226 ZPOOL_CONFIG_VDEV_REBUILD_LAT_HISTO,
7e945072
TH
227 NULL},
228 [IOS_LATENCY] = {
229 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
230 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
231 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
232 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
1b939560 233 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
00888c08 234 ZPOOL_CONFIG_VDEV_REBUILD_LAT_HISTO,
7e945072
TH
235 NULL},
236 [IOS_QUEUES] = {
237 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
238 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
239 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
240 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
241 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
1b939560 242 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
00888c08 243 ZPOOL_CONFIG_VDEV_REBUILD_ACTIVE_QUEUE,
7e945072
TH
244 NULL},
245 [IOS_RQ_HISTO] = {
246 ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
247 ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
248 ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
249 ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
250 ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
251 ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
252 ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
253 ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
254 ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
255 ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
1b939560
BB
256 ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
257 ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
00888c08
TB
258 ZPOOL_CONFIG_VDEV_IND_REBUILD_HISTO,
259 ZPOOL_CONFIG_VDEV_AGG_REBUILD_HISTO,
7e945072
TH
260 NULL},
261};
262
263
264/*
265 * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
266 * Right now, only one histo bit is ever set at one time, so we can
267 * just do a highbit64(a)
268 */
269#define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1)
193a37cb 270
34dc7c2f
BB
271typedef struct zpool_command {
272 const char *name;
273 int (*func)(int, char **);
274 zpool_help_t usage;
275} zpool_command_t;
276
277/*
278 * Master command table. Each ZFS command has a name, associated function, and
279 * usage message. The usage messages need to be internationalized, so we have
280 * to have a function to return the usage message based on a command index.
281 *
282 * These commands are organized according to how they are displayed in the usage
283 * message. An empty command (one with a NULL name) indicates an empty line in
284 * the generic usage message.
285 */
286static zpool_command_t command_table[] = {
50478c6d
T
287 { "version", zpool_do_version, HELP_VERSION },
288 { NULL },
34dc7c2f
BB
289 { "create", zpool_do_create, HELP_CREATE },
290 { "destroy", zpool_do_destroy, HELP_DESTROY },
291 { NULL },
292 { "add", zpool_do_add, HELP_ADD },
293 { "remove", zpool_do_remove, HELP_REMOVE },
294 { NULL },
131cc95c
DK
295 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
296 { NULL },
d2734cce
SD
297 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT },
298 { NULL },
34dc7c2f
BB
299 { "list", zpool_do_list, HELP_LIST },
300 { "iostat", zpool_do_iostat, HELP_IOSTAT },
301 { "status", zpool_do_status, HELP_STATUS },
302 { NULL },
303 { "online", zpool_do_online, HELP_ONLINE },
304 { "offline", zpool_do_offline, HELP_OFFLINE },
305 { "clear", zpool_do_clear, HELP_CLEAR },
1bd201e7 306 { "reopen", zpool_do_reopen, HELP_REOPEN },
34dc7c2f
BB
307 { NULL },
308 { "attach", zpool_do_attach, HELP_ATTACH },
309 { "detach", zpool_do_detach, HELP_DETACH },
310 { "replace", zpool_do_replace, HELP_REPLACE },
428870ff 311 { "split", zpool_do_split, HELP_SPLIT },
34dc7c2f 312 { NULL },
619f0976 313 { "initialize", zpool_do_initialize, HELP_INITIALIZE },
80a91e74 314 { "resilver", zpool_do_resilver, HELP_RESILVER },
1b939560
BB
315 { "scrub", zpool_do_scrub, HELP_SCRUB },
316 { "trim", zpool_do_trim, HELP_TRIM },
34dc7c2f
BB
317 { NULL },
318 { "import", zpool_do_import, HELP_IMPORT },
319 { "export", zpool_do_export, HELP_EXPORT },
320 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
3541dc6d 321 { "reguid", zpool_do_reguid, HELP_REGUID },
34dc7c2f
BB
322 { NULL },
323 { "history", zpool_do_history, HELP_HISTORY },
26685276
BB
324 { "events", zpool_do_events, HELP_EVENTS },
325 { NULL },
34dc7c2f
BB
326 { "get", zpool_do_get, HELP_GET },
327 { "set", zpool_do_set, HELP_SET },
bec1067d 328 { "sync", zpool_do_sync, HELP_SYNC },
e60e158e
JG
329 { NULL },
330 { "wait", zpool_do_wait, HELP_WAIT },
34dc7c2f
BB
331};
332
193a37cb 333#define NCOMMAND (ARRAY_SIZE(command_table))
34dc7c2f 334
cc99f275
DB
335#define VDEV_ALLOC_CLASS_LOGS "logs"
336
6f1ffb06 337static zpool_command_t *current_command;
2a673e76 338static zfs_type_t current_prop_type = (ZFS_TYPE_POOL | ZFS_TYPE_VDEV);
34dc7c2f 339static char history_str[HIS_MAX_RECORD_LEN];
6f1ffb06 340static boolean_t log_history = B_TRUE;
428870ff
BB
341static uint_t timestamp_fmt = NODATE;
342
34dc7c2f 343static const char *
e9aa730c
GM
344get_usage(zpool_help_t idx)
345{
34dc7c2f
BB
346 switch (idx) {
347 case HELP_ADD:
a77f29f9 348 return (gettext("\tadd [-fgLnP] [-o property=value] "
df831108 349 "<pool> <vdev> ...\n"));
34dc7c2f 350 case HELP_ATTACH:
9a49d3f3 351 return (gettext("\tattach [-fsw] [-o property=value] "
df831108 352 "<pool> <device> <new-device>\n"));
34dc7c2f 353 case HELP_CLEAR:
428870ff 354 return (gettext("\tclear [-nF] <pool> [device]\n"));
34dc7c2f 355 case HELP_CREATE:
9ae529ec 356 return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
b128c09f 357 "\t [-O file-system-property=value] ... \n"
34dc7c2f 358 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
d2734cce 359 case HELP_CHECKPOINT:
e60e158e 360 return (gettext("\tcheckpoint [-d [-w]] <pool> ...\n"));
34dc7c2f
BB
361 case HELP_DESTROY:
362 return (gettext("\tdestroy [-f] <pool>\n"));
363 case HELP_DETACH:
364 return (gettext("\tdetach <pool> <device>\n"));
365 case HELP_EXPORT:
859735c0 366 return (gettext("\texport [-af] <pool> ...\n"));
34dc7c2f
BB
367 case HELP_HISTORY:
368 return (gettext("\thistory [-il] [<pool>] ...\n"));
369 case HELP_IMPORT:
370 return (gettext("\timport [-d dir] [-D]\n"
371 "\timport [-o mntopts] [-o property=value] ... \n"
b5256303 372 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
572e2857 373 "[-R root] [-F [-n]] -a\n"
34dc7c2f 374 "\timport [-o mntopts] [-o property=value] ... \n"
b5256303 375 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
572e2857 376 "[-R root] [-F [-n]]\n"
d2734cce 377 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
34dc7c2f 378 case HELP_IOSTAT:
d6418de0
TH
379 return (gettext("\tiostat [[[-c [script1,script2,...]"
380 "[-lq]]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
381 "\t [[pool ...]|[pool vdev ...]|[vdev ...]]"
8fccfa8e 382 " [[-n] interval [count]]\n"));
131cc95c
DK
383 case HELP_LABELCLEAR:
384 return (gettext("\tlabelclear [-f] <vdev>\n"));
34dc7c2f 385 case HELP_LIST:
2a8b84b7 386 return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
63f88c12 387 "[-T d|u] [pool] ... \n"
388 "\t [interval [count]]\n"));
34dc7c2f 389 case HELP_OFFLINE:
4a283c7f 390 return (gettext("\toffline [-f] [-t] <pool> <device> ...\n"));
34dc7c2f 391 case HELP_ONLINE:
aebfb848 392 return (gettext("\tonline [-e] <pool> <device> ...\n"));
34dc7c2f 393 case HELP_REPLACE:
9a49d3f3 394 return (gettext("\treplace [-fsw] [-o property=value] "
628668a3 395 "<pool> <device> [new-device]\n"));
34dc7c2f 396 case HELP_REMOVE:
e60e158e 397 return (gettext("\tremove [-npsw] <pool> <device> ...\n"));
1bd201e7 398 case HELP_REOPEN:
d3f2cd7e 399 return (gettext("\treopen [-n] <pool>\n"));
619f0976 400 case HELP_INITIALIZE:
e60e158e 401 return (gettext("\tinitialize [-c | -s] [-w] <pool> "
a769fb53 402 "[<device> ...]\n"));
34dc7c2f 403 case HELP_SCRUB:
e60e158e 404 return (gettext("\tscrub [-s | -p] [-w] <pool> ...\n"));
80a91e74
TC
405 case HELP_RESILVER:
406 return (gettext("\tresilver <pool> ...\n"));
1b939560 407 case HELP_TRIM:
2288d419 408 return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
1b939560 409 "[<device> ...]\n"));
34dc7c2f 410 case HELP_STATUS:
ad796b8a 411 return (gettext("\tstatus [-c [script1,script2,...]] "
43977948 412 "[-igLpPstvxD] [-T d|u] [pool] ... \n"
63f88c12 413 "\t [interval [count]]\n"));
34dc7c2f
BB
414 case HELP_UPGRADE:
415 return (gettext("\tupgrade\n"
416 "\tupgrade -v\n"
417 "\tupgrade [-V version] <-a | pool ...>\n"));
26685276 418 case HELP_EVENTS:
88f9c939 419 return (gettext("\tevents [-vHf [pool] | -c]\n"));
34dc7c2f 420 case HELP_GET:
2a8b84b7
AS
421 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
422 "<\"all\" | property[,...]> <pool> ...\n"));
34dc7c2f 423 case HELP_SET:
a0276f70
RW
424 return (gettext("\tset <property=value> <pool>\n"
425 "\tset <vdev_property=value> <pool> <vdev>\n"));
428870ff 426 case HELP_SPLIT:
b5256303 427 return (gettext("\tsplit [-gLnPl] [-R altroot] [-o mntopts]\n"
428870ff
BB
428 "\t [-o property=value] <pool> <newpool> "
429 "[<device> ...]\n"));
3541dc6d
GA
430 case HELP_REGUID:
431 return (gettext("\treguid <pool>\n"));
bec1067d
AP
432 case HELP_SYNC:
433 return (gettext("\tsync [pool] ...\n"));
50478c6d
T
434 case HELP_VERSION:
435 return (gettext("\tversion\n"));
e60e158e
JG
436 case HELP_WAIT:
437 return (gettext("\twait [-Hp] [-T d|u] [-t <activity>[,...]] "
438 "<pool> [interval]\n"));
90f1c3c9
AZ
439 default:
440 __builtin_unreachable();
34dc7c2f 441 }
34dc7c2f
BB
442}
443
619f0976
GW
444static void
445zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
446{
447 uint_t children = 0;
448 nvlist_t **child;
449 uint_t i;
450
451 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
452 &child, &children);
453
454 if (children == 0) {
1b939560
BB
455 char *path = zpool_vdev_name(g_zfs, zhp, nvroot,
456 VDEV_NAME_PATH);
457
a84c92f9
NH
458 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
459 strcmp(path, VDEV_TYPE_HOLE) != 0)
1b939560
BB
460 fnvlist_add_boolean(res, path);
461
619f0976
GW
462 free(path);
463 return;
464 }
465
466 for (i = 0; i < children; i++) {
467 zpool_collect_leaves(zhp, child[i], res);
468 }
469}
34dc7c2f
BB
470
471/*
472 * Callback routine that will print out a pool property value.
473 */
474static int
2a673e76 475print_pool_prop_cb(int prop, void *cb)
34dc7c2f
BB
476{
477 FILE *fp = cb;
478
cc99f275 479 (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop));
34dc7c2f
BB
480
481 if (zpool_prop_readonly(prop))
482 (void) fprintf(fp, " NO ");
483 else
428870ff 484 (void) fprintf(fp, " YES ");
34dc7c2f
BB
485
486 if (zpool_prop_values(prop) == NULL)
487 (void) fprintf(fp, "-\n");
488 else
489 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
490
491 return (ZPROP_CONT);
492}
493
2a673e76
AJ
494/*
495 * Callback routine that will print out a vdev property value.
496 */
497static int
498print_vdev_prop_cb(int prop, void *cb)
499{
500 FILE *fp = cb;
501
502 (void) fprintf(fp, "\t%-19s ", vdev_prop_to_name(prop));
503
504 if (vdev_prop_readonly(prop))
505 (void) fprintf(fp, " NO ");
506 else
507 (void) fprintf(fp, " YES ");
508
509 if (vdev_prop_values(prop) == NULL)
510 (void) fprintf(fp, "-\n");
511 else
512 (void) fprintf(fp, "%s\n", vdev_prop_values(prop));
513
514 return (ZPROP_CONT);
515}
516
34dc7c2f
BB
517/*
518 * Display usage message. If we're inside a command, display only the usage for
519 * that command. Otherwise, iterate over the entire command table and display
520 * a complete usage message.
521 */
460748d4 522static __attribute__((noreturn)) void
34dc7c2f
BB
523usage(boolean_t requested)
524{
525 FILE *fp = requested ? stdout : stderr;
526
527 if (current_command == NULL) {
528 int i;
529
530 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
531 (void) fprintf(fp,
532 gettext("where 'command' is one of the following:\n\n"));
533
534 for (i = 0; i < NCOMMAND; i++) {
535 if (command_table[i].name == NULL)
536 (void) fprintf(fp, "\n");
537 else
538 (void) fprintf(fp, "%s",
539 get_usage(command_table[i].usage));
540 }
541 } else {
542 (void) fprintf(fp, gettext("usage:\n"));
543 (void) fprintf(fp, "%s", get_usage(current_command->usage));
544 }
545
546 if (current_command != NULL &&
2a673e76 547 current_prop_type != (ZFS_TYPE_POOL | ZFS_TYPE_VDEV) &&
34dc7c2f
BB
548 ((strcmp(current_command->name, "set") == 0) ||
549 (strcmp(current_command->name, "get") == 0) ||
550 (strcmp(current_command->name, "list") == 0))) {
551
3c1e1933 552 (void) fprintf(fp, "%s",
34dc7c2f
BB
553 gettext("\nthe following properties are supported:\n"));
554
cc99f275 555 (void) fprintf(fp, "\n\t%-19s %s %s\n\n",
34dc7c2f
BB
556 "PROPERTY", "EDIT", "VALUES");
557
558 /* Iterate over all properties */
2a673e76
AJ
559 if (current_prop_type == ZFS_TYPE_POOL) {
560 (void) zprop_iter(print_pool_prop_cb, fp, B_FALSE,
561 B_TRUE, current_prop_type);
9ae529ec 562
2a673e76
AJ
563 (void) fprintf(fp, "\t%-19s ", "feature@...");
564 (void) fprintf(fp, "YES "
565 "disabled | enabled | active\n");
9ae529ec 566
2a673e76
AJ
567 (void) fprintf(fp, gettext("\nThe feature@ properties "
568 "must be appended with a feature name.\n"
569 "See zpool-features(7).\n"));
570 } else if (current_prop_type == ZFS_TYPE_VDEV) {
571 (void) zprop_iter(print_vdev_prop_cb, fp, B_FALSE,
572 B_TRUE, current_prop_type);
573 }
34dc7c2f
BB
574 }
575
576 /*
577 * See comments at end of main().
578 */
579 if (getenv("ZFS_ABORT") != NULL) {
580 (void) printf("dumping core by request\n");
581 abort();
582 }
583
584 exit(requested ? 0 : 2);
585}
586
619f0976 587/*
e60e158e 588 * zpool initialize [-c | -s] [-w] <pool> [<vdev> ...]
619f0976
GW
589 * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
590 * if none specified.
591 *
592 * -c Cancel. Ends active initializing.
593 * -s Suspend. Initializing can then be restarted with no flags.
e60e158e 594 * -w Wait. Blocks until initializing has completed.
619f0976
GW
595 */
596int
597zpool_do_initialize(int argc, char **argv)
598{
599 int c;
600 char *poolname;
601 zpool_handle_t *zhp;
602 nvlist_t *vdevs;
603 int err = 0;
e60e158e 604 boolean_t wait = B_FALSE;
619f0976
GW
605
606 struct option long_options[] = {
607 {"cancel", no_argument, NULL, 'c'},
608 {"suspend", no_argument, NULL, 's'},
e60e158e 609 {"wait", no_argument, NULL, 'w'},
619f0976
GW
610 {0, 0, 0, 0}
611 };
612
1b939560 613 pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
e60e158e 614 while ((c = getopt_long(argc, argv, "csw", long_options, NULL)) != -1) {
619f0976
GW
615 switch (c) {
616 case 'c':
1b939560 617 if (cmd_type != POOL_INITIALIZE_START &&
a769fb53 618 cmd_type != POOL_INITIALIZE_CANCEL) {
619f0976
GW
619 (void) fprintf(stderr, gettext("-c cannot be "
620 "combined with other options\n"));
621 usage(B_FALSE);
622 }
623 cmd_type = POOL_INITIALIZE_CANCEL;
624 break;
625 case 's':
1b939560 626 if (cmd_type != POOL_INITIALIZE_START &&
a769fb53 627 cmd_type != POOL_INITIALIZE_SUSPEND) {
619f0976
GW
628 (void) fprintf(stderr, gettext("-s cannot be "
629 "combined with other options\n"));
630 usage(B_FALSE);
631 }
632 cmd_type = POOL_INITIALIZE_SUSPEND;
633 break;
e60e158e
JG
634 case 'w':
635 wait = B_TRUE;
636 break;
619f0976
GW
637 case '?':
638 if (optopt != 0) {
639 (void) fprintf(stderr,
640 gettext("invalid option '%c'\n"), optopt);
641 } else {
642 (void) fprintf(stderr,
643 gettext("invalid option '%s'\n"),
644 argv[optind - 1]);
645 }
646 usage(B_FALSE);
647 }
648 }
649
650 argc -= optind;
651 argv += optind;
652
653 if (argc < 1) {
654 (void) fprintf(stderr, gettext("missing pool name argument\n"));
655 usage(B_FALSE);
656 return (-1);
657 }
658
e60e158e
JG
659 if (wait && (cmd_type != POOL_INITIALIZE_START)) {
660 (void) fprintf(stderr, gettext("-w cannot be used with -c or "
661 "-s\n"));
662 usage(B_FALSE);
663 }
664
619f0976
GW
665 poolname = argv[0];
666 zhp = zpool_open(g_zfs, poolname);
667 if (zhp == NULL)
668 return (-1);
669
670 vdevs = fnvlist_alloc();
671 if (argc == 1) {
672 /* no individual leaf vdevs specified, so add them all */
673 nvlist_t *config = zpool_get_config(zhp, NULL);
674 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
675 ZPOOL_CONFIG_VDEV_TREE);
676 zpool_collect_leaves(zhp, nvroot, vdevs);
677 } else {
1b939560 678 for (int i = 1; i < argc; i++) {
619f0976
GW
679 fnvlist_add_boolean(vdevs, argv[i]);
680 }
681 }
682
e60e158e
JG
683 if (wait)
684 err = zpool_initialize_wait(zhp, cmd_type, vdevs);
685 else
686 err = zpool_initialize(zhp, cmd_type, vdevs);
619f0976
GW
687
688 fnvlist_free(vdevs);
689 zpool_close(zhp);
690
691 return (err);
692}
693
cc99f275
DB
694/*
695 * print a pool vdev config for dry runs
696 */
697static void
34dc7c2f 698print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
cc99f275 699 const char *match, int name_flags)
34dc7c2f
BB
700{
701 nvlist_t **child;
702 uint_t c, children;
703 char *vname;
cc99f275 704 boolean_t printed = B_FALSE;
34dc7c2f
BB
705
706 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
cc99f275
DB
707 &child, &children) != 0) {
708 if (name != NULL)
709 (void) printf("\t%*s%s\n", indent, "", name);
34dc7c2f 710 return;
cc99f275 711 }
34dc7c2f
BB
712
713 for (c = 0; c < children; c++) {
0cb40fa3 714 uint64_t is_log = B_FALSE, is_hole = B_FALSE;
d1807f16 715 const char *class = "";
34dc7c2f 716
0cb40fa3
AF
717 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
718 &is_hole);
719
720 if (is_hole == B_TRUE) {
721 continue;
722 }
723
34dc7c2f
BB
724 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
725 &is_log);
cc99f275 726 if (is_log)
d1807f16 727 class = VDEV_ALLOC_BIAS_LOG;
cc99f275
DB
728 (void) nvlist_lookup_string(child[c],
729 ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
730 if (strcmp(match, class) != 0)
34dc7c2f
BB
731 continue;
732
cc99f275
DB
733 if (!printed && name != NULL) {
734 (void) printf("\t%*s%s\n", indent, "", name);
735 printed = B_TRUE;
736 }
d2f3e292 737 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
cc99f275
DB
738 print_vdev_tree(zhp, vname, child[c], indent + 2, "",
739 name_flags);
34dc7c2f
BB
740 free(vname);
741 }
742}
743
0cb40fa3
AF
744/*
745 * Print the list of l2cache devices for dry runs.
746 */
747static void
748print_cache_list(nvlist_t *nv, int indent)
749{
750 nvlist_t **child;
751 uint_t c, children;
752
753 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
754 &child, &children) == 0 && children > 0) {
755 (void) printf("\t%*s%s\n", indent, "", "cache");
756 } else {
757 return;
758 }
759 for (c = 0; c < children; c++) {
760 char *vname;
761
762 vname = zpool_vdev_name(g_zfs, NULL, child[c], 0);
763 (void) printf("\t%*s%s\n", indent + 2, "", vname);
764 free(vname);
765 }
766}
767
768/*
769 * Print the list of spares for dry runs.
770 */
771static void
772print_spare_list(nvlist_t *nv, int indent)
773{
774 nvlist_t **child;
775 uint_t c, children;
776
777 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
778 &child, &children) == 0 && children > 0) {
779 (void) printf("\t%*s%s\n", indent, "", "spares");
780 } else {
781 return;
782 }
783 for (c = 0; c < children; c++) {
784 char *vname;
785
786 vname = zpool_vdev_name(g_zfs, NULL, child[c], 0);
787 (void) printf("\t%*s%s\n", indent + 2, "", vname);
788 free(vname);
789 }
790}
791
b9b24bb4
CS
792static boolean_t
793prop_list_contains_feature(nvlist_t *proplist)
794{
795 nvpair_t *nvp;
796 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
797 nvp = nvlist_next_nvpair(proplist, nvp)) {
798 if (zpool_prop_feature(nvpair_name(nvp)))
799 return (B_TRUE);
800 }
801 return (B_FALSE);
802}
803
34dc7c2f
BB
804/*
805 * Add a property pair (name, string-value) into a property nvlist.
806 */
807static int
a926aab9 808add_prop_list(const char *propname, const char *propval, nvlist_t **props,
b128c09f 809 boolean_t poolprop)
34dc7c2f 810{
31864e3d 811 zpool_prop_t prop = ZPOOL_PROP_INVAL;
34dc7c2f 812 nvlist_t *proplist;
b128c09f 813 const char *normnm;
d1807f16 814 const char *strval;
34dc7c2f
BB
815
816 if (*props == NULL &&
817 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
818 (void) fprintf(stderr,
819 gettext("internal error: out of memory\n"));
820 return (1);
821 }
822
823 proplist = *props;
824
b128c09f 825 if (poolprop) {
b9b24bb4 826 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
e086db16 827 const char *cname =
658fb802 828 zpool_prop_to_name(ZPOOL_PROP_COMPATIBILITY);
b9b24bb4 829
31864e3d 830 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
2a673e76
AJ
831 (!zpool_prop_feature(propname) &&
832 !zpool_prop_vdev(propname))) {
b128c09f 833 (void) fprintf(stderr, gettext("property '%s' is "
2a673e76 834 "not a valid pool or vdev property\n"), propname);
b128c09f
BB
835 return (2);
836 }
b9b24bb4
CS
837
838 /*
839 * feature@ properties and version should not be specified
840 * at the same time.
841 */
31864e3d 842 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
b9b24bb4
CS
843 nvlist_exists(proplist, vname)) ||
844 (prop == ZPOOL_PROP_VERSION &&
845 prop_list_contains_feature(proplist))) {
846 (void) fprintf(stderr, gettext("'feature@' and "
847 "'version' properties cannot be specified "
848 "together\n"));
849 return (2);
850 }
851
658fb802 852 /*
e086db16
CB
853 * if version is specified, only "legacy" compatibility
854 * may be requested
658fb802
CB
855 */
856 if ((prop == ZPOOL_PROP_COMPATIBILITY &&
e086db16 857 strcmp(propval, ZPOOL_COMPAT_LEGACY) != 0 &&
658fb802
CB
858 nvlist_exists(proplist, vname)) ||
859 (prop == ZPOOL_PROP_VERSION &&
e086db16
CB
860 nvlist_exists(proplist, cname) &&
861 strcmp(fnvlist_lookup_string(proplist, cname),
862 ZPOOL_COMPAT_LEGACY) != 0)) {
863 (void) fprintf(stderr, gettext("when 'version' is "
864 "specified, the 'compatibility' feature may only "
865 "be set to '" ZPOOL_COMPAT_LEGACY "'\n"));
658fb802
CB
866 return (2);
867 }
b9b24bb4 868
2a673e76 869 if (zpool_prop_feature(propname) || zpool_prop_vdev(propname))
9ae529ec
CS
870 normnm = propname;
871 else
872 normnm = zpool_prop_to_name(prop);
b128c09f 873 } else {
5140a58f 874 zfs_prop_t fsprop = zfs_name_to_prop(propname);
875
876 if (zfs_prop_valid_for_type(fsprop, ZFS_TYPE_FILESYSTEM,
877 B_FALSE)) {
878 normnm = zfs_prop_to_name(fsprop);
879 } else if (zfs_prop_user(propname) ||
880 zfs_prop_userquota(propname)) {
9babb374 881 normnm = propname;
5140a58f 882 } else {
883 (void) fprintf(stderr, gettext("property '%s' is "
884 "not a valid filesystem property\n"), propname);
885 return (2);
b128c09f 886 }
34dc7c2f
BB
887 }
888
b128c09f
BB
889 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
890 prop != ZPOOL_PROP_CACHEFILE) {
34dc7c2f
BB
891 (void) fprintf(stderr, gettext("property '%s' "
892 "specified multiple times\n"), propname);
893 return (2);
894 }
895
b128c09f 896 if (nvlist_add_string(proplist, normnm, propval) != 0) {
34dc7c2f
BB
897 (void) fprintf(stderr, gettext("internal "
898 "error: out of memory\n"));
899 return (1);
900 }
901
902 return (0);
903}
904
2f3ec900
RY
905/*
906 * Set a default property pair (name, string-value) in a property nvlist
907 */
908static int
a926aab9
AZ
909add_prop_list_default(const char *propname, const char *propval,
910 nvlist_t **props)
2f3ec900 911{
d1807f16 912 const char *pval;
2f3ec900
RY
913
914 if (nvlist_lookup_string(*props, propname, &pval) == 0)
915 return (0);
916
917 return (add_prop_list(propname, propval, props, B_TRUE));
918}
919
34dc7c2f 920/*
a77f29f9 921 * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
34dc7c2f
BB
922 *
923 * -f Force addition of devices, even if they appear in use
d2f3e292
RY
924 * -g Display guid for individual vdev name.
925 * -L Follow links when resolving vdev path name.
34dc7c2f
BB
926 * -n Do not add the devices, but display the resulting layout if
927 * they were to be added.
df831108 928 * -o Set property=value.
a77f29f9 929 * -P Display full path for vdev name.
34dc7c2f
BB
930 *
931 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
227d3793 932 * handled by make_root_vdev(), which constructs the nvlist needed to pass to
34dc7c2f
BB
933 * libzfs.
934 */
935int
936zpool_do_add(int argc, char **argv)
937{
938 boolean_t force = B_FALSE;
939 boolean_t dryrun = B_FALSE;
d2f3e292 940 int name_flags = 0;
34dc7c2f
BB
941 int c;
942 nvlist_t *nvroot;
943 char *poolname;
944 int ret;
945 zpool_handle_t *zhp;
946 nvlist_t *config;
df831108
CP
947 nvlist_t *props = NULL;
948 char *propval;
34dc7c2f
BB
949
950 /* check options */
a77f29f9 951 while ((c = getopt(argc, argv, "fgLno:P")) != -1) {
34dc7c2f
BB
952 switch (c) {
953 case 'f':
954 force = B_TRUE;
955 break;
d2f3e292
RY
956 case 'g':
957 name_flags |= VDEV_NAME_GUID;
958 break;
959 case 'L':
960 name_flags |= VDEV_NAME_FOLLOW_LINKS;
961 break;
34dc7c2f
BB
962 case 'n':
963 dryrun = B_TRUE;
964 break;
df831108
CP
965 case 'o':
966 if ((propval = strchr(optarg, '=')) == NULL) {
967 (void) fprintf(stderr, gettext("missing "
968 "'=' for -o option\n"));
969 usage(B_FALSE);
970 }
971 *propval = '\0';
972 propval++;
973
974 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
975 (add_prop_list(optarg, propval, &props, B_TRUE)))
976 usage(B_FALSE);
977 break;
a77f29f9 978 case 'P':
d2f3e292
RY
979 name_flags |= VDEV_NAME_PATH;
980 break;
34dc7c2f
BB
981 case '?':
982 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
983 optopt);
984 usage(B_FALSE);
985 }
986 }
987
988 argc -= optind;
989 argv += optind;
990
991 /* get pool name and check number of arguments */
992 if (argc < 1) {
993 (void) fprintf(stderr, gettext("missing pool name argument\n"));
994 usage(B_FALSE);
995 }
996 if (argc < 2) {
997 (void) fprintf(stderr, gettext("missing vdev specification\n"));
998 usage(B_FALSE);
999 }
1000
1001 poolname = argv[0];
1002
1003 argc--;
1004 argv++;
1005
1006 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
1007 return (1);
1008
1009 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
1010 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
1011 poolname);
1012 zpool_close(zhp);
1013 return (1);
1014 }
1015
dddef7d6 1016 /* unless manually specified use "ashift" pool property (if set) */
1017 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
1018 int intval;
1019 zprop_source_t src;
1020 char strval[ZPOOL_MAXPROPLEN];
1021
1022 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
1023 if (src != ZPROP_SRC_DEFAULT) {
1024 (void) sprintf(strval, "%" PRId32, intval);
1025 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
1026 &props, B_TRUE) == 0);
1027 }
1028 }
1029
227d3793 1030 /* pass off to make_root_vdev for processing */
df831108 1031 nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
b128c09f 1032 argc, argv);
34dc7c2f
BB
1033 if (nvroot == NULL) {
1034 zpool_close(zhp);
1035 return (1);
1036 }
1037
1038 if (dryrun) {
1039 nvlist_t *poolnvroot;
0cb40fa3
AF
1040 nvlist_t **l2child, **sparechild;
1041 uint_t l2children, sparechildren, c;
e02b533e 1042 char *vname;
0cb40fa3 1043 boolean_t hadcache = B_FALSE, hadspare = B_FALSE;
34dc7c2f
BB
1044
1045 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1046 &poolnvroot) == 0);
1047
1048 (void) printf(gettext("would update '%s' to the following "
0cb40fa3 1049 "configuration:\n\n"), zpool_get_name(zhp));
34dc7c2f
BB
1050
1051 /* print original main pool and new tree */
cc99f275
DB
1052 print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
1053 name_flags | VDEV_NAME_TYPE_ID);
1054 print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
1055
1056 /* print other classes: 'dedup', 'special', and 'log' */
c24fa4b1 1057 if (zfs_special_devs(poolnvroot, VDEV_ALLOC_BIAS_DEDUP)) {
1058 print_vdev_tree(zhp, "dedup", poolnvroot, 0,
1059 VDEV_ALLOC_BIAS_DEDUP, name_flags);
1060 print_vdev_tree(zhp, NULL, nvroot, 0,
1061 VDEV_ALLOC_BIAS_DEDUP, name_flags);
1062 } else if (zfs_special_devs(nvroot, VDEV_ALLOC_BIAS_DEDUP)) {
1063 print_vdev_tree(zhp, "dedup", nvroot, 0,
1064 VDEV_ALLOC_BIAS_DEDUP, name_flags);
1065 }
cc99f275 1066
c24fa4b1 1067 if (zfs_special_devs(poolnvroot, VDEV_ALLOC_BIAS_SPECIAL)) {
1068 print_vdev_tree(zhp, "special", poolnvroot, 0,
1069 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
1070 print_vdev_tree(zhp, NULL, nvroot, 0,
1071 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
1072 } else if (zfs_special_devs(nvroot, VDEV_ALLOC_BIAS_SPECIAL)) {
1073 print_vdev_tree(zhp, "special", nvroot, 0,
1074 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
1075 }
cc99f275 1076
c24fa4b1 1077 if (num_logs(poolnvroot) > 0) {
1078 print_vdev_tree(zhp, "logs", poolnvroot, 0,
1079 VDEV_ALLOC_BIAS_LOG, name_flags);
1080 print_vdev_tree(zhp, NULL, nvroot, 0,
1081 VDEV_ALLOC_BIAS_LOG, name_flags);
1082 } else if (num_logs(nvroot) > 0) {
1083 print_vdev_tree(zhp, "logs", nvroot, 0,
1084 VDEV_ALLOC_BIAS_LOG, name_flags);
1085 }
34dc7c2f 1086
e02b533e
TC
1087 /* Do the same for the caches */
1088 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_L2CACHE,
1089 &l2child, &l2children) == 0 && l2children) {
1090 hadcache = B_TRUE;
1091 (void) printf(gettext("\tcache\n"));
1092 for (c = 0; c < l2children; c++) {
1093 vname = zpool_vdev_name(g_zfs, NULL,
d2f3e292 1094 l2child[c], name_flags);
e02b533e
TC
1095 (void) printf("\t %s\n", vname);
1096 free(vname);
1097 }
1098 }
1099 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
1100 &l2child, &l2children) == 0 && l2children) {
1101 if (!hadcache)
1102 (void) printf(gettext("\tcache\n"));
1103 for (c = 0; c < l2children; c++) {
1104 vname = zpool_vdev_name(g_zfs, NULL,
d2f3e292 1105 l2child[c], name_flags);
e02b533e
TC
1106 (void) printf("\t %s\n", vname);
1107 free(vname);
1108 }
1109 }
bf169e9f 1110 /* And finally the spares */
0cb40fa3
AF
1111 if (nvlist_lookup_nvlist_array(poolnvroot, ZPOOL_CONFIG_SPARES,
1112 &sparechild, &sparechildren) == 0 && sparechildren > 0) {
1113 hadspare = B_TRUE;
1114 (void) printf(gettext("\tspares\n"));
1115 for (c = 0; c < sparechildren; c++) {
1116 vname = zpool_vdev_name(g_zfs, NULL,
1117 sparechild[c], name_flags);
1118 (void) printf("\t %s\n", vname);
1119 free(vname);
1120 }
1121 }
1122 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1123 &sparechild, &sparechildren) == 0 && sparechildren > 0) {
1124 if (!hadspare)
1125 (void) printf(gettext("\tspares\n"));
1126 for (c = 0; c < sparechildren; c++) {
1127 vname = zpool_vdev_name(g_zfs, NULL,
1128 sparechild[c], name_flags);
1129 (void) printf("\t %s\n", vname);
1130 free(vname);
1131 }
1132 }
e02b533e 1133
34dc7c2f
BB
1134 ret = 0;
1135 } else {
1136 ret = (zpool_add(zhp, nvroot) != 0);
1137 }
1138
df831108 1139 nvlist_free(props);
34dc7c2f
BB
1140 nvlist_free(nvroot);
1141 zpool_close(zhp);
1142
1143 return (ret);
1144}
1145
1146/*
e60e158e 1147 * zpool remove [-npsw] <pool> <vdev> ...
34dc7c2f 1148 *
a1d477c2 1149 * Removes the given vdev from the pool.
34dc7c2f
BB
1150 */
1151int
1152zpool_do_remove(int argc, char **argv)
1153{
1154 char *poolname;
1155 int i, ret = 0;
884385a0 1156 zpool_handle_t *zhp = NULL;
a1d477c2 1157 boolean_t stop = B_FALSE;
0869b74a 1158 int c;
a1d477c2
MA
1159 boolean_t noop = B_FALSE;
1160 boolean_t parsable = B_FALSE;
e60e158e 1161 boolean_t wait = B_FALSE;
34dc7c2f 1162
a1d477c2 1163 /* check options */
e60e158e 1164 while ((c = getopt(argc, argv, "npsw")) != -1) {
a1d477c2
MA
1165 switch (c) {
1166 case 'n':
1167 noop = B_TRUE;
1168 break;
1169 case 'p':
1170 parsable = B_TRUE;
1171 break;
1172 case 's':
1173 stop = B_TRUE;
1174 break;
e60e158e
JG
1175 case 'w':
1176 wait = B_TRUE;
1177 break;
a1d477c2
MA
1178 case '?':
1179 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1180 optopt);
1181 usage(B_FALSE);
1182 }
1183 }
1184
1185 argc -= optind;
1186 argv += optind;
34dc7c2f
BB
1187
1188 /* get pool name and check number of arguments */
1189 if (argc < 1) {
1190 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1191 usage(B_FALSE);
1192 }
34dc7c2f
BB
1193
1194 poolname = argv[0];
1195
1196 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
1197 return (1);
1198
a1d477c2 1199 if (stop && noop) {
ebe1d036 1200 zpool_close(zhp);
a1d477c2
MA
1201 (void) fprintf(stderr, gettext("stop request ignored\n"));
1202 return (0);
1203 }
1204
1205 if (stop) {
1206 if (argc > 1) {
1207 (void) fprintf(stderr, gettext("too many arguments\n"));
1208 usage(B_FALSE);
1209 }
1210 if (zpool_vdev_remove_cancel(zhp) != 0)
34dc7c2f 1211 ret = 1;
e60e158e
JG
1212 if (wait) {
1213 (void) fprintf(stderr, gettext("invalid option "
1214 "combination: -w cannot be used with -s\n"));
1215 usage(B_FALSE);
1216 }
a1d477c2
MA
1217 } else {
1218 if (argc < 2) {
1219 (void) fprintf(stderr, gettext("missing device\n"));
1220 usage(B_FALSE);
1221 }
1222
1223 for (i = 1; i < argc; i++) {
1224 if (noop) {
1225 uint64_t size;
1226
1227 if (zpool_vdev_indirect_size(zhp, argv[i],
1228 &size) != 0) {
1229 ret = 1;
1230 break;
1231 }
1232 if (parsable) {
1233 (void) printf("%s %llu\n",
1234 argv[i], (unsigned long long)size);
1235 } else {
1236 char valstr[32];
1237 zfs_nicenum(size, valstr,
1238 sizeof (valstr));
1239 (void) printf("Memory that will be "
1240 "used after removing %s: %s\n",
1241 argv[i], valstr);
1242 }
1243 } else {
1244 if (zpool_vdev_remove(zhp, argv[i]) != 0)
1245 ret = 1;
1246 }
1247 }
e60e158e
JG
1248
1249 if (ret == 0 && wait)
1250 ret = zpool_wait(zhp, ZPOOL_WAIT_REMOVE);
34dc7c2f 1251 }
884385a0 1252 zpool_close(zhp);
34dc7c2f
BB
1253
1254 return (ret);
1255}
1256
4dc11532
TH
1257/*
1258 * Return 1 if a vdev is active (being used in a pool)
1259 * Return 0 if a vdev is inactive (offlined or faulted, or not in active pool)
1260 *
1261 * This is useful for checking if a disk in an active pool is offlined or
1262 * faulted.
1263 */
1264static int
1265vdev_is_active(char *vdev_path)
1266{
1267 int fd;
1268 fd = open(vdev_path, O_EXCL);
1269 if (fd < 0) {
1270 return (1); /* cant open O_EXCL - disk is active */
1271 }
1272
1273 close(fd);
1274 return (0); /* disk is inactive in the pool */
1275}
1276
131cc95c 1277/*
dbb38f66
YP
1278 * zpool labelclear [-f] <vdev>
1279 *
1280 * -f Force clearing the label for the vdevs which are members of
1281 * the exported or foreign pools.
131cc95c
DK
1282 *
1283 * Verifies that the vdev is not active and zeros out the label information
1284 * on the device.
1285 */
1286int
1287zpool_do_labelclear(int argc, char **argv)
1288{
dbb38f66
YP
1289 char vdev[MAXPATHLEN];
1290 char *name = NULL;
131cc95c 1291 int c, fd = -1, ret = 0;
dbb38f66 1292 nvlist_t *config;
131cc95c
DK
1293 pool_state_t state;
1294 boolean_t inuse = B_FALSE;
1295 boolean_t force = B_FALSE;
1296
1297 /* check options */
1298 while ((c = getopt(argc, argv, "f")) != -1) {
1299 switch (c) {
1300 case 'f':
1301 force = B_TRUE;
1302 break;
1303 default:
1304 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1305 optopt);
1306 usage(B_FALSE);
1307 }
1308 }
1309
1310 argc -= optind;
1311 argv += optind;
1312
1313 /* get vdev name */
1314 if (argc < 1) {
dbb38f66
YP
1315 (void) fprintf(stderr, gettext("missing vdev name\n"));
1316 usage(B_FALSE);
1317 }
1318 if (argc > 1) {
1319 (void) fprintf(stderr, gettext("too many arguments\n"));
131cc95c
DK
1320 usage(B_FALSE);
1321 }
1322
9368b387
RY
1323 (void) strlcpy(vdev, argv[0], sizeof (vdev));
1324
dbb38f66 1325 /*
9368b387 1326 * If we cannot open an absolute path, we quit.
dbb38f66
YP
1327 * Otherwise if the provided vdev name doesn't point to a file,
1328 * try prepending expected disk paths and partition numbers.
1329 */
9368b387 1330 if ((fd = open(vdev, O_RDWR)) < 0) {
dbb38f66 1331 int error;
9368b387
RY
1332 if (vdev[0] == '/') {
1333 (void) fprintf(stderr, gettext("failed to open "
1334 "%s: %s\n"), vdev, strerror(errno));
1335 return (1);
1336 }
dbb38f66
YP
1337
1338 error = zfs_resolve_shortname(argv[0], vdev, MAXPATHLEN);
1339 if (error == 0 && zfs_dev_is_whole_disk(vdev)) {
1340 if (zfs_append_partition(vdev, MAXPATHLEN) == -1)
1341 error = ENOENT;
1342 }
1343
9368b387
RY
1344 if (error || ((fd = open(vdev, O_RDWR)) < 0)) {
1345 if (errno == ENOENT) {
1346 (void) fprintf(stderr, gettext(
1347 "failed to find device %s, try "
1348 "specifying absolute path instead\n"),
1349 argv[0]);
1350 return (1);
1351 }
1352
1353 (void) fprintf(stderr, gettext("failed to open %s:"
1354 " %s\n"), vdev, strerror(errno));
dbb38f66
YP
1355 return (1);
1356 }
131cc95c
DK
1357 }
1358
066da71e
BB
1359 /*
1360 * Flush all dirty pages for the block device. This should not be
1361 * fatal when the device does not support BLKFLSBUF as would be the
1362 * case for a file vdev.
1363 */
d46f0deb 1364 if ((zfs_dev_flush(fd) != 0) && (errno != ENOTTY))
a167aa7c
GDN
1365 (void) fprintf(stderr, gettext("failed to invalidate "
1366 "cache for %s: %s\n"), vdev, strerror(errno));
1367
066da71e 1368 if (zpool_read_label(fd, &config, NULL) != 0) {
131cc95c 1369 (void) fprintf(stderr,
066da71e 1370 gettext("failed to read label from %s\n"), vdev);
c721ba43
TH
1371 ret = 1;
1372 goto errout;
dbb38f66
YP
1373 }
1374 nvlist_free(config);
131cc95c 1375
dbb38f66
YP
1376 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
1377 if (ret != 0) {
1378 (void) fprintf(stderr,
1379 gettext("failed to check state for %s\n"), vdev);
c721ba43
TH
1380 ret = 1;
1381 goto errout;
131cc95c
DK
1382 }
1383
dbb38f66
YP
1384 if (!inuse)
1385 goto wipe_label;
1386
1387 switch (state) {
1388 default:
1389 case POOL_STATE_ACTIVE:
1390 case POOL_STATE_SPARE:
1391 case POOL_STATE_L2CACHE:
4dc11532
TH
1392 /*
1393 * We allow the user to call 'zpool offline -f'
1394 * on an offlined disk in an active pool. We can check if
1395 * the disk is online by calling vdev_is_active().
1396 */
1397 if (force && !vdev_is_active(vdev))
1398 break;
1399
dbb38f66 1400 (void) fprintf(stderr, gettext(
4dc11532 1401 "%s is a member (%s) of pool \"%s\""),
dbb38f66 1402 vdev, zpool_pool_state_to_name(state), name);
4dc11532
TH
1403
1404 if (force) {
1405 (void) fprintf(stderr, gettext(
1406 ". Offline the disk first to clear its label."));
1407 }
1408 printf("\n");
dbb38f66
YP
1409 ret = 1;
1410 goto errout;
131cc95c 1411
dbb38f66
YP
1412 case POOL_STATE_EXPORTED:
1413 if (force)
131cc95c 1414 break;
dbb38f66
YP
1415 (void) fprintf(stderr, gettext(
1416 "use '-f' to override the following error:\n"
1417 "%s is a member of exported pool \"%s\"\n"),
1418 vdev, name);
1419 ret = 1;
1420 goto errout;
1421
1422 case POOL_STATE_POTENTIALLY_ACTIVE:
1423 if (force)
1424 break;
1425 (void) fprintf(stderr, gettext(
1426 "use '-f' to override the following error:\n"
1427 "%s is a member of potentially active pool \"%s\"\n"),
1428 vdev, name);
1429 ret = 1;
1430 goto errout;
1431
1432 case POOL_STATE_DESTROYED:
1433 /* inuse should never be set for a destroyed pool */
1434 assert(0);
1435 break;
131cc95c
DK
1436 }
1437
1438wipe_label:
dbb38f66
YP
1439 ret = zpool_clear_label(fd);
1440 if (ret != 0) {
131cc95c 1441 (void) fprintf(stderr,
dbb38f66 1442 gettext("failed to clear label for %s\n"), vdev);
131cc95c
DK
1443 }
1444
1445errout:
dbb38f66
YP
1446 free(name);
1447 (void) close(fd);
131cc95c
DK
1448
1449 return (ret);
1450}
1451
34dc7c2f 1452/*
9ae529ec 1453 * zpool create [-fnd] [-o property=value] ...
b128c09f
BB
1454 * [-O file-system-property=value] ...
1455 * [-R root] [-m mountpoint] <pool> <dev> ...
34dc7c2f
BB
1456 *
1457 * -f Force creation, even if devices appear in use
1458 * -n Do not create the pool, but display the resulting layout if it
1459 * were to be created.
1460 * -R Create a pool under an alternate root
1461 * -m Set default mountpoint for the root dataset. By default it's
9ae529ec 1462 * '/<pool>'
34dc7c2f 1463 * -o Set property=value.
e4010f27 1464 * -o Set feature@feature=enabled|disabled.
9ae529ec
CS
1465 * -d Don't automatically enable all supported pool features
1466 * (individual features can be enabled with -o).
b128c09f 1467 * -O Set fsproperty=value in the pool's root file system
34dc7c2f
BB
1468 *
1469 * Creates the named pool according to the given vdev specification. The
227d3793
RM
1470 * bulk of the vdev processing is done in make_root_vdev() in zpool_vdev.c.
1471 * Once we get the nvlist back from make_root_vdev(), we either print out the
1472 * contents (if '-n' was specified), or pass it to libzfs to do the creation.
34dc7c2f
BB
1473 */
1474int
1475zpool_do_create(int argc, char **argv)
1476{
1477 boolean_t force = B_FALSE;
1478 boolean_t dryrun = B_FALSE;
658fb802
CB
1479 boolean_t enable_pool_features = B_TRUE;
1480
34dc7c2f
BB
1481 int c;
1482 nvlist_t *nvroot = NULL;
1483 char *poolname;
023bbe6f 1484 char *tname = NULL;
34dc7c2f
BB
1485 int ret = 1;
1486 char *altroot = NULL;
658fb802 1487 char *compat = NULL;
34dc7c2f 1488 char *mountpoint = NULL;
b128c09f 1489 nvlist_t *fsprops = NULL;
34dc7c2f
BB
1490 nvlist_t *props = NULL;
1491 char *propval;
1492
1493 /* check options */
83e9986f 1494 while ((c = getopt(argc, argv, ":fndR:m:o:O:t:")) != -1) {
34dc7c2f
BB
1495 switch (c) {
1496 case 'f':
1497 force = B_TRUE;
1498 break;
1499 case 'n':
1500 dryrun = B_TRUE;
1501 break;
9ae529ec 1502 case 'd':
658fb802 1503 enable_pool_features = B_FALSE;
9ae529ec 1504 break;
34dc7c2f
BB
1505 case 'R':
1506 altroot = optarg;
1507 if (add_prop_list(zpool_prop_to_name(
b128c09f 1508 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
34dc7c2f 1509 goto errout;
2f3ec900 1510 if (add_prop_list_default(zpool_prop_to_name(
e40ca391 1511 ZPOOL_PROP_CACHEFILE), "none", &props))
34dc7c2f
BB
1512 goto errout;
1513 break;
1514 case 'm':
7bc7f250 1515 /* Equivalent to -O mountpoint=optarg */
34dc7c2f
BB
1516 mountpoint = optarg;
1517 break;
1518 case 'o':
1519 if ((propval = strchr(optarg, '=')) == NULL) {
1520 (void) fprintf(stderr, gettext("missing "
1521 "'=' for -o option\n"));
1522 goto errout;
1523 }
1524 *propval = '\0';
1525 propval++;
1526
b128c09f
BB
1527 if (add_prop_list(optarg, propval, &props, B_TRUE))
1528 goto errout;
9ae529ec
CS
1529
1530 /*
1531 * If the user is creating a pool that doesn't support
1532 * feature flags, don't enable any features.
1533 */
1534 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1535 char *end;
1536 u_longlong_t ver;
1537
1538 ver = strtoull(propval, &end, 10);
1539 if (*end == '\0' &&
1540 ver < SPA_VERSION_FEATURES) {
658fb802 1541 enable_pool_features = B_FALSE;
9ae529ec
CS
1542 }
1543 }
3ac2794c
BB
1544 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1545 altroot = propval;
658fb802
CB
1546 if (zpool_name_to_prop(optarg) ==
1547 ZPOOL_PROP_COMPATIBILITY)
1548 compat = propval;
b128c09f
BB
1549 break;
1550 case 'O':
1551 if ((propval = strchr(optarg, '=')) == NULL) {
1552 (void) fprintf(stderr, gettext("missing "
1553 "'=' for -O option\n"));
1554 goto errout;
1555 }
1556 *propval = '\0';
1557 propval++;
1558
7bc7f250
WA
1559 /*
1560 * Mountpoints are checked and then added later.
1561 * Uniquely among properties, they can be specified
1562 * more than once, to avoid conflict with -m.
1563 */
1564 if (0 == strcmp(optarg,
1565 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1566 mountpoint = propval;
1567 } else if (add_prop_list(optarg, propval, &fsprops,
1568 B_FALSE)) {
34dc7c2f 1569 goto errout;
7bc7f250 1570 }
34dc7c2f 1571 break;
83e9986f
RY
1572 case 't':
1573 /*
1574 * Sanity check temporary pool name.
1575 */
1576 if (strchr(optarg, '/') != NULL) {
1577 (void) fprintf(stderr, gettext("cannot create "
1578 "'%s': invalid character '/' in temporary "
1579 "name\n"), optarg);
1580 (void) fprintf(stderr, gettext("use 'zfs "
1581 "create' to create a dataset\n"));
1582 goto errout;
1583 }
1584
1585 if (add_prop_list(zpool_prop_to_name(
1586 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1587 goto errout;
1588 if (add_prop_list_default(zpool_prop_to_name(
e40ca391 1589 ZPOOL_PROP_CACHEFILE), "none", &props))
83e9986f 1590 goto errout;
023bbe6f 1591 tname = optarg;
83e9986f 1592 break;
34dc7c2f
BB
1593 case ':':
1594 (void) fprintf(stderr, gettext("missing argument for "
1595 "'%c' option\n"), optopt);
1596 goto badusage;
1597 case '?':
1598 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1599 optopt);
1600 goto badusage;
1601 }
1602 }
1603
1604 argc -= optind;
1605 argv += optind;
1606
1607 /* get pool name and check number of arguments */
1608 if (argc < 1) {
1609 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1610 goto badusage;
1611 }
1612 if (argc < 2) {
1613 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1614 goto badusage;
1615 }
1616
1617 poolname = argv[0];
1618
1619 /*
1620 * As a special case, check for use of '/' in the name, and direct the
1621 * user to use 'zfs create' instead.
1622 */
1623 if (strchr(poolname, '/') != NULL) {
1624 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1625 "character '/' in pool name\n"), poolname);
1626 (void) fprintf(stderr, gettext("use 'zfs create' to "
1627 "create a dataset\n"));
1628 goto errout;
1629 }
1630
227d3793 1631 /* pass off to make_root_vdev for bulk processing */
df30f566 1632 nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
b128c09f 1633 argc - 1, argv + 1);
34dc7c2f 1634 if (nvroot == NULL)
b128c09f 1635 goto errout;
34dc7c2f
BB
1636
1637 /* make_root_vdev() allows 0 toplevel children if there are spares */
1638 if (!zfs_allocatable_devs(nvroot)) {
1639 (void) fprintf(stderr, gettext("invalid vdev "
1640 "specification: at least one toplevel vdev must be "
1641 "specified\n"));
1642 goto errout;
1643 }
1644
34dc7c2f
BB
1645 if (altroot != NULL && altroot[0] != '/') {
1646 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1647 "must be an absolute path\n"), altroot);
1648 goto errout;
1649 }
1650
1651 /*
1652 * Check the validity of the mountpoint and direct the user to use the
1653 * '-m' mountpoint option if it looks like its in use.
1654 */
1655 if (mountpoint == NULL ||
1656 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1657 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1658 char buf[MAXPATHLEN];
1659 DIR *dirp;
1660
1661 if (mountpoint && mountpoint[0] != '/') {
1662 (void) fprintf(stderr, gettext("invalid mountpoint "
1663 "'%s': must be an absolute path, 'legacy', or "
1664 "'none'\n"), mountpoint);
1665 goto errout;
1666 }
1667
1668 if (mountpoint == NULL) {
1669 if (altroot != NULL)
1670 (void) snprintf(buf, sizeof (buf), "%s/%s",
1671 altroot, poolname);
1672 else
1673 (void) snprintf(buf, sizeof (buf), "/%s",
1674 poolname);
1675 } else {
1676 if (altroot != NULL)
1677 (void) snprintf(buf, sizeof (buf), "%s%s",
1678 altroot, mountpoint);
1679 else
1680 (void) snprintf(buf, sizeof (buf), "%s",
1681 mountpoint);
1682 }
1683
1684 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1685 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1686 "%s\n"), buf, strerror(errno));
1687 (void) fprintf(stderr, gettext("use '-m' "
1688 "option to provide a different default\n"));
1689 goto errout;
1690 } else if (dirp) {
1691 int count = 0;
1692
1693 while (count < 3 && readdir(dirp) != NULL)
1694 count++;
1695 (void) closedir(dirp);
1696
1697 if (count > 2) {
1698 (void) fprintf(stderr, gettext("mountpoint "
1699 "'%s' exists and is not empty\n"), buf);
1700 (void) fprintf(stderr, gettext("use '-m' "
1701 "option to provide a "
1702 "different default\n"));
1703 goto errout;
1704 }
1705 }
1706 }
1707
7bc7f250
WA
1708 /*
1709 * Now that the mountpoint's validity has been checked, ensure that
1710 * the property is set appropriately prior to creating the pool.
1711 */
1712 if (mountpoint != NULL) {
1713 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1714 mountpoint, &fsprops, B_FALSE);
1715 if (ret != 0)
1716 goto errout;
1717 }
1718
1719 ret = 1;
34dc7c2f
BB
1720 if (dryrun) {
1721 /*
1722 * For a dry run invocation, print out a basic message and run
1723 * through all the vdevs in the list and print out in an
1724 * appropriate hierarchy.
1725 */
1726 (void) printf(gettext("would create '%s' with the "
1727 "following layout:\n\n"), poolname);
1728
cc99f275
DB
1729 print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
1730 print_vdev_tree(NULL, "dedup", nvroot, 0,
1731 VDEV_ALLOC_BIAS_DEDUP, 0);
1732 print_vdev_tree(NULL, "special", nvroot, 0,
1733 VDEV_ALLOC_BIAS_SPECIAL, 0);
1734 print_vdev_tree(NULL, "logs", nvroot, 0,
1735 VDEV_ALLOC_BIAS_LOG, 0);
0cb40fa3
AF
1736 print_cache_list(nvroot, 0);
1737 print_spare_list(nvroot, 0);
34dc7c2f
BB
1738
1739 ret = 0;
1740 } else {
1741 /*
658fb802
CB
1742 * Load in feature set.
1743 * Note: if compatibility property not given, we'll have
1744 * NULL, which means 'all features'.
34dc7c2f 1745 */
658fb802
CB
1746 boolean_t requested_features[SPA_FEATURES];
1747 if (zpool_do_load_compat(compat, requested_features) !=
1748 ZPOOL_COMPATIBILITY_OK)
1749 goto errout;
1750
1751 /*
1752 * props contains list of features to enable.
1753 * For each feature:
1754 * - remove it if feature@name=disabled
1755 * - leave it there if feature@name=enabled
1756 * - add it if:
1757 * - enable_pool_features (ie: no '-d' or '-o version')
1758 * - it's supported by the kernel module
1759 * - it's in the requested feature set
e086db16 1760 * - warn if it's enabled but not in compat
658fb802
CB
1761 */
1762 for (spa_feature_t i = 0; i < SPA_FEATURES; i++) {
e4010f27 1763 char propname[MAXPATHLEN];
d1807f16 1764 const char *propval;
e4010f27 1765 zfeature_info_t *feat = &spa_feature_table[i];
9ae529ec 1766
e4010f27 1767 (void) snprintf(propname, sizeof (propname),
1768 "feature@%s", feat->fi_uname);
1769
e4010f27 1770 if (!nvlist_lookup_string(props, propname, &propval)) {
63652e15
DS
1771 if (strcmp(propval,
1772 ZFS_FEATURE_DISABLED) == 0) {
e4010f27 1773 (void) nvlist_remove_all(props,
1774 propname);
63652e15 1775 } else if (strcmp(propval,
e086db16 1776 ZFS_FEATURE_ENABLED) == 0 &&
63652e15 1777 !requested_features[i]) {
e086db16
CB
1778 (void) fprintf(stderr, gettext(
1779 "Warning: feature \"%s\" enabled "
1780 "but is not in specified "
1781 "'compatibility' feature set.\n"),
1782 feat->fi_uname);
63652e15 1783 }
658fb802
CB
1784 } else if (
1785 enable_pool_features &&
1786 feat->fi_zfs_mod_supported &&
1787 requested_features[i]) {
7bc7f250
WA
1788 ret = add_prop_list(propname,
1789 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1790 if (ret != 0)
9ae529ec
CS
1791 goto errout;
1792 }
1793 }
7bc7f250
WA
1794
1795 ret = 1;
b128c09f
BB
1796 if (zpool_create(g_zfs, poolname,
1797 nvroot, props, fsprops) == 0) {
023bbe6f 1798 zfs_handle_t *pool = zfs_open(g_zfs,
1799 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
34dc7c2f 1800 if (pool != NULL) {
c15d36c6 1801 if (zfs_mount(pool, NULL, 0) == 0) {
b4d9a82f
AZ
1802 ret = zfs_share(pool, NULL);
1803 zfs_commit_shares(NULL);
c15d36c6 1804 }
34dc7c2f
BB
1805 zfs_close(pool);
1806 }
1807 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1808 (void) fprintf(stderr, gettext("pool name may have "
1809 "been omitted\n"));
1810 }
1811 }
1812
1813errout:
1814 nvlist_free(nvroot);
b128c09f 1815 nvlist_free(fsprops);
34dc7c2f
BB
1816 nvlist_free(props);
1817 return (ret);
1818badusage:
b128c09f 1819 nvlist_free(fsprops);
34dc7c2f
BB
1820 nvlist_free(props);
1821 usage(B_FALSE);
1822 return (2);
1823}
1824
1825/*
1826 * zpool destroy <pool>
1827 *
1828 * -f Forcefully unmount any datasets
1829 *
1830 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1831 */
1832int
1833zpool_do_destroy(int argc, char **argv)
1834{
1835 boolean_t force = B_FALSE;
1836 int c;
1837 char *pool;
1838 zpool_handle_t *zhp;
1839 int ret;
1840
1841 /* check options */
1842 while ((c = getopt(argc, argv, "f")) != -1) {
1843 switch (c) {
1844 case 'f':
1845 force = B_TRUE;
1846 break;
1847 case '?':
1848 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1849 optopt);
1850 usage(B_FALSE);
1851 }
1852 }
1853
1854 argc -= optind;
1855 argv += optind;
1856
1857 /* check arguments */
1858 if (argc < 1) {
1859 (void) fprintf(stderr, gettext("missing pool argument\n"));
1860 usage(B_FALSE);
1861 }
1862 if (argc > 1) {
1863 (void) fprintf(stderr, gettext("too many arguments\n"));
1864 usage(B_FALSE);
1865 }
1866
1867 pool = argv[0];
1868
1869 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1870 /*
1871 * As a special case, check for use of '/' in the name, and
1872 * direct the user to use 'zfs destroy' instead.
1873 */
1874 if (strchr(pool, '/') != NULL)
1875 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1876 "destroy a dataset\n"));
1877 return (1);
1878 }
1879
1880 if (zpool_disable_datasets(zhp, force) != 0) {
1881 (void) fprintf(stderr, gettext("could not destroy '%s': "
1882 "could not unmount datasets\n"), zpool_get_name(zhp));
a425f5bf 1883 zpool_close(zhp);
34dc7c2f
BB
1884 return (1);
1885 }
1886
6f1ffb06
MA
1887 /* The history must be logged as part of the export */
1888 log_history = B_FALSE;
1889
1890 ret = (zpool_destroy(zhp, history_str) != 0);
34dc7c2f
BB
1891
1892 zpool_close(zhp);
1893
1894 return (ret);
1895}
1896
859735c0
TF
1897typedef struct export_cbdata {
1898 boolean_t force;
1899 boolean_t hardforce;
1900} export_cbdata_t;
1901
1902/*
1903 * Export one pool
1904 */
65c7cc49 1905static int
859735c0
TF
1906zpool_export_one(zpool_handle_t *zhp, void *data)
1907{
1908 export_cbdata_t *cb = data;
1909
1910 if (zpool_disable_datasets(zhp, cb->force) != 0)
1911 return (1);
1912
1913 /* The history must be logged as part of the export */
1914 log_history = B_FALSE;
1915
1916 if (cb->hardforce) {
1917 if (zpool_export_force(zhp, history_str) != 0)
1918 return (1);
1919 } else if (zpool_export(zhp, cb->force, history_str) != 0) {
1920 return (1);
1921 }
1922
1923 return (0);
1924}
1925
34dc7c2f
BB
1926/*
1927 * zpool export [-f] <pool> ...
1928 *
859735c0 1929 * -a Export all pools
34dc7c2f
BB
1930 * -f Forcefully unmount datasets
1931 *
1932 * Export the given pools. By default, the command will attempt to cleanly
1933 * unmount any active datasets within the pool. If the '-f' flag is specified,
1934 * then the datasets will be forcefully unmounted.
1935 */
1936int
1937zpool_do_export(int argc, char **argv)
1938{
859735c0
TF
1939 export_cbdata_t cb;
1940 boolean_t do_all = B_FALSE;
34dc7c2f 1941 boolean_t force = B_FALSE;
fb5f0bc8 1942 boolean_t hardforce = B_FALSE;
859735c0 1943 int c, ret;
34dc7c2f
BB
1944
1945 /* check options */
859735c0 1946 while ((c = getopt(argc, argv, "afF")) != -1) {
34dc7c2f 1947 switch (c) {
859735c0
TF
1948 case 'a':
1949 do_all = B_TRUE;
1950 break;
34dc7c2f
BB
1951 case 'f':
1952 force = B_TRUE;
1953 break;
fb5f0bc8
BB
1954 case 'F':
1955 hardforce = B_TRUE;
1956 break;
34dc7c2f
BB
1957 case '?':
1958 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1959 optopt);
1960 usage(B_FALSE);
1961 }
1962 }
1963
859735c0
TF
1964 cb.force = force;
1965 cb.hardforce = hardforce;
34dc7c2f
BB
1966 argc -= optind;
1967 argv += optind;
1968
859735c0
TF
1969 if (do_all) {
1970 if (argc != 0) {
1971 (void) fprintf(stderr, gettext("too many arguments\n"));
1972 usage(B_FALSE);
1973 }
1974
1975 return (for_each_pool(argc, argv, B_TRUE, NULL,
2a673e76 1976 ZFS_TYPE_POOL, B_FALSE, zpool_export_one, &cb));
859735c0
TF
1977 }
1978
34dc7c2f
BB
1979 /* check arguments */
1980 if (argc < 1) {
1981 (void) fprintf(stderr, gettext("missing pool argument\n"));
1982 usage(B_FALSE);
1983 }
1984
2a673e76
AJ
1985 ret = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
1986 B_FALSE, zpool_export_one, &cb);
34dc7c2f
BB
1987
1988 return (ret);
1989}
1990
1991/*
1992 * Given a vdev configuration, determine the maximum width needed for the device
1993 * name column.
1994 */
1995static int
d2f3e292
RY
1996max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1997 int name_flags)
34dc7c2f 1998{
e9072c76
AZ
1999 static const char *const subtypes[] =
2000 {ZPOOL_CONFIG_SPARES, ZPOOL_CONFIG_L2CACHE, ZPOOL_CONFIG_CHILDREN};
34dc7c2f 2001
e9072c76
AZ
2002 char *name = zpool_vdev_name(g_zfs, zhp, nv, name_flags);
2003 max = MAX(strlen(name) + depth, max);
34dc7c2f
BB
2004 free(name);
2005
e9072c76
AZ
2006 nvlist_t **child;
2007 uint_t children;
2008 for (size_t i = 0; i < ARRAY_SIZE(subtypes); ++i)
2009 if (nvlist_lookup_nvlist_array(nv, subtypes[i],
2010 &child, &children) == 0)
2011 for (uint_t c = 0; c < children; ++c)
2012 max = MAX(max_width(zhp, child[c], depth + 2,
2013 max, name_flags), max);
34dc7c2f 2014
34dc7c2f
BB
2015 return (max);
2016}
2017
9babb374
BB
2018typedef struct spare_cbdata {
2019 uint64_t cb_guid;
2020 zpool_handle_t *cb_zhp;
2021} spare_cbdata_t;
2022
2023static boolean_t
2024find_vdev(nvlist_t *nv, uint64_t search)
2025{
2026 uint64_t guid;
2027 nvlist_t **child;
2028 uint_t c, children;
2029
2030 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2031 search == guid)
2032 return (B_TRUE);
2033
2034 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2035 &child, &children) == 0) {
2036 for (c = 0; c < children; c++)
2037 if (find_vdev(child[c], search))
2038 return (B_TRUE);
2039 }
2040
2041 return (B_FALSE);
2042}
2043
2044static int
2045find_spare(zpool_handle_t *zhp, void *data)
2046{
2047 spare_cbdata_t *cbp = data;
2048 nvlist_t *config, *nvroot;
2049
2050 config = zpool_get_config(zhp, NULL);
2051 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2052 &nvroot) == 0);
2053
2054 if (find_vdev(nvroot, cbp->cb_guid)) {
2055 cbp->cb_zhp = zhp;
2056 return (1);
2057 }
2058
2059 zpool_close(zhp);
2060 return (0);
2061}
2062
fea33e4e
HJ
2063typedef struct status_cbdata {
2064 int cb_count;
2065 int cb_name_flags;
2066 int cb_namewidth;
2067 boolean_t cb_allpools;
2068 boolean_t cb_verbose;
ad796b8a 2069 boolean_t cb_literal;
fea33e4e
HJ
2070 boolean_t cb_explain;
2071 boolean_t cb_first;
2072 boolean_t cb_dedup_stats;
2073 boolean_t cb_print_status;
ad796b8a 2074 boolean_t cb_print_slow_ios;
a769fb53 2075 boolean_t cb_print_vdev_init;
1b939560 2076 boolean_t cb_print_vdev_trim;
8720e9e7 2077 vdev_cmd_data_list_t *vcdl;
fea33e4e
HJ
2078} status_cbdata_t;
2079
d6418de0 2080/* Return 1 if string is NULL, empty, or whitespace; return 0 otherwise. */
a926aab9
AZ
2081static boolean_t
2082is_blank_str(const char *str)
d6418de0 2083{
a926aab9 2084 for (; str != NULL && *str != '\0'; ++str)
d6418de0 2085 if (!isblank(*str))
a926aab9
AZ
2086 return (B_FALSE);
2087 return (B_TRUE);
d6418de0
TH
2088}
2089
2090/* Print command output lines for specific vdev in a specific pool */
8720e9e7 2091static void
d1807f16 2092zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, const char *path)
8720e9e7 2093{
d6418de0
TH
2094 vdev_cmd_data_t *data;
2095 int i, j;
a926aab9 2096 const char *val;
d6418de0 2097
8720e9e7 2098 for (i = 0; i < vcdl->count; i++) {
d6418de0
TH
2099 if ((strcmp(vcdl->data[i].path, path) != 0) ||
2100 (strcmp(vcdl->data[i].pool, pool) != 0)) {
2101 /* Not the vdev we're looking for */
2102 continue;
8720e9e7 2103 }
d6418de0
TH
2104
2105 data = &vcdl->data[i];
2106 /* Print out all the output values for this vdev */
2107 for (j = 0; j < vcdl->uniq_cols_cnt; j++) {
2108 val = NULL;
2109 /* Does this vdev have values for this column? */
2110 for (int k = 0; k < data->cols_cnt; k++) {
2111 if (strcmp(data->cols[k],
2112 vcdl->uniq_cols[j]) == 0) {
2113 /* yes it does, record the value */
2114 val = data->lines[k];
2115 break;
2116 }
2117 }
2118 /*
2119 * Mark empty values with dashes to make output
2120 * awk-able.
2121 */
7454d2bb 2122 if (val == NULL || is_blank_str(val))
d6418de0
TH
2123 val = "-";
2124
2125 printf("%*s", vcdl->uniq_cols_width[j], val);
2126 if (j < vcdl->uniq_cols_cnt - 1)
a926aab9 2127 fputs(" ", stdout);
d6418de0
TH
2128 }
2129
2130 /* Print out any values that aren't in a column at the end */
2131 for (j = data->cols_cnt; j < data->lines_cnt; j++) {
2132 /* Did we have any columns? If so print a spacer. */
2133 if (vcdl->uniq_cols_cnt > 0)
a926aab9 2134 fputs(" ", stdout);
d6418de0
TH
2135
2136 val = data->lines[j];
a926aab9 2137 fputs(val ?: "", stdout);
d6418de0
TH
2138 }
2139 break;
8720e9e7
TH
2140 }
2141}
2142
1b939560
BB
2143/*
2144 * Print vdev initialization status for leaves
2145 */
2146static void
2147print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
2148{
2149 if (verbose) {
2150 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
2151 vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
2152 vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
2153 !vs->vs_scan_removing) {
2154 char zbuf[1024];
2155 char tbuf[256];
2156 struct tm zaction_ts;
2157
2158 time_t t = vs->vs_initialize_action_time;
2159 int initialize_pct = 100;
2160 if (vs->vs_initialize_state !=
2161 VDEV_INITIALIZE_COMPLETE) {
2162 initialize_pct = (vs->vs_initialize_bytes_done *
2163 100 / (vs->vs_initialize_bytes_est + 1));
2164 }
2165
2166 (void) localtime_r(&t, &zaction_ts);
2167 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
2168
2169 switch (vs->vs_initialize_state) {
2170 case VDEV_INITIALIZE_SUSPENDED:
2171 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2172 gettext("suspended, started at"), tbuf);
2173 break;
2174 case VDEV_INITIALIZE_ACTIVE:
2175 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2176 gettext("started at"), tbuf);
2177 break;
2178 case VDEV_INITIALIZE_COMPLETE:
2179 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2180 gettext("completed at"), tbuf);
2181 break;
2182 }
2183
2184 (void) printf(gettext(" (%d%% initialized%s)"),
2185 initialize_pct, zbuf);
2186 } else {
2187 (void) printf(gettext(" (uninitialized)"));
2188 }
2189 } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) {
2190 (void) printf(gettext(" (initializing)"));
2191 }
2192}
2193
2194/*
2195 * Print vdev TRIM status for leaves
2196 */
2197static void
2198print_status_trim(vdev_stat_t *vs, boolean_t verbose)
2199{
2200 if (verbose) {
2201 if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE ||
2202 vs->vs_trim_state == VDEV_TRIM_SUSPENDED ||
2203 vs->vs_trim_state == VDEV_TRIM_COMPLETE) &&
2204 !vs->vs_scan_removing) {
2205 char zbuf[1024];
2206 char tbuf[256];
2207 struct tm zaction_ts;
2208
2209 time_t t = vs->vs_trim_action_time;
2210 int trim_pct = 100;
2211 if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) {
2212 trim_pct = (vs->vs_trim_bytes_done *
2213 100 / (vs->vs_trim_bytes_est + 1));
2214 }
2215
2216 (void) localtime_r(&t, &zaction_ts);
2217 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
2218
2219 switch (vs->vs_trim_state) {
2220 case VDEV_TRIM_SUSPENDED:
2221 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2222 gettext("suspended, started at"), tbuf);
2223 break;
2224 case VDEV_TRIM_ACTIVE:
2225 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2226 gettext("started at"), tbuf);
2227 break;
2228 case VDEV_TRIM_COMPLETE:
2229 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
2230 gettext("completed at"), tbuf);
2231 break;
2232 }
2233
2234 (void) printf(gettext(" (%d%% trimmed%s)"),
2235 trim_pct, zbuf);
2236 } else if (vs->vs_trim_notsup) {
2237 (void) printf(gettext(" (trim unsupported)"));
2238 } else {
2239 (void) printf(gettext(" (untrimmed)"));
2240 }
2241 } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) {
2242 (void) printf(gettext(" (trimming)"));
2243 }
2244}
2245
9fb2771a
TH
2246/*
2247 * Return the color associated with a health string. This includes returning
2248 * NULL for no color change.
2249 */
a926aab9 2250static const char *
9fb2771a
TH
2251health_str_to_color(const char *health)
2252{
2253 if (strcmp(health, gettext("FAULTED")) == 0 ||
2254 strcmp(health, gettext("SUSPENDED")) == 0 ||
2255 strcmp(health, gettext("UNAVAIL")) == 0) {
2256 return (ANSI_RED);
2257 }
2258
2259 if (strcmp(health, gettext("OFFLINE")) == 0 ||
2260 strcmp(health, gettext("DEGRADED")) == 0 ||
2261 strcmp(health, gettext("REMOVED")) == 0) {
2262 return (ANSI_YELLOW);
2263 }
2264
2265 return (NULL);
2266}
2267
9babb374
BB
2268/*
2269 * Print out configuration state as requested by status_callback.
2270 */
d2f3e292 2271static void
fea33e4e 2272print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
9a49d3f3 2273 nvlist_t *nv, int depth, boolean_t isspare, vdev_rebuild_stat_t *vrs)
9babb374 2274{
2ef0f8c3 2275 nvlist_t **child, *root;
6fe3498c 2276 uint_t c, i, vsc, children;
428870ff 2277 pool_scan_stat_t *ps = NULL;
9babb374 2278 vdev_stat_t *vs;
428870ff 2279 char rbuf[6], wbuf[6], cbuf[6];
9babb374
BB
2280 char *vname;
2281 uint64_t notpresent;
fea33e4e 2282 spare_cbdata_t spare_cb;
6b8655ad 2283 const char *state;
d1807f16
RY
2284 const char *type;
2285 const char *path = NULL;
a926aab9 2286 const char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL;
9babb374 2287
9babb374
BB
2288 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2289 &child, &children) != 0)
2290 children = 0;
2291
428870ff 2292 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
6fe3498c 2293 (uint64_t **)&vs, &vsc) == 0);
428870ff 2294
a1d477c2
MA
2295 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
2296
2297 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
2298 return;
2299
9babb374 2300 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
9fb2771a 2301
9babb374
BB
2302 if (isspare) {
2303 /*
2304 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2305 * online drives.
2306 */
2307 if (vs->vs_aux == VDEV_AUX_SPARED)
9fb2771a 2308 state = gettext("INUSE");
9babb374 2309 else if (vs->vs_state == VDEV_STATE_HEALTHY)
9fb2771a 2310 state = gettext("AVAIL");
9babb374
BB
2311 }
2312
9fb2771a
TH
2313 printf_color(health_str_to_color(state),
2314 "\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
9babb374
BB
2315 name, state);
2316
2317 if (!isspare) {
9fb2771a
TH
2318 if (vs->vs_read_errors)
2319 rcolor = ANSI_RED;
2320
2321 if (vs->vs_write_errors)
2322 wcolor = ANSI_RED;
2323
2324 if (vs->vs_checksum_errors)
2325 ccolor = ANSI_RED;
2326
ad796b8a 2327 if (cb->cb_literal) {
a926aab9 2328 fputc(' ', stdout);
9fb2771a
TH
2329 printf_color(rcolor, "%5llu",
2330 (u_longlong_t)vs->vs_read_errors);
a926aab9 2331 fputc(' ', stdout);
9fb2771a
TH
2332 printf_color(wcolor, "%5llu",
2333 (u_longlong_t)vs->vs_write_errors);
a926aab9 2334 fputc(' ', stdout);
9fb2771a 2335 printf_color(ccolor, "%5llu",
ad796b8a
TH
2336 (u_longlong_t)vs->vs_checksum_errors);
2337 } else {
2338 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2339 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2340 zfs_nicenum(vs->vs_checksum_errors, cbuf,
2341 sizeof (cbuf));
a926aab9 2342 fputc(' ', stdout);
9fb2771a 2343 printf_color(rcolor, "%5s", rbuf);
a926aab9 2344 fputc(' ', stdout);
9fb2771a 2345 printf_color(wcolor, "%5s", wbuf);
a926aab9 2346 fputc(' ', stdout);
9fb2771a 2347 printf_color(ccolor, "%5s", cbuf);
ad796b8a 2348 }
ad796b8a
TH
2349 if (cb->cb_print_slow_ios) {
2350 if (children == 0) {
2351 /* Only leafs vdevs have slow IOs */
2352 zfs_nicenum(vs->vs_slow_ios, rbuf,
2353 sizeof (rbuf));
2354 } else {
2355 snprintf(rbuf, sizeof (rbuf), "-");
2356 }
2357
2358 if (cb->cb_literal)
2359 printf(" %5llu", (u_longlong_t)vs->vs_slow_ios);
2360 else
2361 printf(" %5s", rbuf);
2362 }
9babb374
BB
2363 }
2364
2365 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2366 &notpresent) == 0) {
9babb374 2367 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
9fb2771a 2368 (void) printf(" %s %s", gettext("was"), path);
9babb374
BB
2369 } else if (vs->vs_aux != 0) {
2370 (void) printf(" ");
9fb2771a 2371 color_start(ANSI_RED);
9babb374
BB
2372 switch (vs->vs_aux) {
2373 case VDEV_AUX_OPEN_FAILED:
2374 (void) printf(gettext("cannot open"));
2375 break;
2376
2377 case VDEV_AUX_BAD_GUID_SUM:
2378 (void) printf(gettext("missing device"));
2379 break;
2380
2381 case VDEV_AUX_NO_REPLICAS:
2382 (void) printf(gettext("insufficient replicas"));
2383 break;
2384
2385 case VDEV_AUX_VERSION_NEWER:
2386 (void) printf(gettext("newer version"));
2387 break;
2388
9ae529ec
CS
2389 case VDEV_AUX_UNSUP_FEAT:
2390 (void) printf(gettext("unsupported feature(s)"));
2391 break;
2392
6fe3498c
RM
2393 case VDEV_AUX_ASHIFT_TOO_BIG:
2394 (void) printf(gettext("unsupported minimum blocksize"));
2395 break;
2396
9babb374
BB
2397 case VDEV_AUX_SPARED:
2398 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
fea33e4e
HJ
2399 &spare_cb.cb_guid) == 0);
2400 if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
2401 if (strcmp(zpool_get_name(spare_cb.cb_zhp),
9babb374
BB
2402 zpool_get_name(zhp)) == 0)
2403 (void) printf(gettext("currently in "
2404 "use"));
2405 else
2406 (void) printf(gettext("in use by "
2407 "pool '%s'"),
fea33e4e
HJ
2408 zpool_get_name(spare_cb.cb_zhp));
2409 zpool_close(spare_cb.cb_zhp);
9babb374
BB
2410 } else {
2411 (void) printf(gettext("currently in use"));
2412 }
2413 break;
2414
2415 case VDEV_AUX_ERR_EXCEEDED:
2416 (void) printf(gettext("too many errors"));
2417 break;
2418
2419 case VDEV_AUX_IO_FAILURE:
2420 (void) printf(gettext("experienced I/O failures"));
2421 break;
2422
2423 case VDEV_AUX_BAD_LOG:
2424 (void) printf(gettext("bad intent log"));
2425 break;
2426
428870ff
BB
2427 case VDEV_AUX_EXTERNAL:
2428 (void) printf(gettext("external device fault"));
2429 break;
2430
2431 case VDEV_AUX_SPLIT_POOL:
2432 (void) printf(gettext("split into new pool"));
2433 break;
2434
379ca9cf
OF
2435 case VDEV_AUX_ACTIVE:
2436 (void) printf(gettext("currently in use"));
4265a929 2437 break;
379ca9cf 2438
6cb8e530
PZ
2439 case VDEV_AUX_CHILDREN_OFFLINE:
2440 (void) printf(gettext("all children offline"));
2441 break;
2442
dce1bf99
VKV
2443 case VDEV_AUX_BAD_LABEL:
2444 (void) printf(gettext("invalid label"));
2445 break;
2446
9babb374
BB
2447 default:
2448 (void) printf(gettext("corrupted data"));
2449 break;
2450 }
9fb2771a 2451 color_end();
3928ec53
CS
2452 } else if (children == 0 && !isspare &&
2453 getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") == NULL &&
2454 VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
2455 vs->vs_configured_ashift < vs->vs_physical_ashift) {
2456 (void) printf(
2457 gettext(" block size: %dB configured, %dB native"),
2458 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
428870ff
BB
2459 }
2460
2a673e76
AJ
2461 if (vs->vs_scan_removing != 0) {
2462 (void) printf(gettext(" (removing)"));
e77d59eb 2463 } else if (VDEV_STAT_VALID(vs_noalloc, vsc) && vs->vs_noalloc != 0) {
2a673e76
AJ
2464 (void) printf(gettext(" (non-allocating)"));
2465 }
2466
2ef0f8c3
TH
2467 /* The root vdev has the scrub/resilver stats */
2468 root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
2469 ZPOOL_CONFIG_VDEV_TREE);
2470 (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
428870ff
BB
2471 (uint64_t **)&ps, &c);
2472
e9b12d41
TH
2473 /*
2474 * If you force fault a drive that's resilvering, its scan stats can
2475 * get frozen in time, giving the false impression that it's
2476 * being resilvered. That's why we check the state to see if the vdev
2477 * is healthy before reporting "resilvering" or "repairing".
2478 */
2479 if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0 &&
2480 vs->vs_state == VDEV_STATE_HEALTHY) {
80a91e74
TC
2481 if (vs->vs_scan_processed != 0) {
2482 (void) printf(gettext(" (%s)"),
2483 (ps->pss_func == POOL_SCAN_RESILVER) ?
2484 "resilvering" : "repairing");
2485 } else if (vs->vs_resilver_deferred) {
2486 (void) printf(gettext(" (awaiting resilver)"));
2487 }
9babb374
BB
2488 }
2489
9a49d3f3
BB
2490 /* The top-level vdevs have the rebuild stats */
2491 if (vrs != NULL && vrs->vrs_state == VDEV_REBUILD_ACTIVE &&
e9b12d41 2492 children == 0 && vs->vs_state == VDEV_STATE_HEALTHY) {
9a49d3f3
BB
2493 if (vs->vs_rebuild_processed != 0) {
2494 (void) printf(gettext(" (resilvering)"));
2495 }
2496 }
2497
8720e9e7
TH
2498 if (cb->vcdl != NULL) {
2499 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
2500 printf(" ");
2501 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path);
2502 }
2503 }
2504
b2255edc 2505 /* Display vdev initialization and trim status for leaves. */
1b939560
BB
2506 if (children == 0) {
2507 print_status_initialize(vs, cb->cb_print_vdev_init);
2508 print_status_trim(vs, cb->cb_print_vdev_trim);
619f0976
GW
2509 }
2510
9babb374
BB
2511 (void) printf("\n");
2512
2513 for (c = 0; c < children; c++) {
428870ff 2514 uint64_t islog = B_FALSE, ishole = B_FALSE;
9babb374 2515
428870ff 2516 /* Don't print logs or holes here */
9babb374 2517 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
428870ff
BB
2518 &islog);
2519 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
2520 &ishole);
2521 if (islog || ishole)
9babb374 2522 continue;
cc99f275
DB
2523 /* Only print normal classes here */
2524 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2525 continue;
2526
9a49d3f3
BB
2527 /* Provide vdev_rebuild_stats to children if available */
2528 if (vrs == NULL) {
2529 (void) nvlist_lookup_uint64_array(nv,
2530 ZPOOL_CONFIG_REBUILD_STATS,
2531 (uint64_t **)&vrs, &i);
2532 }
2533
d2f3e292 2534 vname = zpool_vdev_name(g_zfs, zhp, child[c],
fea33e4e
HJ
2535 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2536 print_status_config(zhp, cb, vname, child[c], depth + 2,
9a49d3f3 2537 isspare, vrs);
9babb374
BB
2538 free(vname);
2539 }
2540}
2541
34dc7c2f
BB
2542/*
2543 * Print the configuration of an exported pool. Iterate over all vdevs in the
2544 * pool, printing out the name and status for each one.
2545 */
d2f3e292 2546static void
fea33e4e
HJ
2547print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
2548 int depth)
34dc7c2f
BB
2549{
2550 nvlist_t **child;
2551 uint_t c, children;
2552 vdev_stat_t *vs;
d1807f16
RY
2553 const char *type;
2554 char *vname;
34dc7c2f
BB
2555
2556 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
428870ff
BB
2557 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
2558 strcmp(type, VDEV_TYPE_HOLE) == 0)
34dc7c2f
BB
2559 return;
2560
428870ff 2561 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
2562 (uint64_t **)&vs, &c) == 0);
2563
fea33e4e 2564 (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
34dc7c2f
BB
2565 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
2566
2567 if (vs->vs_aux != 0) {
2568 (void) printf(" ");
2569
2570 switch (vs->vs_aux) {
2571 case VDEV_AUX_OPEN_FAILED:
2572 (void) printf(gettext("cannot open"));
2573 break;
2574
2575 case VDEV_AUX_BAD_GUID_SUM:
2576 (void) printf(gettext("missing device"));
2577 break;
2578
2579 case VDEV_AUX_NO_REPLICAS:
2580 (void) printf(gettext("insufficient replicas"));
2581 break;
2582
2583 case VDEV_AUX_VERSION_NEWER:
2584 (void) printf(gettext("newer version"));
2585 break;
2586
9ae529ec
CS
2587 case VDEV_AUX_UNSUP_FEAT:
2588 (void) printf(gettext("unsupported feature(s)"));
2589 break;
2590
34dc7c2f
BB
2591 case VDEV_AUX_ERR_EXCEEDED:
2592 (void) printf(gettext("too many errors"));
2593 break;
2594
379ca9cf
OF
2595 case VDEV_AUX_ACTIVE:
2596 (void) printf(gettext("currently in use"));
2597 break;
2598
6cb8e530
PZ
2599 case VDEV_AUX_CHILDREN_OFFLINE:
2600 (void) printf(gettext("all children offline"));
2601 break;
2602
dce1bf99
VKV
2603 case VDEV_AUX_BAD_LABEL:
2604 (void) printf(gettext("invalid label"));
2605 break;
2606
34dc7c2f
BB
2607 default:
2608 (void) printf(gettext("corrupted data"));
2609 break;
2610 }
2611 }
2612 (void) printf("\n");
2613
2614 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2615 &child, &children) != 0)
2616 return;
2617
2618 for (c = 0; c < children; c++) {
2619 uint64_t is_log = B_FALSE;
2620
2621 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2622 &is_log);
9babb374 2623 if (is_log)
34dc7c2f 2624 continue;
cc99f275
DB
2625 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2626 continue;
34dc7c2f 2627
d2f3e292 2628 vname = zpool_vdev_name(g_zfs, NULL, child[c],
fea33e4e
HJ
2629 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2630 print_import_config(cb, vname, child[c], depth + 2);
34dc7c2f
BB
2631 free(vname);
2632 }
2633
2634 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2635 &child, &children) == 0) {
2636 (void) printf(gettext("\tcache\n"));
2637 for (c = 0; c < children; c++) {
d2f3e292 2638 vname = zpool_vdev_name(g_zfs, NULL, child[c],
fea33e4e 2639 cb->cb_name_flags);
34dc7c2f
BB
2640 (void) printf("\t %s\n", vname);
2641 free(vname);
2642 }
2643 }
2644
2645 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2646 &child, &children) == 0) {
2647 (void) printf(gettext("\tspares\n"));
2648 for (c = 0; c < children; c++) {
d2f3e292 2649 vname = zpool_vdev_name(g_zfs, NULL, child[c],
fea33e4e 2650 cb->cb_name_flags);
34dc7c2f
BB
2651 (void) printf("\t %s\n", vname);
2652 free(vname);
2653 }
2654 }
2655}
2656
9babb374 2657/*
cc99f275
DB
2658 * Print specialized class vdevs.
2659 *
2660 * These are recorded as top level vdevs in the main pool child array
2661 * but with "is_log" set to 1 or an "alloc_bias" string. We use either
2662 * print_status_config() or print_import_config() to print the top level
2663 * class vdevs then any of their children (eg mirrored slogs) are printed
2664 * recursively - which works because only the top level vdev is marked.
9babb374
BB
2665 */
2666static void
cc99f275
DB
2667print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
2668 const char *class)
9babb374
BB
2669{
2670 uint_t c, children;
2671 nvlist_t **child;
cc99f275
DB
2672 boolean_t printed = B_FALSE;
2673
2674 assert(zhp != NULL || !cb->cb_verbose);
9babb374
BB
2675
2676 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
2677 &children) != 0)
2678 return;
2679
9babb374
BB
2680 for (c = 0; c < children; c++) {
2681 uint64_t is_log = B_FALSE;
d1807f16
RY
2682 const char *bias = NULL;
2683 const char *type = NULL;
9babb374
BB
2684
2685 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2686 &is_log);
cc99f275
DB
2687
2688 if (is_log) {
a926aab9 2689 bias = (char *)VDEV_ALLOC_CLASS_LOGS;
cc99f275
DB
2690 } else {
2691 (void) nvlist_lookup_string(child[c],
2692 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
2693 (void) nvlist_lookup_string(child[c],
2694 ZPOOL_CONFIG_TYPE, &type);
2695 }
2696
2697 if (bias == NULL || strcmp(bias, class) != 0)
2698 continue;
2699 if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
9babb374 2700 continue;
cc99f275
DB
2701
2702 if (!printed) {
2703 (void) printf("\t%s\t\n", gettext(class));
2704 printed = B_TRUE;
2705 }
2706
2707 char *name = zpool_vdev_name(g_zfs, zhp, child[c],
fea33e4e
HJ
2708 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2709 if (cb->cb_print_status)
2710 print_status_config(zhp, cb, name, child[c], 2,
9a49d3f3 2711 B_FALSE, NULL);
9babb374 2712 else
fea33e4e 2713 print_import_config(cb, name, child[c], 2);
9babb374
BB
2714 free(name);
2715 }
2716}
428870ff 2717
34dc7c2f
BB
2718/*
2719 * Display the status for the given pool.
2720 */
0936981d
GW
2721static int
2722show_import(nvlist_t *config, boolean_t report_error)
34dc7c2f
BB
2723{
2724 uint64_t pool_state;
2725 vdev_stat_t *vs;
d1807f16 2726 const char *name;
34dc7c2f 2727 uint64_t guid;
379ca9cf 2728 uint64_t hostid = 0;
a926aab9
AZ
2729 const char *msgid;
2730 const char *hostname = "unknown";
379ca9cf 2731 nvlist_t *nvroot, *nvinfo;
731782ec 2732 zpool_status_t reason;
ffe9d382 2733 zpool_errata_t errata;
34dc7c2f
BB
2734 const char *health;
2735 uint_t vsc;
d1807f16 2736 const char *comment;
fea33e4e 2737 status_cbdata_t cb = { 0 };
34dc7c2f
BB
2738
2739 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2740 &name) == 0);
2741 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2742 &guid) == 0);
2743 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2744 &pool_state) == 0);
2745 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2746 &nvroot) == 0);
2747
428870ff 2748 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
2749 (uint64_t **)&vs, &vsc) == 0);
2750 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2751
ffe9d382 2752 reason = zpool_import_status(config, &msgid, &errata);
34dc7c2f 2753
0936981d
GW
2754 /*
2755 * If we're importing using a cachefile, then we won't report any
2756 * errors unless we are in the scan phase of the import.
2757 */
2758 if (reason != ZPOOL_STATUS_OK && !report_error)
2759 return (reason);
2760
d96eb2b1
DM
2761 (void) printf(gettext(" pool: %s\n"), name);
2762 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
2763 (void) printf(gettext(" state: %s"), health);
34dc7c2f
BB
2764 if (pool_state == POOL_STATE_DESTROYED)
2765 (void) printf(gettext(" (DESTROYED)"));
2766 (void) printf("\n");
2767
2768 switch (reason) {
2769 case ZPOOL_STATUS_MISSING_DEV_R:
2770 case ZPOOL_STATUS_MISSING_DEV_NR:
2771 case ZPOOL_STATUS_BAD_GUID_SUM:
9fb2771a
TH
2772 printf_color(ANSI_BOLD, gettext("status: "));
2773 printf_color(ANSI_YELLOW, gettext("One or more devices are "
d96eb2b1 2774 "missing from the system.\n"));
34dc7c2f
BB
2775 break;
2776
2777 case ZPOOL_STATUS_CORRUPT_LABEL_R:
2778 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
9fb2771a
TH
2779 printf_color(ANSI_BOLD, gettext("status: "));
2780 printf_color(ANSI_YELLOW, gettext("One or more devices contains"
2781 " corrupted data.\n"));
34dc7c2f
BB
2782 break;
2783
2784 case ZPOOL_STATUS_CORRUPT_DATA:
d96eb2b1
DM
2785 (void) printf(
2786 gettext(" status: The pool data is corrupted.\n"));
34dc7c2f
BB
2787 break;
2788
2789 case ZPOOL_STATUS_OFFLINE_DEV:
9fb2771a
TH
2790 printf_color(ANSI_BOLD, gettext("status: "));
2791 printf_color(ANSI_YELLOW, gettext("One or more devices "
34dc7c2f
BB
2792 "are offlined.\n"));
2793 break;
2794
2795 case ZPOOL_STATUS_CORRUPT_POOL:
9fb2771a
TH
2796 printf_color(ANSI_BOLD, gettext("status: "));
2797 printf_color(ANSI_YELLOW, gettext("The pool metadata is "
34dc7c2f
BB
2798 "corrupted.\n"));
2799 break;
2800
2801 case ZPOOL_STATUS_VERSION_OLDER:
9fb2771a
TH
2802 printf_color(ANSI_BOLD, gettext("status: "));
2803 printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
2804 "a legacy on-disk version.\n"));
34dc7c2f
BB
2805 break;
2806
2807 case ZPOOL_STATUS_VERSION_NEWER:
9fb2771a
TH
2808 printf_color(ANSI_BOLD, gettext("status: "));
2809 printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
2810 "an incompatible version.\n"));
34dc7c2f 2811 break;
b128c09f 2812
b9b24bb4 2813 case ZPOOL_STATUS_FEAT_DISABLED:
9fb2771a 2814 printf_color(ANSI_BOLD, gettext("status: "));
e086db16
CB
2815 printf_color(ANSI_YELLOW, gettext("Some supported "
2816 "features are not enabled on the pool.\n\t"
2817 "(Note that they may be intentionally disabled "
2818 "if the\n\t'compatibility' property is set.)\n"));
658fb802
CB
2819 break;
2820
2821 case ZPOOL_STATUS_COMPATIBILITY_ERR:
2822 printf_color(ANSI_BOLD, gettext("status: "));
2823 printf_color(ANSI_YELLOW, gettext("Error reading or parsing "
2824 "the file(s) indicated by the 'compatibility'\n"
2825 "property.\n"));
b9b24bb4
CS
2826 break;
2827
e086db16
CB
2828 case ZPOOL_STATUS_INCOMPATIBLE_FEAT:
2829 printf_color(ANSI_BOLD, gettext("status: "));
2830 printf_color(ANSI_YELLOW, gettext("One or more features "
2831 "are enabled on the pool despite not being\n"
2832 "requested by the 'compatibility' property.\n"));
2833 break;
2834
9ae529ec 2835 case ZPOOL_STATUS_UNSUP_FEAT_READ:
9fb2771a
TH
2836 printf_color(ANSI_BOLD, gettext("status: "));
2837 printf_color(ANSI_YELLOW, gettext("The pool uses the following "
4e33ba4c 2838 "feature(s) not supported on this system:\n"));
9fb2771a 2839 color_start(ANSI_YELLOW);
9ae529ec 2840 zpool_print_unsup_feat(config);
9fb2771a 2841 color_end();
9ae529ec
CS
2842 break;
2843
2844 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
9fb2771a
TH
2845 printf_color(ANSI_BOLD, gettext("status: "));
2846 printf_color(ANSI_YELLOW, gettext("The pool can only be "
2847 "accessed in read-only mode on this system. It\n\tcannot be"
2848 " accessed in read-write mode because it uses the "
9ae529ec 2849 "following\n\tfeature(s) not supported on this system:\n"));
9fb2771a 2850 color_start(ANSI_YELLOW);
9ae529ec 2851 zpool_print_unsup_feat(config);
9fb2771a 2852 color_end();
9ae529ec
CS
2853 break;
2854
379ca9cf 2855 case ZPOOL_STATUS_HOSTID_ACTIVE:
9fb2771a
TH
2856 printf_color(ANSI_BOLD, gettext("status: "));
2857 printf_color(ANSI_YELLOW, gettext("The pool is currently "
379ca9cf
OF
2858 "imported by another system.\n"));
2859 break;
2860
2861 case ZPOOL_STATUS_HOSTID_REQUIRED:
9fb2771a
TH
2862 printf_color(ANSI_BOLD, gettext("status: "));
2863 printf_color(ANSI_YELLOW, gettext("The pool has the "
379ca9cf
OF
2864 "multihost property on. It cannot\n\tbe safely imported "
2865 "when the system hostid is not set.\n"));
2866 break;
2867
34dc7c2f 2868 case ZPOOL_STATUS_HOSTID_MISMATCH:
9fb2771a
TH
2869 printf_color(ANSI_BOLD, gettext("status: "));
2870 printf_color(ANSI_YELLOW, gettext("The pool was last accessed "
2871 "by another system.\n"));
34dc7c2f 2872 break;
b128c09f 2873
34dc7c2f
BB
2874 case ZPOOL_STATUS_FAULTED_DEV_R:
2875 case ZPOOL_STATUS_FAULTED_DEV_NR:
9fb2771a
TH
2876 printf_color(ANSI_BOLD, gettext("status: "));
2877 printf_color(ANSI_YELLOW, gettext("One or more devices are "
34dc7c2f
BB
2878 "faulted.\n"));
2879 break;
2880
b128c09f 2881 case ZPOOL_STATUS_BAD_LOG:
9fb2771a
TH
2882 printf_color(ANSI_BOLD, gettext("status: "));
2883 printf_color(ANSI_YELLOW, gettext("An intent log record cannot "
2884 "be read.\n"));
b128c09f
BB
2885 break;
2886
428870ff 2887 case ZPOOL_STATUS_RESILVERING:
9a49d3f3 2888 case ZPOOL_STATUS_REBUILDING:
9fb2771a
TH
2889 printf_color(ANSI_BOLD, gettext("status: "));
2890 printf_color(ANSI_YELLOW, gettext("One or more devices were "
2891 "being resilvered.\n"));
428870ff
BB
2892 break;
2893
ffe9d382 2894 case ZPOOL_STATUS_ERRATA:
9fb2771a
TH
2895 printf_color(ANSI_BOLD, gettext("status: "));
2896 printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
ffe9d382
BB
2897 errata);
2898 break;
2899
c494aa7f
GW
2900 case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
2901 printf_color(ANSI_BOLD, gettext("status: "));
2902 printf_color(ANSI_YELLOW, gettext("One or more devices are "
2903 "configured to use a non-native block size.\n"
2904 "\tExpect reduced performance.\n"));
2905 break;
2906
34dc7c2f
BB
2907 default:
2908 /*
2909 * No other status can be seen when importing pools.
2910 */
2911 assert(reason == ZPOOL_STATUS_OK);
2912 }
2913
2914 /*
2915 * Print out an action according to the overall state of the pool.
2916 */
2917 if (vs->vs_state == VDEV_STATE_HEALTHY) {
b9b24bb4
CS
2918 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2919 reason == ZPOOL_STATUS_FEAT_DISABLED) {
d96eb2b1 2920 (void) printf(gettext(" action: The pool can be "
34dc7c2f
BB
2921 "imported using its name or numeric identifier, "
2922 "though\n\tsome features will not be available "
2923 "without an explicit 'zpool upgrade'.\n"));
658fb802
CB
2924 } else if (reason == ZPOOL_STATUS_COMPATIBILITY_ERR) {
2925 (void) printf(gettext(" action: The pool can be "
2926 "imported using its name or numeric\n\tidentifier, "
2927 "though the file(s) indicated by its "
2928 "'compatibility'\n\tproperty cannot be parsed at "
2929 "this time.\n"));
b9b24bb4 2930 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
d96eb2b1 2931 (void) printf(gettext(" action: The pool can be "
34dc7c2f
BB
2932 "imported using its name or numeric "
2933 "identifier and\n\tthe '-f' flag.\n"));
ffe9d382
BB
2934 } else if (reason == ZPOOL_STATUS_ERRATA) {
2935 switch (errata) {
2936 case ZPOOL_ERRATA_NONE:
2937 break;
2938
4f2dcb3e
RY
2939 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
2940 (void) printf(gettext(" action: The pool can "
2941 "be imported using its name or numeric "
2942 "identifier,\n\thowever there is a compat"
2943 "ibility issue which should be corrected"
2944 "\n\tby running 'zpool scrub'\n"));
2945 break;
2946
2947 case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
2948 (void) printf(gettext(" action: The pool can"
2949 "not be imported with this version of ZFS "
2950 "due to\n\tan active asynchronous destroy. "
2951 "Revert to an earlier version\n\tand "
2952 "allow the destroy to complete before "
2953 "updating.\n"));
2954 break;
2955
ae76f45c
TC
2956 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
2957 (void) printf(gettext(" action: Existing "
2958 "encrypted datasets contain an on-disk "
2959 "incompatibility, which\n\tneeds to be "
2960 "corrected. Backup these datasets to new "
2961 "encrypted datasets\n\tand destroy the "
2962 "old ones.\n"));
2963 break;
2964
f00ab3f2 2965 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
b3b60984
JS
2966 (void) printf(gettext(" action: Existing "
2967 "encrypted snapshots and bookmarks contain "
2968 "an on-disk\n\tincompatibility. This may "
e2dddb7e
JS
2969 "cause on-disk corruption if they are used"
2970 "\n\twith 'zfs recv'. To correct the "
2971 "issue, enable the bookmark_v2 feature.\n\t"
2972 "No additional action is needed if there "
2973 "are no encrypted snapshots or\n\t"
2974 "bookmarks. If preserving the encrypted "
2975 "snapshots and bookmarks is\n\trequired, "
2976 "use a non-raw send to backup and restore "
2977 "them. Alternately,\n\tthey may be removed"
2978 " to resolve the incompatibility.\n"));
f00ab3f2 2979 break;
ffe9d382
BB
2980 default:
2981 /*
2982 * All errata must contain an action message.
2983 */
2984 assert(0);
2985 }
b9b24bb4 2986 } else {
d96eb2b1 2987 (void) printf(gettext(" action: The pool can be "
34dc7c2f
BB
2988 "imported using its name or numeric "
2989 "identifier.\n"));
b9b24bb4 2990 }
34dc7c2f 2991 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
d96eb2b1 2992 (void) printf(gettext(" action: The pool can be imported "
34dc7c2f
BB
2993 "despite missing or damaged devices. The\n\tfault "
2994 "tolerance of the pool may be compromised if imported.\n"));
2995 } else {
2996 switch (reason) {
2997 case ZPOOL_STATUS_VERSION_NEWER:
d96eb2b1 2998 (void) printf(gettext(" action: The pool cannot be "
34dc7c2f
BB
2999 "imported. Access the pool on a system running "
3000 "newer\n\tsoftware, or recreate the pool from "
3001 "backup.\n"));
3002 break;
9ae529ec 3003 case ZPOOL_STATUS_UNSUP_FEAT_READ:
9fb2771a
TH
3004 printf_color(ANSI_BOLD, gettext("action: "));
3005 printf_color(ANSI_YELLOW, gettext("The pool cannot be "
9ae529ec
CS
3006 "imported. Access the pool on a system that "
3007 "supports\n\tthe required feature(s), or recreate "
3008 "the pool from backup.\n"));
3009 break;
3010 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
9fb2771a
TH
3011 printf_color(ANSI_BOLD, gettext("action: "));
3012 printf_color(ANSI_YELLOW, gettext("The pool cannot be "
9ae529ec
CS
3013 "imported in read-write mode. Import the pool "
3014 "with\n"
3015 "\t\"-o readonly=on\", access the pool on a system "
3016 "that supports the\n\trequired feature(s), or "
3017 "recreate the pool from backup.\n"));
3018 break;
34dc7c2f
BB
3019 case ZPOOL_STATUS_MISSING_DEV_R:
3020 case ZPOOL_STATUS_MISSING_DEV_NR:
3021 case ZPOOL_STATUS_BAD_GUID_SUM:
d96eb2b1 3022 (void) printf(gettext(" action: The pool cannot be "
34dc7c2f
BB
3023 "imported. Attach the missing\n\tdevices and try "
3024 "again.\n"));
3025 break;
379ca9cf
OF
3026 case ZPOOL_STATUS_HOSTID_ACTIVE:
3027 VERIFY0(nvlist_lookup_nvlist(config,
3028 ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
3029
3030 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
3031 hostname = fnvlist_lookup_string(nvinfo,
3032 ZPOOL_CONFIG_MMP_HOSTNAME);
3033
3034 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
3035 hostid = fnvlist_lookup_uint64(nvinfo,
3036 ZPOOL_CONFIG_MMP_HOSTID);
3037
3038 (void) printf(gettext(" action: The pool must be "
bde0f7d4
AZ
3039 "exported from %s (hostid=%"PRIx64")\n\tbefore it "
3040 "can be safely imported.\n"), hostname, hostid);
379ca9cf
OF
3041 break;
3042 case ZPOOL_STATUS_HOSTID_REQUIRED:
3043 (void) printf(gettext(" action: Set a unique system "
b9373170 3044 "hostid with the zgenhostid(8) command.\n"));
379ca9cf 3045 break;
34dc7c2f 3046 default:
d96eb2b1 3047 (void) printf(gettext(" action: The pool cannot be "
34dc7c2f
BB
3048 "imported due to damaged devices or data.\n"));
3049 }
3050 }
3051
d96eb2b1
DM
3052 /* Print the comment attached to the pool. */
3053 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
3054 (void) printf(gettext("comment: %s\n"), comment);
3055
34dc7c2f
BB
3056 /*
3057 * If the state is "closed" or "can't open", and the aux state
3058 * is "corrupt data":
3059 */
3060 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
3061 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
3062 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
3063 if (pool_state == POOL_STATE_DESTROYED)
3064 (void) printf(gettext("\tThe pool was destroyed, "
3065 "but can be imported using the '-Df' flags.\n"));
3066 else if (pool_state != POOL_STATE_EXPORTED)
3067 (void) printf(gettext("\tThe pool may be active on "
3068 "another system, but can be imported using\n\t"
3069 "the '-f' flag.\n"));
3070 }
3071
e458fcca
BB
3072 if (msgid != NULL) {
3073 (void) printf(gettext(
a2f944a1
RM
3074 " see: https://openzfs.github.io/openzfs-docs/msg/%s\n"),
3075 msgid);
e458fcca 3076 }
34dc7c2f 3077
d96eb2b1 3078 (void) printf(gettext(" config:\n\n"));
34dc7c2f 3079
2df9ad1c
GG
3080 cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
3081 VDEV_NAME_TYPE_ID);
fea33e4e
HJ
3082 if (cb.cb_namewidth < 10)
3083 cb.cb_namewidth = 10;
34dc7c2f 3084
fea33e4e 3085 print_import_config(&cb, name, nvroot, 0);
cc99f275
DB
3086
3087 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
3088 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
3089 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
34dc7c2f
BB
3090
3091 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
3092 (void) printf(gettext("\n\tAdditional devices are known to "
3093 "be part of this pool, though their\n\texact "
3094 "configuration cannot be determined.\n"));
3095 }
0936981d 3096 return (0);
34dc7c2f
BB
3097}
3098
379ca9cf
OF
3099static boolean_t
3100zfs_force_import_required(nvlist_t *config)
3101{
3102 uint64_t state;
3103 uint64_t hostid = 0;
3104 nvlist_t *nvinfo;
3105
3106 state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
3107 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
3108
3109 if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
3110 return (B_TRUE);
3111
3112 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
3113 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
3114 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
3115 ZPOOL_CONFIG_MMP_STATE);
3116
3117 if (mmp_state != MMP_STATE_INACTIVE)
3118 return (B_TRUE);
3119 }
3120
3121 return (B_FALSE);
3122}
3123
34dc7c2f
BB
3124/*
3125 * Perform the import for the given configuration. This passes the heavy
3126 * lifting off to zpool_import_props(), and then mounts the datasets contained
3127 * within the pool.
3128 */
3129static int
3130do_import(nvlist_t *config, const char *newname, const char *mntopts,
572e2857 3131 nvlist_t *props, int flags)
34dc7c2f 3132{
b5256303 3133 int ret = 0;
34dc7c2f 3134 zpool_handle_t *zhp;
bf12053c 3135 const char *name;
34dc7c2f 3136 uint64_t version;
34dc7c2f 3137
379ca9cf 3138 name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
379ca9cf 3139 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
34dc7c2f 3140
9ae529ec 3141 if (!SPA_VERSION_IS_SUPPORTED(version)) {
34dc7c2f 3142 (void) fprintf(stderr, gettext("cannot import '%s': pool "
9ae529ec 3143 "is formatted using an unsupported ZFS version\n"), name);
34dc7c2f 3144 return (1);
379ca9cf 3145 } else if (zfs_force_import_required(config) &&
572e2857 3146 !(flags & ZFS_IMPORT_ANY_HOST)) {
379ca9cf
OF
3147 mmp_state_t mmp_state = MMP_STATE_INACTIVE;
3148 nvlist_t *nvinfo;
3149
3150 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
3151 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
3152 mmp_state = fnvlist_lookup_uint64(nvinfo,
3153 ZPOOL_CONFIG_MMP_STATE);
3154
3155 if (mmp_state == MMP_STATE_ACTIVE) {
bf12053c 3156 const char *hostname = "<unknown>";
379ca9cf
OF
3157 uint64_t hostid = 0;
3158
3159 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
3160 hostname = fnvlist_lookup_string(nvinfo,
3161 ZPOOL_CONFIG_MMP_HOSTNAME);
3162
3163 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
3164 hostid = fnvlist_lookup_uint64(nvinfo,
3165 ZPOOL_CONFIG_MMP_HOSTID);
3166
3167 (void) fprintf(stderr, gettext("cannot import '%s': "
3168 "pool is imported on %s (hostid: "
bde0f7d4
AZ
3169 "0x%"PRIx64")\nExport the pool on the other "
3170 "system, then run 'zpool import'.\n"),
3171 name, hostname, hostid);
379ca9cf
OF
3172 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
3173 (void) fprintf(stderr, gettext("Cannot import '%s': "
3174 "pool has the multihost property on and the\n"
3175 "system's hostid is not set. Set a unique hostid "
b9373170 3176 "with the zgenhostid(8) command.\n"), name);
379ca9cf 3177 } else {
bf12053c
AZ
3178 const char *hostname = "<unknown>";
3179 time_t timestamp = 0;
379ca9cf
OF
3180 uint64_t hostid = 0;
3181
3182 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
3183 hostname = fnvlist_lookup_string(config,
3184 ZPOOL_CONFIG_HOSTNAME);
3185
3186 if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
3187 timestamp = fnvlist_lookup_uint64(config,
3188 ZPOOL_CONFIG_TIMESTAMP);
3189
3190 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
3191 hostid = fnvlist_lookup_uint64(config,
3192 ZPOOL_CONFIG_HOSTID);
3193
3194 (void) fprintf(stderr, gettext("cannot import '%s': "
3195 "pool was previously in use from another system.\n"
bde0f7d4 3196 "Last accessed by %s (hostid=%"PRIx64") at %s"
379ca9cf
OF
3197 "The pool can be imported, use 'zpool import -f' "
3198 "to import the pool.\n"), name, hostname,
bde0f7d4 3199 hostid, ctime(&timestamp));
34dc7c2f 3200 }
379ca9cf
OF
3201
3202 return (1);
34dc7c2f
BB
3203 }
3204
572e2857 3205 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
34dc7c2f
BB
3206 return (1);
3207
3208 if (newname != NULL)
bf12053c 3209 name = newname;
34dc7c2f 3210
45d1cae3
BB
3211 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
3212 return (1);
34dc7c2f 3213
b5256303
TC
3214 /*
3215 * Loading keys is best effort. We don't want to return immediately
3216 * if it fails but we do want to give the error to the caller.
3217 */
a401a2c5
AZ
3218 if (flags & ZFS_IMPORT_LOAD_KEYS &&
3219 zfs_crypto_attempt_load_keys(g_zfs, name) != 0)
b5256303 3220 ret = 1;
b5256303 3221
d164b209 3222 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
572e2857 3223 !(flags & ZFS_IMPORT_ONLY) &&
d164b209 3224 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
34dc7c2f
BB
3225 zpool_close(zhp);
3226 return (1);
3227 }
3228
3229 zpool_close(zhp);
b5256303 3230 return (ret);
34dc7c2f
BB
3231}
3232
0936981d
GW
3233static int
3234import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
3235 char *orig_name, char *new_name,
3236 boolean_t do_destroyed, boolean_t pool_specified, boolean_t do_all,
3237 importargs_t *import)
3238{
3239 nvlist_t *config = NULL;
3240 nvlist_t *found_config = NULL;
3241 uint64_t pool_state;
3242
3243 /*
3244 * At this point we have a list of import candidate configs. Even if
3245 * we were searching by pool name or guid, we still need to
3246 * post-process the list to deal with pool state and possible
3247 * duplicate names.
3248 */
3249 int err = 0;
3250 nvpair_t *elem = NULL;
3251 boolean_t first = B_TRUE;
3252 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
3253
3254 verify(nvpair_value_nvlist(elem, &config) == 0);
3255
3256 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
3257 &pool_state) == 0);
3258 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
3259 continue;
3260 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
3261 continue;
3262
3263 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
3264 import->policy) == 0);
3265
3266 if (!pool_specified) {
3267 if (first)
3268 first = B_FALSE;
3269 else if (!do_all)
a926aab9 3270 (void) fputc('\n', stdout);
0936981d
GW
3271
3272 if (do_all) {
3273 err |= do_import(config, NULL, mntopts,
3274 props, flags);
3275 } else {
3276 /*
3277 * If we're importing from cachefile, then
3278 * we don't want to report errors until we
3279 * are in the scan phase of the import. If
3280 * we get an error, then we return that error
3281 * to invoke the scan phase.
3282 */
3283 if (import->cachefile && !import->scan)
3284 err = show_import(config, B_FALSE);
3285 else
3286 (void) show_import(config, B_TRUE);
3287 }
3288 } else if (import->poolname != NULL) {
d1807f16 3289 const char *name;
0936981d
GW
3290
3291 /*
3292 * We are searching for a pool based on name.
3293 */
3294 verify(nvlist_lookup_string(config,
3295 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
3296
3297 if (strcmp(name, import->poolname) == 0) {
3298 if (found_config != NULL) {
3299 (void) fprintf(stderr, gettext(
3300 "cannot import '%s': more than "
3301 "one matching pool\n"),
3302 import->poolname);
3303 (void) fprintf(stderr, gettext(
3304 "import by numeric ID instead\n"));
3305 err = B_TRUE;
3306 }
3307 found_config = config;
3308 }
3309 } else {
3310 uint64_t guid;
3311
3312 /*
3313 * Search for a pool by guid.
3314 */
3315 verify(nvlist_lookup_uint64(config,
3316 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
3317
3318 if (guid == import->guid)
3319 found_config = config;
3320 }
3321 }
3322
3323 /*
3324 * If we were searching for a specific pool, verify that we found a
3325 * pool, and then do the import.
3326 */
3327 if (pool_specified && err == 0) {
3328 if (found_config == NULL) {
3329 (void) fprintf(stderr, gettext("cannot import '%s': "
3330 "no such pool available\n"), orig_name);
3331 err = B_TRUE;
3332 } else {
3333 err |= do_import(found_config, new_name,
3334 mntopts, props, flags);
3335 }
3336 }
3337
3338 /*
3339 * If we were just looking for pools, report an error if none were
3340 * found.
3341 */
3342 if (!pool_specified && first)
3343 (void) fprintf(stderr,
3344 gettext("no pools available to import\n"));
3345 return (err);
3346}
3347
e89f1295
DB
3348typedef struct target_exists_args {
3349 const char *poolname;
3350 uint64_t poolguid;
3351} target_exists_args_t;
3352
3353static int
3354name_or_guid_exists(zpool_handle_t *zhp, void *data)
3355{
3356 target_exists_args_t *args = data;
3357 nvlist_t *config = zpool_get_config(zhp, NULL);
3358 int found = 0;
3359
3360 if (config == NULL)
3361 return (0);
3362
3363 if (args->poolname != NULL) {
d1807f16 3364 const char *pool_name;
e89f1295
DB
3365
3366 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
3367 &pool_name) == 0);
3368 if (strcmp(pool_name, args->poolname) == 0)
3369 found = 1;
3370 } else {
3371 uint64_t pool_guid;
3372
3373 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
3374 &pool_guid) == 0);
3375 if (pool_guid == args->poolguid)
3376 found = 1;
3377 }
3378 zpool_close(zhp);
3379
3380 return (found);
3381}
d2734cce
SD
3382/*
3383 * zpool checkpoint <pool>
3384 * checkpoint --discard <pool>
3385 *
3386 * -d Discard the checkpoint from a checkpointed
3387 * --discard pool.
3388 *
e60e158e
JG
3389 * -w Wait for discarding a checkpoint to complete.
3390 * --wait
3391 *
d2734cce
SD
3392 * Checkpoints the specified pool, by taking a "snapshot" of its
3393 * current state. A pool can only have one checkpoint at a time.
3394 */
3395int
3396zpool_do_checkpoint(int argc, char **argv)
3397{
e60e158e 3398 boolean_t discard, wait;
d2734cce
SD
3399 char *pool;
3400 zpool_handle_t *zhp;
3401 int c, err;
3402
3403 struct option long_options[] = {
3404 {"discard", no_argument, NULL, 'd'},
e60e158e 3405 {"wait", no_argument, NULL, 'w'},
d2734cce
SD
3406 {0, 0, 0, 0}
3407 };
3408
3409 discard = B_FALSE;
e60e158e
JG
3410 wait = B_FALSE;
3411 while ((c = getopt_long(argc, argv, ":dw", long_options, NULL)) != -1) {
d2734cce
SD
3412 switch (c) {
3413 case 'd':
3414 discard = B_TRUE;
3415 break;
e60e158e
JG
3416 case 'w':
3417 wait = B_TRUE;
3418 break;
d2734cce
SD
3419 case '?':
3420 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3421 optopt);
3422 usage(B_FALSE);
3423 }
3424 }
3425
e60e158e
JG
3426 if (wait && !discard) {
3427 (void) fprintf(stderr, gettext("--wait only valid when "
3428 "--discard also specified\n"));
3429 usage(B_FALSE);
3430 }
3431
d2734cce
SD
3432 argc -= optind;
3433 argv += optind;
3434
3435 if (argc < 1) {
3436 (void) fprintf(stderr, gettext("missing pool argument\n"));
3437 usage(B_FALSE);
3438 }
3439
3440 if (argc > 1) {
3441 (void) fprintf(stderr, gettext("too many arguments\n"));
3442 usage(B_FALSE);
3443 }
3444
3445 pool = argv[0];
3446
3447 if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
3448 /* As a special case, check for use of '/' in the name */
3449 if (strchr(pool, '/') != NULL)
3450 (void) fprintf(stderr, gettext("'zpool checkpoint' "
3451 "doesn't work on datasets. To save the state "
3452 "of a dataset from a specific point in time "
3453 "please use 'zfs snapshot'\n"));
3454 return (1);
3455 }
3456
e60e158e 3457 if (discard) {
d2734cce 3458 err = (zpool_discard_checkpoint(zhp) != 0);
e60e158e
JG
3459 if (err == 0 && wait)
3460 err = zpool_wait(zhp, ZPOOL_WAIT_CKPT_DISCARD);
3461 } else {
d2734cce 3462 err = (zpool_checkpoint(zhp) != 0);
e60e158e 3463 }
d2734cce
SD
3464
3465 zpool_close(zhp);
3466
3467 return (err);
3468}
3469
3470#define CHECKPOINT_OPT 1024
3471
34dc7c2f
BB
3472/*
3473 * zpool import [-d dir] [-D]
b5256303 3474 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
0936981d 3475 * [-d dir | -c cachefile | -s] [-f] -a
b5256303 3476 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
0936981d
GW
3477 * [-d dir | -c cachefile | -s] [-f] [-n] [-F] <pool | id>
3478 * [newpool]
34dc7c2f 3479 *
0936981d
GW
3480 * -c Read pool information from a cachefile instead of searching
3481 * devices. If importing from a cachefile config fails, then
3482 * fallback to searching for devices only in the directories that
3483 * exist in the cachefile.
34dc7c2f 3484 *
0936981d 3485 * -d Scan in a specific directory, other than /dev/. More than
34dc7c2f
BB
3486 * one directory can be specified using multiple '-d' options.
3487 *
0936981d
GW
3488 * -D Scan for previously destroyed pools or import all or only
3489 * specified destroyed pools.
34dc7c2f 3490 *
0936981d 3491 * -R Temporarily import the pool, with all mountpoints relative to
34dc7c2f
BB
3492 * the given root. The pool will remain exported when the machine
3493 * is rebooted.
3494 *
0936981d
GW
3495 * -V Import even in the presence of faulted vdevs. This is an
3496 * intentionally undocumented option for testing purposes, and
3497 * treats the pool configuration as complete, leaving any bad
45d1cae3
BB
3498 * vdevs in the FAULTED state. In other words, it does verbatim
3499 * import.
b128c09f 3500 *
0936981d 3501 * -f Force import, even if it appears that the pool is active.
428870ff 3502 *
0936981d 3503 * -F Attempt rewind if necessary.
428870ff 3504 *
0936981d 3505 * -n See if rewind would work, but don't actually rewind.
428870ff 3506 *
0936981d 3507 * -N Import the pool but don't mount datasets.
572e2857 3508 *
0936981d
GW
3509 * -T Specify a starting txg to use for import. This option is
3510 * intentionally undocumented option for testing purposes.
572e2857 3511 *
0936981d 3512 * -a Import all pools found.
34dc7c2f 3513 *
0936981d 3514 * -l Load encryption keys while importing.
b5256303 3515 *
0936981d 3516 * -o Set property=value and/or temporary mount options (without '=').
34dc7c2f 3517 *
0936981d
GW
3518 * -s Scan using the default search path, the libblkid cache will
3519 * not be consulted.
7d11e37e 3520 *
0936981d
GW
3521 * --rewind-to-checkpoint
3522 * Import the pool and revert back to the checkpoint.
d2734cce 3523 *
34dc7c2f
BB
3524 * The import command scans for pools to import, and import pools based on pool
3525 * name and GUID. The pool can also be renamed as part of the import process.
3526 */
3527int
3528zpool_do_import(int argc, char **argv)
3529{
3530 char **searchdirs = NULL;
44867b6d 3531 char *env, *envdup = NULL;
34dc7c2f
BB
3532 int nsearch = 0;
3533 int c;
428870ff 3534 int err = 0;
34dc7c2f
BB
3535 nvlist_t *pools = NULL;
3536 boolean_t do_all = B_FALSE;
3537 boolean_t do_destroyed = B_FALSE;
3538 char *mntopts = NULL;
b128c09f
BB
3539 uint64_t searchguid = 0;
3540 char *searchname = NULL;
34dc7c2f 3541 char *propval;
428870ff 3542 nvlist_t *policy = NULL;
34dc7c2f 3543 nvlist_t *props = NULL;
572e2857 3544 int flags = ZFS_IMPORT_NORMAL;
428870ff
BB
3545 uint32_t rewind_policy = ZPOOL_NO_REWIND;
3546 boolean_t dryrun = B_FALSE;
3547 boolean_t do_rewind = B_FALSE;
3548 boolean_t xtreme_rewind = B_FALSE;
7d11e37e 3549 boolean_t do_scan = B_FALSE;
e89f1295 3550 boolean_t pool_exists = B_FALSE;
0936981d
GW
3551 boolean_t pool_specified = B_FALSE;
3552 uint64_t txg = -1ULL;
34dc7c2f 3553 char *cachefile = NULL;
428870ff 3554 importargs_t idata = { 0 };
572e2857 3555 char *endptr;
34dc7c2f 3556
d2734cce
SD
3557 struct option long_options[] = {
3558 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
3559 {0, 0, 0, 0}
3560 };
3561
34dc7c2f 3562 /* check options */
d2734cce
SD
3563 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:R:stT:VX",
3564 long_options, NULL)) != -1) {
34dc7c2f
BB
3565 switch (c) {
3566 case 'a':
3567 do_all = B_TRUE;
3568 break;
3569 case 'c':
3570 cachefile = optarg;
3571 break;
3572 case 'd':
a281f769
AZ
3573 searchdirs = safe_realloc(searchdirs,
3574 (nsearch + 1) * sizeof (char *));
34dc7c2f
BB
3575 searchdirs[nsearch++] = optarg;
3576 break;
3577 case 'D':
3578 do_destroyed = B_TRUE;
3579 break;
3580 case 'f':
572e2857 3581 flags |= ZFS_IMPORT_ANY_HOST;
34dc7c2f 3582 break;
b128c09f 3583 case 'F':
428870ff
BB
3584 do_rewind = B_TRUE;
3585 break;
b5256303
TC
3586 case 'l':
3587 flags |= ZFS_IMPORT_LOAD_KEYS;
3588 break;
572e2857
BB
3589 case 'm':
3590 flags |= ZFS_IMPORT_MISSING_LOG;
3591 break;
428870ff
BB
3592 case 'n':
3593 dryrun = B_TRUE;
b128c09f 3594 break;
572e2857
BB
3595 case 'N':
3596 flags |= ZFS_IMPORT_ONLY;
3597 break;
34dc7c2f
BB
3598 case 'o':
3599 if ((propval = strchr(optarg, '=')) != NULL) {
3600 *propval = '\0';
3601 propval++;
b128c09f
BB
3602 if (add_prop_list(optarg, propval,
3603 &props, B_TRUE))
34dc7c2f
BB
3604 goto error;
3605 } else {
3606 mntopts = optarg;
3607 }
3608 break;
3609 case 'R':
3610 if (add_prop_list(zpool_prop_to_name(
b128c09f 3611 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
34dc7c2f 3612 goto error;
2f3ec900 3613 if (add_prop_list_default(zpool_prop_to_name(
e40ca391 3614 ZPOOL_PROP_CACHEFILE), "none", &props))
34dc7c2f
BB
3615 goto error;
3616 break;
7d11e37e
BB
3617 case 's':
3618 do_scan = B_TRUE;
3619 break;
26b42f3f
RY
3620 case 't':
3621 flags |= ZFS_IMPORT_TEMP_NAME;
00d2a8c9 3622 if (add_prop_list_default(zpool_prop_to_name(
e40ca391 3623 ZPOOL_PROP_CACHEFILE), "none", &props))
00d2a8c9 3624 goto error;
26b42f3f
RY
3625 break;
3626
572e2857
BB
3627 case 'T':
3628 errno = 0;
dea377c0 3629 txg = strtoull(optarg, &endptr, 0);
572e2857
BB
3630 if (errno != 0 || *endptr != '\0') {
3631 (void) fprintf(stderr,
3632 gettext("invalid txg value\n"));
3633 usage(B_FALSE);
3634 }
3635 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
3636 break;
428870ff 3637 case 'V':
572e2857 3638 flags |= ZFS_IMPORT_VERBATIM;
428870ff
BB
3639 break;
3640 case 'X':
3641 xtreme_rewind = B_TRUE;
3642 break;
d2734cce
SD
3643 case CHECKPOINT_OPT:
3644 flags |= ZFS_IMPORT_CHECKPOINT;
3645 break;
34dc7c2f
BB
3646 case ':':
3647 (void) fprintf(stderr, gettext("missing argument for "
3648 "'%c' option\n"), optopt);
3649 usage(B_FALSE);
3650 break;
3651 case '?':
3652 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3653 optopt);
3654 usage(B_FALSE);
3655 }
3656 }
3657
3658 argc -= optind;
3659 argv += optind;
3660
3661 if (cachefile && nsearch != 0) {
3662 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
3663 usage(B_FALSE);
3664 }
3665
0936981d
GW
3666 if (cachefile && do_scan) {
3667 (void) fprintf(stderr, gettext("-c is incompatible with -s\n"));
3668 usage(B_FALSE);
3669 }
3670
b5256303
TC
3671 if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
3672 (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
3673 usage(B_FALSE);
3674 }
3675
3676 if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
3677 (void) fprintf(stderr, gettext("-l is only meaningful during "
3678 "an import\n"));
3679 usage(B_FALSE);
3680 }
3681
428870ff
BB
3682 if ((dryrun || xtreme_rewind) && !do_rewind) {
3683 (void) fprintf(stderr,
3684 gettext("-n or -X only meaningful with -F\n"));
3685 usage(B_FALSE);
3686 }
3687 if (dryrun)
3688 rewind_policy = ZPOOL_TRY_REWIND;
3689 else if (do_rewind)
3690 rewind_policy = ZPOOL_DO_REWIND;
3691 if (xtreme_rewind)
3692 rewind_policy |= ZPOOL_EXTREME_REWIND;
3693
3694 /* In the future, we can capture further policy and include it here */
3695 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
8a393be3
PZ
3696 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
3697 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
3698 rewind_policy) != 0)
428870ff
BB
3699 goto error;
3700
34dc7c2f
BB
3701 /* check argument count */
3702 if (do_all) {
3703 if (argc != 0) {
3704 (void) fprintf(stderr, gettext("too many arguments\n"));
3705 usage(B_FALSE);
3706 }
3707 } else {
3708 if (argc > 2) {
3709 (void) fprintf(stderr, gettext("too many arguments\n"));
3710 usage(B_FALSE);
3711 }
f74b821a 3712 }
34dc7c2f 3713
f74b821a
BB
3714 /*
3715 * Check for the effective uid. We do this explicitly here because
3716 * otherwise any attempt to discover pools will silently fail.
3717 */
3718 if (argc == 0 && geteuid() != 0) {
3719 (void) fprintf(stderr, gettext("cannot "
3720 "discover pools: permission denied\n"));
d603ed6c 3721
a401a2c5 3722 free(searchdirs);
a425f5bf 3723 nvlist_free(props);
f74b821a
BB
3724 nvlist_free(policy);
3725 return (1);
34dc7c2f
BB
3726 }
3727
34dc7c2f 3728 /*
34dc7c2f
BB
3729 * Depending on the arguments given, we do one of the following:
3730 *
3731 * <none> Iterate through all pools and display information about
3732 * each one.
3733 *
3734 * -a Iterate through all pools and try to import each one.
3735 *
3736 * <id> Find the pool that corresponds to the given GUID/pool
3737 * name and import that one.
3738 *
3739 * -D Above options applies only to destroyed pools.
3740 */
3741 if (argc != 0) {
3742 char *endptr;
3743
3744 errno = 0;
3745 searchguid = strtoull(argv[0], &endptr, 10);
eaa52d32 3746 if (errno != 0 || *endptr != '\0') {
34dc7c2f 3747 searchname = argv[0];
eaa52d32
PJ
3748 searchguid = 0;
3749 }
0936981d 3750 pool_specified = B_TRUE;
34dc7c2f 3751
b128c09f 3752 /*
428870ff 3753 * User specified a name or guid. Ensure it's unique.
b128c09f 3754 */
e89f1295
DB
3755 target_exists_args_t search = {searchname, searchguid};
3756 pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search);
b128c09f
BB
3757 }
3758
44867b6d
BB
3759 /*
3760 * Check the environment for the preferred search path.
3761 */
3762 if ((searchdirs == NULL) && (env = getenv("ZPOOL_IMPORT_PATH"))) {
a281f769 3763 char *dir, *tmp = NULL;
44867b6d
BB
3764
3765 envdup = strdup(env);
3766
a281f769
AZ
3767 for (dir = strtok_r(envdup, ":", &tmp);
3768 dir != NULL;
3769 dir = strtok_r(NULL, ":", &tmp)) {
3770 searchdirs = safe_realloc(searchdirs,
3771 (nsearch + 1) * sizeof (char *));
44867b6d 3772 searchdirs[nsearch++] = dir;
44867b6d
BB
3773 }
3774 }
428870ff
BB
3775
3776 idata.path = searchdirs;
3777 idata.paths = nsearch;
3778 idata.poolname = searchname;
3779 idata.guid = searchguid;
3780 idata.cachefile = cachefile;
7d11e37e 3781 idata.scan = do_scan;
6cb8e530 3782 idata.policy = policy;
428870ff 3783
d9ac17a5
US
3784 libpc_handle_t lpch = {
3785 .lpc_lib_handle = g_zfs,
3786 .lpc_ops = &libzfs_config_ops,
3787 .lpc_printerr = B_TRUE
3788 };
3789 pools = zpool_search_import(&lpch, &idata);
428870ff 3790
e89f1295 3791 if (pools != NULL && pool_exists &&
428870ff
BB
3792 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
3793 (void) fprintf(stderr, gettext("cannot import '%s': "
3794 "a pool with that name already exists\n"),
3795 argv[0]);
3796 (void) fprintf(stderr, gettext("use the form '%s "
3797 "<pool | id> <newpool>' to give it a new name\n"),
3798 "zpool import");
3799 err = 1;
e89f1295 3800 } else if (pools == NULL && pool_exists) {
428870ff
BB
3801 (void) fprintf(stderr, gettext("cannot import '%s': "
3802 "a pool with that name is already created/imported,\n"),
3803 argv[0]);
3804 (void) fprintf(stderr, gettext("and no additional pools "
3805 "with that name were found\n"));
3806 err = 1;
3807 } else if (pools == NULL) {
b128c09f
BB
3808 if (argc != 0) {
3809 (void) fprintf(stderr, gettext("cannot import '%s': "
3810 "no such pool available\n"), argv[0]);
3811 }
428870ff
BB
3812 err = 1;
3813 }
3814
3815 if (err == 1) {
a281f769
AZ
3816 free(searchdirs);
3817 free(envdup);
428870ff 3818 nvlist_free(policy);
a425f5bf 3819 nvlist_free(pools);
3820 nvlist_free(props);
b128c09f
BB
3821 return (1);
3822 }
3823
d8381f50
MA
3824 err = import_pools(pools, props, mntopts, flags,
3825 argc >= 1 ? argv[0] : NULL,
3826 argc >= 2 ? argv[1] : NULL,
3827 do_destroyed, pool_specified, do_all, &idata);
0936981d 3828
b128c09f 3829 /*
0936981d
GW
3830 * If we're using the cachefile and we failed to import, then
3831 * fallback to scanning the directory for pools that match
3832 * those in the cachefile.
b128c09f 3833 */
0936981d
GW
3834 if (err != 0 && cachefile != NULL) {
3835 (void) printf(gettext("cachefile import failed, retrying\n"));
34dc7c2f 3836
0936981d
GW
3837 /*
3838 * We use the scan flag to gather the directories that exist
3839 * in the cachefile. If we need to fallback to searching for
3840 * the pool config, we will only search devices in these
3841 * directories.
3842 */
3843 idata.scan = B_TRUE;
3844 nvlist_free(pools);
d9ac17a5 3845 pools = zpool_search_import(&lpch, &idata);
34dc7c2f 3846
d8381f50
MA
3847 err = import_pools(pools, props, mntopts, flags,
3848 argc >= 1 ? argv[0] : NULL,
3849 argc >= 2 ? argv[1] : NULL,
3850 do_destroyed, pool_specified, do_all, &idata);
34dc7c2f
BB
3851 }
3852
34dc7c2f
BB
3853error:
3854 nvlist_free(props);
3855 nvlist_free(pools);
428870ff 3856 nvlist_free(policy);
a281f769
AZ
3857 free(searchdirs);
3858 free(envdup);
34dc7c2f
BB
3859
3860 return (err ? 1 : 0);
3861}
3862
bec1067d
AP
3863/*
3864 * zpool sync [-f] [pool] ...
3865 *
3866 * -f (undocumented) force uberblock (and config including zpool cache file)
3867 * update.
3868 *
3869 * Sync the specified pool(s).
3870 * Without arguments "zpool sync" will sync all pools.
3871 * This command initiates TXG sync(s) and will return after the TXG(s) commit.
3872 *
3873 */
3874static int
3875zpool_do_sync(int argc, char **argv)
3876{
3877 int ret;
3878 boolean_t force = B_FALSE;
3879
3880 /* check options */
3881 while ((ret = getopt(argc, argv, "f")) != -1) {
3882 switch (ret) {
3883 case 'f':
3884 force = B_TRUE;
3885 break;
3886 case '?':
3887 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3888 optopt);
3889 usage(B_FALSE);
3890 }
3891 }
3892
3893 argc -= optind;
3894 argv += optind;
3895
3896 /* if argc == 0 we will execute zpool_sync_one on all pools */
2a673e76
AJ
3897 ret = for_each_pool(argc, argv, B_FALSE, NULL, ZFS_TYPE_POOL,
3898 B_FALSE, zpool_sync_one, &force);
bec1067d
AP
3899
3900 return (ret);
3901}
3902
34dc7c2f 3903typedef struct iostat_cbdata {
193a37cb 3904 uint64_t cb_flags;
34dc7c2f 3905 int cb_namewidth;
1bd201e7 3906 int cb_iteration;
193a37cb
TH
3907 boolean_t cb_verbose;
3908 boolean_t cb_literal;
3909 boolean_t cb_scripted;
1bd201e7 3910 zpool_list_t *cb_list;
8720e9e7 3911 vdev_cmd_data_list_t *vcdl;
2a673e76 3912 vdev_cbdata_t cb_vdevs;
34dc7c2f
BB
3913} iostat_cbdata_t;
3914
193a37cb
TH
3915/* iostat labels */
3916typedef struct name_and_columns {
3917 const char *name; /* Column name */
3918 unsigned int columns; /* Center name to this number of columns */
3919} name_and_columns_t;
3920
00888c08 3921#define IOSTAT_MAX_LABELS 15 /* Max number of labels on one line */
193a37cb
TH
3922
3923static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
3924{
3925 [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2},
3926 {NULL}},
3927 [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
00888c08
TB
3928 {"asyncq_wait", 2}, {"scrub", 1}, {"trim", 1}, {"rebuild", 1},
3929 {NULL}},
193a37cb
TH
3930 [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
3931 {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
00888c08 3932 {"trimq_write", 2}, {"rebuildq_write", 2}, {NULL}},
57dc41de
TH
3933 [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3934 {"asyncq_wait", 2}, {NULL}},
7e945072 3935 [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
1b939560 3936 {"async_read", 2}, {"async_write", 2}, {"scrub", 2},
00888c08 3937 {"trim", 2}, {"rebuild", 2}, {NULL}},
193a37cb
TH
3938};
3939
3940/* Shorthand - if "columns" field not set, default to 1 column */
3941static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
3942{
3943 [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"},
3944 {"write"}, {NULL}},
3945 [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
00888c08
TB
3946 {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {"wait"},
3947 {NULL}},
193a37cb 3948 [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
1b939560 3949 {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"},
00888c08 3950 {"pend"}, {"activ"}, {"pend"}, {"activ"}, {NULL}},
193a37cb 3951 [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
00888c08
TB
3952 {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {"rebuild"},
3953 {NULL}},
7e945072 3954 [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
00888c08
TB
3955 {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
3956 {"ind"}, {"agg"}, {NULL}},
7e945072
TH
3957};
3958
3959static const char *histo_to_title[] = {
3960 [IOS_L_HISTO] = "latency",
3961 [IOS_RQ_HISTO] = "req_size",
193a37cb
TH
3962};
3963
3964/*
3965 * Return the number of labels in a null-terminated name_and_columns_t
3966 * array.
3967 *
3968 */
3969static unsigned int
3970label_array_len(const name_and_columns_t *labels)
3971{
3972 int i = 0;
3973
3974 while (labels[i].name)
3975 i++;
3976
3977 return (i);
3978}
3979
7e945072
TH
3980/*
3981 * Return the number of strings in a null-terminated string array.
3982 * For example:
3983 *
3984 * const char foo[] = {"bar", "baz", NULL}
3985 *
3986 * returns 2
3987 */
3988static uint64_t
3989str_array_len(const char *array[])
3990{
3991 uint64_t i = 0;
3992 while (array[i])
3993 i++;
3994
3995 return (i);
3996}
3997
3998
193a37cb
TH
3999/*
4000 * Return a default column width for default/latency/queue columns. This does
4001 * not include histograms, which have their columns autosized.
4002 */
4003static unsigned int
4004default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
4005{
4006 unsigned long column_width = 5; /* Normal niceprint */
4007 static unsigned long widths[] = {
4008 /*
4009 * Choose some sane default column sizes for printing the
4010 * raw numbers.
4011 */
4012 [IOS_DEFAULT] = 15, /* 1PB capacity */
4013 [IOS_LATENCY] = 10, /* 1B ns = 10sec */
4014 [IOS_QUEUES] = 6, /* 1M queue entries */
1b939560
BB
4015 [IOS_L_HISTO] = 10, /* 1B ns = 10sec */
4016 [IOS_RQ_HISTO] = 6, /* 1M queue entries */
193a37cb
TH
4017 };
4018
4019 if (cb->cb_literal)
4020 column_width = widths[type];
4021
4022 return (column_width);
4023}
4024
4025/*
4026 * Print the column labels, i.e:
4027 *
4028 * capacity operations bandwidth
4029 * alloc free read write read write ...
4030 *
4031 * If force_column_width is set, use it for the column width. If not set, use
4032 * the default column width.
4033 */
65c7cc49 4034static void
193a37cb
TH
4035print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width,
4036 const name_and_columns_t labels[][IOSTAT_MAX_LABELS])
4037{
4038 int i, idx, s;
1b939560 4039 int text_start, rw_column_width, spaces_to_end;
193a37cb
TH
4040 uint64_t flags = cb->cb_flags;
4041 uint64_t f;
4042 unsigned int column_width = force_column_width;
4043
4044 /* For each bit set in flags */
4045 for (f = flags; f; f &= ~(1ULL << idx)) {
4046 idx = lowbit64(f) - 1;
4047 if (!force_column_width)
4048 column_width = default_column_width(cb, idx);
4049 /* Print our top labels centered over "read write" label. */
4050 for (i = 0; i < label_array_len(labels[idx]); i++) {
4051 const char *name = labels[idx][i].name;
4052 /*
4053 * We treat labels[][].columns == 0 as shorthand
4054 * for one column. It makes writing out the label
4055 * tables more concise.
4056 */
4057 unsigned int columns = MAX(1, labels[idx][i].columns);
4058 unsigned int slen = strlen(name);
4059
4060 rw_column_width = (column_width * columns) +
4061 (2 * (columns - 1));
4062
1b939560
BB
4063 text_start = (int)((rw_column_width) / columns -
4064 slen / columns);
4065 if (text_start < 0)
4066 text_start = 0;
193a37cb
TH
4067
4068 printf(" "); /* Two spaces between columns */
4069
4070 /* Space from beginning of column to label */
4071 for (s = 0; s < text_start; s++)
4072 printf(" ");
4073
4074 printf("%s", name);
4075
4076 /* Print space after label to end of column */
4077 spaces_to_end = rw_column_width - text_start - slen;
1b939560
BB
4078 if (spaces_to_end < 0)
4079 spaces_to_end = 0;
4080
193a37cb
TH
4081 for (s = 0; s < spaces_to_end; s++)
4082 printf(" ");
193a37cb
TH
4083 }
4084 }
193a37cb
TH
4085}
4086
d6418de0
TH
4087
4088/*
4089 * print_cmd_columns - Print custom column titles from -c
4090 *
4091 * If the user specified the "zpool status|iostat -c" then print their custom
4092 * column titles in the header. For example, print_cmd_columns() would print
4093 * the " col1 col2" part of this:
4094 *
4095 * $ zpool iostat -vc 'echo col1=val1; echo col2=val2'
4096 * ...
4097 * capacity operations bandwidth
4098 * pool alloc free read write read write col1 col2
4099 * ---------- ----- ----- ----- ----- ----- ----- ---- ----
4100 * mypool 269K 1008M 0 0 107 946
4101 * mirror 269K 1008M 0 0 107 946
4102 * sdb - - 0 0 102 473 val1 val2
4103 * sdc - - 0 0 5 473 val1 val2
4104 * ---------- ----- ----- ----- ----- ----- ----- ---- ----
4105 */
65c7cc49 4106static void
d6418de0
TH
4107print_cmd_columns(vdev_cmd_data_list_t *vcdl, int use_dashes)
4108{
4109 int i, j;
4110 vdev_cmd_data_t *data = &vcdl->data[0];
4111
4112 if (vcdl->count == 0 || data == NULL)
4113 return;
4114
4115 /*
4116 * Each vdev cmd should have the same column names unless the user did
4117 * something weird with their cmd. Just take the column names from the
4118 * first vdev and assume it works for all of them.
4119 */
4120 for (i = 0; i < vcdl->uniq_cols_cnt; i++) {
4121 printf(" ");
4122 if (use_dashes) {
4123 for (j = 0; j < vcdl->uniq_cols_width[i]; j++)
4124 printf("-");
4125 } else {
9fb2771a 4126 printf_color(ANSI_BOLD, "%*s", vcdl->uniq_cols_width[i],
d6418de0
TH
4127 vcdl->uniq_cols[i]);
4128 }
4129 }
4130}
4131
4132
193a37cb
TH
4133/*
4134 * Utility function to print out a line of dashes like:
4135 *
4136 * -------------------------------- ----- ----- ----- ----- -----
4137 *
4138 * ...or a dashed named-row line like:
4139 *
4140 * logs - - - - -
4141 *
4142 * @cb: iostat data
4143 *
4144 * @force_column_width If non-zero, use the value as the column width.
4145 * Otherwise use the default column widths.
4146 *
4147 * @name: Print a dashed named-row line starting
4148 * with @name. Otherwise, print a regular
4149 * dashed line.
4150 */
4151static void
4152print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width,
4153 const char *name)
4154{
4155 int i;
4156 unsigned int namewidth;
4157 uint64_t flags = cb->cb_flags;
4158 uint64_t f;
4159 int idx;
4160 const name_and_columns_t *labels;
7e945072
TH
4161 const char *title;
4162
4163
4164 if (cb->cb_flags & IOS_ANYHISTO_M) {
4165 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
2a673e76 4166 } else if (cb->cb_vdevs.cb_names_count) {
7e945072
TH
4167 title = "vdev";
4168 } else {
4169 title = "pool";
4170 }
4171
4172 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
4173 name ? strlen(name) : 0);
193a37cb 4174
193a37cb
TH
4175
4176 if (name) {
193a37cb
TH
4177 printf("%-*s", namewidth, name);
4178 } else {
4179 for (i = 0; i < namewidth; i++)
4180 (void) printf("-");
4181 }
4182
4183 /* For each bit in flags */
4184 for (f = flags; f; f &= ~(1ULL << idx)) {
4185 unsigned int column_width;
4186 idx = lowbit64(f) - 1;
4187 if (force_column_width)
4188 column_width = force_column_width;
4189 else
4190 column_width = default_column_width(cb, idx);
4191
4192 labels = iostat_bottom_labels[idx];
4193 for (i = 0; i < label_array_len(labels); i++) {
4194 if (name)
4195 printf(" %*s-", column_width - 1, " ");
4196 else
4197 printf(" %.*s", column_width,
4198 "--------------------");
4199 }
4200 }
193a37cb
TH
4201}
4202
4203
4204static void
4205print_iostat_separator_impl(iostat_cbdata_t *cb,
4206 unsigned int force_column_width)
4207{
4208 print_iostat_dashes(cb, force_column_width, NULL);
4209}
4210
34dc7c2f
BB
4211static void
4212print_iostat_separator(iostat_cbdata_t *cb)
4213{
193a37cb
TH
4214 print_iostat_separator_impl(cb, 0);
4215}
4216
4217static void
4218print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
4219 const char *histo_vdev_name)
4220{
4221 unsigned int namewidth;
7e945072
TH
4222 const char *title;
4223
7bde396a
TR
4224 color_start(ANSI_BOLD);
4225
7e945072
TH
4226 if (cb->cb_flags & IOS_ANYHISTO_M) {
4227 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
2a673e76 4228 } else if (cb->cb_vdevs.cb_names_count) {
7e945072
TH
4229 title = "vdev";
4230 } else {
4231 title = "pool";
4232 }
34dc7c2f 4233
7e945072
TH
4234 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
4235 histo_vdev_name ? strlen(histo_vdev_name) : 0);
193a37cb 4236
7e945072 4237 if (histo_vdev_name)
193a37cb
TH
4238 printf("%-*s", namewidth, histo_vdev_name);
4239 else
4240 printf("%*s", namewidth, "");
4241
7e945072 4242
193a37cb 4243 print_iostat_labels(cb, force_column_width, iostat_top_labels);
d6418de0 4244 printf("\n");
193a37cb 4245
7e945072 4246 printf("%-*s", namewidth, title);
193a37cb
TH
4247
4248 print_iostat_labels(cb, force_column_width, iostat_bottom_labels);
d6418de0
TH
4249 if (cb->vcdl != NULL)
4250 print_cmd_columns(cb->vcdl, 0);
4251
4252 printf("\n");
193a37cb
TH
4253
4254 print_iostat_separator_impl(cb, force_column_width);
d6418de0
TH
4255
4256 if (cb->vcdl != NULL)
4257 print_cmd_columns(cb->vcdl, 1);
4258
7bde396a
TR
4259 color_end();
4260
d6418de0 4261 printf("\n");
34dc7c2f
BB
4262}
4263
4264static void
4265print_iostat_header(iostat_cbdata_t *cb)
4266{
193a37cb 4267 print_iostat_header_impl(cb, 0, NULL);
34dc7c2f
BB
4268}
4269
7bde396a
TR
4270/*
4271 * Prints a size string (i.e. 120M) with the suffix ("M") colored
4272 * by order of magnitude. Uses column_size to add padding.
4273 */
4274static void
f9e1c63f 4275print_stat_color(const char *statbuf, unsigned int column_size)
7bde396a
TR
4276{
4277 fputs(" ", stdout);
f9e1c63f
W
4278 size_t len = strlen(statbuf);
4279 while (len < column_size) {
4280 fputc(' ', stdout);
4281 column_size--;
4282 }
7bde396a
TR
4283 if (*statbuf == '0') {
4284 color_start(ANSI_GRAY);
4285 fputc('0', stdout);
7bde396a
TR
4286 } else {
4287 for (; *statbuf; statbuf++) {
4288 if (*statbuf == 'K') color_start(ANSI_GREEN);
4289 else if (*statbuf == 'M') color_start(ANSI_YELLOW);
4290 else if (*statbuf == 'G') color_start(ANSI_RED);
4291 else if (*statbuf == 'T') color_start(ANSI_BOLD_BLUE);
4292 else if (*statbuf == 'P') color_start(ANSI_MAGENTA);
4293 else if (*statbuf == 'E') color_start(ANSI_CYAN);
4294 fputc(*statbuf, stdout);
4295 if (--column_size <= 0)
4296 break;
4297 }
4298 }
4299 color_end();
7bde396a 4300}
193a37cb 4301
34dc7c2f
BB
4302/*
4303 * Display a single statistic.
4304 */
4305static void
193a37cb
TH
4306print_one_stat(uint64_t value, enum zfs_nicenum_format format,
4307 unsigned int column_size, boolean_t scripted)
34dc7c2f
BB
4308{
4309 char buf[64];
4310
193a37cb
TH
4311 zfs_nicenum_format(value, buf, sizeof (buf), format);
4312
4313 if (scripted)
4314 printf("\t%s", buf);
4315 else
7bde396a 4316 print_stat_color(buf, column_size);
193a37cb
TH
4317}
4318
4319/*
4320 * Calculate the default vdev stats
4321 *
4322 * Subtract oldvs from newvs, apply a scaling factor, and save the resulting
4323 * stats into calcvs.
4324 */
4325static void
4326calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs,
4327 vdev_stat_t *calcvs)
4328{
4329 int i;
4330
4331 memcpy(calcvs, newvs, sizeof (*calcvs));
4332 for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++)
4333 calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]);
4334
4335 for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++)
4336 calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]);
4337}
4338
4339/*
4340 * Internal representation of the extended iostats data.
4341 *
4342 * The extended iostat stats are exported in nvlists as either uint64_t arrays
4343 * or single uint64_t's. We make both look like arrays to make them easier
4344 * to process. In order to make single uint64_t's look like arrays, we set
4345 * __data to the stat data, and then set *data = &__data with count = 1. Then,
4346 * we can just use *data and count.
4347 */
4348struct stat_array {
4349 uint64_t *data;
4350 uint_t count; /* Number of entries in data[] */
4351 uint64_t __data; /* Only used when data is a single uint64_t */
4352};
4353
4354static uint64_t
4ea3f864
GM
4355stat_histo_max(struct stat_array *nva, unsigned int len)
4356{
193a37cb
TH
4357 uint64_t max = 0;
4358 int i;
4359 for (i = 0; i < len; i++)
4360 max = MAX(max, array64_max(nva[i].data, nva[i].count));
4361
4362 return (max);
4363}
4364
4365/*
4366 * Helper function to lookup a uint64_t array or uint64_t value and store its
4367 * data as a stat_array. If the nvpair is a single uint64_t value, then we make
4368 * it look like a one element array to make it easier to process.
4369 */
4370static int
4371nvpair64_to_stat_array(nvlist_t *nvl, const char *name,
4ea3f864
GM
4372 struct stat_array *nva)
4373{
193a37cb
TH
4374 nvpair_t *tmp;
4375 int ret;
4376
4377 verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0);
4378 switch (nvpair_type(tmp)) {
4379 case DATA_TYPE_UINT64_ARRAY:
4380 ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count);
4381 break;
4382 case DATA_TYPE_UINT64:
4383 ret = nvpair_value_uint64(tmp, &nva->__data);
4384 nva->data = &nva->__data;
4385 nva->count = 1;
4386 break;
4387 default:
4388 /* Not a uint64_t */
4389 ret = EINVAL;
4390 break;
4391 }
4392
4393 return (ret);
4394}
4395
4396/*
4397 * Given a list of nvlist names, look up the extended stats in newnv and oldnv,
4398 * subtract them, and return the results in a newly allocated stat_array.
4399 * You must free the returned array after you are done with it with
4400 * free_calc_stats().
4401 *
4402 * Additionally, you can set "oldnv" to NULL if you simply want the newnv
4403 * values.
4404 */
4405static struct stat_array *
4406calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv,
4407 nvlist_t *newnv)
4408{
4409 nvlist_t *oldnvx = NULL, *newnvx;
4410 struct stat_array *oldnva, *newnva, *calcnva;
4411 int i, j;
4412 unsigned int alloc_size = (sizeof (struct stat_array)) * len;
4413
4414 /* Extract our extended stats nvlist from the main list */
4415 verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX,
4416 &newnvx) == 0);
4417 if (oldnv) {
4418 verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX,
4419 &oldnvx) == 0);
4420 }
4421
4422 newnva = safe_malloc(alloc_size);
4423 oldnva = safe_malloc(alloc_size);
4424 calcnva = safe_malloc(alloc_size);
4425
4426 for (j = 0; j < len; j++) {
4427 verify(nvpair64_to_stat_array(newnvx, names[j],
4428 &newnva[j]) == 0);
4429 calcnva[j].count = newnva[j].count;
4430 alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]);
4431 calcnva[j].data = safe_malloc(alloc_size);
4432 memcpy(calcnva[j].data, newnva[j].data, alloc_size);
4433
4434 if (oldnvx) {
4435 verify(nvpair64_to_stat_array(oldnvx, names[j],
4436 &oldnva[j]) == 0);
4437 for (i = 0; i < oldnva[j].count; i++)
4438 calcnva[j].data[i] -= oldnva[j].data[i];
4439 }
4440 }
4441 free(newnva);
4442 free(oldnva);
4443 return (calcnva);
4444}
4445
4446static void
4447free_calc_stats(struct stat_array *nva, unsigned int len)
4448{
4449 int i;
4450 for (i = 0; i < len; i++)
4451 free(nva[i].data);
4452
4453 free(nva);
4454}
4455
4456static void
4457print_iostat_histo(struct stat_array *nva, unsigned int len,
4458 iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth,
4459 double scale)
4460{
4461 int i, j;
4462 char buf[6];
4463 uint64_t val;
4464 enum zfs_nicenum_format format;
4465 unsigned int buckets;
7e945072 4466 unsigned int start_bucket;
193a37cb
TH
4467
4468 if (cb->cb_literal)
4469 format = ZFS_NICENUM_RAW;
4470 else
4471 format = ZFS_NICENUM_1024;
4472
4473 /* All these histos are the same size, so just use nva[0].count */
4474 buckets = nva[0].count;
4475
7e945072
TH
4476 if (cb->cb_flags & IOS_RQ_HISTO_M) {
4477 /* Start at 512 - req size should never be lower than this */
4478 start_bucket = 9;
4479 } else {
4480 start_bucket = 0;
4481 }
193a37cb 4482
7e945072 4483 for (j = start_bucket; j < buckets; j++) {
193a37cb 4484 /* Print histogram bucket label */
7e945072
TH
4485 if (cb->cb_flags & IOS_L_HISTO_M) {
4486 /* Ending range of this bucket */
4487 val = (1UL << (j + 1)) - 1;
4488 zfs_nicetime(val, buf, sizeof (buf));
4489 } else {
4490 /* Request size (starting range of bucket) */
4491 val = (1UL << j);
4492 zfs_nicenum(val, buf, sizeof (buf));
4493 }
4494
193a37cb 4495 if (cb->cb_scripted)
02730c33 4496 printf("%llu", (u_longlong_t)val);
193a37cb
TH
4497 else
4498 printf("%-*s", namewidth, buf);
4499
4500 /* Print the values on the line */
4501 for (i = 0; i < len; i++) {
4502 print_one_stat(nva[i].data[j] * scale, format,
4503 column_width, cb->cb_scripted);
4504 }
4505 printf("\n");
4506 }
4507}
4508
4509static void
4510print_solid_separator(unsigned int length)
4511{
4512 while (length--)
4513 printf("-");
4514 printf("\n");
4515}
4516
4517static void
4518print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv,
4519 nvlist_t *newnv, double scale, const char *name)
4520{
4521 unsigned int column_width;
4522 unsigned int namewidth;
4523 unsigned int entire_width;
7e945072 4524 enum iostat_type type;
193a37cb 4525 struct stat_array *nva;
7e945072
TH
4526 const char **names;
4527 unsigned int names_len;
4528
4529 /* What type of histo are we? */
4530 type = IOS_HISTO_IDX(cb->cb_flags);
4531
4532 /* Get NULL-terminated array of nvlist names for our histo */
4533 names = vsx_type_to_nvlist[type];
4534 names_len = str_array_len(names); /* num of names */
4535
4536 nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv);
193a37cb
TH
4537
4538 if (cb->cb_literal) {
4539 column_width = MAX(5,
7e945072 4540 (unsigned int) log10(stat_histo_max(nva, names_len)) + 1);
193a37cb
TH
4541 } else {
4542 column_width = 5;
4543 }
4544
7e945072
TH
4545 namewidth = MAX(cb->cb_namewidth,
4546 strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]));
193a37cb
TH
4547
4548 /*
4549 * Calculate the entire line width of what we're printing. The
4550 * +2 is for the two spaces between columns:
4551 */
4552 /* read write */
4553 /* ----- ----- */
4554 /* |___| <---------- column_width */
4555 /* */
4556 /* |__________| <--- entire_width */
4557 /* */
4558 entire_width = namewidth + (column_width + 2) *
7e945072 4559 label_array_len(iostat_bottom_labels[type]);
193a37cb
TH
4560
4561 if (cb->cb_scripted)
4562 printf("%s\n", name);
4563 else
4564 print_iostat_header_impl(cb, column_width, name);
4565
7e945072 4566 print_iostat_histo(nva, names_len, cb, column_width,
193a37cb
TH
4567 namewidth, scale);
4568
7e945072 4569 free_calc_stats(nva, names_len);
193a37cb
TH
4570 if (!cb->cb_scripted)
4571 print_solid_separator(entire_width);
4572}
4573
4574/*
4575 * Calculate the average latency of a power-of-two latency histogram
4576 */
4577static uint64_t
4578single_histo_average(uint64_t *histo, unsigned int buckets)
4579{
4580 int i;
4581 uint64_t count = 0, total = 0;
4582
4583 for (i = 0; i < buckets; i++) {
4584 /*
4585 * Our buckets are power-of-two latency ranges. Use the
4586 * midpoint latency of each bucket to calculate the average.
4587 * For example:
4588 *
4589 * Bucket Midpoint
4590 * 8ns-15ns: 12ns
4591 * 16ns-31ns: 24ns
4592 * ...
4593 */
4594 if (histo[i] != 0) {
4595 total += histo[i] * (((1UL << i) + ((1UL << i)/2)));
4596 count += histo[i];
4597 }
4598 }
4599
4600 /* Prevent divide by zero */
4601 return (count == 0 ? 0 : total / count);
4602}
4603
4604static void
e40ca391 4605print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *newnv)
193a37cb 4606{
193a37cb
TH
4607 const char *names[] = {
4608 ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE,
4609 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
4610 ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE,
4611 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
4612 ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE,
4613 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
4614 ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE,
4615 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
4616 ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE,
4617 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
1b939560
BB
4618 ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE,
4619 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
00888c08
TB
4620 ZPOOL_CONFIG_VDEV_REBUILD_PEND_QUEUE,
4621 ZPOOL_CONFIG_VDEV_REBUILD_ACTIVE_QUEUE,
193a37cb
TH
4622 };
4623
4624 struct stat_array *nva;
4625
4626 unsigned int column_width = default_column_width(cb, IOS_QUEUES);
4627 enum zfs_nicenum_format format;
4628
4629 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv);
4630
4631 if (cb->cb_literal)
4632 format = ZFS_NICENUM_RAW;
4633 else
4634 format = ZFS_NICENUM_1024;
4635
e40ca391
AZ
4636 for (int i = 0; i < ARRAY_SIZE(names); i++) {
4637 uint64_t val = nva[i].data[0];
193a37cb
TH
4638 print_one_stat(val, format, column_width, cb->cb_scripted);
4639 }
4640
4641 free_calc_stats(nva, ARRAY_SIZE(names));
4642}
4643
4644static void
4645print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv,
b954e36e 4646 nvlist_t *newnv)
193a37cb
TH
4647{
4648 int i;
4649 uint64_t val;
4650 const char *names[] = {
4651 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
4652 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
4653 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
4654 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
4655 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
4656 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
4657 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
4658 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
4659 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
1b939560 4660 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
00888c08 4661 ZPOOL_CONFIG_VDEV_REBUILD_LAT_HISTO,
193a37cb
TH
4662 };
4663 struct stat_array *nva;
4664
4665 unsigned int column_width = default_column_width(cb, IOS_LATENCY);
4666 enum zfs_nicenum_format format;
4667
4668 nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv);
4669
4670 if (cb->cb_literal)
29eb4942 4671 format = ZFS_NICENUM_RAWTIME;
193a37cb
TH
4672 else
4673 format = ZFS_NICENUM_TIME;
4674
4675 /* Print our avg latencies on the line */
4676 for (i = 0; i < ARRAY_SIZE(names); i++) {
4677 /* Compute average latency for a latency histo */
b954e36e 4678 val = single_histo_average(nva[i].data, nva[i].count);
193a37cb
TH
4679 print_one_stat(val, format, column_width, cb->cb_scripted);
4680 }
4681 free_calc_stats(nva, ARRAY_SIZE(names));
4682}
4683
4684/*
4685 * Print default statistics (capacity/operations/bandwidth)
4686 */
4687static void
4688print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale)
4689{
4690 unsigned int column_width = default_column_width(cb, IOS_DEFAULT);
4691 enum zfs_nicenum_format format;
4692 char na; /* char to print for "not applicable" values */
4693
4694 if (cb->cb_literal) {
4695 format = ZFS_NICENUM_RAW;
4696 na = '0';
4697 } else {
4698 format = ZFS_NICENUM_1024;
4699 na = '-';
4700 }
4701
4702 /* only toplevel vdevs have capacity stats */
4703 if (vs->vs_space == 0) {
4704 if (cb->cb_scripted)
4705 printf("\t%c\t%c", na, na);
4706 else
4707 printf(" %*c %*c", column_width, na, column_width,
4708 na);
4709 } else {
4710 print_one_stat(vs->vs_alloc, format, column_width,
4711 cb->cb_scripted);
4712 print_one_stat(vs->vs_space - vs->vs_alloc, format,
4713 column_width, cb->cb_scripted);
4714 }
4715
4716 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale),
4717 format, column_width, cb->cb_scripted);
4718 print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale),
4719 format, column_width, cb->cb_scripted);
4720 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale),
4721 format, column_width, cb->cb_scripted);
4722 print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale),
4723 format, column_width, cb->cb_scripted);
34dc7c2f
BB
4724}
4725
cf5a9d8c 4726static const char *const class_name[] = {
cc99f275
DB
4727 VDEV_ALLOC_BIAS_DEDUP,
4728 VDEV_ALLOC_BIAS_SPECIAL,
4729 VDEV_ALLOC_CLASS_LOGS
4730};
4731
34dc7c2f
BB
4732/*
4733 * Print out all the statistics for the given vdev. This can either be the
4734 * toplevel configuration, or called recursively. If 'name' is NULL, then this
4735 * is a verbose output, and we don't want to display the toplevel pool stats.
193a37cb
TH
4736 *
4737 * Returns the number of stat lines printed.
34dc7c2f 4738 */
cc99f275 4739static unsigned int
34dc7c2f
BB
4740print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
4741 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
4742{
4743 nvlist_t **oldchild, **newchild;
674b8934 4744 uint_t c, children, oldchildren;
193a37cb 4745 vdev_stat_t *oldvs, *newvs, *calcvs;
34dc7c2f 4746 vdev_stat_t zerovs = { 0 };
193a37cb
TH
4747 char *vname;
4748 int i;
4749 int ret = 0;
34dc7c2f
BB
4750 uint64_t tdelta;
4751 double scale;
193a37cb 4752
a1d477c2
MA
4753 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
4754 return (ret);
4755
75c62019
JCML
4756 calcvs = safe_malloc(sizeof (*calcvs));
4757
34dc7c2f 4758 if (oldnv != NULL) {
428870ff
BB
4759 verify(nvlist_lookup_uint64_array(oldnv,
4760 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
34dc7c2f
BB
4761 } else {
4762 oldvs = &zerovs;
4763 }
4764
193a37cb 4765 /* Do we only want to see a specific vdev? */
2a673e76 4766 for (i = 0; i < cb->cb_vdevs.cb_names_count; i++) {
193a37cb 4767 /* Yes we do. Is this the vdev? */
2a673e76 4768 if (strcmp(name, cb->cb_vdevs.cb_names[i]) == 0) {
193a37cb
TH
4769 /*
4770 * This is our vdev. Since it is the only vdev we
4771 * will be displaying, make depth = 0 so that it
4772 * doesn't get indented.
4773 */
4774 depth = 0;
4775 break;
4776 }
4777 }
4778
2a673e76 4779 if (cb->cb_vdevs.cb_names_count && (i == cb->cb_vdevs.cb_names_count)) {
193a37cb
TH
4780 /* Couldn't match the name */
4781 goto children;
4782 }
4783
4784
428870ff 4785 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f
BB
4786 (uint64_t **)&newvs, &c) == 0);
4787
193a37cb
TH
4788 /*
4789 * Print the vdev name unless it's is a histogram. Histograms
4790 * display the vdev name in the header itself.
4791 */
7e945072 4792 if (!(cb->cb_flags & IOS_ANYHISTO_M)) {
193a37cb
TH
4793 if (cb->cb_scripted) {
4794 printf("%s", name);
4795 } else {
4796 if (strlen(name) + depth > cb->cb_namewidth)
4797 (void) printf("%*s%s", depth, "", name);
4798 else
4799 (void) printf("%*s%s%*s", depth, "", name,
4800 (int)(cb->cb_namewidth - strlen(name) -
4801 depth), "");
4802 }
4803 }
34dc7c2f 4804
193a37cb 4805 /* Calculate our scaling factor */
34dc7c2f 4806 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
7e945072 4807 if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) {
193a37cb
TH
4808 /*
4809 * If we specify printing histograms with no time interval, then
4810 * print the histogram numbers over the entire lifetime of the
4811 * vdev.
4812 */
4813 scale = 1;
34dc7c2f 4814 } else {
193a37cb
TH
4815 if (tdelta == 0)
4816 scale = 1.0;
4817 else
4818 scale = (double)NANOSEC / tdelta;
34dc7c2f
BB
4819 }
4820
193a37cb
TH
4821 if (cb->cb_flags & IOS_DEFAULT_M) {
4822 calc_default_iostats(oldvs, newvs, calcvs);
4823 print_iostat_default(calcvs, cb, scale);
4824 }
4825 if (cb->cb_flags & IOS_LATENCY_M)
b954e36e 4826 print_iostat_latency(cb, oldnv, newnv);
193a37cb 4827 if (cb->cb_flags & IOS_QUEUES_M)
e40ca391 4828 print_iostat_queues(cb, newnv);
7e945072 4829 if (cb->cb_flags & IOS_ANYHISTO_M) {
193a37cb
TH
4830 printf("\n");
4831 print_iostat_histos(cb, oldnv, newnv, scale, name);
4832 }
34dc7c2f 4833
8720e9e7 4834 if (cb->vcdl != NULL) {
d1807f16 4835 const char *path;
8720e9e7
TH
4836 if (nvlist_lookup_string(newnv, ZPOOL_CONFIG_PATH,
4837 &path) == 0) {
d6418de0 4838 printf(" ");
8720e9e7 4839 zpool_print_cmd(cb->vcdl, zpool_get_name(zhp), path);
8720e9e7
TH
4840 }
4841 }
4842
7e945072 4843 if (!(cb->cb_flags & IOS_ANYHISTO_M))
193a37cb 4844 printf("\n");
34dc7c2f 4845
193a37cb 4846 ret++;
34dc7c2f 4847
193a37cb 4848children:
92bc9278 4849
4850 free(calcvs);
4851
34dc7c2f 4852 if (!cb->cb_verbose)
193a37cb 4853 return (ret);
34dc7c2f
BB
4854
4855 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
4856 &newchild, &children) != 0)
193a37cb 4857 return (ret);
34dc7c2f 4858
674b8934
TH
4859 if (oldnv) {
4860 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
4861 &oldchild, &oldchildren) != 0)
4862 return (ret);
4863
4864 children = MIN(oldchildren, children);
4865 }
34dc7c2f 4866
cc99f275
DB
4867 /*
4868 * print normal top-level devices
4869 */
34dc7c2f 4870 for (c = 0; c < children; c++) {
187632dc 4871 uint64_t ishole = B_FALSE, islog = B_FALSE;
428870ff 4872
187632dc
MH
4873 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
4874 &ishole);
4875
4876 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4877 &islog);
4878
4879 if (ishole || islog)
428870ff
BB
4880 continue;
4881
cc99f275
DB
4882 if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
4883 continue;
4884
d2f3e292 4885 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
7b468ed2 4886 cb->cb_vdevs.cb_name_flags | VDEV_NAME_TYPE_ID);
193a37cb 4887 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
34dc7c2f
BB
4888 newchild[c], cb, depth + 2);
4889 free(vname);
4890 }
4891
187632dc 4892 /*
cc99f275 4893 * print all other top-level devices
187632dc 4894 */
cf5a9d8c 4895 for (uint_t n = 0; n < ARRAY_SIZE(class_name); n++) {
cc99f275 4896 boolean_t printed = B_FALSE;
187632dc
MH
4897
4898 for (c = 0; c < children; c++) {
4899 uint64_t islog = B_FALSE;
d1807f16
RY
4900 const char *bias = NULL;
4901 const char *type = NULL;
cc99f275 4902
187632dc
MH
4903 (void) nvlist_lookup_uint64(newchild[c],
4904 ZPOOL_CONFIG_IS_LOG, &islog);
187632dc 4905 if (islog) {
d1807f16 4906 bias = VDEV_ALLOC_CLASS_LOGS;
cc99f275
DB
4907 } else {
4908 (void) nvlist_lookup_string(newchild[c],
4909 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
4910 (void) nvlist_lookup_string(newchild[c],
4911 ZPOOL_CONFIG_TYPE, &type);
187632dc 4912 }
cc99f275
DB
4913 if (bias == NULL || strcmp(bias, class_name[n]) != 0)
4914 continue;
4915 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
4916 continue;
187632dc 4917
cc99f275
DB
4918 if (!printed) {
4919 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) &&
2a673e76
AJ
4920 !cb->cb_scripted &&
4921 !cb->cb_vdevs.cb_names) {
cc99f275
DB
4922 print_iostat_dashes(cb, 0,
4923 class_name[n]);
4924 }
4925 printf("\n");
4926 printed = B_TRUE;
4927 }
4928
4929 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
7b468ed2 4930 cb->cb_vdevs.cb_name_flags | VDEV_NAME_TYPE_ID);
cc99f275
DB
4931 ret += print_vdev_stats(zhp, vname, oldnv ?
4932 oldchild[c] : NULL, newchild[c], cb, depth + 2);
4933 free(vname);
4934 }
187632dc
MH
4935 }
4936
34dc7c2f
BB
4937 /*
4938 * Include level 2 ARC devices in iostat output
4939 */
4940 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
4941 &newchild, &children) != 0)
193a37cb 4942 return (ret);
34dc7c2f 4943
674b8934
TH
4944 if (oldnv) {
4945 if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
4946 &oldchild, &oldchildren) != 0)
4947 return (ret);
4948
4949 children = MIN(oldchildren, children);
4950 }
34dc7c2f
BB
4951
4952 if (children > 0) {
7e945072 4953 if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted &&
2a673e76 4954 !cb->cb_vdevs.cb_names) {
193a37cb
TH
4955 print_iostat_dashes(cb, 0, "cache");
4956 }
5034557b 4957 printf("\n");
193a37cb 4958
34dc7c2f 4959 for (c = 0; c < children; c++) {
428870ff 4960 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2a673e76 4961 cb->cb_vdevs.cb_name_flags);
193a37cb
TH
4962 ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c]
4963 : NULL, newchild[c], cb, depth + 2);
34dc7c2f
BB
4964 free(vname);
4965 }
4966 }
193a37cb
TH
4967
4968 return (ret);
34dc7c2f
BB
4969}
4970
4971static int
4972refresh_iostat(zpool_handle_t *zhp, void *data)
4973{
4974 iostat_cbdata_t *cb = data;
4975 boolean_t missing;
4976
4977 /*
4978 * If the pool has disappeared, remove it from the list and continue.
4979 */
4980 if (zpool_refresh_stats(zhp, &missing) != 0)
4981 return (-1);
4982
4983 if (missing)
4984 pool_list_remove(cb->cb_list, zhp);
4985
4986 return (0);
4987}
4988
4989/*
4990 * Callback to print out the iostats for the given pool.
4991 */
65c7cc49 4992static int
34dc7c2f
BB
4993print_iostat(zpool_handle_t *zhp, void *data)
4994{
4995 iostat_cbdata_t *cb = data;
4996 nvlist_t *oldconfig, *newconfig;
4997 nvlist_t *oldnvroot, *newnvroot;
193a37cb 4998 int ret;
34dc7c2f
BB
4999
5000 newconfig = zpool_get_config(zhp, &oldconfig);
5001
5002 if (cb->cb_iteration == 1)
5003 oldconfig = NULL;
5004
5005 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
5006 &newnvroot) == 0);
5007
5008 if (oldconfig == NULL)
5009 oldnvroot = NULL;
5010 else
5011 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
5012 &oldnvroot) == 0);
5013
193a37cb 5014 ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot,
02730c33 5015 cb, 0);
7e945072 5016 if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) &&
2a673e76
AJ
5017 !cb->cb_scripted && cb->cb_verbose &&
5018 !cb->cb_vdevs.cb_names_count) {
7e945072 5019 print_iostat_separator(cb);
d6418de0
TH
5020 if (cb->vcdl != NULL) {
5021 print_cmd_columns(cb->vcdl, 1);
5022 }
5023 printf("\n");
7e945072 5024 }
34dc7c2f 5025
193a37cb 5026 return (ret);
34dc7c2f
BB
5027}
5028
9fc60702
CS
5029static int
5030get_columns(void)
5031{
5032 struct winsize ws;
5033 int columns = 80;
5034 int error;
5035
5036 if (isatty(STDOUT_FILENO)) {
5037 error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
5038 if (error == 0)
5039 columns = ws.ws_col;
5040 } else {
5041 columns = 999;
5042 }
5043
d1d7e268 5044 return (columns);
9fc60702
CS
5045}
5046
c5eea0ab
BB
5047/*
5048 * Return the required length of the pool/vdev name column. The minimum
5049 * allowed width and output formatting flags must be provided.
5050 */
5051static int
5052get_namewidth(zpool_handle_t *zhp, int min_width, int flags, boolean_t verbose)
34dc7c2f 5053{
34dc7c2f 5054 nvlist_t *config, *nvroot;
c5eea0ab 5055 int width = min_width;
34dc7c2f
BB
5056
5057 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
5058 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5059 &nvroot) == 0);
06b80506 5060 size_t poolname_len = strlen(zpool_get_name(zhp));
c5eea0ab
BB
5061 if (verbose == B_FALSE) {
5062 width = MAX(poolname_len, min_width);
5063 } else {
5064 width = MAX(poolname_len,
5065 max_width(zhp, nvroot, 0, min_width, flags));
5066 }
34dc7c2f 5067 }
9fc60702 5068
c5eea0ab 5069 return (width);
34dc7c2f
BB
5070}
5071
5072/*
428870ff 5073 * Parse the input string, get the 'interval' and 'count' value if there is one.
34dc7c2f 5074 */
428870ff 5075static void
193a37cb 5076get_interval_count(int *argcp, char **argv, float *iv,
428870ff 5077 unsigned long *cnt)
34dc7c2f 5078{
193a37cb
TH
5079 float interval = 0;
5080 unsigned long count = 0;
1fde1e37 5081 int argc = *argcp;
34dc7c2f
BB
5082
5083 /*
5084 * Determine if the last argument is an integer or a pool name
5085 */
3283f137 5086 if (argc > 0 && zfs_isnumber(argv[argc - 1])) {
34dc7c2f
BB
5087 char *end;
5088
5089 errno = 0;
193a37cb 5090 interval = strtof(argv[argc - 1], &end);
34dc7c2f
BB
5091
5092 if (*end == '\0' && errno == 0) {
5093 if (interval == 0) {
61b50107
AZ
5094 (void) fprintf(stderr, gettext(
5095 "interval cannot be zero\n"));
34dc7c2f
BB
5096 usage(B_FALSE);
5097 }
34dc7c2f
BB
5098 /*
5099 * Ignore the last parameter
5100 */
5101 argc--;
5102 } else {
5103 /*
5104 * If this is not a valid number, just plow on. The
5105 * user will get a more informative error message later
5106 * on.
5107 */
5108 interval = 0;
5109 }
5110 }
5111
5112 /*
5113 * If the last argument is also an integer, then we have both a count
428870ff 5114 * and an interval.
34dc7c2f 5115 */
3283f137 5116 if (argc > 0 && zfs_isnumber(argv[argc - 1])) {
34dc7c2f
BB
5117 char *end;
5118
5119 errno = 0;
5120 count = interval;
193a37cb 5121 interval = strtof(argv[argc - 1], &end);
34dc7c2f
BB
5122
5123 if (*end == '\0' && errno == 0) {
5124 if (interval == 0) {
61b50107
AZ
5125 (void) fprintf(stderr, gettext(
5126 "interval cannot be zero\n"));
34dc7c2f
BB
5127 usage(B_FALSE);
5128 }
5129
5130 /*
5131 * Ignore the last parameter
5132 */
5133 argc--;
5134 } else {
5135 interval = 0;
5136 }
5137 }
5138
428870ff
BB
5139 *iv = interval;
5140 *cnt = count;
5141 *argcp = argc;
5142}
5143
5144static void
5145get_timestamp_arg(char c)
5146{
5147 if (c == 'u')
5148 timestamp_fmt = UDATE;
5149 else if (c == 'd')
5150 timestamp_fmt = DDATE;
5151 else
5152 usage(B_FALSE);
5153}
5154
5155/*
193a37cb
TH
5156 * Return stat flags that are supported by all pools by both the module and
5157 * zpool iostat. "*data" should be initialized to all 0xFFs before running.
5158 * It will get ANDed down until only the flags that are supported on all pools
5159 * remain.
5160 */
5161static int
5162get_stat_flags_cb(zpool_handle_t *zhp, void *data)
5163{
5164 uint64_t *mask = data;
5165 nvlist_t *config, *nvroot, *nvx;
5166 uint64_t flags = 0;
5167 int i, j;
5168
193a37cb
TH
5169 config = zpool_get_config(zhp, NULL);
5170 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
5171 &nvroot) == 0);
5172
5173 /* Default stats are always supported, but for completeness.. */
5174 if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS))
5175 flags |= IOS_DEFAULT_M;
5176
5177 /* Get our extended stats nvlist from the main list */
5178 if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX,
5179 &nvx) != 0) {
5180 /*
5181 * No extended stats; they're probably running an older
5182 * module. No big deal, we support that too.
5183 */
5184 goto end;
5185 }
5186
5187 /* For each extended stat, make sure all its nvpairs are supported */
5188 for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) {
5189 if (!vsx_type_to_nvlist[j][0])
5190 continue;
5191
5192 /* Start off by assuming the flag is supported, then check */
5193 flags |= (1ULL << j);
5194 for (i = 0; vsx_type_to_nvlist[j][i]; i++) {
5195 if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) {
5196 /* flag isn't supported */
5197 flags = flags & ~(1ULL << j);
5198 break;
5199 }
5200 }
5201 }
5202end:
5203 *mask = *mask & flags;
5204 return (0);
5205}
5206
5207/*
5208 * Return a bitmask of stats that are supported on all pools by both the module
5209 * and zpool iostat.
5210 */
5211static uint64_t
5212get_stat_flags(zpool_list_t *list)
5213{
5214 uint64_t mask = -1;
5215
5216 /*
5217 * get_stat_flags_cb() will lop off bits from "mask" until only the
5218 * flags that are supported on all pools remain.
5219 */
5220 pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask);
5221 return (mask);
5222}
5223
5224/*
2a673e76 5225 * Return 1 if cb_data->cb_names[0] is this vdev's name, 0 otherwise.
193a37cb
TH
5226 */
5227static int
2a8430a2 5228is_vdev_cb(void *zhp_data, nvlist_t *nv, void *cb_data)
193a37cb 5229{
6f2ffd27 5230 uint64_t guid;
2a673e76 5231 vdev_cbdata_t *cb = cb_data;
2a8430a2 5232 zpool_handle_t *zhp = zhp_data;
193a37cb 5233
6f2ffd27
RW
5234 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) != 0)
5235 return (0);
193a37cb 5236
6f2ffd27 5237 return (guid == zpool_vdev_path_to_guid(zhp, cb->cb_names[0]));
193a37cb
TH
5238}
5239
5240/*
2a673e76 5241 * Returns 1 if cb_data->cb_names[0] is a vdev name, 0 otherwise.
193a37cb
TH
5242 */
5243static int
5244is_vdev(zpool_handle_t *zhp, void *cb_data)
5245{
5246 return (for_each_vdev(zhp, is_vdev_cb, cb_data));
5247}
5248
5249/*
5250 * Check if vdevs are in a pool
5251 *
5252 * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise
5253 * return 0. If pool_name is NULL, then search all pools.
5254 */
5255static int
5256are_vdevs_in_pool(int argc, char **argv, char *pool_name,
2a673e76 5257 vdev_cbdata_t *cb)
193a37cb
TH
5258{
5259 char **tmp_name;
5260 int ret = 0;
5261 int i;
5262 int pool_count = 0;
5263
5264 if ((argc == 0) || !*argv)
5265 return (0);
5266
5267 if (pool_name)
5268 pool_count = 1;
5269
2a673e76
AJ
5270 /* Temporarily hijack cb_names for a second... */
5271 tmp_name = cb->cb_names;
193a37cb
TH
5272
5273 /* Go though our list of prospective vdev names */
5274 for (i = 0; i < argc; i++) {
2a673e76 5275 cb->cb_names = argv + i;
193a37cb
TH
5276
5277 /* Is this name a vdev in our pools? */
5278 ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL,
2a673e76 5279 ZFS_TYPE_POOL, B_FALSE, is_vdev, cb);
193a37cb
TH
5280 if (!ret) {
5281 /* No match */
5282 break;
5283 }
5284 }
5285
2a673e76 5286 cb->cb_names = tmp_name;
193a37cb
TH
5287
5288 return (ret);
5289}
5290
5291static int
5292is_pool_cb(zpool_handle_t *zhp, void *data)
5293{
5294 char *name = data;
5295 if (strcmp(name, zpool_get_name(zhp)) == 0)
5296 return (1);
5297
5298 return (0);
5299}
5300
5301/*
5302 * Do we have a pool named *name? If so, return 1, otherwise 0.
5303 */
5304static int
5305is_pool(char *name)
5306{
2a673e76
AJ
5307 return (for_each_pool(0, NULL, B_TRUE, NULL, ZFS_TYPE_POOL, B_FALSE,
5308 is_pool_cb, name));
193a37cb
TH
5309}
5310
5311/* Are all our argv[] strings pool names? If so return 1, 0 otherwise. */
5312static int
4ea3f864
GM
5313are_all_pools(int argc, char **argv)
5314{
193a37cb
TH
5315 if ((argc == 0) || !*argv)
5316 return (0);
5317
5318 while (--argc >= 0)
5319 if (!is_pool(argv[argc]))
5320 return (0);
5321
5322 return (1);
5323}
5324
5325/*
5326 * Helper function to print out vdev/pool names we can't resolve. Used for an
5327 * error message.
5328 */
5329static void
5330error_list_unresolved_vdevs(int argc, char **argv, char *pool_name,
2a673e76 5331 vdev_cbdata_t *cb)
193a37cb
TH
5332{
5333 int i;
5334 char *name;
5335 char *str;
5336 for (i = 0; i < argc; i++) {
5337 name = argv[i];
5338
5339 if (is_pool(name))
5340 str = gettext("pool");
5341 else if (are_vdevs_in_pool(1, &name, pool_name, cb))
5342 str = gettext("vdev in this pool");
5343 else if (are_vdevs_in_pool(1, &name, NULL, cb))
5344 str = gettext("vdev in another pool");
5345 else
5346 str = gettext("unknown");
5347
5348 fprintf(stderr, "\t%s (%s)\n", name, str);
5349 }
5350}
5351
5352/*
5353 * Same as get_interval_count(), but with additional checks to not misinterpret
5354 * guids as interval/count values. Assumes VDEV_NAME_GUID is set in
2a673e76 5355 * cb.cb_vdevs.cb_name_flags.
193a37cb
TH
5356 */
5357static void
5358get_interval_count_filter_guids(int *argc, char **argv, float *interval,
5359 unsigned long *count, iostat_cbdata_t *cb)
5360{
5361 char **tmpargv = argv;
5362 int argc_for_interval = 0;
5363
5364 /* Is the last arg an interval value? Or a guid? */
2a673e76
AJ
5365 if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL,
5366 &cb->cb_vdevs)) {
193a37cb
TH
5367 /*
5368 * The last arg is not a guid, so it's probably an
5369 * interval value.
5370 */
5371 argc_for_interval++;
5372
5373 if (*argc >= 2 &&
2a673e76
AJ
5374 !are_vdevs_in_pool(1, &argv[*argc - 2], NULL,
5375 &cb->cb_vdevs)) {
193a37cb
TH
5376 /*
5377 * The 2nd to last arg is not a guid, so it's probably
5378 * an interval value.
5379 */
5380 argc_for_interval++;
5381 }
5382 }
5383
5384 /* Point to our list of possible intervals */
5385 tmpargv = &argv[*argc - argc_for_interval];
5386
5387 *argc = *argc - argc_for_interval;
5388 get_interval_count(&argc_for_interval, tmpargv,
5389 interval, count);
5390}
5391
5392/*
5393 * Floating point sleep(). Allows you to pass in a floating point value for
5394 * seconds.
5395 */
5396static void
4ea3f864
GM
5397fsleep(float sec)
5398{
193a37cb
TH
5399 struct timespec req;
5400 req.tv_sec = floor(sec);
5401 req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC;
5402 nanosleep(&req, NULL);
5403}
5404
e60e158e
JG
5405/*
5406 * Terminal height, in rows. Returns -1 if stdout is not connected to a TTY or
5407 * if we were unable to determine its size.
5408 */
5409static int
5410terminal_height(void)
5411{
5412 struct winsize win;
5413
5414 if (isatty(STDOUT_FILENO) == 0)
5415 return (-1);
5416
5417 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1 && win.ws_row > 0)
5418 return (win.ws_row);
5419
5420 return (-1);
5421}
5422
d6418de0
TH
5423/*
5424 * Run one of the zpool status/iostat -c scripts with the help (-h) option and
5425 * print the result.
5426 *
5427 * name: Short name of the script ('iostat').
5428 * path: Full path to the script ('/usr/local/etc/zfs/zpool.d/iostat');
5429 */
5430static void
5431print_zpool_script_help(char *name, char *path)
5432{
a926aab9 5433 char *argv[] = {path, (char *)"-h", NULL};
d6418de0
TH
5434 char **lines = NULL;
5435 int lines_cnt = 0;
5436 int rc;
5437
5438 rc = libzfs_run_process_get_stdout_nopath(path, argv, NULL, &lines,
5439 &lines_cnt);
3e2ecae0
GDN
5440 if (rc != 0 || lines == NULL || lines_cnt <= 0) {
5441 if (lines != NULL)
5442 libzfs_free_str_array(lines, lines_cnt);
d6418de0 5443 return;
3e2ecae0 5444 }
d6418de0
TH
5445
5446 for (int i = 0; i < lines_cnt; i++)
5447 if (!is_blank_str(lines[i]))
5448 printf(" %-14s %s\n", name, lines[i]);
5449
5450 libzfs_free_str_array(lines, lines_cnt);
5451}
5452
193a37cb 5453/*
099700d9 5454 * Go though the zpool status/iostat -c scripts in the user's path, run their
d6418de0
TH
5455 * help option (-h), and print out the results.
5456 */
5457static void
099700d9 5458print_zpool_dir_scripts(char *dirpath)
d6418de0
TH
5459{
5460 DIR *dir;
5461 struct dirent *ent;
5462 char fullpath[MAXPATHLEN];
5463 struct stat dir_stat;
5464
099700d9 5465 if ((dir = opendir(dirpath)) != NULL) {
d6418de0
TH
5466 /* print all the files and directories within directory */
5467 while ((ent = readdir(dir)) != NULL) {
ba87ed14
RY
5468 if (snprintf(fullpath, sizeof (fullpath), "%s/%s",
5469 dirpath, ent->d_name) >= sizeof (fullpath)) {
5470 (void) fprintf(stderr,
5471 gettext("internal error: "
5472 "ZPOOL_SCRIPTS_PATH too large.\n"));
5473 exit(1);
5474 }
d6418de0
TH
5475
5476 /* Print the scripts */
5477 if (stat(fullpath, &dir_stat) == 0)
5478 if (dir_stat.st_mode & S_IXUSR &&
5479 S_ISREG(dir_stat.st_mode))
5480 print_zpool_script_help(ent->d_name,
5481 fullpath);
5482 }
d6418de0 5483 closedir(dir);
d6418de0
TH
5484 }
5485}
5486
099700d9
GDN
5487/*
5488 * Print out help text for all zpool status/iostat -c scripts.
5489 */
5490static void
a926aab9 5491print_zpool_script_list(const char *subcommand)
099700d9 5492{
1ce6d70c 5493 char *dir, *sp, *tmp;
099700d9
GDN
5494
5495 printf(gettext("Available 'zpool %s -c' commands:\n"), subcommand);
5496
5497 sp = zpool_get_cmd_search_path();
5498 if (sp == NULL)
5499 return;
5500
1ce6d70c
AZ
5501 for (dir = strtok_r(sp, ":", &tmp);
5502 dir != NULL;
5503 dir = strtok_r(NULL, ":", &tmp))
099700d9 5504 print_zpool_dir_scripts(dir);
099700d9
GDN
5505
5506 free(sp);
5507}
5508
c5eea0ab
BB
5509/*
5510 * Set the minimum pool/vdev name column width. The width must be at least 10,
5511 * but may be as large as the column width - 42 so it still fits on one line.
a36bad17 5512 * NOTE: 42 is the width of the default capacity/operations/bandwidth output
c5eea0ab
BB
5513 */
5514static int
5515get_namewidth_iostat(zpool_handle_t *zhp, void *data)
5516{
5517 iostat_cbdata_t *cb = data;
a36bad17 5518 int width, available_width;
c5eea0ab 5519
a36bad17
PP
5520 /*
5521 * get_namewidth() returns the maximum width of any name in that column
5522 * for any pool/vdev/device line that will be output.
5523 */
7c0e3941
SW
5524 width = get_namewidth(zhp, cb->cb_namewidth,
5525 cb->cb_vdevs.cb_name_flags | VDEV_NAME_TYPE_ID, cb->cb_verbose);
c5eea0ab 5526
a36bad17
PP
5527 /*
5528 * The width we are calculating is the width of the header and also the
5529 * padding width for names that are less than maximum width. The stats
5530 * take up 42 characters, so the width available for names is:
5531 */
5532 available_width = get_columns() - 42;
5533
5534 /*
5535 * If the maximum width fits on a screen, then great! Make everything
5536 * line up by justifying all lines to the same width. If that max
5537 * width is larger than what's available, the name plus stats won't fit
5538 * on one line, and justifying to that width would cause every line to
5539 * wrap on the screen. We only want lines with long names to wrap.
5540 * Limit the padding to what won't wrap.
5541 */
5542 if (width > available_width)
5543 width = available_width;
5544
5545 /*
5546 * And regardless of whatever the screen width is (get_columns can
5547 * return 0 if the width is not known or less than 42 for a narrow
5548 * terminal) have the width be a minimum of 10.
5549 */
c5eea0ab
BB
5550 if (width < 10)
5551 width = 10;
c5eea0ab 5552
a36bad17 5553 /* Save the calculated width */
c5eea0ab
BB
5554 cb->cb_namewidth = width;
5555
5556 return (0);
5557}
5558
d6418de0
TH
5559/*
5560 * zpool iostat [[-c [script1,script2,...]] [-lq]|[-rw]] [-ghHLpPvy] [-n name]
5561 * [-T d|u] [[ pool ...]|[pool vdev ...]|[vdev ...]]
5562 * [interval [count]]
428870ff 5563 *
8720e9e7 5564 * -c CMD For each vdev, run command CMD
d2f3e292
RY
5565 * -g Display guid for individual vdev name.
5566 * -L Follow links when resolving vdev path name.
a77f29f9 5567 * -P Display full path for vdev name.
428870ff 5568 * -v Display statistics for individual vdevs
193a37cb
TH
5569 * -h Display help
5570 * -p Display values in parsable (exact) format.
5571 * -H Scripted mode. Don't display headers, and separate properties
5572 * by a single tab.
5573 * -l Display average latency
5574 * -q Display queue depths
7e945072
TH
5575 * -w Display latency histograms
5576 * -r Display request size histogram
428870ff 5577 * -T Display a timestamp in date(1) or Unix format
8fccfa8e 5578 * -n Only print headers once
428870ff
BB
5579 *
5580 * This command can be tricky because we want to be able to deal with pool
5581 * creation/destruction as well as vdev configuration changes. The bulk of this
5582 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
5583 * on pool_list_update() to detect the addition of new pools. Configuration
5584 * changes are all handled within libzfs.
5585 */
5586int
5587zpool_do_iostat(int argc, char **argv)
5588{
5589 int c;
5590 int ret;
5591 int npools;
193a37cb
TH
5592 float interval = 0;
5593 unsigned long count = 0;
8fccfa8e 5594 int winheight = 24;
428870ff
BB
5595 zpool_list_t *list;
5596 boolean_t verbose = B_FALSE;
7e945072 5597 boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
3491d6eb 5598 boolean_t queues = B_FALSE, parsable = B_FALSE, scripted = B_FALSE;
41092124 5599 boolean_t omit_since_boot = B_FALSE;
d2f3e292
RY
5600 boolean_t guid = B_FALSE;
5601 boolean_t follow_links = B_FALSE;
5602 boolean_t full_name = B_FALSE;
8fccfa8e 5603 boolean_t headers_once = B_FALSE;
d2f3e292 5604 iostat_cbdata_t cb = { 0 };
8720e9e7 5605 char *cmd = NULL;
428870ff 5606
193a37cb
TH
5607 /* Used for printing error message */
5608 const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q',
7e945072 5609 [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'};
193a37cb
TH
5610
5611 uint64_t unsupported_flags;
5612
428870ff 5613 /* check options */
8fccfa8e 5614 while ((c = getopt(argc, argv, "c:gLPT:vyhplqrwnH")) != -1) {
428870ff 5615 switch (c) {
8720e9e7 5616 case 'c':
d6418de0
TH
5617 if (cmd != NULL) {
5618 fprintf(stderr,
5619 gettext("Can't set -c flag twice\n"));
5620 exit(1);
5621 }
099700d9
GDN
5622
5623 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL &&
5624 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) {
5625 fprintf(stderr, gettext(
5626 "Can't run -c, disabled by "
5627 "ZPOOL_SCRIPTS_ENABLED.\n"));
5628 exit(1);
5629 }
5630
d6418de0
TH
5631 if ((getuid() <= 0 || geteuid() <= 0) &&
5632 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) {
5633 fprintf(stderr, gettext(
5634 "Can't run -c with root privileges "
5635 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n"));
5636 exit(1);
5637 }
8720e9e7 5638 cmd = optarg;
d6418de0 5639 verbose = B_TRUE;
8720e9e7 5640 break;
d2f3e292
RY
5641 case 'g':
5642 guid = B_TRUE;
5643 break;
5644 case 'L':
5645 follow_links = B_TRUE;
5646 break;
a77f29f9 5647 case 'P':
d2f3e292
RY
5648 full_name = B_TRUE;
5649 break;
428870ff
BB
5650 case 'T':
5651 get_timestamp_arg(*optarg);
5652 break;
5653 case 'v':
5654 verbose = B_TRUE;
5655 break;
193a37cb 5656 case 'p':
3491d6eb 5657 parsable = B_TRUE;
193a37cb
TH
5658 break;
5659 case 'l':
5660 latency = B_TRUE;
5661 break;
5662 case 'q':
5663 queues = B_TRUE;
5664 break;
5665 case 'H':
5666 scripted = B_TRUE;
5667 break;
5668 case 'w':
7e945072
TH
5669 l_histo = B_TRUE;
5670 break;
5671 case 'r':
5672 rq_histo = B_TRUE;
193a37cb 5673 break;
41092124
HM
5674 case 'y':
5675 omit_since_boot = B_TRUE;
5676 break;
8fccfa8e
DW
5677 case 'n':
5678 headers_once = B_TRUE;
5679 break;
193a37cb
TH
5680 case 'h':
5681 usage(B_FALSE);
5682 break;
428870ff 5683 case '?':
1528bfdb 5684 if (optopt == 'c') {
099700d9 5685 print_zpool_script_list("iostat");
d6418de0 5686 exit(0);
1528bfdb
TH
5687 } else {
5688 fprintf(stderr,
5689 gettext("invalid option '%c'\n"), optopt);
5690 }
428870ff
BB
5691 usage(B_FALSE);
5692 }
5693 }
5694
5695 argc -= optind;
5696 argv += optind;
5697
3491d6eb 5698 cb.cb_literal = parsable;
193a37cb
TH
5699 cb.cb_scripted = scripted;
5700
5701 if (guid)
2a673e76 5702 cb.cb_vdevs.cb_name_flags |= VDEV_NAME_GUID;
193a37cb 5703 if (follow_links)
2a673e76 5704 cb.cb_vdevs.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
193a37cb 5705 if (full_name)
2a673e76 5706 cb.cb_vdevs.cb_name_flags |= VDEV_NAME_PATH;
193a37cb
TH
5707 cb.cb_iteration = 0;
5708 cb.cb_namewidth = 0;
5709 cb.cb_verbose = verbose;
5710
5711 /* Get our interval and count values (if any) */
5712 if (guid) {
5713 get_interval_count_filter_guids(&argc, argv, &interval,
5714 &count, &cb);
5715 } else {
5716 get_interval_count(&argc, argv, &interval, &count);
5717 }
5718
5719 if (argc == 0) {
5720 /* No args, so just print the defaults. */
5721 } else if (are_all_pools(argc, argv)) {
5722 /* All the args are pool names */
2a673e76 5723 } else if (are_vdevs_in_pool(argc, argv, NULL, &cb.cb_vdevs)) {
193a37cb 5724 /* All the args are vdevs */
2a673e76
AJ
5725 cb.cb_vdevs.cb_names = argv;
5726 cb.cb_vdevs.cb_names_count = argc;
193a37cb
TH
5727 argc = 0; /* No pools to process */
5728 } else if (are_all_pools(1, argv)) {
5729 /* The first arg is a pool name */
2a673e76
AJ
5730 if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0],
5731 &cb.cb_vdevs)) {
193a37cb 5732 /* ...and the rest are vdev names */
2a673e76
AJ
5733 cb.cb_vdevs.cb_names = argv + 1;
5734 cb.cb_vdevs.cb_names_count = argc - 1;
193a37cb
TH
5735 argc = 1; /* One pool to process */
5736 } else {
5737 fprintf(stderr, gettext("Expected either a list of "));
5738 fprintf(stderr, gettext("pools, or list of vdevs in"));
5739 fprintf(stderr, " \"%s\", ", argv[0]);
5740 fprintf(stderr, gettext("but got:\n"));
5741 error_list_unresolved_vdevs(argc - 1, argv + 1,
2a673e76 5742 argv[0], &cb.cb_vdevs);
193a37cb
TH
5743 fprintf(stderr, "\n");
5744 usage(B_FALSE);
5745 return (1);
5746 }
5747 } else {
5748 /*
5749 * The args don't make sense. The first arg isn't a pool name,
5750 * nor are all the args vdevs.
5751 */
5752 fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n"));
5753 fprintf(stderr, "\n");
5754 return (1);
5755 }
5756
2a673e76 5757 if (cb.cb_vdevs.cb_names_count != 0) {
193a37cb
TH
5758 /*
5759 * If user specified vdevs, it implies verbose.
5760 */
5761 cb.cb_verbose = B_TRUE;
5762 }
428870ff 5763
34dc7c2f
BB
5764 /*
5765 * Construct the list of all interesting pools.
5766 */
5767 ret = 0;
2a673e76
AJ
5768 if ((list = pool_list_get(argc, argv, NULL, ZFS_TYPE_POOL, parsable,
5769 &ret)) == NULL)
34dc7c2f
BB
5770 return (1);
5771
5772 if (pool_list_count(list) == 0 && argc != 0) {
5773 pool_list_free(list);
5774 return (1);
5775 }
5776
5777 if (pool_list_count(list) == 0 && interval == 0) {
5778 pool_list_free(list);
5779 (void) fprintf(stderr, gettext("no pools available\n"));
5780 return (1);
5781 }
5782
d6418de0 5783 if ((l_histo || rq_histo) && (cmd != NULL || latency || queues)) {
7e945072
TH
5784 pool_list_free(list);
5785 (void) fprintf(stderr,
d6418de0 5786 gettext("[-r|-w] isn't allowed with [-c|-l|-q]\n"));
7e945072
TH
5787 usage(B_FALSE);
5788 return (1);
5789 }
5790
5791 if (l_histo && rq_histo) {
193a37cb
TH
5792 pool_list_free(list);
5793 (void) fprintf(stderr,
7e945072 5794 gettext("Only one of [-r|-w] can be passed at a time\n"));
193a37cb
TH
5795 usage(B_FALSE);
5796 return (1);
5797 }
5798
34dc7c2f
BB
5799 /*
5800 * Enter the main iostat loop.
5801 */
5802 cb.cb_list = list;
193a37cb 5803
7e945072 5804 if (l_histo) {
193a37cb
TH
5805 /*
5806 * Histograms tables look out of place when you try to display
5807 * them with the other stats, so make a rule that you can only
5808 * print histograms by themselves.
5809 */
5810 cb.cb_flags = IOS_L_HISTO_M;
7e945072
TH
5811 } else if (rq_histo) {
5812 cb.cb_flags = IOS_RQ_HISTO_M;
193a37cb
TH
5813 } else {
5814 cb.cb_flags = IOS_DEFAULT_M;
5815 if (latency)
5816 cb.cb_flags |= IOS_LATENCY_M;
5817 if (queues)
5818 cb.cb_flags |= IOS_QUEUES_M;
5819 }
5820
5821 /*
5822 * See if the module supports all the stats we want to display.
5823 */
5824 unsupported_flags = cb.cb_flags & ~get_stat_flags(list);
5825 if (unsupported_flags) {
5826 uint64_t f;
5827 int idx;
5828 fprintf(stderr,
5829 gettext("The loaded zfs module doesn't support:"));
5830
5831 /* for each bit set in unsupported_flags */
5832 for (f = unsupported_flags; f; f &= ~(1ULL << idx)) {
5833 idx = lowbit64(f) - 1;
5834 fprintf(stderr, " -%c", flag_to_arg[idx]);
5835 }
5836
02730c33 5837 fprintf(stderr, ". Try running a newer module.\n");
193a37cb
TH
5838 pool_list_free(list);
5839
5840 return (1);
5841 }
5842
34dc7c2f 5843 for (;;) {
34dc7c2f 5844 if ((npools = pool_list_count(list)) == 0)
42cb3819 5845 (void) fprintf(stderr, gettext("no pools available\n"));
5a521059 5846 else {
41092124
HM
5847 /*
5848 * If this is the first iteration and -y was supplied
5849 * we skip any printing.
5850 */
5851 boolean_t skip = (omit_since_boot &&
193a37cb 5852 cb.cb_iteration == 0);
41092124 5853
5a521059
PJ
5854 /*
5855 * Refresh all statistics. This is done as an
5856 * explicit step before calculating the maximum name
5857 * width, so that any * configuration changes are
5858 * properly accounted for.
5859 */
5860 (void) pool_list_iter(list, B_FALSE, refresh_iostat,
193a37cb 5861 &cb);
34dc7c2f 5862
5a521059
PJ
5863 /*
5864 * Iterate over all pools to determine the maximum width
5865 * for the pool / device name column across all pools.
5866 */
5867 cb.cb_namewidth = 0;
c5eea0ab
BB
5868 (void) pool_list_iter(list, B_FALSE,
5869 get_namewidth_iostat, &cb);
34dc7c2f 5870
5a521059
PJ
5871 if (timestamp_fmt != NODATE)
5872 print_timestamp(timestamp_fmt);
428870ff 5873
d6418de0
TH
5874 if (cmd != NULL && cb.cb_verbose &&
5875 !(cb.cb_flags & IOS_ANYHISTO_M)) {
5876 cb.vcdl = all_pools_for_each_vdev_run(argc,
2a673e76
AJ
5877 argv, cmd, g_zfs, cb.cb_vdevs.cb_names,
5878 cb.cb_vdevs.cb_names_count,
5879 cb.cb_vdevs.cb_name_flags);
d6418de0
TH
5880 } else {
5881 cb.vcdl = NULL;
5882 }
5883
8fccfa8e
DW
5884
5885 /*
5886 * Check terminal size so we can print headers
5887 * even when terminal window has its height
5888 * changed.
5889 */
e60e158e
JG
5890 winheight = terminal_height();
5891 /*
5892 * Are we connected to TTY? If not, headers_once
5893 * should be true, to avoid breaking scripts.
5894 */
5895 if (winheight < 0)
5896 headers_once = B_TRUE;
8fccfa8e 5897
5a521059 5898 /*
41092124
HM
5899 * If it's the first time and we're not skipping it,
5900 * or either skip or verbose mode, print the header.
193a37cb
TH
5901 *
5902 * The histogram code explicitly prints its header on
5903 * every vdev, so skip this for histograms.
5a521059 5904 */
193a37cb 5905 if (((++cb.cb_iteration == 1 && !skip) ||
8fccfa8e
DW
5906 (skip != verbose) ||
5907 (!headers_once &&
5908 (cb.cb_iteration % winheight) == 0)) &&
7e945072 5909 (!(cb.cb_flags & IOS_ANYHISTO_M)) &&
193a37cb 5910 !cb.cb_scripted)
5a521059 5911 print_iostat_header(&cb);
34dc7c2f 5912
41092124 5913 if (skip) {
193a37cb 5914 (void) fsleep(interval);
41092124
HM
5915 continue;
5916 }
5917
193a37cb 5918 pool_list_iter(list, B_FALSE, print_iostat, &cb);
34dc7c2f 5919
5a521059
PJ
5920 /*
5921 * If there's more than one pool, and we're not in
5922 * verbose mode (which prints a separator for us),
5923 * then print a separator.
193a37cb
TH
5924 *
5925 * In addition, if we're printing specific vdevs then
5926 * we also want an ending separator.
5a521059 5927 */
193a37cb 5928 if (((npools > 1 && !verbose &&
7e945072
TH
5929 !(cb.cb_flags & IOS_ANYHISTO_M)) ||
5930 (!(cb.cb_flags & IOS_ANYHISTO_M) &&
2a673e76 5931 cb.cb_vdevs.cb_names_count)) &&
193a37cb 5932 !cb.cb_scripted) {
5a521059 5933 print_iostat_separator(&cb);
d6418de0
TH
5934 if (cb.vcdl != NULL)
5935 print_cmd_columns(cb.vcdl, 1);
5936 printf("\n");
193a37cb 5937 }
d6418de0
TH
5938
5939 if (cb.vcdl != NULL)
5940 free_vdev_cmd_data_list(cb.vcdl);
5941
5a521059 5942 }
34dc7c2f
BB
5943
5944 /*
5945 * Flush the output so that redirection to a file isn't buffered
5946 * indefinitely.
5947 */
5948 (void) fflush(stdout);
5949
5950 if (interval == 0)
5951 break;
5952
5953 if (count != 0 && --count == 0)
5954 break;
5955
193a37cb 5956 (void) fsleep(interval);
34dc7c2f
BB
5957 }
5958
5959 pool_list_free(list);
5960
5961 return (ret);
5962}
5963
5964typedef struct list_cbdata {
1bd201e7 5965 boolean_t cb_verbose;
d2f3e292 5966 int cb_name_flags;
1bd201e7 5967 int cb_namewidth;
34dc7c2f 5968 boolean_t cb_scripted;
34dc7c2f 5969 zprop_list_t *cb_proplist;
2a8b84b7 5970 boolean_t cb_literal;
34dc7c2f
BB
5971} list_cbdata_t;
5972
cc99f275 5973
34dc7c2f
BB
5974/*
5975 * Given a list of columns to display, output appropriate headers for each one.
5976 */
5977static void
1bd201e7 5978print_header(list_cbdata_t *cb)
34dc7c2f 5979{
1bd201e7 5980 zprop_list_t *pl = cb->cb_proplist;
9ae529ec 5981 char headerbuf[ZPOOL_MAXPROPLEN];
34dc7c2f
BB
5982 const char *header;
5983 boolean_t first = B_TRUE;
5984 boolean_t right_justify;
1bd201e7 5985 size_t width = 0;
34dc7c2f
BB
5986
5987 for (; pl != NULL; pl = pl->pl_next) {
1bd201e7
CS
5988 width = pl->pl_width;
5989 if (first && cb->cb_verbose) {
5990 /*
5991 * Reset the width to accommodate the verbose listing
5992 * of devices.
5993 */
5994 width = cb->cb_namewidth;
5995 }
5996
34dc7c2f 5997 if (!first)
06b80506 5998 (void) fputs(" ", stdout);
34dc7c2f
BB
5999 else
6000 first = B_FALSE;
6001
9ae529ec 6002 right_justify = B_FALSE;
4ff7a8fa 6003 if (pl->pl_prop != ZPROP_USERPROP) {
9ae529ec
CS
6004 header = zpool_prop_column_name(pl->pl_prop);
6005 right_justify = zpool_prop_align_right(pl->pl_prop);
6006 } else {
6007 int i;
6008
6009 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
6010 headerbuf[i] = toupper(pl->pl_user_prop[i]);
6011 headerbuf[i] = '\0';
6012 header = headerbuf;
6013 }
34dc7c2f
BB
6014
6015 if (pl->pl_next == NULL && !right_justify)
06b80506 6016 (void) fputs(header, stdout);
34dc7c2f 6017 else if (right_justify)
1bd201e7 6018 (void) printf("%*s", (int)width, header);
34dc7c2f 6019 else
1bd201e7 6020 (void) printf("%-*s", (int)width, header);
34dc7c2f
BB
6021 }
6022
06b80506 6023 (void) fputc('\n', stdout);
34dc7c2f
BB
6024}
6025
6026/*
6027 * Given a pool and a list of properties, print out all the properties according
cc99f275 6028 * to the described layout. Used by zpool_do_list().
34dc7c2f
BB
6029 */
6030static void
1bd201e7 6031print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
34dc7c2f 6032{
1bd201e7 6033 zprop_list_t *pl = cb->cb_proplist;
34dc7c2f
BB
6034 boolean_t first = B_TRUE;
6035 char property[ZPOOL_MAXPROPLEN];
a926aab9 6036 const char *propstr;
34dc7c2f 6037 boolean_t right_justify;
1bd201e7 6038 size_t width;
34dc7c2f
BB
6039
6040 for (; pl != NULL; pl = pl->pl_next) {
1bd201e7
CS
6041
6042 width = pl->pl_width;
6043 if (first && cb->cb_verbose) {
6044 /*
6045 * Reset the width to accommodate the verbose listing
6046 * of devices.
6047 */
6048 width = cb->cb_namewidth;
6049 }
6050
34dc7c2f 6051 if (!first) {
1bd201e7 6052 if (cb->cb_scripted)
06b80506 6053 (void) fputc('\t', stdout);
34dc7c2f 6054 else
06b80506 6055 (void) fputs(" ", stdout);
34dc7c2f
BB
6056 } else {
6057 first = B_FALSE;
6058 }
6059
6060 right_justify = B_FALSE;
4ff7a8fa 6061 if (pl->pl_prop != ZPROP_USERPROP) {
a05dfd00 6062 if (zpool_get_prop(zhp, pl->pl_prop, property,
2a8b84b7 6063 sizeof (property), NULL, cb->cb_literal) != 0)
34dc7c2f
BB
6064 propstr = "-";
6065 else
6066 propstr = property;
6067
6068 right_justify = zpool_prop_align_right(pl->pl_prop);
9ae529ec
CS
6069 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
6070 zpool_prop_unsupported(pl->pl_user_prop)) &&
6071 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
6072 sizeof (property)) == 0) {
6073 propstr = property;
8eae2d21
AJ
6074 } else if (zfs_prop_user(pl->pl_user_prop) &&
6075 zpool_get_userprop(zhp, pl->pl_user_prop, property,
6076 sizeof (property), NULL) == 0) {
6077 propstr = property;
34dc7c2f
BB
6078 } else {
6079 propstr = "-";
6080 }
6081
34dc7c2f
BB
6082 /*
6083 * If this is being called in scripted mode, or if this is the
6084 * last column and it is left-justified, don't include a width
6085 * format specifier.
6086 */
1bd201e7 6087 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
06b80506 6088 (void) fputs(propstr, stdout);
34dc7c2f 6089 else if (right_justify)
1bd201e7 6090 (void) printf("%*s", (int)width, propstr);
34dc7c2f 6091 else
1bd201e7 6092 (void) printf("%-*s", (int)width, propstr);
34dc7c2f
BB
6093 }
6094
06b80506 6095 (void) fputc('\n', stdout);
34dc7c2f
BB
6096}
6097
1bd201e7 6098static void
c5eea0ab
BB
6099print_one_column(zpool_prop_t prop, uint64_t value, const char *str,
6100 boolean_t scripted, boolean_t valid, enum zfs_nicenum_format format)
1bd201e7
CS
6101{
6102 char propval[64];
6103 boolean_t fixed;
6104 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
6105
a05dfd00 6106 switch (prop) {
1282274f 6107 case ZPOOL_PROP_SIZE:
a05dfd00 6108 case ZPOOL_PROP_EXPANDSZ:
d2734cce 6109 case ZPOOL_PROP_CHECKPOINT:
c5eea0ab 6110 case ZPOOL_PROP_DEDUPRATIO:
a05dfd00
GW
6111 if (value == 0)
6112 (void) strlcpy(propval, "-", sizeof (propval));
6113 else
bc2d8093
CE
6114 zfs_nicenum_format(value, propval, sizeof (propval),
6115 format);
a05dfd00
GW
6116 break;
6117 case ZPOOL_PROP_FRAGMENTATION:
6118 if (value == ZFS_FRAG_INVALID) {
6119 (void) strlcpy(propval, "-", sizeof (propval));
bc2d8093
CE
6120 } else if (format == ZFS_NICENUM_RAW) {
6121 (void) snprintf(propval, sizeof (propval), "%llu",
6122 (unsigned long long)value);
a05dfd00
GW
6123 } else {
6124 (void) snprintf(propval, sizeof (propval), "%llu%%",
6125 (unsigned long long)value);
6126 }
6127 break;
6128 case ZPOOL_PROP_CAPACITY:
cc99f275 6129 /* capacity value is in parts-per-10,000 (aka permyriad) */
bc2d8093
CE
6130 if (format == ZFS_NICENUM_RAW)
6131 (void) snprintf(propval, sizeof (propval), "%llu",
cc99f275 6132 (unsigned long long)value / 100);
bc2d8093 6133 else
cc99f275
DB
6134 (void) snprintf(propval, sizeof (propval),
6135 value < 1000 ? "%1.2f%%" : value < 10000 ?
6136 "%2.1f%%" : "%3.0f%%", value / 100.0);
a05dfd00 6137 break;
c5eea0ab
BB
6138 case ZPOOL_PROP_HEALTH:
6139 width = 8;
96904d87 6140 (void) strlcpy(propval, str, sizeof (propval));
c5eea0ab 6141 break;
a05dfd00 6142 default:
bc2d8093 6143 zfs_nicenum_format(value, propval, sizeof (propval), format);
a05dfd00
GW
6144 }
6145
6146 if (!valid)
6147 (void) strlcpy(propval, "-", sizeof (propval));
1bd201e7
CS
6148
6149 if (scripted)
6150 (void) printf("\t%s", propval);
6151 else
6152 (void) printf(" %*s", (int)width, propval);
6153}
6154
cc99f275
DB
6155/*
6156 * print static default line per vdev
6157 * not compatible with '-o' <proplist> option
6158 */
65c7cc49 6159static void
1bd201e7 6160print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
c5eea0ab 6161 list_cbdata_t *cb, int depth, boolean_t isspare)
1bd201e7
CS
6162{
6163 nvlist_t **child;
6164 vdev_stat_t *vs;
6165 uint_t c, children;
6166 char *vname;
6167 boolean_t scripted = cb->cb_scripted;
8e4c5c9a 6168 uint64_t islog = B_FALSE;
cdb3eb5a
AZ
6169 const char *dashes = "%-*s - - - - "
6170 "- - - - -\n";
1bd201e7
CS
6171
6172 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
6173 (uint64_t **)&vs, &c) == 0);
6174
6175 if (name != NULL) {
a05dfd00
GW
6176 boolean_t toplevel = (vs->vs_space != 0);
6177 uint64_t cap;
bc2d8093 6178 enum zfs_nicenum_format format;
c5eea0ab 6179 const char *state;
bc2d8093
CE
6180
6181 if (cb->cb_literal)
6182 format = ZFS_NICENUM_RAW;
6183 else
6184 format = ZFS_NICENUM_1024;
a05dfd00 6185
a1d477c2
MA
6186 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
6187 return;
6188
1bd201e7
CS
6189 if (scripted)
6190 (void) printf("\t%s", name);
6191 else if (strlen(name) + depth > cb->cb_namewidth)
6192 (void) printf("%*s%s", depth, "", name);
6193 else
6194 (void) printf("%*s%s%*s", depth, "", name,
6195 (int)(cb->cb_namewidth - strlen(name) - depth), "");
6196
a05dfd00
GW
6197 /*
6198 * Print the properties for the individual vdevs. Some
6199 * properties are only applicable to toplevel vdevs. The
6200 * 'toplevel' boolean value is passed to the print_one_column()
6201 * to indicate that the value is valid.
6202 */
e77d59eb 6203 if (VDEV_STAT_VALID(vs_pspace, c) && vs->vs_pspace)
1282274f
A
6204 print_one_column(ZPOOL_PROP_SIZE, vs->vs_pspace, NULL,
6205 scripted, B_TRUE, format);
6206 else
6207 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, NULL,
6208 scripted, toplevel, format);
c5eea0ab 6209 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, NULL,
bc2d8093 6210 scripted, toplevel, format);
c5eea0ab
BB
6211 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
6212 NULL, scripted, toplevel, format);
d2734cce 6213 print_one_column(ZPOOL_PROP_CHECKPOINT,
c5eea0ab
BB
6214 vs->vs_checkpoint_space, NULL, scripted, toplevel, format);
6215 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, NULL,
6216 scripted, B_TRUE, format);
a05dfd00 6217 print_one_column(ZPOOL_PROP_FRAGMENTATION,
c5eea0ab 6218 vs->vs_fragmentation, NULL, scripted,
bc2d8093
CE
6219 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel),
6220 format);
a05dfd00 6221 cap = (vs->vs_space == 0) ? 0 :
cc99f275 6222 (vs->vs_alloc * 10000 / vs->vs_space);
c5eea0ab
BB
6223 print_one_column(ZPOOL_PROP_CAPACITY, cap, NULL,
6224 scripted, toplevel, format);
6225 print_one_column(ZPOOL_PROP_DEDUPRATIO, 0, NULL,
6226 scripted, toplevel, format);
6227 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
6228 if (isspare) {
6229 if (vs->vs_aux == VDEV_AUX_SPARED)
6230 state = "INUSE";
6231 else if (vs->vs_state == VDEV_STATE_HEALTHY)
6232 state = "AVAIL";
6233 }
6234 print_one_column(ZPOOL_PROP_HEALTH, 0, state, scripted,
6235 B_TRUE, format);
06b80506 6236 (void) fputc('\n', stdout);
1bd201e7
CS
6237 }
6238
6239 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
6240 &child, &children) != 0)
6241 return;
6242
cc99f275 6243 /* list the normal vdevs first */
1bd201e7
CS
6244 for (c = 0; c < children; c++) {
6245 uint64_t ishole = B_FALSE;
6246
6247 if (nvlist_lookup_uint64(child[c],
6248 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
6249 continue;
6250
8e4c5c9a 6251 if (nvlist_lookup_uint64(child[c],
cc99f275
DB
6252 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog)
6253 continue;
6254
6255 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
8e4c5c9a 6256 continue;
8e4c5c9a 6257
d2f3e292 6258 vname = zpool_vdev_name(g_zfs, zhp, child[c],
7b468ed2 6259 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
c5eea0ab 6260 print_list_stats(zhp, vname, child[c], cb, depth + 2, B_FALSE);
1bd201e7
CS
6261 free(vname);
6262 }
6263
cc99f275 6264 /* list the classes: 'logs', 'dedup', and 'special' */
cf5a9d8c 6265 for (uint_t n = 0; n < ARRAY_SIZE(class_name); n++) {
cc99f275
DB
6266 boolean_t printed = B_FALSE;
6267
8e4c5c9a 6268 for (c = 0; c < children; c++) {
d1807f16
RY
6269 const char *bias = NULL;
6270 const char *type = NULL;
cc99f275 6271
8e4c5c9a 6272 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
cc99f275 6273 &islog) == 0 && islog) {
d1807f16 6274 bias = VDEV_ALLOC_CLASS_LOGS;
cc99f275
DB
6275 } else {
6276 (void) nvlist_lookup_string(child[c],
6277 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
6278 (void) nvlist_lookup_string(child[c],
6279 ZPOOL_CONFIG_TYPE, &type);
6280 }
6281 if (bias == NULL || strcmp(bias, class_name[n]) != 0)
8e4c5c9a 6282 continue;
cc99f275
DB
6283 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
6284 continue;
6285
6286 if (!printed) {
6287 /* LINTED E_SEC_PRINTF_VAR_FMT */
6288 (void) printf(dashes, cb->cb_namewidth,
6289 class_name[n]);
6290 printed = B_TRUE;
6291 }
d2f3e292 6292 vname = zpool_vdev_name(g_zfs, zhp, child[c],
7b468ed2 6293 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
c5eea0ab
BB
6294 print_list_stats(zhp, vname, child[c], cb, depth + 2,
6295 B_FALSE);
8e4c5c9a
JWK
6296 free(vname);
6297 }
6298 }
6299
1bd201e7 6300 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
8e4c5c9a
JWK
6301 &child, &children) == 0 && children > 0) {
6302 /* LINTED E_SEC_PRINTF_VAR_FMT */
6303 (void) printf(dashes, cb->cb_namewidth, "cache");
6304 for (c = 0; c < children; c++) {
d2f3e292
RY
6305 vname = zpool_vdev_name(g_zfs, zhp, child[c],
6306 cb->cb_name_flags);
c5eea0ab
BB
6307 print_list_stats(zhp, vname, child[c], cb, depth + 2,
6308 B_FALSE);
8e4c5c9a
JWK
6309 free(vname);
6310 }
6311 }
1bd201e7 6312
8e4c5c9a
JWK
6313 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
6314 &children) == 0 && children > 0) {
6315 /* LINTED E_SEC_PRINTF_VAR_FMT */
6316 (void) printf(dashes, cb->cb_namewidth, "spare");
1bd201e7 6317 for (c = 0; c < children; c++) {
d2f3e292
RY
6318 vname = zpool_vdev_name(g_zfs, zhp, child[c],
6319 cb->cb_name_flags);
c5eea0ab
BB
6320 print_list_stats(zhp, vname, child[c], cb, depth + 2,
6321 B_TRUE);
1bd201e7
CS
6322 free(vname);
6323 }
6324 }
6325}
6326
34dc7c2f
BB
6327/*
6328 * Generic callback function to list a pool.
6329 */
65c7cc49 6330static int
34dc7c2f
BB
6331list_callback(zpool_handle_t *zhp, void *data)
6332{
6333 list_cbdata_t *cbp = data;
6334
c5eea0ab 6335 print_pool(zhp, cbp);
34dc7c2f 6336
cc99f275 6337 if (cbp->cb_verbose) {
c5eea0ab 6338 nvlist_t *config, *nvroot;
cc99f275 6339
c5eea0ab 6340 config = zpool_get_config(zhp, NULL);
cc99f275
DB
6341 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
6342 &nvroot) == 0);
c5eea0ab 6343 print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE);
cc99f275
DB
6344 }
6345
c5eea0ab
BB
6346 return (0);
6347}
cc99f275 6348
c5eea0ab
BB
6349/*
6350 * Set the minimum pool/vdev name column width. The width must be at least 9,
6351 * but may be as large as needed.
6352 */
6353static int
6354get_namewidth_list(zpool_handle_t *zhp, void *data)
6355{
6356 list_cbdata_t *cb = data;
6357 int width;
6358
7c0e3941
SW
6359 width = get_namewidth(zhp, cb->cb_namewidth,
6360 cb->cb_name_flags | VDEV_NAME_TYPE_ID, cb->cb_verbose);
1bd201e7 6361
c5eea0ab
BB
6362 if (width < 9)
6363 width = 9;
6364
6365 cb->cb_namewidth = width;
34dc7c2f
BB
6366
6367 return (0);
6368}
6369
6370/*
2a8b84b7 6371 * zpool list [-gHLpP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
34dc7c2f 6372 *
d2f3e292 6373 * -g Display guid for individual vdev name.
34dc7c2f
BB
6374 * -H Scripted mode. Don't display headers, and separate properties
6375 * by a single tab.
d2f3e292 6376 * -L Follow links when resolving vdev path name.
34dc7c2f 6377 * -o List of properties to display. Defaults to
a05dfd00
GW
6378 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
6379 * "dedupratio,health,altroot"
c5eea0ab 6380 * -p Display values in parsable (exact) format.
a77f29f9 6381 * -P Display full path for vdev name.
428870ff 6382 * -T Display a timestamp in date(1) or Unix format
34dc7c2f
BB
6383 *
6384 * List all pools in the system, whether or not they're healthy. Output space
6385 * statistics for each one, as well as health status summary.
6386 */
6387int
6388zpool_do_list(int argc, char **argv)
6389{
6390 int c;
cd72af9c 6391 int ret = 0;
34dc7c2f
BB
6392 list_cbdata_t cb = { 0 };
6393 static char default_props[] =
d2734cce
SD
6394 "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
6395 "capacity,dedupratio,health,altroot";
34dc7c2f 6396 char *props = default_props;
193a37cb
TH
6397 float interval = 0;
6398 unsigned long count = 0;
1bd201e7
CS
6399 zpool_list_t *list;
6400 boolean_t first = B_TRUE;
2a673e76 6401 current_prop_type = ZFS_TYPE_POOL;
34dc7c2f
BB
6402
6403 /* check options */
2a8b84b7 6404 while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
34dc7c2f 6405 switch (c) {
d2f3e292
RY
6406 case 'g':
6407 cb.cb_name_flags |= VDEV_NAME_GUID;
6408 break;
34dc7c2f
BB
6409 case 'H':
6410 cb.cb_scripted = B_TRUE;
6411 break;
d2f3e292
RY
6412 case 'L':
6413 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
6414 break;
34dc7c2f
BB
6415 case 'o':
6416 props = optarg;
6417 break;
a77f29f9 6418 case 'P':
d2f3e292
RY
6419 cb.cb_name_flags |= VDEV_NAME_PATH;
6420 break;
2a8b84b7
AS
6421 case 'p':
6422 cb.cb_literal = B_TRUE;
6423 break;
428870ff
BB
6424 case 'T':
6425 get_timestamp_arg(*optarg);
6426 break;
1bd201e7
CS
6427 case 'v':
6428 cb.cb_verbose = B_TRUE;
cc99f275 6429 cb.cb_namewidth = 8; /* 8 until precalc is avail */
1bd201e7 6430 break;
34dc7c2f
BB
6431 case ':':
6432 (void) fprintf(stderr, gettext("missing argument for "
6433 "'%c' option\n"), optopt);
6434 usage(B_FALSE);
6435 break;
6436 case '?':
6437 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6438 optopt);
6439 usage(B_FALSE);
6440 }
6441 }
6442
6443 argc -= optind;
6444 argv += optind;
6445
428870ff
BB
6446 get_interval_count(&argc, argv, &interval, &count);
6447
34dc7c2f
BB
6448 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
6449 usage(B_FALSE);
6450
428870ff 6451 for (;;) {
3e43edd2 6452 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
2a673e76 6453 ZFS_TYPE_POOL, cb.cb_literal, &ret)) == NULL)
3e43edd2 6454 return (1);
1bd201e7
CS
6455
6456 if (pool_list_count(list) == 0)
6457 break;
34dc7c2f 6458
c5eea0ab
BB
6459 cb.cb_namewidth = 0;
6460 (void) pool_list_iter(list, B_FALSE, get_namewidth_list, &cb);
6461
428870ff
BB
6462 if (timestamp_fmt != NODATE)
6463 print_timestamp(timestamp_fmt);
34dc7c2f 6464
1bd201e7
CS
6465 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
6466 print_header(&cb);
6467 first = B_FALSE;
428870ff 6468 }
1bd201e7 6469 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
428870ff
BB
6470
6471 if (interval == 0)
6472 break;
6473
6474 if (count != 0 && --count == 0)
6475 break;
6476
3e43edd2 6477 pool_list_free(list);
193a37cb 6478 (void) fsleep(interval);
34dc7c2f
BB
6479 }
6480
3e43edd2
GW
6481 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
6482 (void) printf(gettext("no pools available\n"));
6483 ret = 0;
6484 }
6485
6486 pool_list_free(list);
428870ff 6487 zprop_free_list(cb.cb_proplist);
34dc7c2f
BB
6488 return (ret);
6489}
6490
34dc7c2f
BB
6491static int
6492zpool_do_attach_or_replace(int argc, char **argv, int replacing)
6493{
6494 boolean_t force = B_FALSE;
9a49d3f3 6495 boolean_t rebuild = B_FALSE;
e60e158e 6496 boolean_t wait = B_FALSE;
34dc7c2f
BB
6497 int c;
6498 nvlist_t *nvroot;
6499 char *poolname, *old_disk, *new_disk;
6500 zpool_handle_t *zhp;
df831108
CP
6501 nvlist_t *props = NULL;
6502 char *propval;
34dc7c2f
BB
6503 int ret;
6504
6505 /* check options */
9a49d3f3 6506 while ((c = getopt(argc, argv, "fo:sw")) != -1) {
34dc7c2f
BB
6507 switch (c) {
6508 case 'f':
6509 force = B_TRUE;
6510 break;
df831108
CP
6511 case 'o':
6512 if ((propval = strchr(optarg, '=')) == NULL) {
6513 (void) fprintf(stderr, gettext("missing "
6514 "'=' for -o option\n"));
6515 usage(B_FALSE);
6516 }
6517 *propval = '\0';
6518 propval++;
6519
6520 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
6521 (add_prop_list(optarg, propval, &props, B_TRUE)))
6522 usage(B_FALSE);
6523 break;
9a49d3f3
BB
6524 case 's':
6525 rebuild = B_TRUE;
6526 break;
e60e158e
JG
6527 case 'w':
6528 wait = B_TRUE;
6529 break;
34dc7c2f
BB
6530 case '?':
6531 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6532 optopt);
6533 usage(B_FALSE);
6534 }
6535 }
6536
6537 argc -= optind;
6538 argv += optind;
6539
6540 /* get pool name and check number of arguments */
6541 if (argc < 1) {
6542 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6543 usage(B_FALSE);
6544 }
6545
6546 poolname = argv[0];
6547
6548 if (argc < 2) {
6549 (void) fprintf(stderr,
6550 gettext("missing <device> specification\n"));
6551 usage(B_FALSE);
6552 }
6553
6554 old_disk = argv[1];
6555
6556 if (argc < 3) {
6557 if (!replacing) {
6558 (void) fprintf(stderr,
6559 gettext("missing <new_device> specification\n"));
6560 usage(B_FALSE);
6561 }
6562 new_disk = old_disk;
6563 argc -= 1;
6564 argv += 1;
6565 } else {
6566 new_disk = argv[2];
6567 argc -= 2;
6568 argv += 2;
6569 }
6570
6571 if (argc > 1) {
6572 (void) fprintf(stderr, gettext("too many arguments\n"));
6573 usage(B_FALSE);
6574 }
6575
a425f5bf 6576 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) {
6577 nvlist_free(props);
34dc7c2f 6578 return (1);
a425f5bf 6579 }
34dc7c2f
BB
6580
6581 if (zpool_get_config(zhp, NULL) == NULL) {
6582 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
6583 poolname);
6584 zpool_close(zhp);
a425f5bf 6585 nvlist_free(props);
34dc7c2f
BB
6586 return (1);
6587 }
6588
dddef7d6 6589 /* unless manually specified use "ashift" pool property (if set) */
6590 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
6591 int intval;
6592 zprop_source_t src;
6593 char strval[ZPOOL_MAXPROPLEN];
6594
6595 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
6596 if (src != ZPROP_SRC_DEFAULT) {
6597 (void) sprintf(strval, "%" PRId32, intval);
6598 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
6599 &props, B_TRUE) == 0);
6600 }
6601 }
6602
df831108 6603 nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
b128c09f 6604 argc, argv);
34dc7c2f
BB
6605 if (nvroot == NULL) {
6606 zpool_close(zhp);
a425f5bf 6607 nvlist_free(props);
34dc7c2f
BB
6608 return (1);
6609 }
6610
9a49d3f3
BB
6611 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing,
6612 rebuild);
34dc7c2f 6613
e60e158e
JG
6614 if (ret == 0 && wait)
6615 ret = zpool_wait(zhp,
6616 replacing ? ZPOOL_WAIT_REPLACE : ZPOOL_WAIT_RESILVER);
6617
a425f5bf 6618 nvlist_free(props);
34dc7c2f
BB
6619 nvlist_free(nvroot);
6620 zpool_close(zhp);
6621
6622 return (ret);
6623}
6624
6625/*
9a49d3f3 6626 * zpool replace [-fsw] [-o property=value] <pool> <device> <new_device>
34dc7c2f
BB
6627 *
6628 * -f Force attach, even if <new_device> appears to be in use.
9a49d3f3 6629 * -s Use sequential instead of healing reconstruction for resilver.
e60e158e
JG
6630 * -o Set property=value.
6631 * -w Wait for replacing to complete before returning
34dc7c2f
BB
6632 *
6633 * Replace <device> with <new_device>.
6634 */
34dc7c2f
BB
6635int
6636zpool_do_replace(int argc, char **argv)
6637{
6638 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
6639}
6640
6641/*
9a49d3f3 6642 * zpool attach [-fsw] [-o property=value] <pool> <device> <new_device>
34dc7c2f
BB
6643 *
6644 * -f Force attach, even if <new_device> appears to be in use.
9a49d3f3 6645 * -s Use sequential instead of healing reconstruction for resilver.
df831108 6646 * -o Set property=value.
e60e158e 6647 * -w Wait for resilvering to complete before returning
34dc7c2f
BB
6648 *
6649 * Attach <new_device> to the mirror containing <device>. If <device> is not
6650 * part of a mirror, then <device> will be transformed into a mirror of
6651 * <device> and <new_device>. In either case, <new_device> will begin life
6652 * with a DTL of [0, now], and will immediately begin to resilver itself.
6653 */
6654int
6655zpool_do_attach(int argc, char **argv)
6656{
6657 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
6658}
6659
6660/*
6661 * zpool detach [-f] <pool> <device>
6662 *
6663 * -f Force detach of <device>, even if DTLs argue against it
6664 * (not supported yet)
6665 *
6666 * Detach a device from a mirror. The operation will be refused if <device>
6667 * is the last device in the mirror, or if the DTLs indicate that this device
6668 * has the only valid copy of some data.
6669 */
34dc7c2f
BB
6670int
6671zpool_do_detach(int argc, char **argv)
6672{
6673 int c;
6674 char *poolname, *path;
6675 zpool_handle_t *zhp;
6676 int ret;
6677
6678 /* check options */
d02186ee 6679 while ((c = getopt(argc, argv, "")) != -1) {
34dc7c2f 6680 switch (c) {
34dc7c2f
BB
6681 case '?':
6682 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6683 optopt);
6684 usage(B_FALSE);
6685 }
6686 }
6687
6688 argc -= optind;
6689 argv += optind;
6690
6691 /* get pool name and check number of arguments */
6692 if (argc < 1) {
6693 (void) fprintf(stderr, gettext("missing pool name argument\n"));
6694 usage(B_FALSE);
6695 }
6696
6697 if (argc < 2) {
6698 (void) fprintf(stderr,
6699 gettext("missing <device> specification\n"));
6700 usage(B_FALSE);
6701 }
6702
6703 poolname = argv[0];
6704 path = argv[1];
6705
6706 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6707 return (1);
6708
6709 ret = zpool_vdev_detach(zhp, path);
6710
6711 zpool_close(zhp);
6712
6713 return (ret);
6714}
6715
428870ff 6716/*
a77f29f9 6717 * zpool split [-gLnP] [-o prop=val] ...
428870ff
BB
6718 * [-o mntopt] ...
6719 * [-R altroot] <pool> <newpool> [<device> ...]
6720 *
d2f3e292
RY
6721 * -g Display guid for individual vdev name.
6722 * -L Follow links when resolving vdev path name.
428870ff
BB
6723 * -n Do not split the pool, but display the resulting layout if
6724 * it were to be split.
6725 * -o Set property=value, or set mount options.
a77f29f9 6726 * -P Display full path for vdev name.
428870ff 6727 * -R Mount the split-off pool under an alternate root.
b5256303 6728 * -l Load encryption keys while importing.
428870ff
BB
6729 *
6730 * Splits the named pool and gives it the new pool name. Devices to be split
6731 * off may be listed, provided that no more than one device is specified
6732 * per top-level vdev mirror. The newly split pool is left in an exported
6733 * state unless -R is specified.
6734 *
6735 * Restrictions: the top-level of the pool pool must only be made up of
6736 * mirrors; all devices in the pool must be healthy; no device may be
6737 * undergoing a resilvering operation.
6738 */
6739int
6740zpool_do_split(int argc, char **argv)
6741{
6742 char *srcpool, *newpool, *propval;
6743 char *mntopts = NULL;
6744 splitflags_t flags;
6745 int c, ret = 0;
b5256303 6746 boolean_t loadkeys = B_FALSE;
428870ff
BB
6747 zpool_handle_t *zhp;
6748 nvlist_t *config, *props = NULL;
6749
6750 flags.dryrun = B_FALSE;
6751 flags.import = B_FALSE;
d2f3e292 6752 flags.name_flags = 0;
428870ff
BB
6753
6754 /* check options */
b5256303 6755 while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) {
428870ff 6756 switch (c) {
d2f3e292
RY
6757 case 'g':
6758 flags.name_flags |= VDEV_NAME_GUID;
6759 break;
6760 case 'L':
6761 flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
6762 break;
428870ff
BB
6763 case 'R':
6764 flags.import = B_TRUE;
6765 if (add_prop_list(
6766 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
6767 &props, B_TRUE) != 0) {
8a5fc748 6768 nvlist_free(props);
428870ff
BB
6769 usage(B_FALSE);
6770 }
6771 break;
b5256303
TC
6772 case 'l':
6773 loadkeys = B_TRUE;
6774 break;
428870ff
BB
6775 case 'n':
6776 flags.dryrun = B_TRUE;
6777 break;
6778 case 'o':
6779 if ((propval = strchr(optarg, '=')) != NULL) {
6780 *propval = '\0';
6781 propval++;
6782 if (add_prop_list(optarg, propval,
6783 &props, B_TRUE) != 0) {
8a5fc748 6784 nvlist_free(props);
428870ff
BB
6785 usage(B_FALSE);
6786 }
6787 } else {
6788 mntopts = optarg;
6789 }
6790 break;
a77f29f9 6791 case 'P':
d2f3e292
RY
6792 flags.name_flags |= VDEV_NAME_PATH;
6793 break;
428870ff
BB
6794 case ':':
6795 (void) fprintf(stderr, gettext("missing argument for "
6796 "'%c' option\n"), optopt);
6797 usage(B_FALSE);
6798 break;
6799 case '?':
6800 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6801 optopt);
6802 usage(B_FALSE);
6803 break;
6804 }
6805 }
6806
6807 if (!flags.import && mntopts != NULL) {
6808 (void) fprintf(stderr, gettext("setting mntopts is only "
6809 "valid when importing the pool\n"));
6810 usage(B_FALSE);
6811 }
6812
b5256303
TC
6813 if (!flags.import && loadkeys) {
6814 (void) fprintf(stderr, gettext("loading keys is only "
6815 "valid when importing the pool\n"));
6816 usage(B_FALSE);
6817 }
6818
428870ff
BB
6819 argc -= optind;
6820 argv += optind;
6821
6822 if (argc < 1) {
6823 (void) fprintf(stderr, gettext("Missing pool name\n"));
6824 usage(B_FALSE);
6825 }
6826 if (argc < 2) {
6827 (void) fprintf(stderr, gettext("Missing new pool name\n"));
6828 usage(B_FALSE);
6829 }
6830
6831 srcpool = argv[0];
6832 newpool = argv[1];
6833
6834 argc -= 2;
6835 argv += 2;
6836
a425f5bf 6837 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) {
6838 nvlist_free(props);
428870ff 6839 return (1);
a425f5bf 6840 }
428870ff
BB
6841
6842 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
6843 if (config == NULL) {
6844 ret = 1;
6845 } else {
6846 if (flags.dryrun) {
6847 (void) printf(gettext("would create '%s' with the "
6848 "following layout:\n\n"), newpool);
cc99f275 6849 print_vdev_tree(NULL, newpool, config, 0, "",
d2f3e292 6850 flags.name_flags);
0cb40fa3
AF
6851 print_vdev_tree(NULL, "dedup", config, 0,
6852 VDEV_ALLOC_BIAS_DEDUP, 0);
6853 print_vdev_tree(NULL, "special", config, 0,
6854 VDEV_ALLOC_BIAS_SPECIAL, 0);
428870ff 6855 }
428870ff
BB
6856 }
6857
6858 zpool_close(zhp);
6859
a425f5bf 6860 if (ret != 0 || flags.dryrun || !flags.import) {
6861 nvlist_free(config);
6862 nvlist_free(props);
428870ff 6863 return (ret);
a425f5bf 6864 }
428870ff
BB
6865
6866 /*
6867 * The split was successful. Now we need to open the new
6868 * pool and import it.
6869 */
a425f5bf 6870 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) {
6871 nvlist_free(config);
6872 nvlist_free(props);
428870ff 6873 return (1);
a425f5bf 6874 }
b5256303
TC
6875
6876 if (loadkeys) {
6877 ret = zfs_crypto_attempt_load_keys(g_zfs, newpool);
6878 if (ret != 0)
6879 ret = 1;
6880 }
6881
428870ff
BB
6882 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
6883 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
6884 ret = 1;
af909a10 6885 (void) fprintf(stderr, gettext("Split was successful, but "
428870ff
BB
6886 "the datasets could not all be mounted\n"));
6887 (void) fprintf(stderr, gettext("Try doing '%s' with a "
6888 "different altroot\n"), "zpool import");
6889 }
6890 zpool_close(zhp);
a425f5bf 6891 nvlist_free(config);
6892 nvlist_free(props);
428870ff
BB
6893
6894 return (ret);
6895}
6896
6897
6898
34dc7c2f
BB
6899/*
6900 * zpool online <pool> <device> ...
6901 */
6902int
6903zpool_do_online(int argc, char **argv)
6904{
6905 int c, i;
6906 char *poolname;
6907 zpool_handle_t *zhp;
6908 int ret = 0;
6909 vdev_state_t newstate;
9babb374 6910 int flags = 0;
34dc7c2f
BB
6911
6912 /* check options */
d02186ee 6913 while ((c = getopt(argc, argv, "e")) != -1) {
34dc7c2f 6914 switch (c) {
9babb374
BB
6915 case 'e':
6916 flags |= ZFS_ONLINE_EXPAND;
6917 break;
34dc7c2f
BB
6918 case '?':
6919 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6920 optopt);
6921 usage(B_FALSE);
6922 }
6923 }
6924
6925 argc -= optind;
6926 argv += optind;
6927
6928 /* get pool name and check number of arguments */
6929 if (argc < 1) {
6930 (void) fprintf(stderr, gettext("missing pool name\n"));
6931 usage(B_FALSE);
6932 }
6933 if (argc < 2) {
6934 (void) fprintf(stderr, gettext("missing device name\n"));
6935 usage(B_FALSE);
6936 }
6937
6938 poolname = argv[0];
6939
6940 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
6941 return (1);
6942
6943 for (i = 1; i < argc; i++) {
b66c2a08
PD
6944 vdev_state_t oldstate;
6945 boolean_t avail_spare, l2cache;
6946 nvlist_t *tgt = zpool_find_vdev(zhp, argv[i], &avail_spare,
6947 &l2cache, NULL);
6948 if (tgt == NULL) {
6949 ret = 1;
6950 continue;
6951 }
6952 uint_t vsc;
6953 oldstate = ((vdev_stat_t *)fnvlist_lookup_uint64_array(tgt,
6954 ZPOOL_CONFIG_VDEV_STATS, &vsc))->vs_state;
9babb374 6955 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
34dc7c2f
BB
6956 if (newstate != VDEV_STATE_HEALTHY) {
6957 (void) printf(gettext("warning: device '%s' "
6958 "onlined, but remains in faulted state\n"),
6959 argv[i]);
6960 if (newstate == VDEV_STATE_FAULTED)
6961 (void) printf(gettext("use 'zpool "
6962 "clear' to restore a faulted "
6963 "device\n"));
6964 else
6965 (void) printf(gettext("use 'zpool "
6966 "replace' to replace devices "
6967 "that are no longer present\n"));
b66c2a08
PD
6968 if ((flags & ZFS_ONLINE_EXPAND)) {
6969 (void) printf(gettext("%s: failed "
6970 "to expand usable space on "
6971 "unhealthy device '%s'\n"),
6972 (oldstate >= VDEV_STATE_DEGRADED ?
6973 "error" : "warning"), argv[i]);
6974 if (oldstate >= VDEV_STATE_DEGRADED) {
6975 ret = 1;
6976 break;
6977 }
6978 }
34dc7c2f
BB
6979 }
6980 } else {
6981 ret = 1;
6982 }
6983 }
6984
6985 zpool_close(zhp);
6986
6987 return (ret);
6988}
6989
6990/*
6991 * zpool offline [-ft] <pool> <device> ...
6992 *
4a283c7f 6993 * -f Force the device into a faulted state.
34dc7c2f 6994 *
4a283c7f 6995 * -t Only take the device off-line temporarily. The offline/faulted
34dc7c2f
BB
6996 * state will not be persistent across reboots.
6997 */
34dc7c2f
BB
6998int
6999zpool_do_offline(int argc, char **argv)
7000{
7001 int c, i;
7002 char *poolname;
7003 zpool_handle_t *zhp;
7004 int ret = 0;
7005 boolean_t istmp = B_FALSE;
4a283c7f 7006 boolean_t fault = B_FALSE;
34dc7c2f
BB
7007
7008 /* check options */
7009 while ((c = getopt(argc, argv, "ft")) != -1) {
7010 switch (c) {
4a283c7f
TH
7011 case 'f':
7012 fault = B_TRUE;
7013 break;
34dc7c2f
BB
7014 case 't':
7015 istmp = B_TRUE;
7016 break;
34dc7c2f
BB
7017 case '?':
7018 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7019 optopt);
7020 usage(B_FALSE);
7021 }
7022 }
7023
7024 argc -= optind;
7025 argv += optind;
7026
7027 /* get pool name and check number of arguments */
7028 if (argc < 1) {
7029 (void) fprintf(stderr, gettext("missing pool name\n"));
7030 usage(B_FALSE);
7031 }
7032 if (argc < 2) {
7033 (void) fprintf(stderr, gettext("missing device name\n"));
7034 usage(B_FALSE);
7035 }
7036
7037 poolname = argv[0];
7038
7039 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
7040 return (1);
7041
7042 for (i = 1; i < argc; i++) {
4a283c7f
TH
7043 if (fault) {
7044 uint64_t guid = zpool_vdev_path_to_guid(zhp, argv[i]);
7045 vdev_aux_t aux;
7046 if (istmp == B_FALSE) {
7047 /* Force the fault to persist across imports */
7048 aux = VDEV_AUX_EXTERNAL_PERSIST;
7049 } else {
7050 aux = VDEV_AUX_EXTERNAL;
7051 }
7052
7053 if (guid == 0 || zpool_vdev_fault(zhp, guid, aux) != 0)
7054 ret = 1;
7055 } else {
7056 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
7057 ret = 1;
7058 }
34dc7c2f
BB
7059 }
7060
7061 zpool_close(zhp);
7062
7063 return (ret);
7064}
7065
7066/*
7067 * zpool clear <pool> [device]
7068 *
7069 * Clear all errors associated with a pool or a particular device.
7070 */
7071int
7072zpool_do_clear(int argc, char **argv)
7073{
428870ff 7074 int c;
34dc7c2f 7075 int ret = 0;
428870ff
BB
7076 boolean_t dryrun = B_FALSE;
7077 boolean_t do_rewind = B_FALSE;
7078 boolean_t xtreme_rewind = B_FALSE;
7079 uint32_t rewind_policy = ZPOOL_NO_REWIND;
7080 nvlist_t *policy = NULL;
34dc7c2f
BB
7081 zpool_handle_t *zhp;
7082 char *pool, *device;
7083
428870ff
BB
7084 /* check options */
7085 while ((c = getopt(argc, argv, "FnX")) != -1) {
7086 switch (c) {
7087 case 'F':
7088 do_rewind = B_TRUE;
7089 break;
7090 case 'n':
7091 dryrun = B_TRUE;
7092 break;
7093 case 'X':
7094 xtreme_rewind = B_TRUE;
7095 break;
7096 case '?':
7097 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7098 optopt);
7099 usage(B_FALSE);
7100 }
7101 }
7102
7103 argc -= optind;
7104 argv += optind;
7105
7106 if (argc < 1) {
34dc7c2f
BB
7107 (void) fprintf(stderr, gettext("missing pool name\n"));
7108 usage(B_FALSE);
7109 }
7110
428870ff 7111 if (argc > 2) {
34dc7c2f
BB
7112 (void) fprintf(stderr, gettext("too many arguments\n"));
7113 usage(B_FALSE);
7114 }
7115
428870ff
BB
7116 if ((dryrun || xtreme_rewind) && !do_rewind) {
7117 (void) fprintf(stderr,
7118 gettext("-n or -X only meaningful with -F\n"));
7119 usage(B_FALSE);
7120 }
7121 if (dryrun)
7122 rewind_policy = ZPOOL_TRY_REWIND;
7123 else if (do_rewind)
7124 rewind_policy = ZPOOL_DO_REWIND;
7125 if (xtreme_rewind)
7126 rewind_policy |= ZPOOL_EXTREME_REWIND;
7127
7128 /* In future, further rewind policy choices can be passed along here */
7129 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
8a393be3
PZ
7130 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
7131 rewind_policy) != 0) {
428870ff 7132 return (1);
8a393be3 7133 }
428870ff
BB
7134
7135 pool = argv[0];
7136 device = argc == 2 ? argv[1] : NULL;
34dc7c2f 7137
428870ff
BB
7138 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
7139 nvlist_free(policy);
34dc7c2f 7140 return (1);
428870ff 7141 }
34dc7c2f 7142
428870ff 7143 if (zpool_clear(zhp, device, policy) != 0)
34dc7c2f
BB
7144 ret = 1;
7145
7146 zpool_close(zhp);
7147
428870ff
BB
7148 nvlist_free(policy);
7149
34dc7c2f
BB
7150 return (ret);
7151}
7152
3541dc6d
GA
7153/*
7154 * zpool reguid <pool>
7155 */
7156int
7157zpool_do_reguid(int argc, char **argv)
7158{
7159 int c;
7160 char *poolname;
7161 zpool_handle_t *zhp;
7162 int ret = 0;
7163
7164 /* check options */
7165 while ((c = getopt(argc, argv, "")) != -1) {
7166 switch (c) {
7167 case '?':
7168 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7169 optopt);
7170 usage(B_FALSE);
7171 }
7172 }
7173
7174 argc -= optind;
7175 argv += optind;
7176
7177 /* get pool name and check number of arguments */
7178 if (argc < 1) {
7179 (void) fprintf(stderr, gettext("missing pool name\n"));
7180 usage(B_FALSE);
7181 }
7182
7183 if (argc > 1) {
7184 (void) fprintf(stderr, gettext("too many arguments\n"));
7185 usage(B_FALSE);
7186 }
7187
7188 poolname = argv[0];
7189 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
7190 return (1);
7191
7192 ret = zpool_reguid(zhp);
7193
7194 zpool_close(zhp);
7195 return (ret);
7196}
7197
7198
1bd201e7
CS
7199/*
7200 * zpool reopen <pool>
7201 *
7202 * Reopen the pool so that the kernel can update the sizes of all vdevs.
1bd201e7
CS
7203 */
7204int
7205zpool_do_reopen(int argc, char **argv)
7206{
5853fe79 7207 int c;
1bd201e7 7208 int ret = 0;
d3f2cd7e 7209 boolean_t scrub_restart = B_TRUE;
1bd201e7 7210
5853fe79 7211 /* check options */
d3f2cd7e 7212 while ((c = getopt(argc, argv, "n")) != -1) {
5853fe79 7213 switch (c) {
d3f2cd7e
AB
7214 case 'n':
7215 scrub_restart = B_FALSE;
7216 break;
5853fe79
GW
7217 case '?':
7218 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7219 optopt);
7220 usage(B_FALSE);
7221 }
7222 }
7223
d3f2cd7e
AB
7224 argc -= optind;
7225 argv += optind;
1bd201e7 7226
d3f2cd7e 7227 /* if argc == 0 we will execute zpool_reopen_one on all pools */
2a673e76
AJ
7228 ret = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
7229 B_FALSE, zpool_reopen_one, &scrub_restart);
1bd201e7 7230
1bd201e7
CS
7231 return (ret);
7232}
7233
34dc7c2f
BB
7234typedef struct scrub_cbdata {
7235 int cb_type;
0ea05c64 7236 pool_scrub_cmd_t cb_scrub_cmd;
34dc7c2f
BB
7237} scrub_cbdata_t;
7238
d2734cce
SD
7239static boolean_t
7240zpool_has_checkpoint(zpool_handle_t *zhp)
7241{
7242 nvlist_t *config, *nvroot;
7243
7244 config = zpool_get_config(zhp, NULL);
7245
7246 if (config != NULL) {
7247 pool_checkpoint_stat_t *pcs = NULL;
7248 uint_t c;
7249
7250 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
7251 (void) nvlist_lookup_uint64_array(nvroot,
7252 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
7253
7254 if (pcs == NULL || pcs->pcs_state == CS_NONE)
7255 return (B_FALSE);
7256
7257 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
7258 pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
7259 return (B_TRUE);
7260 }
7261
7262 return (B_FALSE);
7263}
7264
65c7cc49 7265static int
34dc7c2f
BB
7266scrub_callback(zpool_handle_t *zhp, void *data)
7267{
7268 scrub_cbdata_t *cb = data;
7269 int err;
7270
7271 /*
7272 * Ignore faulted pools.
7273 */
7274 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
80a91e74 7275 (void) fprintf(stderr, gettext("cannot scan '%s': pool is "
34dc7c2f
BB
7276 "currently unavailable\n"), zpool_get_name(zhp));
7277 return (1);
7278 }
7279
0ea05c64 7280 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
34dc7c2f 7281
d2734cce
SD
7282 if (err == 0 && zpool_has_checkpoint(zhp) &&
7283 cb->cb_type == POOL_SCAN_SCRUB) {
7284 (void) printf(gettext("warning: will not scrub state that "
7285 "belongs to the checkpoint of pool '%s'\n"),
7286 zpool_get_name(zhp));
7287 }
7288
34dc7c2f
BB
7289 return (err != 0);
7290}
7291
e60e158e
JG
7292static int
7293wait_callback(zpool_handle_t *zhp, void *data)
7294{
7295 zpool_wait_activity_t *act = data;
7296 return (zpool_wait(zhp, *act));
7297}
7298
34dc7c2f 7299/*
e60e158e 7300 * zpool scrub [-s | -p] [-w] <pool> ...
34dc7c2f
BB
7301 *
7302 * -s Stop. Stops any in-progress scrub.
0ea05c64 7303 * -p Pause. Pause in-progress scrub.
e60e158e 7304 * -w Wait. Blocks until scrub has completed.
34dc7c2f
BB
7305 */
7306int
7307zpool_do_scrub(int argc, char **argv)
7308{
7309 int c;
7310 scrub_cbdata_t cb;
e60e158e
JG
7311 boolean_t wait = B_FALSE;
7312 int error;
34dc7c2f 7313
428870ff 7314 cb.cb_type = POOL_SCAN_SCRUB;
0ea05c64 7315 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
34dc7c2f
BB
7316
7317 /* check options */
e60e158e 7318 while ((c = getopt(argc, argv, "spw")) != -1) {
34dc7c2f
BB
7319 switch (c) {
7320 case 's':
428870ff 7321 cb.cb_type = POOL_SCAN_NONE;
34dc7c2f 7322 break;
0ea05c64
AP
7323 case 'p':
7324 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
7325 break;
e60e158e
JG
7326 case 'w':
7327 wait = B_TRUE;
7328 break;
34dc7c2f
BB
7329 case '?':
7330 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7331 optopt);
7332 usage(B_FALSE);
7333 }
7334 }
7335
0ea05c64
AP
7336 if (cb.cb_type == POOL_SCAN_NONE &&
7337 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
7338 (void) fprintf(stderr, gettext("invalid option combination: "
7339 "-s and -p are mutually exclusive\n"));
7340 usage(B_FALSE);
7341 }
7342
e60e158e
JG
7343 if (wait && (cb.cb_type == POOL_SCAN_NONE ||
7344 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE)) {
7345 (void) fprintf(stderr, gettext("invalid option combination: "
7346 "-w cannot be used with -p or -s\n"));
7347 usage(B_FALSE);
7348 }
7349
34dc7c2f
BB
7350 argc -= optind;
7351 argv += optind;
7352
7353 if (argc < 1) {
7354 (void) fprintf(stderr, gettext("missing pool name argument\n"));
7355 usage(B_FALSE);
7356 }
7357
2a673e76
AJ
7358 error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
7359 B_FALSE, scrub_callback, &cb);
e60e158e
JG
7360
7361 if (wait && !error) {
7362 zpool_wait_activity_t act = ZPOOL_WAIT_SCRUB;
2a673e76
AJ
7363 error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
7364 B_FALSE, wait_callback, &act);
e60e158e
JG
7365 }
7366
7367 return (error);
34dc7c2f
BB
7368}
7369
80a91e74
TC
7370/*
7371 * zpool resilver <pool> ...
7372 *
7373 * Restarts any in-progress resilver
7374 */
7375int
7376zpool_do_resilver(int argc, char **argv)
7377{
7378 int c;
7379 scrub_cbdata_t cb;
7380
7381 cb.cb_type = POOL_SCAN_RESILVER;
7382 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
80a91e74
TC
7383
7384 /* check options */
7385 while ((c = getopt(argc, argv, "")) != -1) {
7386 switch (c) {
7387 case '?':
7388 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
7389 optopt);
7390 usage(B_FALSE);
7391 }
7392 }
7393
7394 argc -= optind;
7395 argv += optind;
7396
7397 if (argc < 1) {
7398 (void) fprintf(stderr, gettext("missing pool name argument\n"));
7399 usage(B_FALSE);
7400 }
7401
2a673e76
AJ
7402 return (for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
7403 B_FALSE, scrub_callback, &cb));
80a91e74
TC
7404}
7405
1b939560
BB
7406/*
7407 * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...]
7408 *
7409 * -c Cancel. Ends any in-progress trim.
7410 * -d Secure trim. Requires kernel and device support.
7411 * -r <rate> Sets the TRIM rate in bytes (per second). Supports
7412 * adding a multiplier suffix such as 'k' or 'm'.
7413 * -s Suspend. TRIM can then be restarted with no flags.
2288d419 7414 * -w Wait. Blocks until trimming has completed.
1b939560
BB
7415 */
7416int
7417zpool_do_trim(int argc, char **argv)
7418{
7419 struct option long_options[] = {
7420 {"cancel", no_argument, NULL, 'c'},
7421 {"secure", no_argument, NULL, 'd'},
7422 {"rate", required_argument, NULL, 'r'},
7423 {"suspend", no_argument, NULL, 's'},
2288d419 7424 {"wait", no_argument, NULL, 'w'},
1b939560
BB
7425 {0, 0, 0, 0}
7426 };
7427
7428 pool_trim_func_t cmd_type = POOL_TRIM_START;
7429 uint64_t rate = 0;
7430 boolean_t secure = B_FALSE;
2288d419 7431 boolean_t wait = B_FALSE;
1b939560
BB
7432
7433 int c;
2288d419 7434 while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
1b939560
BB
7435 != -1) {
7436 switch (c) {
7437 case 'c':
7438 if (cmd_type != POOL_TRIM_START &&
7439 cmd_type != POOL_TRIM_CANCEL) {
7440 (void) fprintf(stderr, gettext("-c cannot be "
7441 "combined with other options\n"));
7442 usage(B_FALSE);
7443 }
7444 cmd_type = POOL_TRIM_CANCEL;
7445 break;
7446 case 'd':
7447 if (cmd_type != POOL_TRIM_START) {
7448 (void) fprintf(stderr, gettext("-d cannot be "
7449 "combined with the -c or -s options\n"));
7450 usage(B_FALSE);
7451 }
7452 secure = B_TRUE;
7453 break;
7454 case 'r':
7455 if (cmd_type != POOL_TRIM_START) {
7456 (void) fprintf(stderr, gettext("-r cannot be "
7457 "combined with the -c or -s options\n"));
7458 usage(B_FALSE);
7459 }
a4cecfbd
TS
7460 if (zfs_nicestrtonum(g_zfs, optarg, &rate) == -1) {
7461 (void) fprintf(stderr, "%s: %s\n",
7462 gettext("invalid value for rate"),
7463 libzfs_error_description(g_zfs));
1b939560
BB
7464 usage(B_FALSE);
7465 }
7466 break;
7467 case 's':
7468 if (cmd_type != POOL_TRIM_START &&
7469 cmd_type != POOL_TRIM_SUSPEND) {
7470 (void) fprintf(stderr, gettext("-s cannot be "
7471 "combined with other options\n"));
7472 usage(B_FALSE);
7473 }
7474 cmd_type = POOL_TRIM_SUSPEND;
7475 break;
2288d419
BB
7476 case 'w':
7477 wait = B_TRUE;
7478 break;
1b939560
BB
7479 case '?':
7480 if (optopt != 0) {
7481 (void) fprintf(stderr,
7482 gettext("invalid option '%c'\n"), optopt);
7483 } else {
7484 (void) fprintf(stderr,
7485 gettext("invalid option '%s'\n"),
7486 argv[optind - 1]);
7487 }
7488 usage(B_FALSE);
7489 }
7490 }
7491
7492 argc -= optind;
7493 argv += optind;
7494
7495 if (argc < 1) {
7496 (void) fprintf(stderr, gettext("missing pool name argument\n"));
7497 usage(B_FALSE);
7498 return (-1);
7499 }
7500
2288d419
BB
7501 if (wait && (cmd_type != POOL_TRIM_START)) {
7502 (void) fprintf(stderr, gettext("-w cannot be used with -c or "
7503 "-s\n"));
7504 usage(B_FALSE);
7505 }
7506
1b939560
BB
7507 char *poolname = argv[0];
7508 zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
7509 if (zhp == NULL)
7510 return (-1);
7511
7512 trimflags_t trim_flags = {
7513 .secure = secure,
7514 .rate = rate,
2288d419 7515 .wait = wait,
1b939560
BB
7516 };
7517
7518 nvlist_t *vdevs = fnvlist_alloc();
7519 if (argc == 1) {
7520 /* no individual leaf vdevs specified, so add them all */
7521 nvlist_t *config = zpool_get_config(zhp, NULL);
7522 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
7523 ZPOOL_CONFIG_VDEV_TREE);
7524 zpool_collect_leaves(zhp, nvroot, vdevs);
7525 trim_flags.fullpool = B_TRUE;
7526 } else {
7527 trim_flags.fullpool = B_FALSE;
7528 for (int i = 1; i < argc; i++) {
7529 fnvlist_add_boolean(vdevs, argv[i]);
7530 }
7531 }
7532
7533 int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
7534
7535 fnvlist_free(vdevs);
7536 zpool_close(zhp);
7537
7538 return (error);
7539}
80a91e74 7540
9a49d3f3
BB
7541/*
7542 * Converts a total number of seconds to a human readable string broken
7543 * down in to days/hours/minutes/seconds.
7544 */
7545static void
7546secs_to_dhms(uint64_t total, char *buf)
7547{
7548 uint64_t days = total / 60 / 60 / 24;
7549 uint64_t hours = (total / 60 / 60) % 24;
7550 uint64_t mins = (total / 60) % 60;
7551 uint64_t secs = (total % 60);
7552
7553 if (days > 0) {
7554 (void) sprintf(buf, "%llu days %02llu:%02llu:%02llu",
7555 (u_longlong_t)days, (u_longlong_t)hours,
7556 (u_longlong_t)mins, (u_longlong_t)secs);
7557 } else {
7558 (void) sprintf(buf, "%02llu:%02llu:%02llu",
7559 (u_longlong_t)hours, (u_longlong_t)mins,
7560 (u_longlong_t)secs);
7561 }
7562}
7563
34dc7c2f
BB
7564/*
7565 * Print out detailed scrub status.
7566 */
a1d477c2 7567static void
9a49d3f3 7568print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
34dc7c2f 7569{
0ea05c64 7570 time_t start, end, pause;
d4a72f23 7571 uint64_t pass_scanned, scanned, pass_issued, issued, total;
9a49d3f3 7572 uint64_t elapsed, scan_rate, issue_rate;
34dc7c2f 7573 double fraction_done;
d4a72f23 7574 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
9a49d3f3 7575 char srate_buf[7], irate_buf[7], time_buf[32];
34dc7c2f 7576
9fb2771a
TH
7577 printf(" ");
7578 printf_color(ANSI_BOLD, gettext("scan:"));
7579 printf(" ");
34dc7c2f 7580
428870ff
BB
7581 /* If there's never been a scan, there's not much to say. */
7582 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
7583 ps->pss_func >= POOL_SCAN_FUNCS) {
34dc7c2f
BB
7584 (void) printf(gettext("none requested\n"));
7585 return;
7586 }
7587
428870ff
BB
7588 start = ps->pss_start_time;
7589 end = ps->pss_end_time;
0ea05c64 7590 pause = ps->pss_pass_scrub_pause;
d4a72f23 7591
e7fbeb60 7592 zfs_nicebytes(ps->pss_processed, processed_buf, sizeof (processed_buf));
34dc7c2f 7593
c85ac731
BB
7594 int is_resilver = ps->pss_func == POOL_SCAN_RESILVER;
7595 int is_scrub = ps->pss_func == POOL_SCAN_SCRUB;
7596 assert(is_resilver || is_scrub);
d4a72f23
TC
7597
7598 /* Scan is finished or canceled. */
428870ff 7599 if (ps->pss_state == DSS_FINISHED) {
9a49d3f3 7600 secs_to_dhms(end - start, time_buf);
428870ff 7601
c85ac731 7602 if (is_scrub) {
d4a72f23 7603 (void) printf(gettext("scrub repaired %s "
9a49d3f3
BB
7604 "in %s with %llu errors on %s"), processed_buf,
7605 time_buf, (u_longlong_t)ps->pss_errors,
7606 ctime(&end));
c85ac731 7607 } else if (is_resilver) {
d4a72f23 7608 (void) printf(gettext("resilvered %s "
9a49d3f3
BB
7609 "in %s with %llu errors on %s"), processed_buf,
7610 time_buf, (u_longlong_t)ps->pss_errors,
7611 ctime(&end));
428870ff 7612 }
428870ff
BB
7613 return;
7614 } else if (ps->pss_state == DSS_CANCELED) {
c85ac731 7615 if (is_scrub) {
428870ff
BB
7616 (void) printf(gettext("scrub canceled on %s"),
7617 ctime(&end));
c85ac731 7618 } else if (is_resilver) {
428870ff
BB
7619 (void) printf(gettext("resilver canceled on %s"),
7620 ctime(&end));
7621 }
34dc7c2f
BB
7622 return;
7623 }
7624
428870ff
BB
7625 assert(ps->pss_state == DSS_SCANNING);
7626
d4a72f23 7627 /* Scan is in progress. Resilvers can't be paused. */
c85ac731 7628 if (is_scrub) {
0ea05c64
AP
7629 if (pause == 0) {
7630 (void) printf(gettext("scrub in progress since %s"),
7631 ctime(&start));
7632 } else {
d4a72f23
TC
7633 (void) printf(gettext("scrub paused since %s"),
7634 ctime(&pause));
7635 (void) printf(gettext("\tscrub started on %s"),
0ea05c64
AP
7636 ctime(&start));
7637 }
c85ac731 7638 } else if (is_resilver) {
428870ff
BB
7639 (void) printf(gettext("resilver in progress since %s"),
7640 ctime(&start));
7641 }
34dc7c2f 7642
d4a72f23
TC
7643 scanned = ps->pss_examined;
7644 pass_scanned = ps->pss_pass_exam;
7645 issued = ps->pss_issued;
7646 pass_issued = ps->pss_pass_issued;
428870ff 7647 total = ps->pss_to_examine;
428870ff 7648
d4a72f23
TC
7649 /* we are only done with a block once we have issued the IO for it */
7650 fraction_done = (double)issued / total;
7651
7652 /* elapsed time for this pass, rounding up to 1 if it's 0 */
428870ff 7653 elapsed = time(NULL) - ps->pss_pass_start;
0ea05c64 7654 elapsed -= ps->pss_pass_scrub_spent_paused;
d4a72f23
TC
7655 elapsed = (elapsed != 0) ? elapsed : 1;
7656
7657 scan_rate = pass_scanned / elapsed;
7658 issue_rate = pass_issued / elapsed;
9a49d3f3 7659 uint64_t total_secs_left = (issue_rate != 0 && total >= issued) ?
d4a72f23 7660 ((total - issued) / issue_rate) : UINT64_MAX;
9a49d3f3 7661 secs_to_dhms(total_secs_left, time_buf);
d4a72f23
TC
7662
7663 /* format all of the numbers we will be reporting */
7664 zfs_nicebytes(scanned, scanned_buf, sizeof (scanned_buf));
7665 zfs_nicebytes(issued, issued_buf, sizeof (issued_buf));
e7fbeb60 7666 zfs_nicebytes(total, total_buf, sizeof (total_buf));
d4a72f23
TC
7667 zfs_nicebytes(scan_rate, srate_buf, sizeof (srate_buf));
7668 zfs_nicebytes(issue_rate, irate_buf, sizeof (irate_buf));
428870ff 7669
d4a72f23 7670 /* do not print estimated time if we have a paused scrub */
0ea05c64 7671 if (pause == 0) {
d4a72f23
TC
7672 (void) printf(gettext("\t%s scanned at %s/s, "
7673 "%s issued at %s/s, %s total\n"),
7674 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
572e2857 7675 } else {
d4a72f23
TC
7676 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
7677 scanned_buf, issued_buf, total_buf);
572e2857 7678 }
428870ff 7679
c85ac731 7680 if (is_resilver) {
d4a72f23 7681 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
428870ff 7682 processed_buf, 100 * fraction_done);
c85ac731 7683 } else if (is_scrub) {
d4a72f23 7684 (void) printf(gettext("\t%s repaired, %.2f%% done"),
428870ff
BB
7685 processed_buf, 100 * fraction_done);
7686 }
d4a72f23
TC
7687
7688 if (pause == 0) {
c85ac731
BB
7689 /*
7690 * Only provide an estimate iff:
7691 * 1) the time remaining is valid, and
7692 * 2) the issue rate exceeds 10 MB/s, and
7693 * 3) it's either:
7694 * a) a resilver which has started repairs, or
7695 * b) a scrub which has entered the issue phase.
7696 */
85bdc684 7697 if (total_secs_left != UINT64_MAX &&
c85ac731
BB
7698 issue_rate >= 10 * 1024 * 1024 &&
7699 ((is_resilver && ps->pss_processed > 0) ||
7700 (is_scrub && issued > 0))) {
9a49d3f3
BB
7701 (void) printf(gettext(", %s to go\n"), time_buf);
7702 } else {
7703 (void) printf(gettext(", no estimated "
7704 "completion time\n"));
7705 }
7706 } else {
7707 (void) printf(gettext("\n"));
7708 }
7709}
7710
7711static void
7712print_rebuild_status_impl(vdev_rebuild_stat_t *vrs, char *vdev_name)
7713{
7714 if (vrs == NULL || vrs->vrs_state == VDEV_REBUILD_NONE)
7715 return;
7716
7717 printf(" ");
7718 printf_color(ANSI_BOLD, gettext("scan:"));
7719 printf(" ");
7720
7721 uint64_t bytes_scanned = vrs->vrs_bytes_scanned;
7722 uint64_t bytes_issued = vrs->vrs_bytes_issued;
7723 uint64_t bytes_rebuilt = vrs->vrs_bytes_rebuilt;
7724 uint64_t bytes_est = vrs->vrs_bytes_est;
7725 uint64_t scan_rate = (vrs->vrs_pass_bytes_scanned /
7726 (vrs->vrs_pass_time_ms + 1)) * 1000;
7727 uint64_t issue_rate = (vrs->vrs_pass_bytes_issued /
7728 (vrs->vrs_pass_time_ms + 1)) * 1000;
7729 double scan_pct = MIN((double)bytes_scanned * 100 /
7730 (bytes_est + 1), 100);
7731
7732 /* Format all of the numbers we will be reporting */
7733 char bytes_scanned_buf[7], bytes_issued_buf[7];
7734 char bytes_rebuilt_buf[7], bytes_est_buf[7];
7735 char scan_rate_buf[7], issue_rate_buf[7], time_buf[32];
7736 zfs_nicebytes(bytes_scanned, bytes_scanned_buf,
7737 sizeof (bytes_scanned_buf));
7738 zfs_nicebytes(bytes_issued, bytes_issued_buf,
7739 sizeof (bytes_issued_buf));
7740 zfs_nicebytes(bytes_rebuilt, bytes_rebuilt_buf,
7741 sizeof (bytes_rebuilt_buf));
7742 zfs_nicebytes(bytes_est, bytes_est_buf, sizeof (bytes_est_buf));
7743 zfs_nicebytes(scan_rate, scan_rate_buf, sizeof (scan_rate_buf));
7744 zfs_nicebytes(issue_rate, issue_rate_buf, sizeof (issue_rate_buf));
7745
7746 time_t start = vrs->vrs_start_time;
7747 time_t end = vrs->vrs_end_time;
7748
7749 /* Rebuild is finished or canceled. */
7750 if (vrs->vrs_state == VDEV_REBUILD_COMPLETE) {
7751 secs_to_dhms(vrs->vrs_scan_time_ms / 1000, time_buf);
7752 (void) printf(gettext("resilvered (%s) %s in %s "
7753 "with %llu errors on %s"), vdev_name, bytes_rebuilt_buf,
7754 time_buf, (u_longlong_t)vrs->vrs_errors, ctime(&end));
7755 return;
7756 } else if (vrs->vrs_state == VDEV_REBUILD_CANCELED) {
7757 (void) printf(gettext("resilver (%s) canceled on %s"),
7758 vdev_name, ctime(&end));
7759 return;
7760 } else if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
7761 (void) printf(gettext("resilver (%s) in progress since %s"),
7762 vdev_name, ctime(&start));
7763 }
7764
7765 assert(vrs->vrs_state == VDEV_REBUILD_ACTIVE);
7766
7767 secs_to_dhms(MAX((int64_t)bytes_est - (int64_t)bytes_scanned, 0) /
7768 MAX(scan_rate, 1), time_buf);
7769
7770 (void) printf(gettext("\t%s scanned at %s/s, %s issued %s/s, "
7771 "%s total\n"), bytes_scanned_buf, scan_rate_buf,
7772 bytes_issued_buf, issue_rate_buf, bytes_est_buf);
7773 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
7774 bytes_rebuilt_buf, scan_pct);
7775
7776 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
7777 if (scan_rate >= 10 * 1024 * 1024) {
7778 (void) printf(gettext(", %s to go\n"), time_buf);
d4a72f23
TC
7779 } else {
7780 (void) printf(gettext(", no estimated "
7781 "completion time\n"));
7782 }
7783 } else {
7784 (void) printf(gettext("\n"));
7785 }
34dc7c2f
BB
7786}
7787
d2734cce 7788/*
9a49d3f3
BB
7789 * Print rebuild status for top-level vdevs.
7790 */
7791static void
7792print_rebuild_status(zpool_handle_t *zhp, nvlist_t *nvroot)
7793{
7794 nvlist_t **child;
7795 uint_t children;
7796
7797 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
7798 &child, &children) != 0)
7799 children = 0;
7800
7801 for (uint_t c = 0; c < children; c++) {
7802 vdev_rebuild_stat_t *vrs;
7803 uint_t i;
7804
7805 if (nvlist_lookup_uint64_array(child[c],
7806 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) {
7807 char *name = zpool_vdev_name(g_zfs, zhp,
7808 child[c], VDEV_NAME_TYPE_ID);
7809 print_rebuild_status_impl(vrs, name);
7810 free(name);
7811 }
7812 }
7813}
7814
7815/*
7816 * As we don't scrub checkpointed blocks, we want to warn the user that we
7817 * skipped scanning some blocks if a checkpoint exists or existed at any
7818 * time during the scan. If a sequential instead of healing reconstruction
7819 * was performed then the blocks were reconstructed. However, their checksums
7820 * have not been verified so we still print the warning.
d2734cce
SD
7821 */
7822static void
7823print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
7824{
7825 if (ps == NULL || pcs == NULL)
7826 return;
7827
7828 if (pcs->pcs_state == CS_NONE ||
7829 pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
7830 return;
7831
7832 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
7833
7834 if (ps->pss_state == DSS_NONE)
7835 return;
7836
7837 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
7838 ps->pss_end_time < pcs->pcs_start_time)
7839 return;
7840
7841 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
7842 (void) printf(gettext(" scan warning: skipped blocks "
7843 "that are only referenced by the checkpoint.\n"));
7844 } else {
7845 assert(ps->pss_state == DSS_SCANNING);
7846 (void) printf(gettext(" scan warning: skipping blocks "
7847 "that are only referenced by the checkpoint.\n"));
7848 }
7849}
7850
9a49d3f3
BB
7851/*
7852 * Returns B_TRUE if there is an active rebuild in progress. Otherwise,
7853 * B_FALSE is returned and 'rebuild_end_time' is set to the end time for
7854 * the last completed (or cancelled) rebuild.
7855 */
7856static boolean_t
7857check_rebuilding(nvlist_t *nvroot, uint64_t *rebuild_end_time)
7858{
7859 nvlist_t **child;
7860 uint_t children;
7861 boolean_t rebuilding = B_FALSE;
7862 uint64_t end_time = 0;
7863
7864 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
7865 &child, &children) != 0)
7866 children = 0;
7867
7868 for (uint_t c = 0; c < children; c++) {
7869 vdev_rebuild_stat_t *vrs;
7870 uint_t i;
7871
7872 if (nvlist_lookup_uint64_array(child[c],
7873 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i) == 0) {
7874
7875 if (vrs->vrs_end_time > end_time)
7876 end_time = vrs->vrs_end_time;
7877
7878 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
7879 rebuilding = B_TRUE;
7880 end_time = 0;
7881 break;
7882 }
7883 }
7884 }
7885
7886 if (rebuild_end_time != NULL)
7887 *rebuild_end_time = end_time;
7888
7889 return (rebuilding);
7890}
7891
7892/*
7893 * Print the scan status.
7894 */
7895static void
7896print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
7897{
7898 uint64_t rebuild_end_time = 0, resilver_end_time = 0;
7899 boolean_t have_resilver = B_FALSE, have_scrub = B_FALSE;
7900 boolean_t active_resilver = B_FALSE;
7901 pool_checkpoint_stat_t *pcs = NULL;
7902 pool_scan_stat_t *ps = NULL;
7903 uint_t c;
7904
7905 if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
7906 (uint64_t **)&ps, &c) == 0) {
7907 if (ps->pss_func == POOL_SCAN_RESILVER) {
7908 resilver_end_time = ps->pss_end_time;
7909 active_resilver = (ps->pss_state == DSS_SCANNING);
7910 }
7911
7912 have_resilver = (ps->pss_func == POOL_SCAN_RESILVER);
7913 have_scrub = (ps->pss_func == POOL_SCAN_SCRUB);
7914 }
7915
7916 boolean_t active_rebuild = check_rebuilding(nvroot, &rebuild_end_time);
7917 boolean_t have_rebuild = (active_rebuild || (rebuild_end_time > 0));
7918
7919 /* Always print the scrub status when available. */
7920 if (have_scrub)
7921 print_scan_scrub_resilver_status(ps);
7922
7923 /*
7924 * When there is an active resilver or rebuild print its status.
7925 * Otherwise print the status of the last resilver or rebuild.
7926 */
7927 if (active_resilver || (!active_rebuild && have_resilver &&
7928 resilver_end_time && resilver_end_time > rebuild_end_time)) {
7929 print_scan_scrub_resilver_status(ps);
7930 } else if (active_rebuild || (!active_resilver && have_rebuild &&
7931 rebuild_end_time && rebuild_end_time > resilver_end_time)) {
7932 print_rebuild_status(zhp, nvroot);
7933 }
7934
7935 (void) nvlist_lookup_uint64_array(nvroot,
7936 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
7937 print_checkpoint_scan_warning(ps, pcs);
7938}
7939
a1d477c2
MA
7940/*
7941 * Print out detailed removal status.
7942 */
7943static void
7944print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
7945{
7946 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
7947 time_t start, end;
7948 nvlist_t *config, *nvroot;
7949 nvlist_t **child;
7950 uint_t children;
7951 char *vdev_name;
7952
7953 if (prs == NULL || prs->prs_state == DSS_NONE)
7954 return;
7955
7956 /*
7957 * Determine name of vdev.
7958 */
7959 config = zpool_get_config(zhp, NULL);
7960 nvroot = fnvlist_lookup_nvlist(config,
7961 ZPOOL_CONFIG_VDEV_TREE);
7962 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
7963 &child, &children) == 0);
7964 assert(prs->prs_removing_vdev < children);
7965 vdev_name = zpool_vdev_name(g_zfs, zhp,
7966 child[prs->prs_removing_vdev], B_TRUE);
7967
95a78a03 7968 printf_color(ANSI_BOLD, gettext("remove: "));
a1d477c2
MA
7969
7970 start = prs->prs_start_time;
7971 end = prs->prs_end_time;
7972 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
7973
7974 /*
7975 * Removal is finished or canceled.
7976 */
7977 if (prs->prs_state == DSS_FINISHED) {
7978 uint64_t minutes_taken = (end - start) / 60;
7979
7980 (void) printf(gettext("Removal of vdev %llu copied %s "
7981 "in %lluh%um, completed on %s"),
7982 (longlong_t)prs->prs_removing_vdev,
7983 copied_buf,
7984 (u_longlong_t)(minutes_taken / 60),
7985 (uint_t)(minutes_taken % 60),
7986 ctime((time_t *)&end));
7987 } else if (prs->prs_state == DSS_CANCELED) {
7988 (void) printf(gettext("Removal of %s canceled on %s"),
7989 vdev_name, ctime(&end));
7990 } else {
7991 uint64_t copied, total, elapsed, mins_left, hours_left;
7992 double fraction_done;
7993 uint_t rate;
7994
7995 assert(prs->prs_state == DSS_SCANNING);
7996
7997 /*
7998 * Removal is in progress.
7999 */
8000 (void) printf(gettext(
8001 "Evacuation of %s in progress since %s"),
8002 vdev_name, ctime(&start));
8003
8004 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
8005 total = prs->prs_to_copy;
8006 fraction_done = (double)copied / total;
8007
8008 /* elapsed time for this pass */
8009 elapsed = time(NULL) - prs->prs_start_time;
8010 elapsed = elapsed > 0 ? elapsed : 1;
8011 rate = copied / elapsed;
8012 rate = rate > 0 ? rate : 1;
8013 mins_left = ((total - copied) / rate) / 60;
8014 hours_left = mins_left / 60;
8015
8016 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
8017 zfs_nicenum(total, total_buf, sizeof (total_buf));
8018 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
8019
8020 /*
8021 * do not print estimated time if hours_left is more than
8022 * 30 days
8023 */
fd1c366f
TL
8024 (void) printf(gettext(
8025 "\t%s copied out of %s at %s/s, %.2f%% done"),
a1d477c2
MA
8026 examined_buf, total_buf, rate_buf, 100 * fraction_done);
8027 if (hours_left < (30 * 24)) {
8028 (void) printf(gettext(", %lluh%um to go\n"),
8029 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
8030 } else {
8031 (void) printf(gettext(
8032 ", (copy is slow, no estimated time)\n"));
8033 }
8034 }
75c62019 8035 free(vdev_name);
a1d477c2
MA
8036
8037 if (prs->prs_mapping_memory > 0) {
8038 char mem_buf[7];
8039 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
fd1c366f
TL
8040 (void) printf(gettext(
8041 "\t%s memory used for removed device mappings\n"),
a1d477c2
MA
8042 mem_buf);
8043 }
8044}
8045
d2734cce
SD
8046static void
8047print_checkpoint_status(pool_checkpoint_stat_t *pcs)
8048{
8049 time_t start;
8050 char space_buf[7];
8051
8052 if (pcs == NULL || pcs->pcs_state == CS_NONE)
8053 return;
8054
8055 (void) printf(gettext("checkpoint: "));
8056
8057 start = pcs->pcs_start_time;
8058 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
8059
8060 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
8061 char *date = ctime(&start);
8062
8063 /*
8064 * ctime() adds a newline at the end of the generated
8065 * string, thus the weird format specifier and the
8066 * strlen() call used to chop it off from the output.
8067 */
8068 (void) printf(gettext("created %.*s, consumes %s\n"),
8069 (int)(strlen(date) - 1), date, space_buf);
8070 return;
8071 }
8072
8073 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
8074
8075 (void) printf(gettext("discarding, %s remaining.\n"),
8076 space_buf);
8077}
8078
34dc7c2f
BB
8079static void
8080print_error_log(zpool_handle_t *zhp)
8081{
8082 nvlist_t *nverrlist = NULL;
8083 nvpair_t *elem;
8084 char *pathname;
8085 size_t len = MAXPATHLEN * 2;
8086
56a6054d 8087 if (zpool_get_errlog(zhp, &nverrlist) != 0)
34dc7c2f 8088 return;
34dc7c2f
BB
8089
8090 (void) printf("errors: Permanent errors have been "
8091 "detected in the following files:\n\n");
8092
8093 pathname = safe_malloc(len);
8094 elem = NULL;
8095 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
8096 nvlist_t *nv;
8097 uint64_t dsobj, obj;
8098
8099 verify(nvpair_value_nvlist(elem, &nv) == 0);
8100 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
8101 &dsobj) == 0);
8102 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
8103 &obj) == 0);
8104 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
8105 (void) printf("%7s %s\n", "", pathname);
8106 }
8107 free(pathname);
8108 nvlist_free(nverrlist);
8109}
8110
8111static void
fea33e4e
HJ
8112print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
8113 uint_t nspares)
34dc7c2f
BB
8114{
8115 uint_t i;
8116 char *name;
8117
8118 if (nspares == 0)
8119 return;
8120
8121 (void) printf(gettext("\tspares\n"));
8122
8123 for (i = 0; i < nspares; i++) {
fea33e4e
HJ
8124 name = zpool_vdev_name(g_zfs, zhp, spares[i],
8125 cb->cb_name_flags);
9a49d3f3 8126 print_status_config(zhp, cb, name, spares[i], 2, B_TRUE, NULL);
34dc7c2f
BB
8127 free(name);
8128 }
8129}
8130
8131static void
fea33e4e
HJ
8132print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
8133 uint_t nl2cache)
34dc7c2f
BB
8134{
8135 uint_t i;
8136 char *name;
8137
8138 if (nl2cache == 0)
8139 return;
8140
8141 (void) printf(gettext("\tcache\n"));
8142
8143 for (i = 0; i < nl2cache; i++) {
fea33e4e
HJ
8144 name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
8145 cb->cb_name_flags);
9a49d3f3
BB
8146 print_status_config(zhp, cb, name, l2cache[i], 2,
8147 B_FALSE, NULL);
34dc7c2f
BB
8148 free(name);
8149 }
8150}
8151
428870ff
BB
8152static void
8153print_dedup_stats(nvlist_t *config)
8154{
8155 ddt_histogram_t *ddh;
8156 ddt_stat_t *dds;
8157 ddt_object_t *ddo;
8158 uint_t c;
e7fbeb60 8159 char dspace[6], mspace[6];
428870ff
BB
8160
8161 /*
8162 * If the pool was faulted then we may not have been able to
32a9872b 8163 * obtain the config. Otherwise, if we have anything in the dedup
428870ff
BB
8164 * table continue processing the stats.
8165 */
8166 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
24024589 8167 (uint64_t **)&ddo, &c) != 0)
428870ff
BB
8168 return;
8169
8170 (void) printf("\n");
24024589
YP
8171 (void) printf(gettext(" dedup: "));
8172 if (ddo->ddo_count == 0) {
8173 (void) printf(gettext("no DDT entries\n"));
8174 return;
8175 }
8176
e7fbeb60 8177 zfs_nicebytes(ddo->ddo_dspace, dspace, sizeof (dspace));
8178 zfs_nicebytes(ddo->ddo_mspace, mspace, sizeof (mspace));
8179 (void) printf("DDT entries %llu, size %s on disk, %s in core\n",
428870ff 8180 (u_longlong_t)ddo->ddo_count,
e7fbeb60 8181 dspace,
8182 mspace);
428870ff
BB
8183
8184 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
8185 (uint64_t **)&dds, &c) == 0);
8186 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
8187 (uint64_t **)&ddh, &c) == 0);
8188 zpool_dump_ddt(dds, ddh);
8189}
8190
34dc7c2f
BB
8191/*
8192 * Display a summary of pool status. Displays a summary such as:
8193 *
8194 * pool: tank
8195 * status: DEGRADED
8196 * reason: One or more devices ...
a2f944a1 8197 * see: https://openzfs.github.io/openzfs-docs/msg/ZFS-xxxx-01
34dc7c2f
BB
8198 * config:
8199 * mirror DEGRADED
8200 * c1t0d0 OK
8201 * c2t0d0 UNAVAIL
8202 *
8203 * When given the '-v' option, we print out the complete config. If the '-e'
8204 * option is specified, then we print out error rate information as well.
8205 */
65c7cc49 8206static int
34dc7c2f
BB
8207status_callback(zpool_handle_t *zhp, void *data)
8208{
8209 status_cbdata_t *cbp = data;
8210 nvlist_t *config, *nvroot;
a926aab9 8211 const char *msgid;
731782ec 8212 zpool_status_t reason;
ffe9d382 8213 zpool_errata_t errata;
34dc7c2f
BB
8214 const char *health;
8215 uint_t c;
8216 vdev_stat_t *vs;
8217
8218 config = zpool_get_config(zhp, NULL);
ffe9d382 8219 reason = zpool_get_status(zhp, &msgid, &errata);
34dc7c2f
BB
8220
8221 cbp->cb_count++;
8222
8223 /*
8224 * If we were given 'zpool status -x', only report those pools with
8225 * problems.
8226 */
c5b247f3
TC
8227 if (cbp->cb_explain &&
8228 (reason == ZPOOL_STATUS_OK ||
8229 reason == ZPOOL_STATUS_VERSION_OLDER ||
658fb802 8230 reason == ZPOOL_STATUS_FEAT_DISABLED ||
e086db16
CB
8231 reason == ZPOOL_STATUS_COMPATIBILITY_ERR ||
8232 reason == ZPOOL_STATUS_INCOMPATIBLE_FEAT)) {
34dc7c2f
BB
8233 if (!cbp->cb_allpools) {
8234 (void) printf(gettext("pool '%s' is healthy\n"),
8235 zpool_get_name(zhp));
8236 if (cbp->cb_first)
8237 cbp->cb_first = B_FALSE;
8238 }
8239 return (0);
8240 }
8241
8242 if (cbp->cb_first)
8243 cbp->cb_first = B_FALSE;
8244 else
8245 (void) printf("\n");
8246
a1d477c2 8247 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
428870ff 8248 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
34dc7c2f 8249 (uint64_t **)&vs, &c) == 0);
f0ed6c74
TH
8250
8251 health = zpool_get_state_str(zhp);
34dc7c2f 8252
9fb2771a
TH
8253 printf(" ");
8254 printf_color(ANSI_BOLD, gettext("pool:"));
8255 printf(" %s\n", zpool_get_name(zhp));
a926aab9 8256 fputc(' ', stdout);
9fb2771a
TH
8257 printf_color(ANSI_BOLD, gettext("state: "));
8258
8259 printf_color(health_str_to_color(health), "%s", health);
8260
a926aab9 8261 fputc('\n', stdout);
34dc7c2f
BB
8262
8263 switch (reason) {
8264 case ZPOOL_STATUS_MISSING_DEV_R:
9fb2771a
TH
8265 printf_color(ANSI_BOLD, gettext("status: "));
8266 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8267 "not be opened. Sufficient replicas exist for\n\tthe pool "
8268 "to continue functioning in a degraded state.\n"));
8269 printf_color(ANSI_BOLD, gettext("action: "));
8270 printf_color(ANSI_YELLOW, gettext("Attach the missing device "
8271 "and online it using 'zpool online'.\n"));
34dc7c2f
BB
8272 break;
8273
8274 case ZPOOL_STATUS_MISSING_DEV_NR:
9fb2771a
TH
8275 printf_color(ANSI_BOLD, gettext("status: "));
8276 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8277 "not be opened. There are insufficient\n\treplicas for the"
8278 " pool to continue functioning.\n"));
8279 printf_color(ANSI_BOLD, gettext("action: "));
8280 printf_color(ANSI_YELLOW, gettext("Attach the missing device "
8281 "and online it using 'zpool online'.\n"));
34dc7c2f
BB
8282 break;
8283
8284 case ZPOOL_STATUS_CORRUPT_LABEL_R:
9fb2771a
TH
8285 printf_color(ANSI_BOLD, gettext("status: "));
8286 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8287 "not be used because the label is missing or\n\tinvalid. "
34dc7c2f
BB
8288 "Sufficient replicas exist for the pool to continue\n\t"
8289 "functioning in a degraded state.\n"));
9fb2771a
TH
8290 printf_color(ANSI_BOLD, gettext("action: "));
8291 printf_color(ANSI_YELLOW, gettext("Replace the device using "
34dc7c2f
BB
8292 "'zpool replace'.\n"));
8293 break;
8294
8295 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
9fb2771a
TH
8296 printf_color(ANSI_BOLD, gettext("status: "));
8297 printf_color(ANSI_YELLOW, gettext("One or more devices could "
8298 "not be used because the label is missing \n\tor invalid. "
34dc7c2f
BB
8299 "There are insufficient replicas for the pool to "
8300 "continue\n\tfunctioning.\n"));
428870ff
BB
8301 zpool_explain_recover(zpool_get_handle(zhp),
8302 zpool_get_name(zhp), reason, config);
34dc7c2f
BB
8303 break;
8304
8305 case ZPOOL_STATUS_FAILING_DEV:
9fb2771a
TH
8306 printf_color(ANSI_BOLD, gettext("status: "));
8307 printf_color(ANSI_YELLOW, gettext("One or more devices has "
34dc7c2f
BB
8308 "experienced an unrecoverable error. An\n\tattempt was "
8309 "made to correct the error. Applications are "
8310 "unaffected.\n"));
9fb2771a
TH
8311 printf_color(ANSI_BOLD, gettext("action: "));
8312 printf_color(ANSI_YELLOW, gettext("Determine if the "
8313 "device needs to be replaced, and clear the errors\n\tusing"
8314 " 'zpool clear' or replace the device with 'zpool "
34dc7c2f
BB
8315 "replace'.\n"));
8316 break;
8317
8318 case ZPOOL_STATUS_OFFLINE_DEV:
9fb2771a
TH
8319 printf_color(ANSI_BOLD, gettext("status: "));
8320 printf_color(ANSI_YELLOW, gettext("One or more devices has "
34dc7c2f
BB
8321 "been taken offline by the administrator.\n\tSufficient "
8322 "replicas exist for the pool to continue functioning in "
8323 "a\n\tdegraded state.\n"));
9fb2771a
TH
8324 printf_color(ANSI_BOLD, gettext("action: "));
8325 printf_color(ANSI_YELLOW, gettext("Online the device "
8326 "using 'zpool online' or replace the device with\n\t'zpool "
34dc7c2f
BB
8327 "replace'.\n"));
8328 break;
8329
45d1cae3 8330 case ZPOOL_STATUS_REMOVED_DEV:
9fb2771a
TH
8331 printf_color(ANSI_BOLD, gettext("status: "));
8332 printf_color(ANSI_YELLOW, gettext("One or more devices has "
45d1cae3
BB
8333 "been removed by the administrator.\n\tSufficient "
8334 "replicas exist for the pool to continue functioning in "
8335 "a\n\tdegraded state.\n"));
9fb2771a
TH
8336 printf_color(ANSI_BOLD, gettext("action: "));
8337 printf_color(ANSI_YELLOW, gettext("Online the device "
8338 "using zpool online' or replace the device with\n\t'zpool "
45d1cae3
BB
8339 "replace'.\n"));
8340 break;
8341
34dc7c2f 8342 case ZPOOL_STATUS_RESILVERING:
9a49d3f3 8343 case ZPOOL_STATUS_REBUILDING:
9fb2771a
TH
8344 printf_color(ANSI_BOLD, gettext("status: "));
8345 printf_color(ANSI_YELLOW, gettext("One or more devices is "
34dc7c2f
BB
8346 "currently being resilvered. The pool will\n\tcontinue "
8347 "to function, possibly in a degraded state.\n"));
9fb2771a
TH
8348 printf_color(ANSI_BOLD, gettext("action: "));
8349 printf_color(ANSI_YELLOW, gettext("Wait for the resilver to "
34dc7c2f
BB
8350 "complete.\n"));
8351 break;
8352
9a49d3f3
BB
8353 case ZPOOL_STATUS_REBUILD_SCRUB:
8354 printf_color(ANSI_BOLD, gettext("status: "));
8355 printf_color(ANSI_YELLOW, gettext("One or more devices have "
8356 "been sequentially resilvered, scrubbing\n\tthe pool "
8357 "is recommended.\n"));
8358 printf_color(ANSI_BOLD, gettext("action: "));
8359 printf_color(ANSI_YELLOW, gettext("Use 'zpool scrub' to "
8360 "verify all data checksums.\n"));
8361 break;
8362
34dc7c2f 8363 case ZPOOL_STATUS_CORRUPT_DATA:
9fb2771a
TH
8364 printf_color(ANSI_BOLD, gettext("status: "));
8365 printf_color(ANSI_YELLOW, gettext("One or more devices has "
34dc7c2f
BB
8366 "experienced an error resulting in data\n\tcorruption. "
8367 "Applications may be affected.\n"));
9fb2771a
TH
8368 printf_color(ANSI_BOLD, gettext("action: "));
8369 printf_color(ANSI_YELLOW, gettext("Restore the file in question"
8370 " if possible. Otherwise restore the\n\tentire pool from "
34dc7c2f
BB
8371 "backup.\n"));
8372 break;
8373
8374 case ZPOOL_STATUS_CORRUPT_POOL:
9fb2771a
TH
8375 printf_color(ANSI_BOLD, gettext("status: "));
8376 printf_color(ANSI_YELLOW, gettext("The pool metadata is "
8377 "corrupted and the pool cannot be opened.\n"));
428870ff
BB
8378 zpool_explain_recover(zpool_get_handle(zhp),
8379 zpool_get_name(zhp), reason, config);
34dc7c2f
BB
8380 break;
8381
8382 case ZPOOL_STATUS_VERSION_OLDER:
9fb2771a
TH
8383 printf_color(ANSI_BOLD, gettext("status: "));
8384 printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
8385 "a legacy on-disk format. The pool can\n\tstill be used, "
b9b24bb4 8386 "but some features are unavailable.\n"));
9fb2771a
TH
8387 printf_color(ANSI_BOLD, gettext("action: "));
8388 printf_color(ANSI_YELLOW, gettext("Upgrade the pool using "
8389 "'zpool upgrade'. Once this is done, the\n\tpool will no "
8390 "longer be accessible on software that does not support\n\t"
f52b31ea 8391 "feature flags.\n"));
34dc7c2f
BB
8392 break;
8393
8394 case ZPOOL_STATUS_VERSION_NEWER:
9fb2771a
TH
8395 printf_color(ANSI_BOLD, gettext("status: "));
8396 printf_color(ANSI_YELLOW, gettext("The pool has been upgraded "
8397 "to a newer, incompatible on-disk version.\n\tThe pool "
8398 "cannot be accessed on this system.\n"));
8399 printf_color(ANSI_BOLD, gettext("action: "));
8400 printf_color(ANSI_YELLOW, gettext("Access the pool from a "
8401 "system running more recent software, or\n\trestore the "
8402 "pool from backup.\n"));
34dc7c2f
BB
8403 break;
8404
b9b24bb4 8405 case ZPOOL_STATUS_FEAT_DISABLED:
9fb2771a 8406 printf_color(ANSI_BOLD, gettext("status: "));
658fb802
CB
8407 printf_color(ANSI_YELLOW, gettext("Some supported and "
8408 "requested features are not enabled on the pool.\n\t"
8409 "The pool can still be used, but some features are "
8410 "unavailable.\n"));
9fb2771a
TH
8411 printf_color(ANSI_BOLD, gettext("action: "));
8412 printf_color(ANSI_YELLOW, gettext("Enable all features using "
b9b24bb4
CS
8413 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
8414 "longer be accessible by software that does not support\n\t"
2badb345 8415 "the features. See zpool-features(7) for details.\n"));
b9b24bb4
CS
8416 break;
8417
658fb802
CB
8418 case ZPOOL_STATUS_COMPATIBILITY_ERR:
8419 printf_color(ANSI_BOLD, gettext("status: "));
8420 printf_color(ANSI_YELLOW, gettext("This pool has a "
8421 "compatibility list specified, but it could not be\n\t"
8422 "read/parsed at this time. The pool can still be used, "
8423 "but this\n\tshould be investigated.\n"));
8424 printf_color(ANSI_BOLD, gettext("action: "));
8425 printf_color(ANSI_YELLOW, gettext("Check the value of the "
8426 "'compatibility' property against the\n\t"
8427 "appropriate file in " ZPOOL_SYSCONF_COMPAT_D " or "
8428 ZPOOL_DATA_COMPAT_D ".\n"));
8429 break;
8430
e086db16
CB
8431 case ZPOOL_STATUS_INCOMPATIBLE_FEAT:
8432 printf_color(ANSI_BOLD, gettext("status: "));
8433 printf_color(ANSI_YELLOW, gettext("One or more features "
8434 "are enabled on the pool despite not being\n\t"
8435 "requested by the 'compatibility' property.\n"));
8436 printf_color(ANSI_BOLD, gettext("action: "));
8437 printf_color(ANSI_YELLOW, gettext("Consider setting "
8438 "'compatibility' to an appropriate value, or\n\t"
8439 "adding needed features to the relevant file in\n\t"
8440 ZPOOL_SYSCONF_COMPAT_D " or " ZPOOL_DATA_COMPAT_D ".\n"));
8441 break;
8442
9ae529ec 8443 case ZPOOL_STATUS_UNSUP_FEAT_READ:
9fb2771a
TH
8444 printf_color(ANSI_BOLD, gettext("status: "));
8445 printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed "
8446 "on this system because it uses the\n\tfollowing feature(s)"
8447 " not supported on this system:\n"));
9ae529ec
CS
8448 zpool_print_unsup_feat(config);
8449 (void) printf("\n");
9fb2771a
TH
8450 printf_color(ANSI_BOLD, gettext("action: "));
8451 printf_color(ANSI_YELLOW, gettext("Access the pool from a "
8452 "system that supports the required feature(s),\n\tor "
8453 "restore the pool from backup.\n"));
9ae529ec
CS
8454 break;
8455
8456 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
9fb2771a
TH
8457 printf_color(ANSI_BOLD, gettext("status: "));
8458 printf_color(ANSI_YELLOW, gettext("The pool can only be "
8459 "accessed in read-only mode on this system. It\n\tcannot be"
8460 " accessed in read-write mode because it uses the "
9ae529ec
CS
8461 "following\n\tfeature(s) not supported on this system:\n"));
8462 zpool_print_unsup_feat(config);
8463 (void) printf("\n");
9fb2771a
TH
8464 printf_color(ANSI_BOLD, gettext("action: "));
8465 printf_color(ANSI_YELLOW, gettext("The pool cannot be accessed "
8466 "in read-write mode. Import the pool with\n"
9ae529ec
CS
8467 "\t\"-o readonly=on\", access the pool from a system that "
8468 "supports the\n\trequired feature(s), or restore the "
8469 "pool from backup.\n"));
8470 break;
8471
34dc7c2f 8472 case ZPOOL_STATUS_FAULTED_DEV_R:
9fb2771a
TH
8473 printf_color(ANSI_BOLD, gettext("status: "));
8474 printf_color(ANSI_YELLOW, gettext("One or more devices are "
34dc7c2f
BB
8475 "faulted in response to persistent errors.\n\tSufficient "
8476 "replicas exist for the pool to continue functioning "
8477 "in a\n\tdegraded state.\n"));
9fb2771a
TH
8478 printf_color(ANSI_BOLD, gettext("action: "));
8479 printf_color(ANSI_YELLOW, gettext("Replace the faulted device, "
34dc7c2f
BB
8480 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
8481 break;
8482
8483 case ZPOOL_STATUS_FAULTED_DEV_NR:
9fb2771a
TH
8484 printf_color(ANSI_BOLD, gettext("status: "));
8485 printf_color(ANSI_YELLOW, gettext("One or more devices are "
34dc7c2f
BB
8486 "faulted in response to persistent errors. There are "
8487 "insufficient replicas for the pool to\n\tcontinue "
8488 "functioning.\n"));
9fb2771a
TH
8489 printf_color(ANSI_BOLD, gettext("action: "));
8490 printf_color(ANSI_YELLOW, gettext("Destroy and re-create the "
8491 "pool from a backup source. Manually marking the device\n"
34dc7c2f
BB
8492 "\trepaired using 'zpool clear' may allow some data "
8493 "to be recovered.\n"));
8494 break;
8495
cec3a0a1 8496 case ZPOOL_STATUS_IO_FAILURE_MMP:
9fb2771a
TH
8497 printf_color(ANSI_BOLD, gettext("status: "));
8498 printf_color(ANSI_YELLOW, gettext("The pool is suspended "
8499 "because multihost writes failed or were delayed;\n\t"
8500 "another system could import the pool undetected.\n"));
8501 printf_color(ANSI_BOLD, gettext("action: "));
8502 printf_color(ANSI_YELLOW, gettext("Make sure the pool's devices"
8503 " are connected, then reboot your system and\n\timport the "
cec3a0a1
OF
8504 "pool.\n"));
8505 break;
8506
b128c09f
BB
8507 case ZPOOL_STATUS_IO_FAILURE_WAIT:
8508 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
9fb2771a
TH
8509 printf_color(ANSI_BOLD, gettext("status: "));
8510 printf_color(ANSI_YELLOW, gettext("One or more devices are "
b128c09f 8511 "faulted in response to IO failures.\n"));
9fb2771a
TH
8512 printf_color(ANSI_BOLD, gettext("action: "));
8513 printf_color(ANSI_YELLOW, gettext("Make sure the affected "
8514 "devices are connected, then run 'zpool clear'.\n"));
b128c09f
BB
8515 break;
8516
8517 case ZPOOL_STATUS_BAD_LOG:
9fb2771a
TH
8518 printf_color(ANSI_BOLD, gettext("status: "));
8519 printf_color(ANSI_YELLOW, gettext("An intent log record "
b128c09f 8520 "could not be read.\n"
2627e752 8521 "\tWaiting for administrator intervention to fix the "
b128c09f 8522 "faulted pool.\n"));
9fb2771a
TH
8523 printf_color(ANSI_BOLD, gettext("action: "));
8524 printf_color(ANSI_YELLOW, gettext("Either restore the affected "
b128c09f
BB
8525 "device(s) and run 'zpool online',\n"
8526 "\tor ignore the intent log records by running "
8527 "'zpool clear'.\n"));
8528 break;
8529
6fe3498c
RM
8530 case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
8531 (void) printf(gettext("status: One or more devices are "
8532 "configured to use a non-native block size.\n"
8533 "\tExpect reduced performance.\n"));
8534 (void) printf(gettext("action: Replace affected devices with "
8535 "devices that support the\n\tconfigured block size, or "
8536 "migrate data to a properly configured\n\tpool.\n"));
8537 break;
8538
1cbae971 8539 case ZPOOL_STATUS_HOSTID_MISMATCH:
9fb2771a
TH
8540 printf_color(ANSI_BOLD, gettext("status: "));
8541 printf_color(ANSI_YELLOW, gettext("Mismatch between pool hostid"
8542 " and system hostid on imported pool.\n\tThis pool was "
1cbae971
RY
8543 "previously imported into a system with a different "
8544 "hostid,\n\tand then was verbatim imported into this "
8545 "system.\n"));
9fb2771a
TH
8546 printf_color(ANSI_BOLD, gettext("action: "));
8547 printf_color(ANSI_YELLOW, gettext("Export this pool on all "
8548 "systems on which it is imported.\n"
1cbae971
RY
8549 "\tThen import it to correct the mismatch.\n"));
8550 break;
8551
ffe9d382 8552 case ZPOOL_STATUS_ERRATA:
9fb2771a
TH
8553 printf_color(ANSI_BOLD, gettext("status: "));
8554 printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
ffe9d382
BB
8555 errata);
8556
8557 switch (errata) {
8558 case ZPOOL_ERRATA_NONE:
8559 break;
8560
4f2dcb3e 8561 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
9fb2771a
TH
8562 printf_color(ANSI_BOLD, gettext("action: "));
8563 printf_color(ANSI_YELLOW, gettext("To correct the issue"
8564 " run 'zpool scrub'.\n"));
4f2dcb3e
RY
8565 break;
8566
ae76f45c
TC
8567 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
8568 (void) printf(gettext("\tExisting encrypted datasets "
8569 "contain an on-disk incompatibility\n\twhich "
8570 "needs to be corrected.\n"));
9fb2771a
TH
8571 printf_color(ANSI_BOLD, gettext("action: "));
8572 printf_color(ANSI_YELLOW, gettext("To correct the issue"
8573 " backup existing encrypted datasets to new\n\t"
ae76f45c
TC
8574 "encrypted datasets and destroy the old ones. "
8575 "'zfs mount -o ro' can\n\tbe used to temporarily "
8576 "mount existing encrypted datasets readonly.\n"));
8577 break;
8578
f00ab3f2 8579 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
e2dddb7e
JS
8580 (void) printf(gettext("\tExisting encrypted snapshots "
8581 "and bookmarks contain an on-disk\n\tincompat"
8582 "ibility. This may cause on-disk corruption if "
8583 "they are used\n\twith 'zfs recv'.\n"));
9fb2771a
TH
8584 printf_color(ANSI_BOLD, gettext("action: "));
8585 printf_color(ANSI_YELLOW, gettext("To correct the"
8586 "issue, enable the bookmark_v2 feature. No "
8587 "additional\n\taction is needed if there are no "
8588 "encrypted snapshots or bookmarks.\n\tIf preserving"
8589 "the encrypted snapshots and bookmarks is required,"
8590 " use\n\ta non-raw send to backup and restore them."
8591 " Alternately, they may be\n\tremoved to resolve "
e2dddb7e 8592 "the incompatibility.\n"));
f00ab3f2
TC
8593 break;
8594
ffe9d382
BB
8595 default:
8596 /*
8597 * All errata which allow the pool to be imported
8598 * must contain an action message.
8599 */
8600 assert(0);
8601 }
8602 break;
8603
34dc7c2f
BB
8604 default:
8605 /*
8606 * The remaining errors can't actually be generated, yet.
8607 */
8608 assert(reason == ZPOOL_STATUS_OK);
8609 }
8610
9fb2771a
TH
8611 if (msgid != NULL) {
8612 printf(" ");
8613 printf_color(ANSI_BOLD, gettext("see:"));
a2f944a1
RM
8614 printf(gettext(
8615 " https://openzfs.github.io/openzfs-docs/msg/%s\n"),
8616 msgid);
9fb2771a 8617 }
34dc7c2f
BB
8618
8619 if (config != NULL) {
34dc7c2f
BB
8620 uint64_t nerr;
8621 nvlist_t **spares, **l2cache;
8622 uint_t nspares, nl2cache;
d2734cce 8623 pool_checkpoint_stat_t *pcs = NULL;
a1d477c2 8624 pool_removal_stat_t *prs = NULL;
34dc7c2f 8625
9a49d3f3
BB
8626 print_scan_status(zhp, nvroot);
8627
a1d477c2
MA
8628 (void) nvlist_lookup_uint64_array(nvroot,
8629 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
8630 print_removal_status(zhp, prs);
9a49d3f3
BB
8631
8632 (void) nvlist_lookup_uint64_array(nvroot,
8633 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
d2734cce 8634 print_checkpoint_status(pcs);
a1d477c2 8635
fea33e4e 8636 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
5f20c145 8637 cbp->cb_name_flags | VDEV_NAME_TYPE_ID);
fea33e4e
HJ
8638 if (cbp->cb_namewidth < 10)
8639 cbp->cb_namewidth = 10;
34dc7c2f 8640
9fb2771a 8641 color_start(ANSI_BOLD);
34dc7c2f 8642 (void) printf(gettext("config:\n\n"));
d6418de0 8643 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s"),
fea33e4e
HJ
8644 cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
8645 "CKSUM");
9fb2771a 8646 color_end();
d6418de0 8647
9fb2771a
TH
8648 if (cbp->cb_print_slow_ios) {
8649 printf_color(ANSI_BOLD, " %5s", gettext("SLOW"));
8650 }
ad796b8a 8651
d6418de0
TH
8652 if (cbp->vcdl != NULL)
8653 print_cmd_columns(cbp->vcdl, 0);
8654
8655 printf("\n");
cc99f275 8656
fea33e4e 8657 print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
9a49d3f3 8658 B_FALSE, NULL);
34dc7c2f 8659
cc99f275
DB
8660 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
8661 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
8662 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
8663
34dc7c2f
BB
8664 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
8665 &l2cache, &nl2cache) == 0)
fea33e4e 8666 print_l2cache(zhp, cbp, l2cache, nl2cache);
34dc7c2f
BB
8667
8668 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
8669 &spares, &nspares) == 0)
fea33e4e 8670 print_spares(zhp, cbp, spares, nspares);
34dc7c2f
BB
8671
8672 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
8673 &nerr) == 0) {
34dc7c2f 8674 (void) printf("\n");
018f2604
MA
8675 if (nerr == 0) {
8676 (void) printf(gettext(
8677 "errors: No known data errors\n"));
8678 } else if (!cbp->cb_verbose) {
34dc7c2f
BB
8679 (void) printf(gettext("errors: %llu data "
8680 "errors, use '-v' for a list\n"),
8681 (u_longlong_t)nerr);
018f2604 8682 } else {
34dc7c2f 8683 print_error_log(zhp);
018f2604 8684 }
34dc7c2f 8685 }
428870ff
BB
8686
8687 if (cbp->cb_dedup_stats)
8688 print_dedup_stats(config);
34dc7c2f
BB
8689 } else {
8690 (void) printf(gettext("config: The configuration cannot be "
8691 "determined.\n"));
8692 }
8693
8694 return (0);
8695}
8696
8697/*
1b939560 8698 * zpool status [-c [script1,script2,...]] [-igLpPstvx] [-T d|u] [pool] ...
d6418de0 8699 * [interval [count]]
34dc7c2f 8700 *
8720e9e7 8701 * -c CMD For each vdev, run command CMD
a769fb53 8702 * -i Display vdev initialization status.
d2f3e292
RY
8703 * -g Display guid for individual vdev name.
8704 * -L Follow links when resolving vdev path name.
ad796b8a 8705 * -p Display values in parsable (exact) format.
a77f29f9 8706 * -P Display full path for vdev name.
ad796b8a 8707 * -s Display slow IOs column.
34dc7c2f
BB
8708 * -v Display complete error logs
8709 * -x Display only pools with potential problems
428870ff 8710 * -D Display dedup status (undocumented)
1b939560 8711 * -t Display vdev TRIM status.
428870ff 8712 * -T Display a timestamp in date(1) or Unix format
34dc7c2f
BB
8713 *
8714 * Describes the health status of all pools or some subset.
8715 */
8716int
8717zpool_do_status(int argc, char **argv)
8718{
8719 int c;
8720 int ret;
193a37cb
TH
8721 float interval = 0;
8722 unsigned long count = 0;
34dc7c2f 8723 status_cbdata_t cb = { 0 };
8720e9e7 8724 char *cmd = NULL;
34dc7c2f
BB
8725
8726 /* check options */
1b939560 8727 while ((c = getopt(argc, argv, "c:igLpPsvxDtT:")) != -1) {
34dc7c2f 8728 switch (c) {
8720e9e7 8729 case 'c':
d6418de0
TH
8730 if (cmd != NULL) {
8731 fprintf(stderr,
8732 gettext("Can't set -c flag twice\n"));
8733 exit(1);
8734 }
099700d9
GDN
8735
8736 if (getenv("ZPOOL_SCRIPTS_ENABLED") != NULL &&
8737 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_ENABLED")) {
8738 fprintf(stderr, gettext(
8739 "Can't run -c, disabled by "
8740 "ZPOOL_SCRIPTS_ENABLED.\n"));
8741 exit(1);
8742 }
8743
d6418de0
TH
8744 if ((getuid() <= 0 || geteuid() <= 0) &&
8745 !libzfs_envvar_is_set("ZPOOL_SCRIPTS_AS_ROOT")) {
8746 fprintf(stderr, gettext(
8747 "Can't run -c with root privileges "
8748 "unless ZPOOL_SCRIPTS_AS_ROOT is set.\n"));
8749 exit(1);
8750 }
8720e9e7
TH
8751 cmd = optarg;
8752 break;
a769fb53
BB
8753 case 'i':
8754 cb.cb_print_vdev_init = B_TRUE;
8755 break;
d2f3e292
RY
8756 case 'g':
8757 cb.cb_name_flags |= VDEV_NAME_GUID;
8758 break;
8759 case 'L':
8760 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
8761 break;
ad796b8a
TH
8762 case 'p':
8763 cb.cb_literal = B_TRUE;
8764 break;
a77f29f9 8765 case 'P':
d2f3e292
RY
8766 cb.cb_name_flags |= VDEV_NAME_PATH;
8767 break;
ad796b8a
TH
8768 case 's':
8769 cb.cb_print_slow_ios = B_TRUE;
8770 break;
34dc7c2f
BB
8771 case 'v':
8772 cb.cb_verbose = B_TRUE;
8773 break;
8774 case 'x':
8775 cb.cb_explain = B_TRUE;
8776 break;
428870ff
BB
8777 case 'D':
8778 cb.cb_dedup_stats = B_TRUE;
8779 break;
1b939560
BB
8780 case 't':
8781 cb.cb_print_vdev_trim = B_TRUE;
8782 break;
428870ff
BB
8783 case 'T':
8784 get_timestamp_arg(*optarg);
8785 break;
34dc7c2f 8786 case '?':
1528bfdb 8787 if (optopt == 'c') {
099700d9 8788 print_zpool_script_list("status");
d6418de0 8789 exit(0);
1528bfdb
TH
8790 } else {
8791 fprintf(stderr,
8792 gettext("invalid option '%c'\n"), optopt);
8793 }
34dc7c2f
BB
8794 usage(B_FALSE);
8795 }
8796 }
8797
8798 argc -= optind;
8799 argv += optind;
8800
428870ff 8801 get_interval_count(&argc, argv, &interval, &count);
34dc7c2f
BB
8802
8803 if (argc == 0)
8804 cb.cb_allpools = B_TRUE;
8805
428870ff 8806 cb.cb_first = B_TRUE;
fea33e4e 8807 cb.cb_print_status = B_TRUE;
34dc7c2f 8808
428870ff
BB
8809 for (;;) {
8810 if (timestamp_fmt != NODATE)
8811 print_timestamp(timestamp_fmt);
34dc7c2f 8812
8720e9e7 8813 if (cmd != NULL)
1528bfdb
TH
8814 cb.vcdl = all_pools_for_each_vdev_run(argc, argv, cmd,
8815 NULL, NULL, 0, 0);
8720e9e7 8816
2a673e76
AJ
8817 ret = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
8818 cb.cb_literal, status_callback, &cb);
428870ff 8819
8720e9e7
TH
8820 if (cb.vcdl != NULL)
8821 free_vdev_cmd_data_list(cb.vcdl);
8822
428870ff 8823 if (argc == 0 && cb.cb_count == 0)
42cb3819 8824 (void) fprintf(stderr, gettext("no pools available\n"));
428870ff
BB
8825 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
8826 (void) printf(gettext("all pools are healthy\n"));
8827
8828 if (ret != 0)
8829 return (ret);
8830
8831 if (interval == 0)
8832 break;
8833
8834 if (count != 0 && --count == 0)
8835 break;
8836
193a37cb 8837 (void) fsleep(interval);
428870ff
BB
8838 }
8839
8840 return (0);
34dc7c2f
BB
8841}
8842
8843typedef struct upgrade_cbdata {
34dc7c2f 8844 int cb_first;
34dc7c2f
BB
8845 int cb_argc;
8846 uint64_t cb_version;
8847 char **cb_argv;
8848} upgrade_cbdata_t;
8849
287be44f
DS
8850static int
8851check_unsupp_fs(zfs_handle_t *zhp, void *unsupp_fs)
8852{
02730c33 8853 int zfs_version = (int)zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
287be44f
DS
8854 int *count = (int *)unsupp_fs;
8855
8856 if (zfs_version > ZPL_VERSION) {
8857 (void) printf(gettext("%s (v%d) is not supported by this "
8858 "implementation of ZFS.\n"),
8859 zfs_get_name(zhp), zfs_version);
8860 (*count)++;
8861 }
8862
baca06c2 8863 zfs_iter_filesystems_v2(zhp, 0, check_unsupp_fs, unsupp_fs);
287be44f
DS
8864
8865 zfs_close(zhp);
8866
8867 return (0);
8868}
8869
b9b24bb4
CS
8870static int
8871upgrade_version(zpool_handle_t *zhp, uint64_t version)
8872{
8873 int ret;
8874 nvlist_t *config;
8875 uint64_t oldversion;
287be44f 8876 int unsupp_fs = 0;
b9b24bb4
CS
8877
8878 config = zpool_get_config(zhp, NULL);
8879 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
8880 &oldversion) == 0);
8881
e086db16
CB
8882 char compat[ZFS_MAXPROPLEN];
8883 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat,
8884 ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
8885 compat[0] = '\0';
8886
b9b24bb4
CS
8887 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
8888 assert(oldversion < version);
8889
287be44f
DS
8890 ret = zfs_iter_root(zpool_get_handle(zhp), check_unsupp_fs, &unsupp_fs);
8891 if (ret != 0)
8892 return (ret);
8893
8894 if (unsupp_fs) {
5c7afad4
BB
8895 (void) fprintf(stderr, gettext("Upgrade not performed due "
8896 "to %d unsupported filesystems (max v%d).\n"),
02730c33 8897 unsupp_fs, (int)ZPL_VERSION);
287be44f
DS
8898 return (1);
8899 }
8900
e086db16
CB
8901 if (strcmp(compat, ZPOOL_COMPAT_LEGACY) == 0) {
8902 (void) fprintf(stderr, gettext("Upgrade not performed because "
8903 "'compatibility' property set to '"
8904 ZPOOL_COMPAT_LEGACY "'.\n"));
8905 return (1);
8906 }
8907
b9b24bb4
CS
8908 ret = zpool_upgrade(zhp, version);
8909 if (ret != 0)
8910 return (ret);
8911
8912 if (version >= SPA_VERSION_FEATURES) {
8913 (void) printf(gettext("Successfully upgraded "
8914 "'%s' from version %llu to feature flags.\n"),
02730c33 8915 zpool_get_name(zhp), (u_longlong_t)oldversion);
b9b24bb4
CS
8916 } else {
8917 (void) printf(gettext("Successfully upgraded "
8918 "'%s' from version %llu to version %llu.\n"),
02730c33
BB
8919 zpool_get_name(zhp), (u_longlong_t)oldversion,
8920 (u_longlong_t)version);
b9b24bb4
CS
8921 }
8922
8923 return (0);
8924}
8925
8926static int
8927upgrade_enable_all(zpool_handle_t *zhp, int *countp)
8928{
8929 int i, ret, count;
8930 boolean_t firstff = B_TRUE;
8931 nvlist_t *enabled = zpool_get_features(zhp);
8932
658fb802
CB
8933 char compat[ZFS_MAXPROPLEN];
8934 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY, compat,
8935 ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
8936 compat[0] = '\0';
8937
8938 boolean_t requested_features[SPA_FEATURES];
8939 if (zpool_do_load_compat(compat, requested_features) !=
8940 ZPOOL_COMPATIBILITY_OK)
8941 return (-1);
8942
b9b24bb4
CS
8943 count = 0;
8944 for (i = 0; i < SPA_FEATURES; i++) {
8945 const char *fname = spa_feature_table[i].fi_uname;
8946 const char *fguid = spa_feature_table[i].fi_guid;
35ec5179
BB
8947
8948 if (!spa_feature_table[i].fi_zfs_mod_supported)
8949 continue;
8950
658fb802 8951 if (!nvlist_exists(enabled, fguid) && requested_features[i]) {
b9b24bb4
CS
8952 char *propname;
8953 verify(-1 != asprintf(&propname, "feature@%s", fname));
8954 ret = zpool_set_prop(zhp, propname,
8955 ZFS_FEATURE_ENABLED);
8956 if (ret != 0) {
8957 free(propname);
8958 return (ret);
8959 }
8960 count++;
8961
8962 if (firstff) {
8963 (void) printf(gettext("Enabled the "
8964 "following features on '%s':\n"),
8965 zpool_get_name(zhp));
8966 firstff = B_FALSE;
8967 }
8968 (void) printf(gettext(" %s\n"), fname);
8969 free(propname);
8970 }
8971 }
8972
8973 if (countp != NULL)
8974 *countp = count;
8975 return (0);
8976}
8977
34dc7c2f
BB
8978static int
8979upgrade_cb(zpool_handle_t *zhp, void *arg)
8980{
8981 upgrade_cbdata_t *cbp = arg;
8982 nvlist_t *config;
8983 uint64_t version;
65d9212a 8984 boolean_t modified_pool = B_FALSE;
b9b24bb4 8985 int ret;
34dc7c2f
BB
8986
8987 config = zpool_get_config(zhp, NULL);
8988 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
8989 &version) == 0);
8990
b9b24bb4 8991 assert(SPA_VERSION_IS_SUPPORTED(version));
34dc7c2f 8992
b9b24bb4
CS
8993 if (version < cbp->cb_version) {
8994 cbp->cb_first = B_FALSE;
8995 ret = upgrade_version(zhp, cbp->cb_version);
8996 if (ret != 0)
8997 return (ret);
65d9212a 8998 modified_pool = B_TRUE;
b9b24bb4 8999
b9b24bb4
CS
9000 /*
9001 * If they did "zpool upgrade -a", then we could
9002 * be doing ioctls to different pools. We need
9003 * to log this history once to each pool, and bypass
9004 * the normal history logging that happens in main().
9005 */
9006 (void) zpool_log_history(g_zfs, history_str);
9007 log_history = B_FALSE;
b9b24bb4
CS
9008 }
9009
9010 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
9011 int count;
9012 ret = upgrade_enable_all(zhp, &count);
9013 if (ret != 0)
9014 return (ret);
9015
9016 if (count > 0) {
34dc7c2f 9017 cbp->cb_first = B_FALSE;
65d9212a 9018 modified_pool = B_TRUE;
34dc7c2f 9019 }
b9b24bb4 9020 }
34dc7c2f 9021
65d9212a 9022 if (modified_pool) {
9023 (void) printf("\n");
9024 (void) after_zpool_upgrade(zhp);
b9b24bb4
CS
9025 }
9026
9027 return (0);
9028}
9029
9030static int
9031upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
9032{
9033 upgrade_cbdata_t *cbp = arg;
9034 nvlist_t *config;
9035 uint64_t version;
9036
9037 config = zpool_get_config(zhp, NULL);
9038 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
9039 &version) == 0);
9040
9041 assert(SPA_VERSION_IS_SUPPORTED(version));
9042
9043 if (version < SPA_VERSION_FEATURES) {
34dc7c2f
BB
9044 if (cbp->cb_first) {
9045 (void) printf(gettext("The following pools are "
b9b24bb4
CS
9046 "formatted with legacy version numbers and can\n"
9047 "be upgraded to use feature flags. After "
9048 "being upgraded, these pools\nwill no "
9049 "longer be accessible by software that does not "
e086db16
CB
9050 "support feature\nflags.\n\n"
9051 "Note that setting a pool's 'compatibility' "
9052 "feature to '" ZPOOL_COMPAT_LEGACY "' will\n"
9053 "inhibit upgrades.\n\n"));
34dc7c2f
BB
9054 (void) printf(gettext("VER POOL\n"));
9055 (void) printf(gettext("--- ------------\n"));
9056 cbp->cb_first = B_FALSE;
9057 }
9058
9059 (void) printf("%2llu %s\n", (u_longlong_t)version,
9060 zpool_get_name(zhp));
9061 }
9062
b9b24bb4
CS
9063 return (0);
9064}
9065
9066static int
9067upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
9068{
9069 upgrade_cbdata_t *cbp = arg;
9070 nvlist_t *config;
9071 uint64_t version;
9072
9073 config = zpool_get_config(zhp, NULL);
9074 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
9075 &version) == 0);
9076
9077 if (version >= SPA_VERSION_FEATURES) {
9078 int i;
9079 boolean_t poolfirst = B_TRUE;
9080 nvlist_t *enabled = zpool_get_features(zhp);
9081
9082 for (i = 0; i < SPA_FEATURES; i++) {
9083 const char *fguid = spa_feature_table[i].fi_guid;
9084 const char *fname = spa_feature_table[i].fi_uname;
35ec5179
BB
9085
9086 if (!spa_feature_table[i].fi_zfs_mod_supported)
9087 continue;
9088
b9b24bb4
CS
9089 if (!nvlist_exists(enabled, fguid)) {
9090 if (cbp->cb_first) {
9091 (void) printf(gettext("\nSome "
9092 "supported features are not "
9093 "enabled on the following pools. "
9094 "Once a\nfeature is enabled the "
9095 "pool may become incompatible with "
9096 "software\nthat does not support "
9097 "the feature. See "
2badb345 9098 "zpool-features(7) for "
e086db16
CB
9099 "details.\n\n"
9100 "Note that the pool "
9101 "'compatibility' feature can be "
9102 "used to inhibit\nfeature "
9103 "upgrades.\n\n"));
b9b24bb4
CS
9104 (void) printf(gettext("POOL "
9105 "FEATURE\n"));
9106 (void) printf(gettext("------"
9107 "---------\n"));
9108 cbp->cb_first = B_FALSE;
9109 }
9110
9111 if (poolfirst) {
9112 (void) printf(gettext("%s\n"),
9113 zpool_get_name(zhp));
9114 poolfirst = B_FALSE;
9115 }
9116
9117 (void) printf(gettext(" %s\n"), fname);
9118 }
6f1ffb06
MA
9119 /*
9120 * If they did "zpool upgrade -a", then we could
9121 * be doing ioctls to different pools. We need
9122 * to log this history once to each pool, and bypass
9123 * the normal history logging that happens in main().
9124 */
9125 (void) zpool_log_history(g_zfs, history_str);
9126 log_history = B_FALSE;
b9b24bb4
CS
9127 }
9128 }
9129
9130 return (0);
34dc7c2f
BB
9131}
9132
34dc7c2f
BB
9133static int
9134upgrade_one(zpool_handle_t *zhp, void *data)
9135{
65d9212a 9136 boolean_t modified_pool = B_FALSE;
34dc7c2f
BB
9137 upgrade_cbdata_t *cbp = data;
9138 uint64_t cur_version;
9139 int ret;
9140
9141 if (strcmp("log", zpool_get_name(zhp)) == 0) {
c66989ba 9142 (void) fprintf(stderr, gettext("'log' is now a reserved word\n"
34dc7c2f
BB
9143 "Pool 'log' must be renamed using export and import"
9144 " to upgrade.\n"));
9145 return (1);
9146 }
9147
9148 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
9149 if (cur_version > cbp->cb_version) {
9150 (void) printf(gettext("Pool '%s' is already formatted "
b9b24bb4 9151 "using more current version '%llu'.\n\n"),
02730c33 9152 zpool_get_name(zhp), (u_longlong_t)cur_version);
34dc7c2f
BB
9153 return (0);
9154 }
b9b24bb4
CS
9155
9156 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
34dc7c2f 9157 (void) printf(gettext("Pool '%s' is already formatted "
b9b24bb4 9158 "using version %llu.\n\n"), zpool_get_name(zhp),
02730c33 9159 (u_longlong_t)cbp->cb_version);
34dc7c2f
BB
9160 return (0);
9161 }
9162
b9b24bb4 9163 if (cur_version != cbp->cb_version) {
65d9212a 9164 modified_pool = B_TRUE;
b9b24bb4
CS
9165 ret = upgrade_version(zhp, cbp->cb_version);
9166 if (ret != 0)
9167 return (ret);
9168 }
34dc7c2f 9169
b9b24bb4
CS
9170 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
9171 int count = 0;
9172 ret = upgrade_enable_all(zhp, &count);
9173 if (ret != 0)
9174 return (ret);
9175
9176 if (count != 0) {
65d9212a 9177 modified_pool = B_TRUE;
b9b24bb4
CS
9178 } else if (cur_version == SPA_VERSION) {
9179 (void) printf(gettext("Pool '%s' already has all "
658fb802 9180 "supported and requested features enabled.\n"),
b9b24bb4
CS
9181 zpool_get_name(zhp));
9182 }
9183 }
9184
65d9212a 9185 if (modified_pool) {
9186 (void) printf("\n");
9187 (void) after_zpool_upgrade(zhp);
34dc7c2f
BB
9188 }
9189
b9b24bb4 9190 return (0);
34dc7c2f
BB
9191}
9192
9193/*
9194 * zpool upgrade
9195 * zpool upgrade -v
9196 * zpool upgrade [-V version] <-a | pool ...>
9197 *
9198 * With no arguments, display downrev'd ZFS pool available for upgrade.
9199 * Individual pools can be upgraded by specifying the pool, and '-a' will
9200 * upgrade all pools.
9201 */
9202int
9203zpool_do_upgrade(int argc, char **argv)
9204{
9205 int c;
9206 upgrade_cbdata_t cb = { 0 };
9207 int ret = 0;
9208 boolean_t showversions = B_FALSE;
b9b24bb4 9209 boolean_t upgradeall = B_FALSE;
34dc7c2f
BB
9210 char *end;
9211
9212
9213 /* check options */
9babb374 9214 while ((c = getopt(argc, argv, ":avV:")) != -1) {
34dc7c2f
BB
9215 switch (c) {
9216 case 'a':
b9b24bb4 9217 upgradeall = B_TRUE;
34dc7c2f
BB
9218 break;
9219 case 'v':
9220 showversions = B_TRUE;
9221 break;
9222 case 'V':
9223 cb.cb_version = strtoll(optarg, &end, 10);
9ae529ec
CS
9224 if (*end != '\0' ||
9225 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
34dc7c2f
BB
9226 (void) fprintf(stderr,
9227 gettext("invalid version '%s'\n"), optarg);
9228 usage(B_FALSE);
9229 }
9230 break;
9babb374
BB
9231 case ':':
9232 (void) fprintf(stderr, gettext("missing argument for "
9233 "'%c' option\n"), optopt);
9234 usage(B_FALSE);
9235 break;
34dc7c2f
BB
9236 case '?':
9237 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9238 optopt);
9239 usage(B_FALSE);
9240 }
9241 }
9242
9243 cb.cb_argc = argc;
9244 cb.cb_argv = argv;
9245 argc -= optind;
9246 argv += optind;
9247
9248 if (cb.cb_version == 0) {
9249 cb.cb_version = SPA_VERSION;
b9b24bb4 9250 } else if (!upgradeall && argc == 0) {
34dc7c2f
BB
9251 (void) fprintf(stderr, gettext("-V option is "
9252 "incompatible with other arguments\n"));
9253 usage(B_FALSE);
9254 }
9255
9256 if (showversions) {
b9b24bb4 9257 if (upgradeall || argc != 0) {
34dc7c2f
BB
9258 (void) fprintf(stderr, gettext("-v option is "
9259 "incompatible with other arguments\n"));
9260 usage(B_FALSE);
9261 }
b9b24bb4 9262 } else if (upgradeall) {
34dc7c2f
BB
9263 if (argc != 0) {
9264 (void) fprintf(stderr, gettext("-a option should not "
9265 "be used along with a pool name\n"));
9266 usage(B_FALSE);
9267 }
9268 }
9269
63652e15 9270 (void) printf("%s", gettext("This system supports ZFS pool feature "
9ae529ec 9271 "flags.\n\n"));
34dc7c2f 9272 if (showversions) {
b9b24bb4
CS
9273 int i;
9274
9275 (void) printf(gettext("The following features are "
9276 "supported:\n\n"));
9277 (void) printf(gettext("FEAT DESCRIPTION\n"));
9278 (void) printf("----------------------------------------------"
9279 "---------------\n");
9280 for (i = 0; i < SPA_FEATURES; i++) {
9281 zfeature_info_t *fi = &spa_feature_table[i];
03ef8f09
MM
9282 if (!fi->fi_zfs_mod_supported)
9283 continue;
241b5415
MA
9284 const char *ro =
9285 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
b9b24bb4
CS
9286 " (read-only compatible)" : "";
9287
9288 (void) printf("%-37s%s\n", fi->fi_uname, ro);
9289 (void) printf(" %s\n", fi->fi_desc);
9290 }
9291 (void) printf("\n");
9292
9293 (void) printf(gettext("The following legacy versions are also "
34dc7c2f
BB
9294 "supported:\n\n"));
9295 (void) printf(gettext("VER DESCRIPTION\n"));
9296 (void) printf("--- -----------------------------------------"
9297 "---------------\n");
9298 (void) printf(gettext(" 1 Initial ZFS version\n"));
9299 (void) printf(gettext(" 2 Ditto blocks "
9300 "(replicated metadata)\n"));
9301 (void) printf(gettext(" 3 Hot spares and double parity "
9302 "RAID-Z\n"));
9303 (void) printf(gettext(" 4 zpool history\n"));
9304 (void) printf(gettext(" 5 Compression using the gzip "
9305 "algorithm\n"));
9306 (void) printf(gettext(" 6 bootfs pool property\n"));
9307 (void) printf(gettext(" 7 Separate intent log devices\n"));
9308 (void) printf(gettext(" 8 Delegated administration\n"));
9309 (void) printf(gettext(" 9 refquota and refreservation "
9310 "properties\n"));
9311 (void) printf(gettext(" 10 Cache devices\n"));
b128c09f
BB
9312 (void) printf(gettext(" 11 Improved scrub performance\n"));
9313 (void) printf(gettext(" 12 Snapshot properties\n"));
9314 (void) printf(gettext(" 13 snapused property\n"));
9babb374
BB
9315 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
9316 (void) printf(gettext(" 15 user/group space accounting\n"));
9317 (void) printf(gettext(" 16 stmf property support\n"));
45d1cae3 9318 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
428870ff
BB
9319 (void) printf(gettext(" 18 Snapshot user holds\n"));
9320 (void) printf(gettext(" 19 Log device removal\n"));
9321 (void) printf(gettext(" 20 Compression using zle "
9322 "(zero-length encoding)\n"));
9323 (void) printf(gettext(" 21 Deduplication\n"));
9324 (void) printf(gettext(" 22 Received properties\n"));
9325 (void) printf(gettext(" 23 Slim ZIL\n"));
9326 (void) printf(gettext(" 24 System attributes\n"));
9327 (void) printf(gettext(" 25 Improved scrub stats\n"));
9328 (void) printf(gettext(" 26 Improved snapshot deletion "
9329 "performance\n"));
572e2857
BB
9330 (void) printf(gettext(" 27 Improved snapshot creation "
9331 "performance\n"));
9332 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
428870ff
BB
9333 (void) printf(gettext("\nFor more information on a particular "
9334 "version, including supported releases,\n"));
9335 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
b9b24bb4
CS
9336 } else if (argc == 0 && upgradeall) {
9337 cb.cb_first = B_TRUE;
34dc7c2f 9338 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
b9b24bb4
CS
9339 if (ret == 0 && cb.cb_first) {
9340 if (cb.cb_version == SPA_VERSION) {
9341 (void) printf(gettext("All pools are already "
9342 "formatted using feature flags.\n\n"));
9343 (void) printf(gettext("Every feature flags "
658fb802
CB
9344 "pool already has all supported and "
9345 "requested features enabled.\n"));
b9b24bb4
CS
9346 } else {
9347 (void) printf(gettext("All pools are already "
9348 "formatted with version %llu or higher.\n"),
02730c33 9349 (u_longlong_t)cb.cb_version);
34dc7c2f
BB
9350 }
9351 }
b9b24bb4
CS
9352 } else if (argc == 0) {
9353 cb.cb_first = B_TRUE;
9354 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
9355 assert(ret == 0);
34dc7c2f 9356
b9b24bb4
CS
9357 if (cb.cb_first) {
9358 (void) printf(gettext("All pools are formatted "
9359 "using feature flags.\n\n"));
9360 } else {
9361 (void) printf(gettext("\nUse 'zpool upgrade -v' "
9362 "for a list of available legacy versions.\n"));
9363 }
9364
9365 cb.cb_first = B_TRUE;
9366 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
9367 assert(ret == 0);
9368
9369 if (cb.cb_first) {
9370 (void) printf(gettext("Every feature flags pool has "
658fb802 9371 "all supported and requested features enabled.\n"));
b9b24bb4
CS
9372 } else {
9373 (void) printf(gettext("\n"));
34dc7c2f
BB
9374 }
9375 } else {
2a673e76
AJ
9376 ret = for_each_pool(argc, argv, B_FALSE, NULL, ZFS_TYPE_POOL,
9377 B_FALSE, upgrade_one, &cb);
34dc7c2f
BB
9378 }
9379
9380 return (ret);
9381}
9382
9383typedef struct hist_cbdata {
9384 boolean_t first;
6f1ffb06
MA
9385 boolean_t longfmt;
9386 boolean_t internal;
34dc7c2f
BB
9387} hist_cbdata_t;
9388
7125a109
CC
9389static void
9390print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
34dc7c2f 9391{
34dc7c2f
BB
9392 nvlist_t **records;
9393 uint_t numrecords;
7125a109 9394 int i;
34dc7c2f
BB
9395
9396 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
9397 &records, &numrecords) == 0);
9398 for (i = 0; i < numrecords; i++) {
6f1ffb06 9399 nvlist_t *rec = records[i];
2ac90457 9400 char tbuf[64] = "";
34dc7c2f 9401
6f1ffb06
MA
9402 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
9403 time_t tsec;
9404 struct tm t;
34dc7c2f 9405
6f1ffb06
MA
9406 tsec = fnvlist_lookup_uint64(records[i],
9407 ZPOOL_HIST_TIME);
9408 (void) localtime_r(&tsec, &t);
9409 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
9410 }
9411
2ac90457
MA
9412 if (nvlist_exists(rec, ZPOOL_HIST_ELAPSED_NS)) {
9413 uint64_t elapsed_ns = fnvlist_lookup_int64(records[i],
9414 ZPOOL_HIST_ELAPSED_NS);
9415 (void) snprintf(tbuf + strlen(tbuf),
9416 sizeof (tbuf) - strlen(tbuf),
9417 " (%lldms)", (long long)elapsed_ns / 1000 / 1000);
9418 }
9419
6f1ffb06
MA
9420 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
9421 (void) printf("%s %s", tbuf,
9422 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
9423 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
9424 int ievent =
9425 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
9426 if (!cb->internal)
34dc7c2f 9427 continue;
6f1ffb06
MA
9428 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
9429 (void) printf("%s unrecognized record:\n",
9430 tbuf);
9431 dump_nvlist(rec, 4);
34dc7c2f 9432 continue;
6f1ffb06
MA
9433 }
9434 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
9435 zfs_history_event_names[ievent],
02730c33 9436 (longlong_t)fnvlist_lookup_uint64(
d1d7e268 9437 rec, ZPOOL_HIST_TXG),
6f1ffb06
MA
9438 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
9439 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
9440 if (!cb->internal)
9441 continue;
9442 (void) printf("%s [txg:%lld] %s", tbuf,
02730c33 9443 (longlong_t)fnvlist_lookup_uint64(
d1d7e268 9444 rec, ZPOOL_HIST_TXG),
6f1ffb06
MA
9445 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
9446 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
9447 (void) printf(" %s (%llu)",
9448 fnvlist_lookup_string(rec,
9449 ZPOOL_HIST_DSNAME),
d1d7e268 9450 (u_longlong_t)fnvlist_lookup_uint64(rec,
6f1ffb06
MA
9451 ZPOOL_HIST_DSID));
9452 }
9453 (void) printf(" %s", fnvlist_lookup_string(rec,
9454 ZPOOL_HIST_INT_STR));
9455 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
9456 if (!cb->internal)
9457 continue;
9458 (void) printf("%s ioctl %s\n", tbuf,
9459 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
9460 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
9461 (void) printf(" input:\n");
9462 dump_nvlist(fnvlist_lookup_nvlist(rec,
9463 ZPOOL_HIST_INPUT_NVL), 8);
9464 }
9465 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
9466 (void) printf(" output:\n");
9467 dump_nvlist(fnvlist_lookup_nvlist(rec,
9468 ZPOOL_HIST_OUTPUT_NVL), 8);
9469 }
d66aab7c
MA
9470 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_SIZE)) {
9471 (void) printf(" output nvlist omitted; "
9472 "original size: %lldKB\n",
9473 (longlong_t)fnvlist_lookup_int64(rec,
9474 ZPOOL_HIST_OUTPUT_SIZE) / 1024);
9475 }
d99a0153
CW
9476 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
9477 (void) printf(" errno: %lld\n",
9478 (longlong_t)fnvlist_lookup_int64(rec,
9479 ZPOOL_HIST_ERRNO));
9480 }
6f1ffb06
MA
9481 } else {
9482 if (!cb->internal)
9483 continue;
9484 (void) printf("%s unrecognized record:\n", tbuf);
9485 dump_nvlist(rec, 4);
34dc7c2f 9486 }
34dc7c2f
BB
9487
9488 if (!cb->longfmt) {
9489 (void) printf("\n");
9490 continue;
9491 }
9492 (void) printf(" [");
6f1ffb06
MA
9493 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
9494 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
9495 struct passwd *pwd = getpwuid(who);
9496 (void) printf("user %d ", (int)who);
9497 if (pwd != NULL)
9498 (void) printf("(%s) ", pwd->pw_name);
34dc7c2f 9499 }
6f1ffb06
MA
9500 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
9501 (void) printf("on %s",
9502 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
34dc7c2f 9503 }
6f1ffb06
MA
9504 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
9505 (void) printf(":%s",
9506 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
34dc7c2f
BB
9507 }
9508
9509 (void) printf("]");
9510 (void) printf("\n");
9511 }
7125a109
CC
9512}
9513
9514/*
9515 * Print out the command history for a specific pool.
9516 */
9517static int
9518get_history_one(zpool_handle_t *zhp, void *data)
9519{
9520 nvlist_t *nvhis;
9521 int ret;
9522 hist_cbdata_t *cb = (hist_cbdata_t *)data;
9523 uint64_t off = 0;
9524 boolean_t eof = B_FALSE;
9525
9526 cb->first = B_FALSE;
9527
9528 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
9529
9530 while (!eof) {
9531 if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
9532 return (ret);
9533
9534 print_history_records(nvhis, cb);
9535 nvlist_free(nvhis);
9536 }
34dc7c2f 9537 (void) printf("\n");
34dc7c2f
BB
9538
9539 return (ret);
9540}
9541
9542/*
9543 * zpool history <pool>
9544 *
9545 * Displays the history of commands that modified pools.
9546 */
34dc7c2f
BB
9547int
9548zpool_do_history(int argc, char **argv)
9549{
9550 hist_cbdata_t cbdata = { 0 };
9551 int ret;
9552 int c;
9553
9554 cbdata.first = B_TRUE;
9555 /* check options */
9556 while ((c = getopt(argc, argv, "li")) != -1) {
9557 switch (c) {
9558 case 'l':
6f1ffb06 9559 cbdata.longfmt = B_TRUE;
34dc7c2f
BB
9560 break;
9561 case 'i':
6f1ffb06 9562 cbdata.internal = B_TRUE;
34dc7c2f
BB
9563 break;
9564 case '?':
9565 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9566 optopt);
9567 usage(B_FALSE);
9568 }
9569 }
9570 argc -= optind;
9571 argv += optind;
9572
2a673e76
AJ
9573 ret = for_each_pool(argc, argv, B_FALSE, NULL, ZFS_TYPE_POOL,
9574 B_FALSE, get_history_one, &cbdata);
34dc7c2f
BB
9575
9576 if (argc == 0 && cbdata.first == B_TRUE) {
42cb3819 9577 (void) fprintf(stderr, gettext("no pools available\n"));
34dc7c2f
BB
9578 return (0);
9579 }
9580
9581 return (ret);
9582}
9583
26685276
BB
9584typedef struct ev_opts {
9585 int verbose;
c5343ba7 9586 int scripted;
26685276
BB
9587 int follow;
9588 int clear;
88f9c939 9589 char poolname[ZFS_MAX_DATASET_NAME_LEN];
26685276
BB
9590} ev_opts_t;
9591
9592static void
1e1c3980 9593zpool_do_events_short(nvlist_t *nvl, ev_opts_t *opts)
26685276 9594{
d1807f16
RY
9595 char ctime_str[26], str[32];
9596 const char *ptr;
26685276
BB
9597 int64_t *tv;
9598 uint_t n;
9599
9600 verify(nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0);
9601 memset(str, ' ', 32);
9602 (void) ctime_r((const time_t *)&tv[0], ctime_str);
7cd723e6
GA
9603 (void) memcpy(str, ctime_str+4, 6); /* 'Jun 30' */
9604 (void) memcpy(str+7, ctime_str+20, 4); /* '1993' */
9605 (void) memcpy(str+12, ctime_str+11, 8); /* '21:49:08' */
d1d7e268 9606 (void) sprintf(str+20, ".%09lld", (longlong_t)tv[1]); /* '.123456789' */
1e1c3980
SH
9607 if (opts->scripted)
9608 (void) printf(gettext("%s\t"), str);
9609 else
9610 (void) printf(gettext("%s "), str);
26685276
BB
9611
9612 verify(nvlist_lookup_string(nvl, FM_CLASS, &ptr) == 0);
9613 (void) printf(gettext("%s\n"), ptr);
9614}
9615
9616static void
9617zpool_do_events_nvprint(nvlist_t *nvl, int depth)
9618{
9619 nvpair_t *nvp;
9620
9621 for (nvp = nvlist_next_nvpair(nvl, NULL);
9622 nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) {
9623
9624 data_type_t type = nvpair_type(nvp);
9625 const char *name = nvpair_name(nvp);
9626
9627 boolean_t b;
9628 uint8_t i8;
9629 uint16_t i16;
9630 uint32_t i32;
9631 uint64_t i64;
d1807f16 9632 const char *str;
26685276
BB
9633 nvlist_t *cnv;
9634
9635 printf(gettext("%*s%s = "), depth, "", name);
9636
9637 switch (type) {
9638 case DATA_TYPE_BOOLEAN:
9639 printf(gettext("%s"), "1");
9640 break;
9641
9642 case DATA_TYPE_BOOLEAN_VALUE:
9643 (void) nvpair_value_boolean_value(nvp, &b);
9644 printf(gettext("%s"), b ? "1" : "0");
9645 break;
9646
9647 case DATA_TYPE_BYTE:
9648 (void) nvpair_value_byte(nvp, &i8);
9649 printf(gettext("0x%x"), i8);
9650 break;
9651
9652 case DATA_TYPE_INT8:
9653 (void) nvpair_value_int8(nvp, (void *)&i8);
9654 printf(gettext("0x%x"), i8);
9655 break;
9656
9657 case DATA_TYPE_UINT8:
9658 (void) nvpair_value_uint8(nvp, &i8);
9659 printf(gettext("0x%x"), i8);
9660 break;
9661
9662 case DATA_TYPE_INT16:
9663 (void) nvpair_value_int16(nvp, (void *)&i16);
9664 printf(gettext("0x%x"), i16);
9665 break;
9666
9667 case DATA_TYPE_UINT16:
9668 (void) nvpair_value_uint16(nvp, &i16);
9669 printf(gettext("0x%x"), i16);
9670 break;
9671
9672 case DATA_TYPE_INT32:
9673 (void) nvpair_value_int32(nvp, (void *)&i32);
9674 printf(gettext("0x%x"), i32);
9675 break;
9676
9677 case DATA_TYPE_UINT32:
9678 (void) nvpair_value_uint32(nvp, &i32);
9679 printf(gettext("0x%x"), i32);
9680 break;
9681
9682 case DATA_TYPE_INT64:
9683 (void) nvpair_value_int64(nvp, (void *)&i64);
9684 printf(gettext("0x%llx"), (u_longlong_t)i64);
9685 break;
9686
9687 case DATA_TYPE_UINT64:
9688 (void) nvpair_value_uint64(nvp, &i64);
d02ca379
DB
9689 /*
9690 * translate vdev state values to readable
9691 * strings to aide zpool events consumers
9692 */
9693 if (strcmp(name,
9694 FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
9695 strcmp(name,
9696 FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
9697 printf(gettext("\"%s\" (0x%llx)"),
9698 zpool_state_to_name(i64, VDEV_AUX_NONE),
9699 (u_longlong_t)i64);
9700 } else {
9701 printf(gettext("0x%llx"), (u_longlong_t)i64);
9702 }
26685276
BB
9703 break;
9704
9705 case DATA_TYPE_HRTIME:
9706 (void) nvpair_value_hrtime(nvp, (void *)&i64);
9707 printf(gettext("0x%llx"), (u_longlong_t)i64);
9708 break;
9709
9710 case DATA_TYPE_STRING:
9711 (void) nvpair_value_string(nvp, &str);
9712 printf(gettext("\"%s\""), str ? str : "<NULL>");
9713 break;
9714
9715 case DATA_TYPE_NVLIST:
9716 printf(gettext("(embedded nvlist)\n"));
9717 (void) nvpair_value_nvlist(nvp, &cnv);
9718 zpool_do_events_nvprint(cnv, depth + 8);
c5343ba7 9719 printf(gettext("%*s(end %s)"), depth, "", name);
26685276
BB
9720 break;
9721
9722 case DATA_TYPE_NVLIST_ARRAY: {
9723 nvlist_t **val;
9724 uint_t i, nelem;
9725
9726 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
9727 printf(gettext("(%d embedded nvlists)\n"), nelem);
9728 for (i = 0; i < nelem; i++) {
9729 printf(gettext("%*s%s[%d] = %s\n"),
d1d7e268 9730 depth, "", name, i, "(embedded nvlist)");
26685276
BB
9731 zpool_do_events_nvprint(val[i], depth + 8);
9732 printf(gettext("%*s(end %s[%i])\n"),
d1d7e268 9733 depth, "", name, i);
26685276
BB
9734 }
9735 printf(gettext("%*s(end %s)\n"), depth, "", name);
9736 }
9737 break;
9738
9739 case DATA_TYPE_INT8_ARRAY: {
9740 int8_t *val;
9741 uint_t i, nelem;
9742
9743 (void) nvpair_value_int8_array(nvp, &val, &nelem);
9744 for (i = 0; i < nelem; i++)
9745 printf(gettext("0x%x "), val[i]);
9746
9747 break;
9748 }
9749
9750 case DATA_TYPE_UINT8_ARRAY: {
9751 uint8_t *val;
9752 uint_t i, nelem;
9753
9754 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
9755 for (i = 0; i < nelem; i++)
9756 printf(gettext("0x%x "), val[i]);
9757
9758 break;
9759 }
9760
9761 case DATA_TYPE_INT16_ARRAY: {
9762 int16_t *val;
9763 uint_t i, nelem;
9764
9765 (void) nvpair_value_int16_array(nvp, &val, &nelem);
9766 for (i = 0; i < nelem; i++)
9767 printf(gettext("0x%x "), val[i]);
9768
9769 break;
9770 }
9771
9772 case DATA_TYPE_UINT16_ARRAY: {
9773 uint16_t *val;
9774 uint_t i, nelem;
9775
9776 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
9777 for (i = 0; i < nelem; i++)
9778 printf(gettext("0x%x "), val[i]);
9779
9780 break;
9781 }
9782
9783 case DATA_TYPE_INT32_ARRAY: {
9784 int32_t *val;
9785 uint_t i, nelem;
9786
9787 (void) nvpair_value_int32_array(nvp, &val, &nelem);
9788 for (i = 0; i < nelem; i++)
9789 printf(gettext("0x%x "), val[i]);
9790
9791 break;
9792 }
9793
9794 case DATA_TYPE_UINT32_ARRAY: {
9795 uint32_t *val;
9796 uint_t i, nelem;
9797
9798 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
9799 for (i = 0; i < nelem; i++)
9800 printf(gettext("0x%x "), val[i]);
9801
9802 break;
9803 }
9804
9805 case DATA_TYPE_INT64_ARRAY: {
9806 int64_t *val;
9807 uint_t i, nelem;
9808
9809 (void) nvpair_value_int64_array(nvp, &val, &nelem);
9810 for (i = 0; i < nelem; i++)
d1d7e268
MK
9811 printf(gettext("0x%llx "),
9812 (u_longlong_t)val[i]);
26685276
BB
9813
9814 break;
9815 }
9816
9817 case DATA_TYPE_UINT64_ARRAY: {
9818 uint64_t *val;
9819 uint_t i, nelem;
9820
9821 (void) nvpair_value_uint64_array(nvp, &val, &nelem);
9822 for (i = 0; i < nelem; i++)
d1d7e268
MK
9823 printf(gettext("0x%llx "),
9824 (u_longlong_t)val[i]);
26685276
BB
9825
9826 break;
9827 }
9828
d21705ea 9829 case DATA_TYPE_STRING_ARRAY: {
d1807f16 9830 const char **str;
d21705ea
BB
9831 uint_t i, nelem;
9832
9833 (void) nvpair_value_string_array(nvp, &str, &nelem);
9834 for (i = 0; i < nelem; i++)
9835 printf(gettext("\"%s\" "),
9836 str[i] ? str[i] : "<NULL>");
9837
9838 break;
9839 }
9840
26685276
BB
9841 case DATA_TYPE_BOOLEAN_ARRAY:
9842 case DATA_TYPE_BYTE_ARRAY:
9843 case DATA_TYPE_DOUBLE:
6b64382b 9844 case DATA_TYPE_DONTCARE:
26685276
BB
9845 case DATA_TYPE_UNKNOWN:
9846 printf(gettext("<unknown>"));
9847 break;
9848 }
9849
9850 printf(gettext("\n"));
9851 }
9852}
9853
9854static int
9855zpool_do_events_next(ev_opts_t *opts)
9856{
9857 nvlist_t *nvl;
9b101a73 9858 int zevent_fd, ret, dropped;
d1807f16 9859 const char *pool;
26685276 9860
9b101a73
BB
9861 zevent_fd = open(ZFS_DEV, O_RDWR);
9862 VERIFY(zevent_fd >= 0);
26685276 9863
c5343ba7
BB
9864 if (!opts->scripted)
9865 (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS");
26685276
BB
9866
9867 while (1) {
9868 ret = zpool_events_next(g_zfs, &nvl, &dropped,
8c7aa0cf 9869 (opts->follow ? ZEVENT_NONE : ZEVENT_NONBLOCK), zevent_fd);
26685276
BB
9870 if (ret || nvl == NULL)
9871 break;
9872
9873 if (dropped > 0)
9874 (void) printf(gettext("dropped %d events\n"), dropped);
9875
88f9c939 9876 if (strlen(opts->poolname) > 0 &&
9877 nvlist_lookup_string(nvl, FM_FMRI_ZFS_POOL, &pool) == 0 &&
9878 strcmp(opts->poolname, pool) != 0)
9879 continue;
9880
1e1c3980 9881 zpool_do_events_short(nvl, opts);
26685276
BB
9882
9883 if (opts->verbose) {
9884 zpool_do_events_nvprint(nvl, 8);
9885 printf(gettext("\n"));
9886 }
50fe577d 9887 (void) fflush(stdout);
26685276
BB
9888
9889 nvlist_free(nvl);
9890 }
9891
9b101a73 9892 VERIFY(0 == close(zevent_fd));
26685276
BB
9893
9894 return (ret);
9895}
9896
9897static int
e40ca391 9898zpool_do_events_clear(void)
26685276
BB
9899{
9900 int count, ret;
9901
9902 ret = zpool_events_clear(g_zfs, &count);
9903 if (!ret)
9904 (void) printf(gettext("cleared %d events\n"), count);
9905
9906 return (ret);
9907}
9908
9909/*
88f9c939 9910 * zpool events [-vHf [pool] | -c]
26685276
BB
9911 *
9912 * Displays events logs by ZFS.
9913 */
9914int
9915zpool_do_events(int argc, char **argv)
9916{
9917 ev_opts_t opts = { 0 };
9918 int ret;
9919 int c;
9920
9921 /* check options */
c5343ba7 9922 while ((c = getopt(argc, argv, "vHfc")) != -1) {
26685276
BB
9923 switch (c) {
9924 case 'v':
9925 opts.verbose = 1;
c5343ba7
BB
9926 break;
9927 case 'H':
9928 opts.scripted = 1;
26685276
BB
9929 break;
9930 case 'f':
9931 opts.follow = 1;
9932 break;
9933 case 'c':
9934 opts.clear = 1;
9935 break;
9936 case '?':
9937 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
9938 optopt);
9939 usage(B_FALSE);
9940 }
9941 }
9942 argc -= optind;
9943 argv += optind;
9944
88f9c939 9945 if (argc > 1) {
9946 (void) fprintf(stderr, gettext("too many arguments\n"));
9947 usage(B_FALSE);
9948 } else if (argc == 1) {
9949 (void) strlcpy(opts.poolname, argv[0], sizeof (opts.poolname));
9950 if (!zfs_name_valid(opts.poolname, ZFS_TYPE_POOL)) {
9951 (void) fprintf(stderr,
9952 gettext("invalid pool name '%s'\n"), opts.poolname);
9953 usage(B_FALSE);
9954 }
9955 }
9956
9957 if ((argc == 1 || opts.verbose || opts.scripted || opts.follow) &&
9958 opts.clear) {
9959 (void) fprintf(stderr,
9960 gettext("invalid options combined with -c\n"));
9961 usage(B_FALSE);
9962 }
9963
26685276 9964 if (opts.clear)
e40ca391 9965 ret = zpool_do_events_clear();
26685276
BB
9966 else
9967 ret = zpool_do_events_next(&opts);
9968
d1d7e268 9969 return (ret);
26685276
BB
9970}
9971
34dc7c2f 9972static int
2a673e76 9973get_callback_vdev(zpool_handle_t *zhp, char *vdevname, void *data)
34dc7c2f
BB
9974{
9975 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
2a673e76 9976 char value[ZFS_MAXPROPLEN];
34dc7c2f 9977 zprop_source_t srctype;
34dc7c2f 9978
2a673e76
AJ
9979 for (zprop_list_t *pl = cbp->cb_proplist; pl != NULL;
9980 pl = pl->pl_next) {
9981 char *prop_name;
34dc7c2f 9982 /*
2a673e76
AJ
9983 * If the first property is pool name, it is a special
9984 * placeholder that we can skip. This will also skip
34dc7c2f
BB
9985 * over the name property when 'all' is specified.
9986 */
9987 if (pl->pl_prop == ZPOOL_PROP_NAME &&
9988 pl == cbp->cb_proplist)
9989 continue;
9990
2a673e76
AJ
9991 if (pl->pl_prop == ZPROP_INVAL) {
9992 prop_name = pl->pl_user_prop;
9993 } else {
9994 prop_name = (char *)vdev_prop_to_name(pl->pl_prop);
9995 }
9996 if (zpool_get_vdev_prop(zhp, vdevname, pl->pl_prop,
9997 prop_name, value, sizeof (value), &srctype,
9998 cbp->cb_literal) == 0) {
9999 zprop_print_one_property(vdevname, cbp, prop_name,
10000 value, srctype, NULL, NULL);
10001 }
10002 }
34dc7c2f 10003
2a673e76
AJ
10004 return (0);
10005}
10006
10007static int
3e4ed421 10008get_callback_vdev_cb(void *zhp_data, nvlist_t *nv, void *data)
2a673e76
AJ
10009{
10010 zpool_handle_t *zhp = zhp_data;
10011 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3e4ed421
RW
10012 char *vdevname;
10013 const char *type;
2a673e76
AJ
10014 int ret;
10015
3e4ed421
RW
10016 /*
10017 * zpool_vdev_name() transforms the root vdev name (i.e., root-0) to the
10018 * pool name for display purposes, which is not desired. Fallback to
10019 * zpool_vdev_name() when not dealing with the root vdev.
10020 */
10021 type = fnvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE);
10022 if (zhp != NULL && strcmp(type, "root") == 0)
10023 vdevname = strdup("root-0");
10024 else
10025 vdevname = zpool_vdev_name(g_zfs, zhp, nv,
10026 cbp->cb_vdevs.cb_name_flags);
2a673e76 10027
3e4ed421 10028 (void) vdev_expand_proplist(zhp, vdevname, &cbp->cb_proplist);
2a673e76 10029
2a673e76
AJ
10030 ret = get_callback_vdev(zhp, vdevname, data);
10031
3e4ed421
RW
10032 free(vdevname);
10033
2a673e76
AJ
10034 return (ret);
10035}
10036
10037static int
10038get_callback(zpool_handle_t *zhp, void *data)
10039{
10040 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
8eae2d21 10041 char value[ZFS_MAXPROPLEN];
2a673e76
AJ
10042 zprop_source_t srctype;
10043 zprop_list_t *pl;
10044 int vid;
10045
10046 if (cbp->cb_type == ZFS_TYPE_VDEV) {
10047 if (strcmp(cbp->cb_vdevs.cb_names[0], "all-vdevs") == 0) {
2a673e76 10048 for_each_vdev(zhp, get_callback_vdev_cb, data);
9ae529ec 10049 } else {
2a673e76
AJ
10050 /* Adjust column widths for vdev properties */
10051 for (vid = 0; vid < cbp->cb_vdevs.cb_names_count;
10052 vid++) {
10053 vdev_expand_proplist(zhp,
10054 cbp->cb_vdevs.cb_names[vid],
10055 &cbp->cb_proplist);
10056 }
10057 /* Display the properties */
10058 for (vid = 0; vid < cbp->cb_vdevs.cb_names_count;
10059 vid++) {
10060 get_callback_vdev(zhp,
10061 cbp->cb_vdevs.cb_names[vid], data);
10062 }
10063 }
10064 } else {
10065 assert(cbp->cb_type == ZFS_TYPE_POOL);
10066 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
10067 /*
10068 * Skip the special fake placeholder. This will also
10069 * skip over the name property when 'all' is specified.
10070 */
10071 if (pl->pl_prop == ZPOOL_PROP_NAME &&
10072 pl == cbp->cb_proplist)
9ae529ec
CS
10073 continue;
10074
2a673e76 10075 if (pl->pl_prop == ZPROP_INVAL &&
8eae2d21
AJ
10076 zfs_prop_user(pl->pl_user_prop)) {
10077 srctype = ZPROP_SRC_LOCAL;
10078
10079 if (zpool_get_userprop(zhp, pl->pl_user_prop,
10080 value, sizeof (value), &srctype) != 0)
10081 continue;
10082
10083 zprop_print_one_property(zpool_get_name(zhp),
10084 cbp, pl->pl_user_prop, value, srctype,
10085 NULL, NULL);
10086 } else if (pl->pl_prop == ZPROP_INVAL &&
2a673e76
AJ
10087 (zpool_prop_feature(pl->pl_user_prop) ||
10088 zpool_prop_unsupported(pl->pl_user_prop))) {
10089 srctype = ZPROP_SRC_LOCAL;
10090
10091 if (zpool_prop_get_feature(zhp,
10092 pl->pl_user_prop, value,
10093 sizeof (value)) == 0) {
10094 zprop_print_one_property(
10095 zpool_get_name(zhp), cbp,
10096 pl->pl_user_prop, value, srctype,
10097 NULL, NULL);
10098 }
10099 } else {
10100 if (zpool_get_prop(zhp, pl->pl_prop, value,
10101 sizeof (value), &srctype,
10102 cbp->cb_literal) != 0)
10103 continue;
10104
10105 zprop_print_one_property(zpool_get_name(zhp),
10106 cbp, zpool_prop_to_name(pl->pl_prop),
10107 value, srctype, NULL, NULL);
10108 }
9ae529ec 10109 }
34dc7c2f 10110 }
2a673e76 10111
34dc7c2f
BB
10112 return (0);
10113}
10114
2a8b84b7
AS
10115/*
10116 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
10117 *
10118 * -H Scripted mode. Don't display headers, and separate properties
10119 * by a single tab.
10120 * -o List of columns to display. Defaults to
10121 * "name,property,value,source".
4e33ba4c 10122 * -p Display values in parsable (exact) format.
2a8b84b7
AS
10123 *
10124 * Get properties of pools in the system. Output space statistics
10125 * for each one as well as other attributes.
10126 */
34dc7c2f
BB
10127int
10128zpool_do_get(int argc, char **argv)
10129{
10130 zprop_get_cbdata_t cb = { 0 };
10131 zprop_list_t fake_name = { 0 };
2a8b84b7
AS
10132 int ret;
10133 int c, i;
2a673e76 10134 char *propstr = NULL;
3e4ed421 10135 char *vdev = NULL;
2a8b84b7
AS
10136
10137 cb.cb_first = B_TRUE;
10138
10139 /*
10140 * Set up default columns and sources.
10141 */
10142 cb.cb_sources = ZPROP_SRC_ALL;
10143 cb.cb_columns[0] = GET_COL_NAME;
10144 cb.cb_columns[1] = GET_COL_PROPERTY;
10145 cb.cb_columns[2] = GET_COL_VALUE;
10146 cb.cb_columns[3] = GET_COL_SOURCE;
10147 cb.cb_type = ZFS_TYPE_POOL;
2a673e76
AJ
10148 cb.cb_vdevs.cb_name_flags |= VDEV_NAME_TYPE_ID;
10149 current_prop_type = cb.cb_type;
34dc7c2f 10150
d65e7381 10151 /* check options */
2a8b84b7 10152 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
d65e7381
RE
10153 switch (c) {
10154 case 'p':
10155 cb.cb_literal = B_TRUE;
10156 break;
79eb71dc
TF
10157 case 'H':
10158 cb.cb_scripted = B_TRUE;
10159 break;
2a8b84b7 10160 case 'o':
861166b0 10161 memset(&cb.cb_columns, 0, sizeof (cb.cb_columns));
2a8b84b7 10162 i = 0;
66cd170d
AZ
10163
10164 for (char *tok; (tok = strsep(&optarg, ",")); ) {
10165 static const char *const col_opts[] =
2a8b84b7 10166 { "name", "property", "value", "source",
66cd170d
AZ
10167 "all" };
10168 static const zfs_get_column_t col_cols[] =
10169 { GET_COL_NAME, GET_COL_PROPERTY, GET_COL_VALUE,
10170 GET_COL_SOURCE };
2a8b84b7 10171
c7978784 10172 if (i == ZFS_GET_NCOLS - 1) {
2a8b84b7
AS
10173 (void) fprintf(stderr, gettext("too "
10174 "many fields given to -o "
10175 "option\n"));
10176 usage(B_FALSE);
10177 }
79eb71dc 10178
66cd170d
AZ
10179 for (c = 0; c < ARRAY_SIZE(col_opts); ++c)
10180 if (strcmp(tok, col_opts[c]) == 0)
10181 goto found;
10182
10183 (void) fprintf(stderr,
10184 gettext("invalid column name '%s'\n"), tok);
10185 usage(B_FALSE);
10186
10187found:
10188 if (c >= 4) {
2a8b84b7
AS
10189 if (i > 0) {
10190 (void) fprintf(stderr,
10191 gettext("\"all\" conflicts "
10192 "with specific fields "
10193 "given to -o option\n"));
10194 usage(B_FALSE);
10195 }
66cd170d
AZ
10196
10197 memcpy(cb.cb_columns, col_cols,
10198 sizeof (col_cols));
c7978784 10199 i = ZFS_GET_NCOLS - 1;
66cd170d
AZ
10200 } else
10201 cb.cb_columns[i++] = col_cols[c];
2a8b84b7
AS
10202 }
10203 break;
d65e7381
RE
10204 case '?':
10205 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
10206 optopt);
10207 usage(B_FALSE);
10208 }
10209 }
10210
10211 argc -= optind;
10212 argv += optind;
10213
10214 if (argc < 1) {
9ae529ec
CS
10215 (void) fprintf(stderr, gettext("missing property "
10216 "argument\n"));
34dc7c2f 10217 usage(B_FALSE);
9ae529ec 10218 }
34dc7c2f 10219
2a673e76
AJ
10220 /* Properties list is needed later by zprop_get_list() */
10221 propstr = argv[0];
34dc7c2f 10222
d65e7381
RE
10223 argc--;
10224 argv++;
10225
2a673e76
AJ
10226 if (argc == 0) {
10227 /* No args, so just print the defaults. */
10228 } else if (are_all_pools(argc, argv)) {
10229 /* All the args are pool names */
10230 } else if (are_all_pools(1, argv)) {
10231 /* The first arg is a pool name */
10232 if ((argc == 2 && strcmp(argv[1], "all-vdevs") == 0) ||
3e4ed421 10233 (argc == 2 && strcmp(argv[1], "root") == 0) ||
2a673e76
AJ
10234 are_vdevs_in_pool(argc - 1, argv + 1, argv[0],
10235 &cb.cb_vdevs)) {
3e4ed421
RW
10236
10237 if (strcmp(argv[1], "root") == 0)
10238 vdev = strdup("root-0");
10239 else
10240 vdev = strdup(argv[1]);
10241
2a673e76 10242 /* ... and the rest are vdev names */
3e4ed421 10243 cb.cb_vdevs.cb_names = &vdev;
2a673e76
AJ
10244 cb.cb_vdevs.cb_names_count = argc - 1;
10245 cb.cb_type = ZFS_TYPE_VDEV;
10246 argc = 1; /* One pool to process */
10247 } else {
10248 fprintf(stderr, gettext("Expected a list of vdevs in"
10249 " \"%s\", but got:\n"), argv[0]);
10250 error_list_unresolved_vdevs(argc - 1, argv + 1,
10251 argv[0], &cb.cb_vdevs);
10252 fprintf(stderr, "\n");
10253 usage(B_FALSE);
10254 return (1);
10255 }
10256 } else {
10257 /*
10258 * The first arg isn't a pool name,
10259 */
10260 fprintf(stderr, gettext("missing pool name.\n"));
10261 fprintf(stderr, "\n");
10262 usage(B_FALSE);
10263 return (1);
10264 }
10265
10266 if (zprop_get_list(g_zfs, propstr, &cb.cb_proplist,
10267 cb.cb_type) != 0) {
10268 /* Use correct list of valid properties (pool or vdev) */
10269 current_prop_type = cb.cb_type;
10270 usage(B_FALSE);
10271 }
10272
34dc7c2f
BB
10273 if (cb.cb_proplist != NULL) {
10274 fake_name.pl_prop = ZPOOL_PROP_NAME;
10275 fake_name.pl_width = strlen(gettext("NAME"));
10276 fake_name.pl_next = cb.cb_proplist;
10277 cb.cb_proplist = &fake_name;
10278 }
10279
2a673e76
AJ
10280 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, cb.cb_type,
10281 cb.cb_literal, get_callback, &cb);
34dc7c2f
BB
10282
10283 if (cb.cb_proplist == &fake_name)
10284 zprop_free_list(fake_name.pl_next);
10285 else
10286 zprop_free_list(cb.cb_proplist);
10287
3e4ed421
RW
10288 if (vdev != NULL)
10289 free(vdev);
10290
34dc7c2f
BB
10291 return (ret);
10292}
10293
10294typedef struct set_cbdata {
10295 char *cb_propname;
10296 char *cb_value;
2a673e76
AJ
10297 zfs_type_t cb_type;
10298 vdev_cbdata_t cb_vdevs;
34dc7c2f
BB
10299 boolean_t cb_any_successful;
10300} set_cbdata_t;
10301
65c7cc49 10302static int
2a673e76 10303set_pool_callback(zpool_handle_t *zhp, set_cbdata_t *cb)
34dc7c2f
BB
10304{
10305 int error;
34dc7c2f 10306
e086db16
CB
10307 /* Check if we have out-of-bounds features */
10308 if (strcmp(cb->cb_propname, ZPOOL_CONFIG_COMPATIBILITY) == 0) {
10309 boolean_t features[SPA_FEATURES];
10310 if (zpool_do_load_compat(cb->cb_value, features) !=
10311 ZPOOL_COMPATIBILITY_OK)
10312 return (-1);
10313
10314 nvlist_t *enabled = zpool_get_features(zhp);
10315 spa_feature_t i;
10316 for (i = 0; i < SPA_FEATURES; i++) {
10317 const char *fguid = spa_feature_table[i].fi_guid;
10318 if (nvlist_exists(enabled, fguid) && !features[i])
10319 break;
10320 }
10321 if (i < SPA_FEATURES)
10322 (void) fprintf(stderr, gettext("Warning: one or "
10323 "more features already enabled on pool '%s'\n"
10324 "are not present in this compatibility set.\n"),
10325 zpool_get_name(zhp));
10326 }
10327
10328 /* if we're setting a feature, check it's in compatibility set */
10329 if (zpool_prop_feature(cb->cb_propname) &&
10330 strcmp(cb->cb_value, ZFS_FEATURE_ENABLED) == 0) {
10331 char *fname = strchr(cb->cb_propname, '@') + 1;
10332 spa_feature_t f;
10333
10334 if (zfeature_lookup_name(fname, &f) == 0) {
10335 char compat[ZFS_MAXPROPLEN];
10336 if (zpool_get_prop(zhp, ZPOOL_PROP_COMPATIBILITY,
10337 compat, ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
10338 compat[0] = '\0';
10339
10340 boolean_t features[SPA_FEATURES];
10341 if (zpool_do_load_compat(compat, features) !=
10342 ZPOOL_COMPATIBILITY_OK) {
10343 (void) fprintf(stderr, gettext("Error: "
10344 "cannot enable feature '%s' on pool '%s'\n"
10345 "because the pool's 'compatibility' "
10346 "property cannot be parsed.\n"),
10347 fname, zpool_get_name(zhp));
10348 return (-1);
10349 }
10350
10351 if (!features[f]) {
10352 (void) fprintf(stderr, gettext("Error: "
10353 "cannot enable feature '%s' on pool '%s'\n"
10354 "as it is not specified in this pool's "
10355 "current compatibility set.\n"
10356 "Consider setting 'compatibility' to a "
10357 "less restrictive set, or to 'off'.\n"),
10358 fname, zpool_get_name(zhp));
10359 return (-1);
10360 }
10361 }
10362 }
10363
34dc7c2f
BB
10364 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
10365
2a673e76
AJ
10366 return (error);
10367}
10368
10369static int
10370set_callback(zpool_handle_t *zhp, void *data)
10371{
10372 int error;
10373 set_cbdata_t *cb = (set_cbdata_t *)data;
10374
10375 if (cb->cb_type == ZFS_TYPE_VDEV) {
10376 error = zpool_set_vdev_prop(zhp, *cb->cb_vdevs.cb_names,
10377 cb->cb_propname, cb->cb_value);
10378 } else {
10379 assert(cb->cb_type == ZFS_TYPE_POOL);
10380 error = set_pool_callback(zhp, cb);
10381 }
34dc7c2f 10382
2a673e76 10383 cb->cb_any_successful = !error;
34dc7c2f
BB
10384 return (error);
10385}
10386
10387int
10388zpool_do_set(int argc, char **argv)
10389{
10390 set_cbdata_t cb = { 0 };
10391 int error;
3e4ed421 10392 char *vdev = NULL;
34dc7c2f 10393
2a673e76 10394 current_prop_type = ZFS_TYPE_POOL;
34dc7c2f
BB
10395 if (argc > 1 && argv[1][0] == '-') {
10396 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
10397 argv[1][1]);
10398 usage(B_FALSE);
10399 }
10400
10401 if (argc < 2) {
10402 (void) fprintf(stderr, gettext("missing property=value "
10403 "argument\n"));
10404 usage(B_FALSE);
10405 }
10406
10407 if (argc < 3) {
10408 (void) fprintf(stderr, gettext("missing pool name\n"));
10409 usage(B_FALSE);
10410 }
10411
2a673e76 10412 if (argc > 4) {
34dc7c2f
BB
10413 (void) fprintf(stderr, gettext("too many pool names\n"));
10414 usage(B_FALSE);
10415 }
10416
10417 cb.cb_propname = argv[1];
2a673e76
AJ
10418 cb.cb_type = ZFS_TYPE_POOL;
10419 cb.cb_vdevs.cb_name_flags |= VDEV_NAME_TYPE_ID;
34dc7c2f
BB
10420 cb.cb_value = strchr(cb.cb_propname, '=');
10421 if (cb.cb_value == NULL) {
10422 (void) fprintf(stderr, gettext("missing value in "
10423 "property=value argument\n"));
10424 usage(B_FALSE);
10425 }
10426
10427 *(cb.cb_value) = '\0';
10428 cb.cb_value++;
2a673e76
AJ
10429 argc -= 2;
10430 argv += 2;
10431
7a85f58d
RW
10432 /* argv[0] is pool name */
10433 if (!is_pool(argv[0])) {
10434 (void) fprintf(stderr,
10435 gettext("cannot open '%s': is not a pool\n"), argv[0]);
10436 return (EINVAL);
10437 }
10438
10439 /* argv[1], when supplied, is vdev name */
10440 if (argc == 2) {
3e4ed421
RW
10441
10442 if (strcmp(argv[1], "root") == 0)
10443 vdev = strdup("root-0");
10444 else
10445 vdev = strdup(argv[1]);
10446
10447 if (!are_vdevs_in_pool(1, &vdev, argv[0], &cb.cb_vdevs)) {
7a85f58d
RW
10448 (void) fprintf(stderr, gettext(
10449 "cannot find '%s' in '%s': device not in pool\n"),
3e4ed421
RW
10450 vdev, argv[0]);
10451 free(vdev);
7a85f58d
RW
10452 return (EINVAL);
10453 }
3e4ed421 10454 cb.cb_vdevs.cb_names = &vdev;
2a673e76
AJ
10455 cb.cb_vdevs.cb_names_count = 1;
10456 cb.cb_type = ZFS_TYPE_VDEV;
2a673e76 10457 }
34dc7c2f 10458
7a85f58d 10459 error = for_each_pool(1, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
2a673e76 10460 B_FALSE, set_callback, &cb);
34dc7c2f 10461
3e4ed421
RW
10462 if (vdev != NULL)
10463 free(vdev);
10464
34dc7c2f
BB
10465 return (error);
10466}
2288d419
BB
10467
10468/* Add up the total number of bytes left to initialize/trim across all vdevs */
e60e158e 10469static uint64_t
2288d419 10470vdev_activity_remaining(nvlist_t *nv, zpool_wait_activity_t activity)
e60e158e
JG
10471{
10472 uint64_t bytes_remaining;
10473 nvlist_t **child;
10474 uint_t c, children;
10475 vdev_stat_t *vs;
10476
2288d419
BB
10477 assert(activity == ZPOOL_WAIT_INITIALIZE ||
10478 activity == ZPOOL_WAIT_TRIM);
10479
e60e158e
JG
10480 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
10481 (uint64_t **)&vs, &c) == 0);
10482
2288d419
BB
10483 if (activity == ZPOOL_WAIT_INITIALIZE &&
10484 vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE)
e60e158e
JG
10485 bytes_remaining = vs->vs_initialize_bytes_est -
10486 vs->vs_initialize_bytes_done;
2288d419
BB
10487 else if (activity == ZPOOL_WAIT_TRIM &&
10488 vs->vs_trim_state == VDEV_TRIM_ACTIVE)
10489 bytes_remaining = vs->vs_trim_bytes_est -
10490 vs->vs_trim_bytes_done;
e60e158e
JG
10491 else
10492 bytes_remaining = 0;
10493
10494 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
10495 &child, &children) != 0)
10496 children = 0;
10497
10498 for (c = 0; c < children; c++)
2288d419 10499 bytes_remaining += vdev_activity_remaining(child[c], activity);
e60e158e
JG
10500
10501 return (bytes_remaining);
10502}
10503
9a49d3f3
BB
10504/* Add up the total number of bytes left to rebuild across top-level vdevs */
10505static uint64_t
10506vdev_activity_top_remaining(nvlist_t *nv)
10507{
10508 uint64_t bytes_remaining = 0;
10509 nvlist_t **child;
10510 uint_t children;
10511 int error;
10512
10513 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
10514 &child, &children) != 0)
10515 children = 0;
10516
10517 for (uint_t c = 0; c < children; c++) {
10518 vdev_rebuild_stat_t *vrs;
10519 uint_t i;
10520
10521 error = nvlist_lookup_uint64_array(child[c],
10522 ZPOOL_CONFIG_REBUILD_STATS, (uint64_t **)&vrs, &i);
10523 if (error == 0) {
10524 if (vrs->vrs_state == VDEV_REBUILD_ACTIVE) {
10525 bytes_remaining += (vrs->vrs_bytes_est -
10526 vrs->vrs_bytes_rebuilt);
10527 }
10528 }
10529 }
10530
10531 return (bytes_remaining);
10532}
10533
e60e158e
JG
10534/* Whether any vdevs are 'spare' or 'replacing' vdevs */
10535static boolean_t
10536vdev_any_spare_replacing(nvlist_t *nv)
10537{
10538 nvlist_t **child;
10539 uint_t c, children;
d1807f16 10540 const char *vdev_type;
e60e158e
JG
10541
10542 (void) nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &vdev_type);
10543
10544 if (strcmp(vdev_type, VDEV_TYPE_REPLACING) == 0 ||
b2255edc
BB
10545 strcmp(vdev_type, VDEV_TYPE_SPARE) == 0 ||
10546 strcmp(vdev_type, VDEV_TYPE_DRAID_SPARE) == 0) {
e60e158e
JG
10547 return (B_TRUE);
10548 }
10549
10550 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
10551 &child, &children) != 0)
10552 children = 0;
10553
10554 for (c = 0; c < children; c++) {
10555 if (vdev_any_spare_replacing(child[c]))
10556 return (B_TRUE);
10557 }
10558
10559 return (B_FALSE);
10560}
10561
10562typedef struct wait_data {
10563 char *wd_poolname;
10564 boolean_t wd_scripted;
10565 boolean_t wd_exact;
10566 boolean_t wd_headers_once;
d553fb9b 10567 boolean_t wd_should_exit;
e60e158e
JG
10568 /* Which activities to wait for */
10569 boolean_t wd_enabled[ZPOOL_WAIT_NUM_ACTIVITIES];
10570 float wd_interval;
d553fb9b
JL
10571 pthread_cond_t wd_cv;
10572 pthread_mutex_t wd_mutex;
e60e158e
JG
10573} wait_data_t;
10574
10575/*
10576 * Print to stdout a single line, containing one column for each activity that
10577 * we are waiting for specifying how many bytes of work are left for that
10578 * activity.
10579 */
10580static void
10581print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
10582{
10583 nvlist_t *config, *nvroot;
10584 uint_t c;
10585 int i;
10586 pool_checkpoint_stat_t *pcs = NULL;
10587 pool_scan_stat_t *pss = NULL;
10588 pool_removal_stat_t *prs = NULL;
a926aab9
AZ
10589 const char *const headers[] = {"DISCARD", "FREE", "INITIALIZE",
10590 "REPLACE", "REMOVE", "RESILVER", "SCRUB", "TRIM"};
e60e158e
JG
10591 int col_widths[ZPOOL_WAIT_NUM_ACTIVITIES];
10592
10593 /* Calculate the width of each column */
10594 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10595 /*
10596 * Make sure we have enough space in the col for pretty-printed
10597 * numbers and for the column header, and then leave a couple
10598 * spaces between cols for readability.
10599 */
10600 col_widths[i] = MAX(strlen(headers[i]), 6) + 2;
10601 }
10602
10603 /* Print header if appropriate */
10604 int term_height = terminal_height();
10605 boolean_t reprint_header = (!wd->wd_headers_once && term_height > 0 &&
10606 row % (term_height-1) == 0);
10607 if (!wd->wd_scripted && (row == 0 || reprint_header)) {
10608 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10609 if (wd->wd_enabled[i])
10610 (void) printf("%*s", col_widths[i], headers[i]);
10611 }
a926aab9 10612 (void) fputc('\n', stdout);
e60e158e
JG
10613 }
10614
10615 /* Bytes of work remaining in each activity */
10616 int64_t bytes_rem[ZPOOL_WAIT_NUM_ACTIVITIES] = {0};
10617
10618 bytes_rem[ZPOOL_WAIT_FREE] =
10619 zpool_get_prop_int(zhp, ZPOOL_PROP_FREEING, NULL);
10620
10621 config = zpool_get_config(zhp, NULL);
10622 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
10623
10624 (void) nvlist_lookup_uint64_array(nvroot,
10625 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
10626 if (pcs != NULL && pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
10627 bytes_rem[ZPOOL_WAIT_CKPT_DISCARD] = pcs->pcs_space;
10628
10629 (void) nvlist_lookup_uint64_array(nvroot,
10630 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
10631 if (prs != NULL && prs->prs_state == DSS_SCANNING)
10632 bytes_rem[ZPOOL_WAIT_REMOVE] = prs->prs_to_copy -
10633 prs->prs_copied;
10634
10635 (void) nvlist_lookup_uint64_array(nvroot,
10636 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&pss, &c);
10637 if (pss != NULL && pss->pss_state == DSS_SCANNING &&
10638 pss->pss_pass_scrub_pause == 0) {
10639 int64_t rem = pss->pss_to_examine - pss->pss_issued;
10640 if (pss->pss_func == POOL_SCAN_SCRUB)
10641 bytes_rem[ZPOOL_WAIT_SCRUB] = rem;
10642 else
10643 bytes_rem[ZPOOL_WAIT_RESILVER] = rem;
9a49d3f3
BB
10644 } else if (check_rebuilding(nvroot, NULL)) {
10645 bytes_rem[ZPOOL_WAIT_RESILVER] =
10646 vdev_activity_top_remaining(nvroot);
e60e158e
JG
10647 }
10648
2288d419
BB
10649 bytes_rem[ZPOOL_WAIT_INITIALIZE] =
10650 vdev_activity_remaining(nvroot, ZPOOL_WAIT_INITIALIZE);
10651 bytes_rem[ZPOOL_WAIT_TRIM] =
10652 vdev_activity_remaining(nvroot, ZPOOL_WAIT_TRIM);
e60e158e
JG
10653
10654 /*
10655 * A replace finishes after resilvering finishes, so the amount of work
10656 * left for a replace is the same as for resilvering.
10657 *
10658 * It isn't quite correct to say that if we have any 'spare' or
10659 * 'replacing' vdevs and a resilver is happening, then a replace is in
10660 * progress, like we do here. When a hot spare is used, the faulted vdev
10661 * is not removed after the hot spare is resilvered, so parent 'spare'
10662 * vdev is not removed either. So we could have a 'spare' vdev, but be
10663 * resilvering for a different reason. However, we use it as a heuristic
10664 * because we don't have access to the DTLs, which could tell us whether
10665 * or not we have really finished resilvering a hot spare.
10666 */
10667 if (vdev_any_spare_replacing(nvroot))
10668 bytes_rem[ZPOOL_WAIT_REPLACE] = bytes_rem[ZPOOL_WAIT_RESILVER];
10669
10670 if (timestamp_fmt != NODATE)
10671 print_timestamp(timestamp_fmt);
10672
10673 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10674 char buf[64];
10675 if (!wd->wd_enabled[i])
10676 continue;
10677
10678 if (wd->wd_exact)
10679 (void) snprintf(buf, sizeof (buf), "%" PRIi64,
10680 bytes_rem[i]);
10681 else
10682 zfs_nicenum(bytes_rem[i], buf, sizeof (buf));
10683
10684 if (wd->wd_scripted)
10685 (void) printf(i == 0 ? "%s" : "\t%s", buf);
10686 else
10687 (void) printf(" %*s", col_widths[i] - 1, buf);
10688 }
10689 (void) printf("\n");
10690 (void) fflush(stdout);
10691}
10692
65c7cc49 10693static void *
e60e158e
JG
10694wait_status_thread(void *arg)
10695{
10696 wait_data_t *wd = (wait_data_t *)arg;
10697 zpool_handle_t *zhp;
10698
10699 if ((zhp = zpool_open(g_zfs, wd->wd_poolname)) == NULL)
10700 return (void *)(1);
10701
10702 for (int row = 0; ; row++) {
10703 boolean_t missing;
10704 struct timespec timeout;
d553fb9b 10705 int ret = 0;
e60e158e
JG
10706 (void) clock_gettime(CLOCK_REALTIME, &timeout);
10707
10708 if (zpool_refresh_stats(zhp, &missing) != 0 || missing ||
10709 zpool_props_refresh(zhp) != 0) {
10710 zpool_close(zhp);
10711 return (void *)(uintptr_t)(missing ? 0 : 1);
10712 }
10713
10714 print_wait_status_row(wd, zhp, row);
10715
10716 timeout.tv_sec += floor(wd->wd_interval);
10717 long nanos = timeout.tv_nsec +
10718 (wd->wd_interval - floor(wd->wd_interval)) * NANOSEC;
10719 if (nanos >= NANOSEC) {
10720 timeout.tv_sec++;
10721 timeout.tv_nsec = nanos - NANOSEC;
10722 } else {
10723 timeout.tv_nsec = nanos;
10724 }
d553fb9b
JL
10725 pthread_mutex_lock(&wd->wd_mutex);
10726 if (!wd->wd_should_exit)
10727 ret = pthread_cond_timedwait(&wd->wd_cv, &wd->wd_mutex,
10728 &timeout);
10729 pthread_mutex_unlock(&wd->wd_mutex);
10730 if (ret == 0) {
e60e158e 10731 break; /* signaled by main thread */
d553fb9b
JL
10732 } else if (ret != ETIMEDOUT) {
10733 (void) fprintf(stderr, gettext("pthread_cond_timedwait "
10734 "failed: %s\n"), strerror(ret));
e60e158e
JG
10735 zpool_close(zhp);
10736 return (void *)(uintptr_t)(1);
10737 }
10738 }
10739
10740 zpool_close(zhp);
10741 return (void *)(0);
10742}
10743
10744int
10745zpool_do_wait(int argc, char **argv)
10746{
10747 boolean_t verbose = B_FALSE;
675508f6 10748 int c, i;
e60e158e
JG
10749 unsigned long count;
10750 pthread_t status_thr;
10751 int error = 0;
10752 zpool_handle_t *zhp;
10753
10754 wait_data_t wd;
10755 wd.wd_scripted = B_FALSE;
10756 wd.wd_exact = B_FALSE;
10757 wd.wd_headers_once = B_FALSE;
d553fb9b 10758 wd.wd_should_exit = B_FALSE;
e60e158e 10759
d553fb9b
JL
10760 pthread_mutex_init(&wd.wd_mutex, NULL);
10761 pthread_cond_init(&wd.wd_cv, NULL);
e60e158e
JG
10762
10763 /* By default, wait for all types of activity. */
10764 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++)
10765 wd.wd_enabled[i] = B_TRUE;
10766
10767 while ((c = getopt(argc, argv, "HpT:t:")) != -1) {
10768 switch (c) {
10769 case 'H':
10770 wd.wd_scripted = B_TRUE;
10771 break;
10772 case 'n':
10773 wd.wd_headers_once = B_TRUE;
10774 break;
10775 case 'p':
10776 wd.wd_exact = B_TRUE;
10777 break;
10778 case 'T':
10779 get_timestamp_arg(*optarg);
10780 break;
10781 case 't':
e60e158e 10782 /* Reset activities array */
861166b0 10783 memset(&wd.wd_enabled, 0, sizeof (wd.wd_enabled));
e60e158e 10784
675508f6
AZ
10785 for (char *tok; (tok = strsep(&optarg, ",")); ) {
10786 static const char *const col_opts[] = {
10787 "discard", "free", "initialize", "replace",
10788 "remove", "resilver", "scrub", "trim" };
10789
10790 for (i = 0; i < ARRAY_SIZE(col_opts); ++i)
10791 if (strcmp(tok, col_opts[i]) == 0) {
10792 wd.wd_enabled[i] = B_TRUE;
10793 goto found;
10794 }
e60e158e 10795
675508f6
AZ
10796 (void) fprintf(stderr,
10797 gettext("invalid activity '%s'\n"), tok);
10798 usage(B_FALSE);
10799found:;
e60e158e
JG
10800 }
10801 break;
e60e158e
JG
10802 case '?':
10803 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
10804 optopt);
10805 usage(B_FALSE);
10806 }
10807 }
10808
10809 argc -= optind;
10810 argv += optind;
10811
10812 get_interval_count(&argc, argv, &wd.wd_interval, &count);
10813 if (count != 0) {
10814 /* This subcmd only accepts an interval, not a count */
10815 (void) fprintf(stderr, gettext("too many arguments\n"));
10816 usage(B_FALSE);
10817 }
10818
10819 if (wd.wd_interval != 0)
10820 verbose = B_TRUE;
10821
10822 if (argc < 1) {
10823 (void) fprintf(stderr, gettext("missing 'pool' argument\n"));
10824 usage(B_FALSE);
10825 }
10826 if (argc > 1) {
10827 (void) fprintf(stderr, gettext("too many arguments\n"));
10828 usage(B_FALSE);
10829 }
10830
10831 wd.wd_poolname = argv[0];
10832
10833 if ((zhp = zpool_open(g_zfs, wd.wd_poolname)) == NULL)
10834 return (1);
10835
10836 if (verbose) {
10837 /*
10838 * We use a separate thread for printing status updates because
10839 * the main thread will call lzc_wait(), which blocks as long
10840 * as an activity is in progress, which can be a long time.
10841 */
10842 if (pthread_create(&status_thr, NULL, wait_status_thread, &wd)
10843 != 0) {
10844 (void) fprintf(stderr, gettext("failed to create status"
10845 "thread: %s\n"), strerror(errno));
10846 zpool_close(zhp);
10847 return (1);
10848 }
10849 }
10850
10851 /*
10852 * Loop over all activities that we are supposed to wait for until none
10853 * of them are in progress. Note that this means we can end up waiting
10854 * for more activities to complete than just those that were in progress
10855 * when we began waiting; if an activity we are interested in begins
10856 * while we are waiting for another activity, we will wait for both to
10857 * complete before exiting.
10858 */
10859 for (;;) {
10860 boolean_t missing = B_FALSE;
10861 boolean_t any_waited = B_FALSE;
10862
10863 for (i = 0; i < ZPOOL_WAIT_NUM_ACTIVITIES; i++) {
10864 boolean_t waited;
10865
10866 if (!wd.wd_enabled[i])
10867 continue;
10868
10869 error = zpool_wait_status(zhp, i, &missing, &waited);
10870 if (error != 0 || missing)
10871 break;
10872
10873 any_waited = (any_waited || waited);
10874 }
10875
10876 if (error != 0 || missing || !any_waited)
10877 break;
10878 }
10879
10880 zpool_close(zhp);
10881
10882 if (verbose) {
10883 uintptr_t status;
d553fb9b
JL
10884 pthread_mutex_lock(&wd.wd_mutex);
10885 wd.wd_should_exit = B_TRUE;
10886 pthread_cond_signal(&wd.wd_cv);
10887 pthread_mutex_unlock(&wd.wd_mutex);
e60e158e
JG
10888 (void) pthread_join(status_thr, (void *)&status);
10889 if (status != 0)
10890 error = status;
10891 }
10892
d553fb9b
JL
10893 pthread_mutex_destroy(&wd.wd_mutex);
10894 pthread_cond_destroy(&wd.wd_cv);
e60e158e
JG
10895 return (error);
10896}
34dc7c2f
BB
10897
10898static int
a926aab9 10899find_command_idx(const char *command, int *idx)
34dc7c2f 10900{
a926aab9 10901 for (int i = 0; i < NCOMMAND; ++i) {
34dc7c2f
BB
10902 if (command_table[i].name == NULL)
10903 continue;
10904
10905 if (strcmp(command, command_table[i].name) == 0) {
10906 *idx = i;
10907 return (0);
10908 }
10909 }
10910 return (1);
10911}
10912
50478c6d
T
10913/*
10914 * Display version message
10915 */
10916static int
10917zpool_do_version(int argc, char **argv)
10918{
e40ca391 10919 (void) argc, (void) argv;
2b4f2fc9 10920 return (zfs_version_print() != 0);
50478c6d
T
10921}
10922
658fb802
CB
10923/*
10924 * Do zpool_load_compat() and print error message on failure
10925 */
10926static zpool_compat_status_t
10927zpool_do_load_compat(const char *compat, boolean_t *list)
10928{
e086db16
CB
10929 char report[1024];
10930
658fb802
CB
10931 zpool_compat_status_t ret;
10932
e086db16
CB
10933 ret = zpool_load_compat(compat, list, report, 1024);
10934 switch (ret) {
10935
658fb802
CB
10936 case ZPOOL_COMPATIBILITY_OK:
10937 break;
e086db16
CB
10938
10939 case ZPOOL_COMPATIBILITY_NOFILES:
658fb802 10940 case ZPOOL_COMPATIBILITY_BADFILE:
e086db16
CB
10941 case ZPOOL_COMPATIBILITY_BADTOKEN:
10942 (void) fprintf(stderr, "Error: %s\n", report);
658fb802 10943 break;
e086db16
CB
10944
10945 case ZPOOL_COMPATIBILITY_WARNTOKEN:
10946 (void) fprintf(stderr, "Warning: %s\n", report);
10947 ret = ZPOOL_COMPATIBILITY_OK;
658fb802
CB
10948 break;
10949 }
10950 return (ret);
10951}
10952
34dc7c2f
BB
10953int
10954main(int argc, char **argv)
10955{
8e896579 10956 int ret = 0;
d4ed6673 10957 int i = 0;
34dc7c2f 10958 char *cmdname;
edc05fdb 10959 char **newargv;
34dc7c2f
BB
10960
10961 (void) setlocale(LC_ALL, "");
c2c7ca0d 10962 (void) setlocale(LC_NUMERIC, "C");
34dc7c2f 10963 (void) textdomain(TEXT_DOMAIN);
5b4136bd 10964 srand(time(NULL));
34dc7c2f 10965
34dc7c2f
BB
10966 opterr = 0;
10967
10968 /*
10969 * Make sure the user has specified some command.
10970 */
10971 if (argc < 2) {
10972 (void) fprintf(stderr, gettext("missing command\n"));
10973 usage(B_FALSE);
10974 }
10975
10976 cmdname = argv[1];
10977
10978 /*
10979 * Special case '-?'
10980 */
d1d7e268 10981 if ((strcmp(cmdname, "-?") == 0) || strcmp(cmdname, "--help") == 0)
34dc7c2f
BB
10982 usage(B_TRUE);
10983
50478c6d
T
10984 /*
10985 * Special case '-V|--version'
10986 */
10987 if ((strcmp(cmdname, "-V") == 0) || (strcmp(cmdname, "--version") == 0))
10988 return (zpool_do_version(argc, argv));
10989
65037d9b 10990 if ((g_zfs = libzfs_init()) == NULL) {
afc8f0a6 10991 (void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
9b020fd9 10992 return (1);
65037d9b 10993 }
9b020fd9
BB
10994
10995 libzfs_print_on_error(g_zfs, B_TRUE);
10996
6f1ffb06 10997 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
34dc7c2f 10998
edc05fdb
D
10999 /*
11000 * Many commands modify input strings for string parsing reasons.
11001 * We create a copy to protect the original argv.
11002 */
a3dcc0aa 11003 newargv = safe_malloc((argc + 1) * sizeof (newargv[0]));
edc05fdb
D
11004 for (i = 0; i < argc; i++)
11005 newargv[i] = strdup(argv[i]);
11006 newargv[argc] = NULL;
11007
34dc7c2f
BB
11008 /*
11009 * Run the appropriate command.
11010 */
11011 if (find_command_idx(cmdname, &i) == 0) {
11012 current_command = &command_table[i];
edc05fdb 11013 ret = command_table[i].func(argc - 1, newargv + 1);
34dc7c2f
BB
11014 } else if (strchr(cmdname, '=')) {
11015 verify(find_command_idx("set", &i) == 0);
11016 current_command = &command_table[i];
edc05fdb 11017 ret = command_table[i].func(argc, newargv);
34dc7c2f
BB
11018 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
11019 /*
11020 * 'freeze' is a vile debugging abomination, so we treat
11021 * it as such.
11022 */
4807c0ba
TC
11023 zfs_cmd_t zc = {"\0"};
11024
11025 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
11026 ret = zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc);
11027 if (ret != 0) {
11028 (void) fprintf(stderr,
11029 gettext("failed to freeze pool: %d\n"), errno);
11030 ret = 1;
11031 }
11032
11033 log_history = 0;
34dc7c2f
BB
11034 } else {
11035 (void) fprintf(stderr, gettext("unrecognized "
11036 "command '%s'\n"), cmdname);
11037 usage(B_FALSE);
d4ed6673 11038 ret = 1;
34dc7c2f
BB
11039 }
11040
edc05fdb
D
11041 for (i = 0; i < argc; i++)
11042 free(newargv[i]);
11043 free(newargv);
11044
6f1ffb06
MA
11045 if (ret == 0 && log_history)
11046 (void) zpool_log_history(g_zfs, history_str);
11047
34dc7c2f
BB
11048 libzfs_fini(g_zfs);
11049
11050 /*
11051 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
11052 * for the purposes of running ::findleaks.
11053 */
11054 if (getenv("ZFS_ABORT") != NULL) {
11055 (void) printf("dumping core by request\n");
11056 abort();
11057 }
11058
11059 return (ret);
11060}