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