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