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