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