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