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