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