1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
28 * Copyright 2016 Nexenta Systems, Inc.
29 * Copyright (c) 2017 Datto Inc.
30 * Copyright (c) 2017, Intel Corporation.
31 * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
32 * Copyright 2020 Joyent, Inc.
33 * Copyright (c) 2012 by Cyril Plisko. All rights reserved.
34 * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
35 */
36
37 #include <assert.h>
38 #include <ctype.h>
39 #include <dirent.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <getopt.h>
43 #include <libgen.h>
44 #include <libintl.h>
45 #include <libuutil.h>
46 #include <locale.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <strings.h>
51 #include <unistd.h>
52 #include <priv.h>
53 #include <pwd.h>
54 #include <zone.h>
55 #include <zfs_prop.h>
56 #include <sys/fs/zfs.h>
57 #include <sys/stat.h>
58 #include <sys/debug.h>
59 #include <math.h>
60 #include <sys/sysmacros.h>
61 #include <sys/termios.h>
62
63 #include <libzfs.h>
64 #include <libzutil.h>
65
66 #include "zpool_util.h"
67 #include "zfs_comutil.h"
68 #include "zfeature_common.h"
69
70 #include "statcommon.h"
71
72 libzfs_handle_t *g_zfs;
73
74 static int zpool_do_create(int, char **);
75 static int zpool_do_destroy(int, char **);
76
77 static int zpool_do_add(int, char **);
78 static int zpool_do_remove(int, char **);
79 static int zpool_do_labelclear(int, char **);
80
81 static int zpool_do_checkpoint(int, char **);
82
83 static int zpool_do_list(int, char **);
84 static int zpool_do_iostat(int, char **);
85 static int zpool_do_status(int, char **);
86
87 static int zpool_do_online(int, char **);
88 static int zpool_do_offline(int, char **);
89 static int zpool_do_clear(int, char **);
90 static int zpool_do_reopen(int, char **);
91
92 static int zpool_do_reguid(int, char **);
93
94 static int zpool_do_attach(int, char **);
95 static int zpool_do_detach(int, char **);
96 static int zpool_do_replace(int, char **);
97 static int zpool_do_split(int, char **);
98
99 static int zpool_do_initialize(int, char **);
100 static int zpool_do_scrub(int, char **);
101 static int zpool_do_resilver(int, char **);
102 static int zpool_do_trim(int, char **);
103
104 static int zpool_do_import(int, char **);
105 static int zpool_do_export(int, char **);
106
107 static int zpool_do_upgrade(int, char **);
108
109 static int zpool_do_history(int, char **);
110
111 static int zpool_do_get(int, char **);
112 static int zpool_do_set(int, char **);
113
114 static int zpool_do_sync(int, char **);
115
116 /*
117 * These libumem hooks provide a reasonable set of defaults for the allocator's
118 * debugging facilities.
119 */
120
121 #ifdef DEBUG
122 const char *
_umem_debug_init(void)123 _umem_debug_init(void)
124 {
125 return ("default,verbose"); /* $UMEM_DEBUG setting */
126 }
127
128 const char *
_umem_logging_init(void)129 _umem_logging_init(void)
130 {
131 return ("fail,contents"); /* $UMEM_LOGGING setting */
132 }
133 #endif
134
135 typedef enum {
136 HELP_ADD,
137 HELP_ATTACH,
138 HELP_CLEAR,
139 HELP_CREATE,
140 HELP_CHECKPOINT,
141 HELP_DESTROY,
142 HELP_DETACH,
143 HELP_EXPORT,
144 HELP_HISTORY,
145 HELP_IMPORT,
146 HELP_IOSTAT,
147 HELP_LABELCLEAR,
148 HELP_LIST,
149 HELP_OFFLINE,
150 HELP_ONLINE,
151 HELP_REPLACE,
152 HELP_REMOVE,
153 HELP_INITIALIZE,
154 HELP_SCRUB,
155 HELP_RESILVER,
156 HELP_TRIM,
157 HELP_STATUS,
158 HELP_UPGRADE,
159 HELP_GET,
160 HELP_SET,
161 HELP_SPLIT,
162 HELP_SYNC,
163 HELP_REGUID,
164 HELP_REOPEN
165 } zpool_help_t;
166
167
168 /*
169 * Flags for stats to display with "zpool iostats"
170 */
171 enum iostat_type {
172 IOS_DEFAULT = 0,
173 IOS_LATENCY = 1,
174 IOS_QUEUES = 2,
175 IOS_L_HISTO = 3,
176 IOS_RQ_HISTO = 4,
177 IOS_COUNT, /* always last element */
178 };
179
180 /* iostat_type entries as bitmasks */
181 #define IOS_DEFAULT_M (1ULL << IOS_DEFAULT)
182 #define IOS_LATENCY_M (1ULL << IOS_LATENCY)
183 #define IOS_QUEUES_M (1ULL << IOS_QUEUES)
184 #define IOS_L_HISTO_M (1ULL << IOS_L_HISTO)
185 #define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO)
186
187 /* Mask of all the histo bits */
188 #define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M)
189
190 /*
191 * Lookup table for iostat flags to nvlist names. Basically a list
192 * of all the nvlists a flag requires. Also specifies the order in
193 * which data gets printed in zpool iostat.
194 */
195 static const char *vsx_type_to_nvlist[IOS_COUNT][13] = {
196 [IOS_L_HISTO] = {
197 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
198 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
199 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
200 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
201 ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO,
202 ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO,
203 ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO,
204 ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO,
205 ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO,
206 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
207 NULL},
208 [IOS_LATENCY] = {
209 ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO,
210 ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO,
211 ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO,
212 ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO,
213 ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO,
214 NULL},
215 [IOS_QUEUES] = {
216 ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE,
217 ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE,
218 ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE,
219 ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
220 ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
221 ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE,
222 NULL},
223 [IOS_RQ_HISTO] = {
224 ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
225 ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
226 ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO,
227 ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO,
228 ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO,
229 ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO,
230 ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO,
231 ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO,
232 ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO,
233 ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO,
234 ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO,
235 ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO,
236 NULL},
237 };
238
239
240 /*
241 * Given a cb->cb_flags with a histogram bit set, return the iostat_type.
242 * Right now, only one histo bit is ever set at one time, so we can
243 * just do a highbit64(a)
244 */
245 #define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1)
246
247 typedef struct zpool_command {
248 const char *name;
249 int (*func)(int, char **);
250 zpool_help_t usage;
251 } zpool_command_t;
252
253 /*
254 * Master command table. Each ZFS command has a name, associated function, and
255 * usage message. The usage messages need to be internationalized, so we have
256 * to have a function to return the usage message based on a command index.
257 *
258 * These commands are organized according to how they are displayed in the usage
259 * message. An empty command (one with a NULL name) indicates an empty line in
260 * the generic usage message.
261 */
262 static zpool_command_t command_table[] = {
263 { "create", zpool_do_create, HELP_CREATE },
264 { "destroy", zpool_do_destroy, HELP_DESTROY },
265 { NULL },
266 { "add", zpool_do_add, HELP_ADD },
267 { "remove", zpool_do_remove, HELP_REMOVE },
268 { NULL },
269 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
270 { NULL },
271 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT },
272 { NULL },
273 { "list", zpool_do_list, HELP_LIST },
274 { "iostat", zpool_do_iostat, HELP_IOSTAT },
275 { "status", zpool_do_status, HELP_STATUS },
276 { NULL },
277 { "online", zpool_do_online, HELP_ONLINE },
278 { "offline", zpool_do_offline, HELP_OFFLINE },
279 { "clear", zpool_do_clear, HELP_CLEAR },
280 { "reopen", zpool_do_reopen, HELP_REOPEN },
281 { NULL },
282 { "attach", zpool_do_attach, HELP_ATTACH },
283 { "detach", zpool_do_detach, HELP_DETACH },
284 { "replace", zpool_do_replace, HELP_REPLACE },
285 { "split", zpool_do_split, HELP_SPLIT },
286 { NULL },
287 { "initialize", zpool_do_initialize, HELP_INITIALIZE },
288 { "resilver", zpool_do_resilver, HELP_RESILVER },
289 { "scrub", zpool_do_scrub, HELP_SCRUB },
290 { "trim", zpool_do_trim, HELP_TRIM },
291 { NULL },
292 { "import", zpool_do_import, HELP_IMPORT },
293 { "export", zpool_do_export, HELP_EXPORT },
294 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
295 { "reguid", zpool_do_reguid, HELP_REGUID },
296 { NULL },
297 { "history", zpool_do_history, HELP_HISTORY },
298 { "get", zpool_do_get, HELP_GET },
299 { "set", zpool_do_set, HELP_SET },
300 { "sync", zpool_do_sync, HELP_SYNC },
301 };
302
303 #define NCOMMAND (ARRAY_SIZE(command_table))
304
305 #define VDEV_ALLOC_CLASS_LOGS "logs"
306
307 static zpool_command_t *current_command;
308 static char history_str[HIS_MAX_RECORD_LEN];
309 static boolean_t log_history = B_TRUE;
310 static uint_t timestamp_fmt = NODATE;
311
312 static const char *
get_usage(zpool_help_t idx)313 get_usage(zpool_help_t idx)
314 {
315 switch (idx) {
316 case HELP_ADD:
317 return (gettext("\tadd [-fgLnP] [-o property=value] "
318 "<pool> <vdev> ...\n"));
319 case HELP_ATTACH:
320 return (gettext("\tattach [-f] [-o property=value] "
321 "<pool> <device> <new-device>\n"));
322 case HELP_CLEAR:
323 return (gettext("\tclear [-nF] <pool> [device]\n"));
324 case HELP_CREATE:
325 return (gettext("\tcreate [-fnd] [-B] "
326 "[-o property=value] ... \n"
327 "\t [-O file-system-property=value] ...\n"
328 "\t [-m mountpoint] [-R root] [-t tempname] "
329 "<pool> <vdev> ...\n"));
330 case HELP_CHECKPOINT:
331 return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
332 case HELP_DESTROY:
333 return (gettext("\tdestroy [-f] <pool>\n"));
334 case HELP_DETACH:
335 return (gettext("\tdetach <pool> <device>\n"));
336 case HELP_EXPORT:
337 return (gettext("\texport [-f] <pool> ...\n"));
338 case HELP_HISTORY:
339 return (gettext("\thistory [-il] [<pool>] ...\n"));
340 case HELP_IMPORT:
341 return (gettext("\timport [-d dir] [-D]\n"
342 "\timport [-d dir | -c cachefile] [-F [-n]] [-l] "
343 "<pool | id>\n"
344 "\timport [-o mntopts] [-o property=value] ... \n"
345 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
346 "[-R root] [-F [-n]] -a\n"
347 "\timport [-o mntopts] [-o property=value] ... \n"
348 "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
349 "[-R root] [-F [-n]] [-t]\n"
350 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
351 case HELP_IOSTAT:
352 return (gettext("\tiostat "
353 "[[-lq]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
354 "\t [[pool] ...]|[pool vdev ...]|[vdev ...]]"
355 " [[-n] interval [count]]\n"));
356 case HELP_LABELCLEAR:
357 return (gettext("\tlabelclear [-f] <vdev>\n"));
358 case HELP_LIST:
359 return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
360 "[-T d|u] [pool] ... [interval [count]]\n"));
361 case HELP_OFFLINE:
362 return (gettext("\toffline [-t] <pool> <device> ...\n"));
363 case HELP_ONLINE:
364 return (gettext("\tonline <pool> <device> ...\n"));
365 case HELP_REPLACE:
366 return (gettext("\treplace [-f] <pool> <device> "
367 "[new-device]\n"));
368 case HELP_REMOVE:
369 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
370 case HELP_REOPEN:
371 return (gettext("\treopen <pool>\n"));
372 case HELP_INITIALIZE:
373 return (gettext("\tinitialize [-c | -s] <pool> "
374 "[<device> ...]\n"));
375 case HELP_SCRUB:
376 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
377 case HELP_RESILVER:
378 return (gettext("\tresilver <pool> ...\n"));
379 case HELP_TRIM:
380 return (gettext("\ttrim [-d] [-r <rate>] [-c | -s] <pool> "
381 "[<device> ...]\n"));
382 case HELP_STATUS:
383 return (gettext("\tstatus "
384 "[-igLpPsvxD] [-T d|u] [pool] ... "
385 "[interval [count]]\n"));
386 case HELP_UPGRADE:
387 return (gettext("\tupgrade\n"
388 "\tupgrade -v\n"
389 "\tupgrade [-V version] <-a | pool ...>\n"));
390 case HELP_GET:
391 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
392 "<\"all\" | property[,...]> <pool> ...\n"));
393 case HELP_SET:
394 return (gettext("\tset <property=value> <pool> \n"));
395 case HELP_SPLIT:
396 return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n"
397 "\t [-o property=value] <pool> <newpool> "
398 "[<device> ...]\n"));
399 case HELP_REGUID:
400 return (gettext("\treguid <pool>\n"));
401 case HELP_SYNC:
402 return (gettext("\tsync [pool] ...\n"));
403 }
404
405 abort();
406 /* NOTREACHED */
407 }
408
409 static void
zpool_collect_leaves(zpool_handle_t * zhp,nvlist_t * nvroot,nvlist_t * res)410 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
411 {
412 uint_t children = 0;
413 nvlist_t **child;
414 uint_t i;
415
416 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
417 &child, &children);
418
419 if (children == 0) {
420 char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 0);
421
422 if (strcmp(path, VDEV_TYPE_INDIRECT) != 0)
423 fnvlist_add_boolean(res, path);
424
425 free(path);
426 return;
427 }
428
429 for (i = 0; i < children; i++) {
430 zpool_collect_leaves(zhp, child[i], res);
431 }
432 }
433
434 /*
435 * Callback routine that will print out a pool property value.
436 */
437 static int
print_prop_cb(int prop,void * cb)438 print_prop_cb(int prop, void *cb)
439 {
440 FILE *fp = cb;
441
442 (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop));
443
444 if (zpool_prop_readonly(prop))
445 (void) fprintf(fp, " NO ");
446 else
447 (void) fprintf(fp, " YES ");
448
449 if (zpool_prop_values(prop) == NULL)
450 (void) fprintf(fp, "-\n");
451 else
452 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
453
454 return (ZPROP_CONT);
455 }
456
457 /*
458 * Display usage message. If we're inside a command, display only the usage for
459 * that command. Otherwise, iterate over the entire command table and display
460 * a complete usage message.
461 */
462 void
usage(boolean_t requested)463 usage(boolean_t requested)
464 {
465 FILE *fp = requested ? stdout : stderr;
466
467 if (current_command == NULL) {
468 int i;
469
470 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
471 (void) fprintf(fp,
472 gettext("where 'command' is one of the following:\n\n"));
473
474 for (i = 0; i < NCOMMAND; i++) {
475 if (command_table[i].name == NULL)
476 (void) fprintf(fp, "\n");
477 else
478 (void) fprintf(fp, "%s",
479 get_usage(command_table[i].usage));
480 }
481 } else {
482 (void) fprintf(fp, gettext("usage:\n"));
483 (void) fprintf(fp, "%s", get_usage(current_command->usage));
484 }
485
486 if (current_command != NULL &&
487 ((strcmp(current_command->name, "set") == 0) ||
488 (strcmp(current_command->name, "get") == 0) ||
489 (strcmp(current_command->name, "list") == 0))) {
490
491 (void) fprintf(fp,
492 gettext("\nthe following properties are supported:\n"));
493
494 (void) fprintf(fp, "\n\t%-19s %s %s\n\n",
495 "PROPERTY", "EDIT", "VALUES");
496
497 /* Iterate over all properties */
498 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
499 ZFS_TYPE_POOL);
500
501 (void) fprintf(fp, "\t%-19s ", "feature@...");
502 (void) fprintf(fp, "YES disabled | enabled | active\n");
503
504 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
505 "appended with a feature name.\nSee zpool-features(5).\n"));
506 }
507
508 /*
509 * See comments at end of main().
510 */
511 if (getenv("ZFS_ABORT") != NULL) {
512 (void) printf("dumping core by request\n");
513 abort();
514 }
515
516 exit(requested ? 0 : 2);
517 }
518
519 /*
520 * print a pool vdev config for dry runs
521 */
522 static void
print_vdev_tree(zpool_handle_t * zhp,const char * name,nvlist_t * nv,int indent,const char * match,int name_flags)523 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
524 const char *match, int name_flags)
525 {
526 nvlist_t **child;
527 uint_t c, children;
528 char *vname;
529 boolean_t printed = B_FALSE;
530
531 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
532 &child, &children) != 0) {
533 if (name != NULL)
534 (void) printf("\t%*s%s\n", indent, "", name);
535 return;
536 }
537
538 for (c = 0; c < children; c++) {
539 uint64_t is_log = B_FALSE;
540 char *class = "";
541
542 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
543 &is_log);
544 if (is_log)
545 class = VDEV_ALLOC_BIAS_LOG;
546 (void) nvlist_lookup_string(child[c],
547 ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
548 if (strcmp(match, class) != 0)
549 continue;
550
551 if (!printed && name != NULL) {
552 (void) printf("\t%*s%s\n", indent, "", name);
553 printed = B_TRUE;
554 }
555 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
556 print_vdev_tree(zhp, vname, child[c], indent + 2, "",
557 name_flags);
558 free(vname);
559 }
560 }
561
562 static boolean_t
prop_list_contains_feature(nvlist_t * proplist)563 prop_list_contains_feature(nvlist_t *proplist)
564 {
565 nvpair_t *nvp;
566 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
567 nvp = nvlist_next_nvpair(proplist, nvp)) {
568 if (zpool_prop_feature(nvpair_name(nvp)))
569 return (B_TRUE);
570 }
571 return (B_FALSE);
572 }
573
574 /*
575 * Add a property pair (name, string-value) into a property nvlist.
576 */
577 static int
add_prop_list(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)578 add_prop_list(const char *propname, char *propval, nvlist_t **props,
579 boolean_t poolprop)
580 {
581 zpool_prop_t prop = ZPOOL_PROP_INVAL;
582 zfs_prop_t fprop;
583 nvlist_t *proplist;
584 const char *normnm;
585 char *strval;
586
587 if (*props == NULL &&
588 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
589 (void) fprintf(stderr,
590 gettext("internal error: out of memory\n"));
591 return (1);
592 }
593
594 proplist = *props;
595
596 if (poolprop) {
597 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
598
599 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
600 !zpool_prop_feature(propname)) {
601 (void) fprintf(stderr, gettext("property '%s' is "
602 "not a valid pool property\n"), propname);
603 return (2);
604 }
605
606 /*
607 * feature@ properties and version should not be specified
608 * at the same time.
609 */
610 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
611 nvlist_exists(proplist, vname)) ||
612 (prop == ZPOOL_PROP_VERSION &&
613 prop_list_contains_feature(proplist))) {
614 (void) fprintf(stderr, gettext("'feature@' and "
615 "'version' properties cannot be specified "
616 "together\n"));
617 return (2);
618 }
619
620
621 if (zpool_prop_feature(propname))
622 normnm = propname;
623 else
624 normnm = zpool_prop_to_name(prop);
625 } else {
626 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
627 normnm = zfs_prop_to_name(fprop);
628 } else {
629 normnm = propname;
630 }
631 }
632
633 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
634 prop != ZPOOL_PROP_CACHEFILE) {
635 (void) fprintf(stderr, gettext("property '%s' "
636 "specified multiple times\n"), propname);
637 return (2);
638 }
639
640 if (nvlist_add_string(proplist, normnm, propval) != 0) {
641 (void) fprintf(stderr, gettext("internal "
642 "error: out of memory\n"));
643 return (1);
644 }
645
646 return (0);
647 }
648
649 /*
650 * Set a default property pair (name, string-value) in a property nvlist
651 */
652 static int
add_prop_list_default(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)653 add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
654 boolean_t poolprop)
655 {
656 char *pval;
657
658 if (nvlist_lookup_string(*props, propname, &pval) == 0)
659 return (0);
660
661 return (add_prop_list(propname, propval, props, poolprop));
662 }
663
664 /*
665 * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
666 *
667 * -f Force addition of devices, even if they appear in use
668 * -g Display guid for individual vdev name.
669 * -L Follow links when resolving vdev path name.
670 * -n Do not add the devices, but display the resulting layout if
671 * they were to be added.
672 * -P Display full path for vdev name.
673 * -o Set property=value.
674 *
675 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
676 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
677 * libzfs.
678 */
679 int
zpool_do_add(int argc,char ** argv)680 zpool_do_add(int argc, char **argv)
681 {
682 boolean_t force = B_FALSE;
683 boolean_t dryrun = B_FALSE;
684 int name_flags = 0;
685 int c;
686 nvlist_t *nvroot;
687 char *poolname;
688 zpool_boot_label_t boot_type;
689 uint64_t boot_size;
690 int ret;
691 zpool_handle_t *zhp;
692 nvlist_t *config;
693 nvlist_t *props = NULL;
694 char *propval;
695
696 /* check options */
697 while ((c = getopt(argc, argv, "fgLnPo:")) != -1) {
698 switch (c) {
699 case 'f':
700 force = B_TRUE;
701 break;
702 case 'g':
703 name_flags |= VDEV_NAME_GUID;
704 break;
705 case 'L':
706 name_flags |= VDEV_NAME_FOLLOW_LINKS;
707 break;
708 case 'n':
709 dryrun = B_TRUE;
710 break;
711 case 'P':
712 name_flags |= VDEV_NAME_PATH;
713 break;
714 case 'o':
715 if ((propval = strchr(optarg, '=')) == NULL) {
716 (void) fprintf(stderr, gettext("missing "
717 "'=' for -o option\n"));
718 usage(B_FALSE);
719 }
720 *propval = '\0';
721 propval++;
722
723 if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) ||
724 (add_prop_list(optarg, propval, &props, B_TRUE)))
725 usage(B_FALSE);
726 break;
727 case '?':
728 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
729 optopt);
730 usage(B_FALSE);
731 }
732 }
733
734 argc -= optind;
735 argv += optind;
736
737 /* get pool name and check number of arguments */
738 if (argc < 1) {
739 (void) fprintf(stderr, gettext("missing pool name argument\n"));
740 usage(B_FALSE);
741 }
742 if (argc < 2) {
743 (void) fprintf(stderr, gettext("missing vdev specification\n"));
744 usage(B_FALSE);
745 }
746
747 poolname = argv[0];
748
749 argc--;
750 argv++;
751
752 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
753 return (1);
754
755 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
756 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
757 poolname);
758 zpool_close(zhp);
759 return (1);
760 }
761
762 if (zpool_is_bootable(zhp))
763 boot_type = ZPOOL_COPY_BOOT_LABEL;
764 else
765 boot_type = ZPOOL_NO_BOOT_LABEL;
766
767 /* unless manually specified use "ashift" pool property (if set) */
768 if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) {
769 int intval;
770 zprop_source_t src;
771 char strval[ZPOOL_MAXPROPLEN];
772
773 intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src);
774 if (src != ZPROP_SRC_DEFAULT) {
775 (void) sprintf(strval, "%" PRId32, intval);
776 verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval,
777 &props, B_TRUE) == 0);
778 }
779 }
780
781 /* pass off to get_vdev_spec for processing */
782 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
783 nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
784 boot_type, boot_size, argc, argv);
785 if (nvroot == NULL) {
786 zpool_close(zhp);
787 return (1);
788 }
789
790 if (dryrun) {
791 nvlist_t *poolnvroot;
792
793 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
794 &poolnvroot) == 0);
795
796 (void) printf(gettext("would update '%s' to the following "
797 "configuration:\n"), zpool_get_name(zhp));
798
799 /* print original main pool and new tree */
800 print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
801 name_flags | VDEV_NAME_TYPE_ID);
802 print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
803
804 /* print other classes: 'dedup', 'special', and 'log' */
805 print_vdev_tree(zhp, "dedup", poolnvroot, 0,
806 VDEV_ALLOC_BIAS_DEDUP, name_flags);
807 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP,
808 name_flags);
809
810 print_vdev_tree(zhp, "special", poolnvroot, 0,
811 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
812 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL,
813 name_flags);
814
815 print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG,
816 name_flags);
817 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG,
818 name_flags);
819
820 ret = 0;
821 } else {
822 ret = (zpool_add(zhp, nvroot) != 0);
823 }
824
825 nvlist_free(props);
826 nvlist_free(nvroot);
827 zpool_close(zhp);
828
829 return (ret);
830 }
831
832 /*
833 * zpool remove <pool> <vdev> ...
834 *
835 * Removes the given vdev from the pool.
836 */
837 int
zpool_do_remove(int argc,char ** argv)838 zpool_do_remove(int argc, char **argv)
839 {
840 char *poolname;
841 int i, ret = 0;
842 zpool_handle_t *zhp;
843 boolean_t stop = B_FALSE;
844 boolean_t noop = B_FALSE;
845 boolean_t parsable = B_FALSE;
846 char c;
847
848 /* check options */
849 while ((c = getopt(argc, argv, "nps")) != -1) {
850 switch (c) {
851 case 'n':
852 noop = B_TRUE;
853 break;
854 case 'p':
855 parsable = B_TRUE;
856 break;
857 case 's':
858 stop = B_TRUE;
859 break;
860 case '?':
861 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
862 optopt);
863 usage(B_FALSE);
864 }
865 }
866
867 argc -= optind;
868 argv += optind;
869
870 /* get pool name and check number of arguments */
871 if (argc < 1) {
872 (void) fprintf(stderr, gettext("missing pool name argument\n"));
873 usage(B_FALSE);
874 }
875
876 poolname = argv[0];
877
878 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
879 return (1);
880
881 if (stop && noop) {
882 (void) fprintf(stderr, gettext("stop request ignored\n"));
883 return (0);
884 }
885
886 if (stop) {
887 if (argc > 1) {
888 (void) fprintf(stderr, gettext("too many arguments\n"));
889 usage(B_FALSE);
890 }
891 if (zpool_vdev_remove_cancel(zhp) != 0)
892 ret = 1;
893 } else {
894 if (argc < 2) {
895 (void) fprintf(stderr, gettext("missing device\n"));
896 usage(B_FALSE);
897 }
898
899 for (i = 1; i < argc; i++) {
900 if (noop) {
901 uint64_t size;
902
903 if (zpool_vdev_indirect_size(zhp, argv[i],
904 &size) != 0) {
905 ret = 1;
906 break;
907 }
908 if (parsable) {
909 (void) printf("%s %llu\n",
910 argv[i], size);
911 } else {
912 char valstr[32];
913 zfs_nicenum(size, valstr,
914 sizeof (valstr));
915 (void) printf("Memory that will be "
916 "used after removing %s: %s\n",
917 argv[i], valstr);
918 }
919 } else {
920 if (zpool_vdev_remove(zhp, argv[i]) != 0)
921 ret = 1;
922 }
923 }
924 }
925
926 return (ret);
927 }
928
929 /*
930 * zpool labelclear [-f] <vdev>
931 *
932 * -f Force clearing the label for the vdevs which are members of
933 * the exported or foreign pools.
934 *
935 * Verifies that the vdev is not active and zeros out the label information
936 * on the device.
937 */
938 int
zpool_do_labelclear(int argc,char ** argv)939 zpool_do_labelclear(int argc, char **argv)
940 {
941 char vdev[MAXPATHLEN];
942 char *name = NULL;
943 struct stat st;
944 int c, fd, ret = 0;
945 nvlist_t *config;
946 pool_state_t state;
947 boolean_t inuse = B_FALSE;
948 boolean_t force = B_FALSE;
949
950 /* check options */
951 while ((c = getopt(argc, argv, "f")) != -1) {
952 switch (c) {
953 case 'f':
954 force = B_TRUE;
955 break;
956 default:
957 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
958 optopt);
959 usage(B_FALSE);
960 }
961 }
962
963 argc -= optind;
964 argv += optind;
965
966 /* get vdev name */
967 if (argc < 1) {
968 (void) fprintf(stderr, gettext("missing vdev name\n"));
969 usage(B_FALSE);
970 }
971 if (argc > 1) {
972 (void) fprintf(stderr, gettext("too many arguments\n"));
973 usage(B_FALSE);
974 }
975
976 /*
977 * Check if we were given absolute path and use it as is.
978 * Otherwise if the provided vdev name doesn't point to a file,
979 * try prepending dsk path and appending s0.
980 */
981 (void) strlcpy(vdev, argv[0], sizeof (vdev));
982 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
983 char *s;
984
985 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
986 ZFS_DISK_ROOT, argv[0]);
987 if ((s = strrchr(argv[0], 's')) == NULL ||
988 !isdigit(*(s + 1)))
989 (void) strlcat(vdev, "s0", sizeof (vdev));
990 if (stat(vdev, &st) != 0) {
991 (void) fprintf(stderr, gettext(
992 "failed to find device %s, try specifying absolute "
993 "path instead\n"), argv[0]);
994 return (1);
995 }
996 }
997
998 if ((fd = open(vdev, O_RDWR)) < 0) {
999 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
1000 vdev, strerror(errno));
1001 return (1);
1002 }
1003
1004 if (zpool_read_label(fd, &config, NULL) != 0) {
1005 (void) fprintf(stderr,
1006 gettext("failed to read label from %s\n"), vdev);
1007 return (1);
1008 }
1009 nvlist_free(config);
1010
1011 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
1012 if (ret != 0) {
1013 (void) fprintf(stderr,
1014 gettext("failed to check state for %s\n"), vdev);
1015 return (1);
1016 }
1017
1018 if (!inuse)
1019 goto wipe_label;
1020
1021 switch (state) {
1022 default:
1023 case POOL_STATE_ACTIVE:
1024 case POOL_STATE_SPARE:
1025 case POOL_STATE_L2CACHE:
1026 (void) fprintf(stderr, gettext(
1027 "%s is a member (%s) of pool \"%s\"\n"),
1028 vdev, zpool_pool_state_to_name(state), name);
1029 ret = 1;
1030 goto errout;
1031
1032 case POOL_STATE_EXPORTED:
1033 if (force)
1034 break;
1035 (void) fprintf(stderr, gettext(
1036 "use '-f' to override the following error:\n"
1037 "%s is a member of exported pool \"%s\"\n"),
1038 vdev, name);
1039 ret = 1;
1040 goto errout;
1041
1042 case POOL_STATE_POTENTIALLY_ACTIVE:
1043 if (force)
1044 break;
1045 (void) fprintf(stderr, gettext(
1046 "use '-f' to override the following error:\n"
1047 "%s is a member of potentially active pool \"%s\"\n"),
1048 vdev, name);
1049 ret = 1;
1050 goto errout;
1051
1052 case POOL_STATE_DESTROYED:
1053 /* inuse should never be set for a destroyed pool */
1054 assert(0);
1055 break;
1056 }
1057
1058 wipe_label:
1059 ret = zpool_clear_label(fd);
1060 if (ret != 0) {
1061 (void) fprintf(stderr,
1062 gettext("failed to clear label for %s\n"), vdev);
1063 }
1064
1065 errout:
1066 free(name);
1067 (void) close(fd);
1068
1069 return (ret);
1070 }
1071
1072 /*
1073 * zpool create [-fnd] [-B] [-o property=value] ...
1074 * [-O file-system-property=value] ...
1075 * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ...
1076 *
1077 * -B Create boot partition.
1078 * -f Force creation, even if devices appear in use
1079 * -n Do not create the pool, but display the resulting layout if it
1080 * were to be created.
1081 * -R Create a pool under an alternate root
1082 * -m Set default mountpoint for the root dataset. By default it's
1083 * '/<pool>'
1084 * -t Use the temporary name until the pool is exported.
1085 * -o Set property=value.
1086 * -o Set feature@feature=enabled|disabled.
1087 * -d Don't automatically enable all supported pool features
1088 * (individual features can be enabled with -o).
1089 * -O Set fsproperty=value in the pool's root file system
1090 *
1091 * Creates the named pool according to the given vdev specification. The
1092 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
1093 * we get the nvlist back from get_vdev_spec(), we either print out the contents
1094 * (if '-n' was specified), or pass it to libzfs to do the creation.
1095 */
1096
1097 #define SYSTEM256 (256 * 1024 * 1024)
1098 int
zpool_do_create(int argc,char ** argv)1099 zpool_do_create(int argc, char **argv)
1100 {
1101 boolean_t force = B_FALSE;
1102 boolean_t dryrun = B_FALSE;
1103 boolean_t enable_all_pool_feat = B_TRUE;
1104 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
1105 uint64_t boot_size = 0;
1106 int c;
1107 nvlist_t *nvroot = NULL;
1108 char *poolname;
1109 char *tname = NULL;
1110 int ret = 1;
1111 char *altroot = NULL;
1112 char *mountpoint = NULL;
1113 nvlist_t *fsprops = NULL;
1114 nvlist_t *props = NULL;
1115 char *propval;
1116
1117 /* check options */
1118 while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) {
1119 switch (c) {
1120 case 'f':
1121 force = B_TRUE;
1122 break;
1123 case 'n':
1124 dryrun = B_TRUE;
1125 break;
1126 case 'd':
1127 enable_all_pool_feat = B_FALSE;
1128 break;
1129 case 'B':
1130 /*
1131 * We should create the system partition.
1132 * Also make sure the size is set.
1133 */
1134 boot_type = ZPOOL_CREATE_BOOT_LABEL;
1135 if (boot_size == 0)
1136 boot_size = SYSTEM256;
1137 break;
1138 case 'R':
1139 altroot = optarg;
1140 if (add_prop_list(zpool_prop_to_name(
1141 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1142 goto errout;
1143 if (add_prop_list_default(zpool_prop_to_name(
1144 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1145 goto errout;
1146 break;
1147 case 'm':
1148 /* Equivalent to -O mountpoint=optarg */
1149 mountpoint = optarg;
1150 break;
1151 case 'o':
1152 if ((propval = strchr(optarg, '=')) == NULL) {
1153 (void) fprintf(stderr, gettext("missing "
1154 "'=' for -o option\n"));
1155 goto errout;
1156 }
1157 *propval = '\0';
1158 propval++;
1159
1160 if (add_prop_list(optarg, propval, &props, B_TRUE))
1161 goto errout;
1162
1163 /*
1164 * Get bootsize value for make_root_vdev().
1165 */
1166 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
1167 if (zfs_nicestrtonum(g_zfs, propval,
1168 &boot_size) < 0 || boot_size == 0) {
1169 (void) fprintf(stderr,
1170 gettext("bad boot partition size "
1171 "'%s': %s\n"), propval,
1172 libzfs_error_description(g_zfs));
1173 goto errout;
1174 }
1175 }
1176
1177 /*
1178 * If the user is creating a pool that doesn't support
1179 * feature flags, don't enable any features.
1180 */
1181 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1182 char *end;
1183 u_longlong_t ver;
1184
1185 ver = strtoull(propval, &end, 10);
1186 if (*end == '\0' &&
1187 ver < SPA_VERSION_FEATURES) {
1188 enable_all_pool_feat = B_FALSE;
1189 }
1190 }
1191 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1192 altroot = propval;
1193 break;
1194 case 'O':
1195 if ((propval = strchr(optarg, '=')) == NULL) {
1196 (void) fprintf(stderr, gettext("missing "
1197 "'=' for -O option\n"));
1198 goto errout;
1199 }
1200 *propval = '\0';
1201 propval++;
1202
1203 /*
1204 * Mountpoints are checked and then added later.
1205 * Uniquely among properties, they can be specified
1206 * more than once, to avoid conflict with -m.
1207 */
1208 if (0 == strcmp(optarg,
1209 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1210 mountpoint = propval;
1211 } else if (add_prop_list(optarg, propval, &fsprops,
1212 B_FALSE)) {
1213 goto errout;
1214 }
1215 break;
1216 case 't':
1217 /*
1218 * Sanity check temporary pool name.
1219 */
1220 if (strchr(optarg, '/') != NULL) {
1221 (void) fprintf(stderr, gettext("cannot create "
1222 "'%s': invalid character '/' in temporary "
1223 "name\n"), optarg);
1224 (void) fprintf(stderr, gettext("use 'zfs "
1225 "create' to create a dataset\n"));
1226 goto errout;
1227 }
1228
1229 if (add_prop_list(zpool_prop_to_name(
1230 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1231 goto errout;
1232 if (add_prop_list_default(zpool_prop_to_name(
1233 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1234 goto errout;
1235 tname = optarg;
1236 break;
1237 case ':':
1238 (void) fprintf(stderr, gettext("missing argument for "
1239 "'%c' option\n"), optopt);
1240 goto badusage;
1241 case '?':
1242 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1243 optopt);
1244 goto badusage;
1245 }
1246 }
1247
1248 argc -= optind;
1249 argv += optind;
1250
1251 /* get pool name and check number of arguments */
1252 if (argc < 1) {
1253 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1254 goto badusage;
1255 }
1256 if (argc < 2) {
1257 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1258 goto badusage;
1259 }
1260
1261 poolname = argv[0];
1262
1263 /*
1264 * As a special case, check for use of '/' in the name, and direct the
1265 * user to use 'zfs create' instead.
1266 */
1267 if (strchr(poolname, '/') != NULL) {
1268 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1269 "character '/' in pool name\n"), poolname);
1270 (void) fprintf(stderr, gettext("use 'zfs create' to "
1271 "create a dataset\n"));
1272 goto errout;
1273 }
1274
1275 /*
1276 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1277 * and not set otherwise.
1278 */
1279 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1280 const char *propname;
1281 char *strptr, *buf = NULL;
1282 int rv;
1283
1284 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1285 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1286 (void) asprintf(&buf, "%" PRIu64, boot_size);
1287 if (buf == NULL) {
1288 (void) fprintf(stderr,
1289 gettext("internal error: out of memory\n"));
1290 goto errout;
1291 }
1292 rv = add_prop_list(propname, buf, &props, B_TRUE);
1293 free(buf);
1294 if (rv != 0)
1295 goto errout;
1296 }
1297 } else {
1298 const char *propname;
1299 char *strptr;
1300
1301 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1302 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1303 (void) fprintf(stderr, gettext("error: setting boot "
1304 "partition size requires option '-B'\n"));
1305 goto errout;
1306 }
1307 }
1308
1309 /* pass off to get_vdev_spec for bulk processing */
1310 nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
1311 boot_type, boot_size, argc - 1, argv + 1);
1312 if (nvroot == NULL)
1313 goto errout;
1314
1315 /* make_root_vdev() allows 0 toplevel children if there are spares */
1316 if (!zfs_allocatable_devs(nvroot)) {
1317 (void) fprintf(stderr, gettext("invalid vdev "
1318 "specification: at least one toplevel vdev must be "
1319 "specified\n"));
1320 goto errout;
1321 }
1322
1323 if (altroot != NULL && altroot[0] != '/') {
1324 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1325 "must be an absolute path\n"), altroot);
1326 goto errout;
1327 }
1328
1329 /*
1330 * Check the validity of the mountpoint and direct the user to use the
1331 * '-m' mountpoint option if it looks like its in use.
1332 */
1333 if (mountpoint == NULL ||
1334 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1335 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1336 char buf[MAXPATHLEN];
1337 DIR *dirp;
1338
1339 if (mountpoint && mountpoint[0] != '/') {
1340 (void) fprintf(stderr, gettext("invalid mountpoint "
1341 "'%s': must be an absolute path, 'legacy', or "
1342 "'none'\n"), mountpoint);
1343 goto errout;
1344 }
1345
1346 if (mountpoint == NULL) {
1347 if (altroot != NULL)
1348 (void) snprintf(buf, sizeof (buf), "%s/%s",
1349 altroot, poolname);
1350 else
1351 (void) snprintf(buf, sizeof (buf), "/%s",
1352 poolname);
1353 } else {
1354 if (altroot != NULL)
1355 (void) snprintf(buf, sizeof (buf), "%s%s",
1356 altroot, mountpoint);
1357 else
1358 (void) snprintf(buf, sizeof (buf), "%s",
1359 mountpoint);
1360 }
1361
1362 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1363 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1364 "%s\n"), buf, strerror(errno));
1365 (void) fprintf(stderr, gettext("use '-m' "
1366 "option to provide a different default\n"));
1367 goto errout;
1368 } else if (dirp) {
1369 int count = 0;
1370
1371 while (count < 3 && readdir(dirp) != NULL)
1372 count++;
1373 (void) closedir(dirp);
1374
1375 if (count > 2) {
1376 (void) fprintf(stderr, gettext("mountpoint "
1377 "'%s' exists and is not empty\n"), buf);
1378 (void) fprintf(stderr, gettext("use '-m' "
1379 "option to provide a "
1380 "different default\n"));
1381 goto errout;
1382 }
1383 }
1384 }
1385
1386 /*
1387 * Now that the mountpoint's validity has been checked, ensure that
1388 * the property is set appropriately prior to creating the pool.
1389 */
1390 if (mountpoint != NULL) {
1391 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1392 mountpoint, &fsprops, B_FALSE);
1393 if (ret != 0)
1394 goto errout;
1395 }
1396
1397 ret = 1;
1398 if (dryrun) {
1399 /*
1400 * For a dry run invocation, print out a basic message and run
1401 * through all the vdevs in the list and print out in an
1402 * appropriate hierarchy.
1403 */
1404 (void) printf(gettext("would create '%s' with the "
1405 "following layout:\n\n"), poolname);
1406
1407 print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
1408 print_vdev_tree(NULL, "dedup", nvroot, 0,
1409 VDEV_ALLOC_BIAS_DEDUP, 0);
1410 print_vdev_tree(NULL, "special", nvroot, 0,
1411 VDEV_ALLOC_BIAS_SPECIAL, 0);
1412 print_vdev_tree(NULL, "logs", nvroot, 0,
1413 VDEV_ALLOC_BIAS_LOG, 0);
1414
1415 ret = 0;
1416 } else {
1417 /*
1418 * Hand off to libzfs.
1419 */
1420
1421 spa_feature_t i;
1422 for (i = 0; i < SPA_FEATURES; i++) {
1423 char propname[MAXPATHLEN];
1424 char *propval;
1425 zfeature_info_t *feat = &spa_feature_table[i];
1426 (void) snprintf(propname, sizeof (propname),
1427 "feature@%s", feat->fi_uname);
1428
1429 /*
1430 * Only features contained in props will be enabled:
1431 * remove from the nvlist every ZFS_FEATURE_DISABLED
1432 * value and add every missing ZFS_FEATURE_ENABLED if
1433 * enable_all_pool_feat is set.
1434 */
1435 if (!nvlist_lookup_string(props, propname, &propval)) {
1436 if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0)
1437 (void) nvlist_remove_all(props,
1438 propname);
1439 } else if (enable_all_pool_feat) {
1440 ret = add_prop_list(propname,
1441 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1442 if (ret != 0)
1443 goto errout;
1444 }
1445 }
1446
1447 ret = 1;
1448 if (zpool_create(g_zfs, poolname,
1449 nvroot, props, fsprops) == 0) {
1450 zfs_handle_t *pool = zfs_open(g_zfs,
1451 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1452 if (pool != NULL) {
1453 if (zfs_mount(pool, NULL, 0) == 0)
1454 ret = zfs_shareall(pool);
1455 zfs_close(pool);
1456 }
1457 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1458 (void) fprintf(stderr, gettext("pool name may have "
1459 "been omitted\n"));
1460 }
1461 }
1462
1463 errout:
1464 nvlist_free(nvroot);
1465 nvlist_free(fsprops);
1466 nvlist_free(props);
1467 return (ret);
1468 badusage:
1469 nvlist_free(fsprops);
1470 nvlist_free(props);
1471 usage(B_FALSE);
1472 return (2);
1473 }
1474
1475 /*
1476 * zpool destroy <pool>
1477 *
1478 * -f Forcefully unmount any datasets
1479 *
1480 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1481 */
1482 int
zpool_do_destroy(int argc,char ** argv)1483 zpool_do_destroy(int argc, char **argv)
1484 {
1485 boolean_t force = B_FALSE;
1486 int c;
1487 char *pool;
1488 zpool_handle_t *zhp;
1489 int ret;
1490
1491 /* check options */
1492 while ((c = getopt(argc, argv, "f")) != -1) {
1493 switch (c) {
1494 case 'f':
1495 force = B_TRUE;
1496 break;
1497 case '?':
1498 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1499 optopt);
1500 usage(B_FALSE);
1501 }
1502 }
1503
1504 argc -= optind;
1505 argv += optind;
1506
1507 /* check arguments */
1508 if (argc < 1) {
1509 (void) fprintf(stderr, gettext("missing pool argument\n"));
1510 usage(B_FALSE);
1511 }
1512 if (argc > 1) {
1513 (void) fprintf(stderr, gettext("too many arguments\n"));
1514 usage(B_FALSE);
1515 }
1516
1517 pool = argv[0];
1518
1519 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1520 /*
1521 * As a special case, check for use of '/' in the name, and
1522 * direct the user to use 'zfs destroy' instead.
1523 */
1524 if (strchr(pool, '/') != NULL)
1525 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1526 "destroy a dataset\n"));
1527 return (1);
1528 }
1529
1530 if (zpool_disable_datasets(zhp, force) != 0) {
1531 (void) fprintf(stderr, gettext("could not destroy '%s': "
1532 "could not unmount datasets\n"), zpool_get_name(zhp));
1533 return (1);
1534 }
1535
1536 /* The history must be logged as part of the export */
1537 log_history = B_FALSE;
1538
1539 ret = (zpool_destroy(zhp, history_str) != 0);
1540
1541 zpool_close(zhp);
1542
1543 return (ret);
1544 }
1545
1546 /*
1547 * zpool export [-f] <pool> ...
1548 *
1549 * -f Forcefully unmount datasets
1550 *
1551 * Export the given pools. By default, the command will attempt to cleanly
1552 * unmount any active datasets within the pool. If the '-f' flag is specified,
1553 * then the datasets will be forcefully unmounted.
1554 */
1555 int
zpool_do_export(int argc,char ** argv)1556 zpool_do_export(int argc, char **argv)
1557 {
1558 boolean_t force = B_FALSE;
1559 boolean_t hardforce = B_FALSE;
1560 int c;
1561 zpool_handle_t *zhp;
1562 int ret;
1563 int i;
1564
1565 /* check options */
1566 while ((c = getopt(argc, argv, "fF")) != -1) {
1567 switch (c) {
1568 case 'f':
1569 force = B_TRUE;
1570 break;
1571 case 'F':
1572 hardforce = B_TRUE;
1573 break;
1574 case '?':
1575 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1576 optopt);
1577 usage(B_FALSE);
1578 }
1579 }
1580
1581 argc -= optind;
1582 argv += optind;
1583
1584 /* check arguments */
1585 if (argc < 1) {
1586 (void) fprintf(stderr, gettext("missing pool argument\n"));
1587 usage(B_FALSE);
1588 }
1589
1590 ret = 0;
1591 for (i = 0; i < argc; i++) {
1592 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1593 ret = 1;
1594 continue;
1595 }
1596
1597 if (zpool_disable_datasets(zhp, force) != 0) {
1598 ret = 1;
1599 zpool_close(zhp);
1600 continue;
1601 }
1602
1603 /* The history must be logged as part of the export */
1604 log_history = B_FALSE;
1605
1606 if (hardforce) {
1607 if (zpool_export_force(zhp, history_str) != 0)
1608 ret = 1;
1609 } else if (zpool_export(zhp, force, history_str) != 0) {
1610 ret = 1;
1611 }
1612
1613 zpool_close(zhp);
1614 }
1615
1616 return (ret);
1617 }
1618
1619 /*
1620 * Given a vdev configuration, determine the maximum width needed for the device
1621 * name column.
1622 */
1623 static int
max_width(zpool_handle_t * zhp,nvlist_t * nv,int depth,int max,int name_flags)1624 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1625 int name_flags)
1626 {
1627 char *name;
1628 nvlist_t **child;
1629 uint_t c, children;
1630 int ret;
1631
1632 name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID);
1633 if (strlen(name) + depth > max)
1634 max = strlen(name) + depth;
1635
1636 free(name);
1637
1638 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1639 &child, &children) == 0) {
1640 for (c = 0; c < children; c++)
1641 if ((ret = max_width(zhp, child[c], depth + 2,
1642 max, name_flags)) > max)
1643 max = ret;
1644 }
1645
1646 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1647 &child, &children) == 0) {
1648 for (c = 0; c < children; c++)
1649 if ((ret = max_width(zhp, child[c], depth + 2,
1650 max, name_flags)) > max)
1651 max = ret;
1652 }
1653
1654 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1655 &child, &children) == 0) {
1656 for (c = 0; c < children; c++)
1657 if ((ret = max_width(zhp, child[c], depth + 2,
1658 max, name_flags)) > max)
1659 max = ret;
1660 }
1661
1662 return (max);
1663 }
1664
1665 typedef struct spare_cbdata {
1666 uint64_t cb_guid;
1667 zpool_handle_t *cb_zhp;
1668 } spare_cbdata_t;
1669
1670 static boolean_t
find_vdev(nvlist_t * nv,uint64_t search)1671 find_vdev(nvlist_t *nv, uint64_t search)
1672 {
1673 uint64_t guid;
1674 nvlist_t **child;
1675 uint_t c, children;
1676
1677 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1678 search == guid)
1679 return (B_TRUE);
1680
1681 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1682 &child, &children) == 0) {
1683 for (c = 0; c < children; c++)
1684 if (find_vdev(child[c], search))
1685 return (B_TRUE);
1686 }
1687
1688 return (B_FALSE);
1689 }
1690
1691 static int
find_spare(zpool_handle_t * zhp,void * data)1692 find_spare(zpool_handle_t *zhp, void *data)
1693 {
1694 spare_cbdata_t *cbp = data;
1695 nvlist_t *config, *nvroot;
1696
1697 config = zpool_get_config(zhp, NULL);
1698 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1699 &nvroot) == 0);
1700
1701 if (find_vdev(nvroot, cbp->cb_guid)) {
1702 cbp->cb_zhp = zhp;
1703 return (1);
1704 }
1705
1706 zpool_close(zhp);
1707 return (0);
1708 }
1709
1710 typedef struct status_cbdata {
1711 int cb_count;
1712 int cb_name_flags;
1713 int cb_namewidth;
1714 boolean_t cb_allpools;
1715 boolean_t cb_verbose;
1716 boolean_t cb_literal;
1717 boolean_t cb_explain;
1718 boolean_t cb_first;
1719 boolean_t cb_dedup_stats;
1720 boolean_t cb_print_status;
1721 boolean_t cb_print_slow_ios;
1722 boolean_t cb_print_vdev_init;
1723 boolean_t cb_print_vdev_trim;
1724 } status_cbdata_t;
1725
1726 /*
1727 * Print vdev initialization status for leaves
1728 */
1729 static void
print_status_initialize(vdev_stat_t * vs,boolean_t verbose)1730 print_status_initialize(vdev_stat_t *vs, boolean_t verbose)
1731 {
1732 if (verbose) {
1733 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
1734 vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
1735 vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
1736 !vs->vs_scan_removing) {
1737 char zbuf[1024];
1738 char tbuf[256];
1739 struct tm zaction_ts;
1740
1741 time_t t = vs->vs_initialize_action_time;
1742 int initialize_pct = 100;
1743 if (vs->vs_initialize_state !=
1744 VDEV_INITIALIZE_COMPLETE) {
1745 initialize_pct = (vs->vs_initialize_bytes_done *
1746 100 / (vs->vs_initialize_bytes_est + 1));
1747 }
1748
1749 (void) localtime_r(&t, &zaction_ts);
1750 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1751
1752 switch (vs->vs_initialize_state) {
1753 case VDEV_INITIALIZE_SUSPENDED:
1754 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1755 gettext("suspended, started at"), tbuf);
1756 break;
1757 case VDEV_INITIALIZE_ACTIVE:
1758 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1759 gettext("started at"), tbuf);
1760 break;
1761 case VDEV_INITIALIZE_COMPLETE:
1762 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1763 gettext("completed at"), tbuf);
1764 break;
1765 }
1766
1767 (void) printf(gettext(" (%d%% initialized%s)"),
1768 initialize_pct, zbuf);
1769 } else {
1770 (void) printf(gettext(" (uninitialized)"));
1771 }
1772 } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) {
1773 (void) printf(gettext(" (initializing)"));
1774 }
1775 }
1776
1777 /*
1778 * Print vdev TRIM status for leaves
1779 */
1780 static void
print_status_trim(vdev_stat_t * vs,boolean_t verbose)1781 print_status_trim(vdev_stat_t *vs, boolean_t verbose)
1782 {
1783 if (verbose) {
1784 if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE ||
1785 vs->vs_trim_state == VDEV_TRIM_SUSPENDED ||
1786 vs->vs_trim_state == VDEV_TRIM_COMPLETE) &&
1787 !vs->vs_scan_removing) {
1788 char zbuf[1024];
1789 char tbuf[256];
1790 struct tm zaction_ts;
1791
1792 time_t t = vs->vs_trim_action_time;
1793 int trim_pct = 100;
1794 if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) {
1795 trim_pct = (vs->vs_trim_bytes_done *
1796 100 / (vs->vs_trim_bytes_est + 1));
1797 }
1798
1799 (void) localtime_r(&t, &zaction_ts);
1800 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1801
1802 switch (vs->vs_trim_state) {
1803 case VDEV_TRIM_SUSPENDED:
1804 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1805 gettext("suspended, started at"), tbuf);
1806 break;
1807 case VDEV_TRIM_ACTIVE:
1808 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1809 gettext("started at"), tbuf);
1810 break;
1811 case VDEV_TRIM_COMPLETE:
1812 (void) snprintf(zbuf, sizeof (zbuf), ", %s %s",
1813 gettext("completed at"), tbuf);
1814 break;
1815 }
1816
1817 (void) printf(gettext(" (%d%% trimmed%s)"),
1818 trim_pct, zbuf);
1819 } else if (vs->vs_trim_notsup) {
1820 (void) printf(gettext(" (trim unsupported)"));
1821 } else {
1822 (void) printf(gettext(" (untrimmed)"));
1823 }
1824 } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) {
1825 (void) printf(gettext(" (trimming)"));
1826 }
1827 }
1828
1829 /*
1830 * Print out configuration state as requested by status_callback.
1831 */
1832 static void
print_status_config(zpool_handle_t * zhp,status_cbdata_t * cb,const char * name,nvlist_t * nv,int depth,boolean_t isspare)1833 print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
1834 nvlist_t *nv, int depth, boolean_t isspare)
1835 {
1836 nvlist_t **child, *root;
1837 uint_t c, children;
1838 pool_scan_stat_t *ps = NULL;
1839 vdev_stat_t *vs;
1840 char rbuf[6], wbuf[6], cbuf[6];
1841 char *vname;
1842 uint64_t notpresent;
1843 spare_cbdata_t spare_cb;
1844 const char *state;
1845 char *type;
1846
1847 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1848 &child, &children) != 0)
1849 children = 0;
1850
1851 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1852 (uint64_t **)&vs, &c) == 0);
1853
1854 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1855
1856 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1857 return;
1858
1859 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1860 if (isspare) {
1861 /*
1862 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1863 * online drives.
1864 */
1865 if (vs->vs_aux == VDEV_AUX_SPARED)
1866 state = "INUSE";
1867 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1868 state = "AVAIL";
1869 }
1870
1871 (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
1872 name, state);
1873
1874 if (!isspare) {
1875 if (cb->cb_literal) {
1876 printf(" %5llu %5llu %5llu",
1877 (u_longlong_t)vs->vs_read_errors,
1878 (u_longlong_t)vs->vs_write_errors,
1879 (u_longlong_t)vs->vs_checksum_errors);
1880 } else {
1881 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1882 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1883 zfs_nicenum(vs->vs_checksum_errors, cbuf,
1884 sizeof (cbuf));
1885 printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1886 }
1887
1888 if (cb->cb_print_slow_ios) {
1889 if (children == 0) {
1890 /* Only leafs vdevs have slow IOs */
1891 zfs_nicenum(vs->vs_slow_ios, rbuf,
1892 sizeof (rbuf));
1893 } else {
1894 (void) snprintf(rbuf, sizeof (rbuf), "-");
1895 }
1896
1897 if (cb->cb_literal)
1898 printf(" %5llu", (u_longlong_t)vs->vs_slow_ios);
1899 else
1900 printf(" %5s", rbuf);
1901 }
1902
1903 }
1904
1905 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1906 ¬present) == 0) {
1907 char *path;
1908 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1909 (void) printf(" was %s", path);
1910 } else if (vs->vs_aux != 0) {
1911 (void) printf(" ");
1912
1913 switch (vs->vs_aux) {
1914 case VDEV_AUX_OPEN_FAILED:
1915 (void) printf(gettext("cannot open"));
1916 break;
1917
1918 case VDEV_AUX_BAD_GUID_SUM:
1919 (void) printf(gettext("missing device"));
1920 break;
1921
1922 case VDEV_AUX_NO_REPLICAS:
1923 (void) printf(gettext("insufficient replicas"));
1924 break;
1925
1926 case VDEV_AUX_VERSION_NEWER:
1927 (void) printf(gettext("newer version"));
1928 break;
1929
1930 case VDEV_AUX_UNSUP_FEAT:
1931 (void) printf(gettext("unsupported feature(s)"));
1932 break;
1933
1934 case VDEV_AUX_SPARED:
1935 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1936 &spare_cb.cb_guid) == 0);
1937 if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
1938 if (strcmp(zpool_get_name(spare_cb.cb_zhp),
1939 zpool_get_name(zhp)) == 0)
1940 (void) printf(gettext("currently in "
1941 "use"));
1942 else
1943 (void) printf(gettext("in use by "
1944 "pool '%s'"),
1945 zpool_get_name(spare_cb.cb_zhp));
1946 zpool_close(spare_cb.cb_zhp);
1947 } else {
1948 (void) printf(gettext("currently in use"));
1949 }
1950 break;
1951
1952 case VDEV_AUX_ERR_EXCEEDED:
1953 (void) printf(gettext("too many errors"));
1954 break;
1955
1956 case VDEV_AUX_IO_FAILURE:
1957 (void) printf(gettext("experienced I/O failures"));
1958 break;
1959
1960 case VDEV_AUX_BAD_LOG:
1961 (void) printf(gettext("bad intent log"));
1962 break;
1963
1964 case VDEV_AUX_EXTERNAL:
1965 (void) printf(gettext("external device fault"));
1966 break;
1967
1968 case VDEV_AUX_SPLIT_POOL:
1969 (void) printf(gettext("split into new pool"));
1970 break;
1971
1972 case VDEV_AUX_ACTIVE:
1973 (void) printf(gettext("currently in use"));
1974 break;
1975
1976 case VDEV_AUX_CHILDREN_OFFLINE:
1977 (void) printf(gettext("all children offline"));
1978 break;
1979
1980 default:
1981 (void) printf(gettext("corrupted data"));
1982 break;
1983 }
1984 }
1985
1986 /* The root vdev has the scrub/resilver stats */
1987 root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
1988 ZPOOL_CONFIG_VDEV_TREE);
1989 (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
1990 (uint64_t **)&ps, &c);
1991
1992 if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) {
1993 if (vs->vs_scan_processed != 0) {
1994 (void) printf(gettext(" (%s)"),
1995 (ps->pss_func == POOL_SCAN_RESILVER) ?
1996 "resilvering" : "repairing");
1997 } else if (vs->vs_resilver_deferred) {
1998 (void) printf(gettext(" (awaiting resilver)"));
1999 }
2000 }
2001
2002 /* Display vdev initialization and trim status for leaves */
2003 if (children == 0) {
2004 print_status_initialize(vs, cb->cb_print_vdev_init);
2005 print_status_trim(vs, cb->cb_print_vdev_trim);
2006 }
2007
2008 (void) printf("\n");
2009
2010 for (c = 0; c < children; c++) {
2011 uint64_t islog = B_FALSE, ishole = B_FALSE;
2012
2013 /* Don't print logs or holes here */
2014 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2015 &islog);
2016 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
2017 &ishole);
2018 if (islog || ishole)
2019 continue;
2020 /* Only print normal classes here */
2021 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2022 continue;
2023
2024 vname = zpool_vdev_name(g_zfs, zhp, child[c],
2025 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2026
2027 print_status_config(zhp, cb, vname, child[c], depth + 2,
2028 isspare);
2029 free(vname);
2030 }
2031 }
2032
2033 /*
2034 * Print the configuration of an exported pool. Iterate over all vdevs in the
2035 * pool, printing out the name and status for each one.
2036 */
2037 static void
print_import_config(status_cbdata_t * cb,const char * name,nvlist_t * nv,int depth)2038 print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
2039 int depth)
2040 {
2041 nvlist_t **child;
2042 uint_t c, children;
2043 vdev_stat_t *vs;
2044 char *type, *vname;
2045
2046 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
2047 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
2048 strcmp(type, VDEV_TYPE_HOLE) == 0)
2049 return;
2050
2051 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2052 (uint64_t **)&vs, &c) == 0);
2053
2054 (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
2055 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
2056
2057 if (vs->vs_aux != 0) {
2058 (void) printf(" ");
2059
2060 switch (vs->vs_aux) {
2061 case VDEV_AUX_OPEN_FAILED:
2062 (void) printf(gettext("cannot open"));
2063 break;
2064
2065 case VDEV_AUX_BAD_GUID_SUM:
2066 (void) printf(gettext("missing device"));
2067 break;
2068
2069 case VDEV_AUX_NO_REPLICAS:
2070 (void) printf(gettext("insufficient replicas"));
2071 break;
2072
2073 case VDEV_AUX_VERSION_NEWER:
2074 (void) printf(gettext("newer version"));
2075 break;
2076
2077 case VDEV_AUX_UNSUP_FEAT:
2078 (void) printf(gettext("unsupported feature(s)"));
2079 break;
2080
2081 case VDEV_AUX_ERR_EXCEEDED:
2082 (void) printf(gettext("too many errors"));
2083 break;
2084
2085 case VDEV_AUX_ACTIVE:
2086 (void) printf(gettext("currently in use"));
2087 break;
2088
2089 case VDEV_AUX_CHILDREN_OFFLINE:
2090 (void) printf(gettext("all children offline"));
2091 break;
2092
2093 default:
2094 (void) printf(gettext("corrupted data"));
2095 break;
2096 }
2097 }
2098 (void) printf("\n");
2099
2100 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2101 &child, &children) != 0)
2102 return;
2103
2104 for (c = 0; c < children; c++) {
2105 uint64_t is_log = B_FALSE;
2106
2107 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2108 &is_log);
2109 if (is_log)
2110 continue;
2111 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
2112 continue;
2113
2114 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2115 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2116 print_import_config(cb, vname, child[c], depth + 2);
2117 free(vname);
2118 }
2119
2120 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2121 &child, &children) == 0) {
2122 (void) printf(gettext("\tcache\n"));
2123 for (c = 0; c < children; c++) {
2124 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2125 cb->cb_name_flags);
2126 (void) printf("\t %s\n", vname);
2127 free(vname);
2128 }
2129 }
2130
2131 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
2132 &child, &children) == 0) {
2133 (void) printf(gettext("\tspares\n"));
2134 for (c = 0; c < children; c++) {
2135 vname = zpool_vdev_name(g_zfs, NULL, child[c],
2136 cb->cb_name_flags);
2137 (void) printf("\t %s\n", vname);
2138 free(vname);
2139 }
2140 }
2141 }
2142
2143 /*
2144 * Print specialized class vdevs.
2145 *
2146 * These are recorded as top level vdevs in the main pool child array
2147 * but with "is_log" set to 1 or an "alloc_bias" string. We use either
2148 * print_status_config() or print_import_config() to print the top level
2149 * class vdevs then any of their children (eg mirrored slogs) are printed
2150 * recursively - which works because only the top level vdev is marked.
2151 */
2152 static void
print_class_vdevs(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t * nv,const char * class)2153 print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
2154 const char *class)
2155 {
2156 uint_t c, children;
2157 nvlist_t **child;
2158 boolean_t printed = B_FALSE;
2159
2160 assert(zhp != NULL || !cb->cb_verbose);
2161
2162 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
2163 &children) != 0)
2164 return;
2165
2166 for (c = 0; c < children; c++) {
2167 uint64_t is_log = B_FALSE;
2168 char *bias = NULL;
2169 char *type = NULL;
2170
2171 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2172 &is_log);
2173
2174 if (is_log) {
2175 bias = VDEV_ALLOC_CLASS_LOGS;
2176 } else {
2177 (void) nvlist_lookup_string(child[c],
2178 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
2179 (void) nvlist_lookup_string(child[c],
2180 ZPOOL_CONFIG_TYPE, &type);
2181 }
2182
2183 if (bias == NULL || strcmp(bias, class) != 0)
2184 continue;
2185 if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
2186 continue;
2187
2188 if (!printed) {
2189 (void) printf("\t%s\t\n", gettext(class));
2190 printed = B_TRUE;
2191 }
2192
2193 char *name = zpool_vdev_name(g_zfs, zhp, child[c],
2194 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
2195 if (cb->cb_print_status)
2196 print_status_config(zhp, cb, name, child[c], 2,
2197 B_FALSE);
2198 else
2199 print_import_config(cb, name, child[c], 2);
2200 free(name);
2201 }
2202 }
2203
2204 /*
2205 * Display the status for the given pool.
2206 */
2207 static void
show_import(nvlist_t * config)2208 show_import(nvlist_t *config)
2209 {
2210 uint64_t pool_state;
2211 vdev_stat_t *vs;
2212 char *name;
2213 uint64_t guid;
2214 uint64_t hostid = 0;
2215 char *msgid;
2216 char *hostname = "unknown";
2217 nvlist_t *nvroot, *nvinfo;
2218 int reason;
2219 zpool_errata_t errata;
2220 const char *health;
2221 uint_t vsc;
2222 char *comment;
2223 status_cbdata_t cb = { 0 };
2224
2225 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2226 &name) == 0);
2227 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2228 &guid) == 0);
2229 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2230 &pool_state) == 0);
2231 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2232 &nvroot) == 0);
2233
2234 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
2235 (uint64_t **)&vs, &vsc) == 0);
2236 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2237
2238 reason = zpool_import_status(config, &msgid, &errata);
2239
2240 (void) printf(gettext(" pool: %s\n"), name);
2241 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
2242 (void) printf(gettext(" state: %s"), health);
2243 if (pool_state == POOL_STATE_DESTROYED)
2244 (void) printf(gettext(" (DESTROYED)"));
2245 (void) printf("\n");
2246
2247 switch (reason) {
2248 case ZPOOL_STATUS_MISSING_DEV_R:
2249 case ZPOOL_STATUS_MISSING_DEV_NR:
2250 case ZPOOL_STATUS_BAD_GUID_SUM:
2251 (void) printf(gettext(" status: One or more devices are "
2252 "missing from the system.\n"));
2253 break;
2254
2255 case ZPOOL_STATUS_CORRUPT_LABEL_R:
2256 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2257 (void) printf(gettext(" status: One or more devices contains "
2258 "corrupted data.\n"));
2259 break;
2260
2261 case ZPOOL_STATUS_CORRUPT_DATA:
2262 (void) printf(
2263 gettext(" status: The pool data is corrupted.\n"));
2264 break;
2265
2266 case ZPOOL_STATUS_OFFLINE_DEV:
2267 (void) printf(gettext(" status: One or more devices "
2268 "are offlined.\n"));
2269 break;
2270
2271 case ZPOOL_STATUS_CORRUPT_POOL:
2272 (void) printf(gettext(" status: The pool metadata is "
2273 "corrupted.\n"));
2274 break;
2275
2276 case ZPOOL_STATUS_VERSION_OLDER:
2277 (void) printf(gettext(" status: The pool is formatted using a "
2278 "legacy on-disk version.\n"));
2279 break;
2280
2281 case ZPOOL_STATUS_VERSION_NEWER:
2282 (void) printf(gettext(" status: The pool is formatted using an "
2283 "incompatible version.\n"));
2284 break;
2285
2286 case ZPOOL_STATUS_FEAT_DISABLED:
2287 (void) printf(gettext(" status: Some supported features are "
2288 "not enabled on the pool.\n"));
2289 break;
2290
2291 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2292 (void) printf(gettext("status: The pool uses the following "
2293 "feature(s) not supported on this system:\n"));
2294 zpool_print_unsup_feat(config);
2295 break;
2296
2297 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2298 (void) printf(gettext("status: The pool can only be accessed "
2299 "in read-only mode on this system. It\n\tcannot be "
2300 "accessed in read-write mode because it uses the "
2301 "following\n\tfeature(s) not supported on this system:\n"));
2302 zpool_print_unsup_feat(config);
2303 break;
2304
2305 case ZPOOL_STATUS_HOSTID_ACTIVE:
2306 (void) printf(gettext(" status: The pool is currently "
2307 "imported by another system.\n"));
2308 break;
2309
2310 case ZPOOL_STATUS_HOSTID_REQUIRED:
2311 (void) printf(gettext(" status: The pool has the "
2312 "multihost property on. It cannot\n\tbe safely imported "
2313 "when the system hostid is not set.\n"));
2314 break;
2315
2316 case ZPOOL_STATUS_HOSTID_MISMATCH:
2317 (void) printf(gettext(" status: The pool was last accessed by "
2318 "another system.\n"));
2319 break;
2320
2321 case ZPOOL_STATUS_FAULTED_DEV_R:
2322 case ZPOOL_STATUS_FAULTED_DEV_NR:
2323 (void) printf(gettext(" status: One or more devices are "
2324 "faulted.\n"));
2325 break;
2326
2327 case ZPOOL_STATUS_BAD_LOG:
2328 (void) printf(gettext(" status: An intent log record cannot be "
2329 "read.\n"));
2330 break;
2331
2332 case ZPOOL_STATUS_RESILVERING:
2333 (void) printf(gettext(" status: One or more devices were being "
2334 "resilvered.\n"));
2335 break;
2336
2337 case ZPOOL_STATUS_ERRATA:
2338 (void) printf(gettext(" status: Errata #%d detected.\n"),
2339 errata);
2340 break;
2341
2342 default:
2343 /*
2344 * No other status can be seen when importing pools.
2345 */
2346 assert(reason == ZPOOL_STATUS_OK);
2347 }
2348
2349 /*
2350 * Print out an action according to the overall state of the pool.
2351 */
2352 if (vs->vs_state == VDEV_STATE_HEALTHY) {
2353 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2354 reason == ZPOOL_STATUS_FEAT_DISABLED) {
2355 (void) printf(gettext(" action: The pool can be "
2356 "imported using its name or numeric identifier, "
2357 "though\n\tsome features will not be available "
2358 "without an explicit 'zpool upgrade'.\n"));
2359 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
2360 (void) printf(gettext(" action: The pool can be "
2361 "imported using its name or numeric "
2362 "identifier and\n\tthe '-f' flag.\n"));
2363 } else if (reason == ZPOOL_STATUS_ERRATA) {
2364 switch (errata) {
2365 case ZPOOL_ERRATA_NONE:
2366 break;
2367
2368 case ZPOOL_ERRATA_ZOL_2094_SCRUB:
2369 (void) printf(gettext(" action: The pool can "
2370 "be imported using its name or numeric "
2371 "identifier,\n\thowever there is a compat"
2372 "ibility issue which should be corrected"
2373 "\n\tby running 'zpool scrub'\n"));
2374 break;
2375
2376 case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
2377 (void) printf(gettext(" action: The pool can"
2378 "not be imported with this version of ZFS "
2379 "due to\n\tan active asynchronous destroy. "
2380 "Revert to an earlier version\n\tand "
2381 "allow the destroy to complete before "
2382 "updating.\n"));
2383 break;
2384
2385 case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
2386 (void) printf(gettext(" action: Existing "
2387 "encrypted datasets contain an on-disk "
2388 "incompatibility, which\n\tneeds to be "
2389 "corrected. Backup these datasets to new "
2390 "encrypted datasets\n\tand destroy the "
2391 "old ones.\n"));
2392 break;
2393 case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
2394 (void) printf(gettext(" action: Any existing "
2395 "encrypted datasets contain an on-disk "
2396 "incompatibility which\n\tmay cause "
2397 "on-disk corruption with 'zfs recv' and "
2398 "which needs to be\n\tcorrected. Enable "
2399 "the bookmark_v2 feature and backup "
2400 "these datasets to new encrypted "
2401 "datasets and\n\tdestroy the old ones. "
2402 "If this pool does not contain any "
2403 "encrypted datasets, simply enable\n\t"
2404 "the bookmark_v2 feature.\n"));
2405 break;
2406 default:
2407 /*
2408 * All errata must contain an action message.
2409 */
2410 assert(0);
2411 }
2412 } else {
2413 (void) printf(gettext(" action: The pool can be "
2414 "imported using its name or numeric "
2415 "identifier.\n"));
2416 }
2417 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2418 (void) printf(gettext(" action: The pool can be imported "
2419 "despite missing or damaged devices. The\n\tfault "
2420 "tolerance of the pool may be compromised if imported.\n"));
2421 } else {
2422 switch (reason) {
2423 case ZPOOL_STATUS_VERSION_NEWER:
2424 (void) printf(gettext(" action: The pool cannot be "
2425 "imported. Access the pool on a system running "
2426 "newer\n\tsoftware, or recreate the pool from "
2427 "backup.\n"));
2428 break;
2429 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2430 (void) printf(gettext("action: The pool cannot be "
2431 "imported. Access the pool on a system that "
2432 "supports\n\tthe required feature(s), or recreate "
2433 "the pool from backup.\n"));
2434 break;
2435 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2436 (void) printf(gettext("action: The pool cannot be "
2437 "imported in read-write mode. Import the pool "
2438 "with\n"
2439 "\t\"-o readonly=on\", access the pool on a system "
2440 "that supports the\n\trequired feature(s), or "
2441 "recreate the pool from backup.\n"));
2442 break;
2443 case ZPOOL_STATUS_MISSING_DEV_R:
2444 case ZPOOL_STATUS_MISSING_DEV_NR:
2445 case ZPOOL_STATUS_BAD_GUID_SUM:
2446 (void) printf(gettext(" action: The pool cannot be "
2447 "imported. Attach the missing\n\tdevices and try "
2448 "again.\n"));
2449 break;
2450 case ZPOOL_STATUS_HOSTID_ACTIVE:
2451 VERIFY0(nvlist_lookup_nvlist(config,
2452 ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
2453
2454 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2455 hostname = fnvlist_lookup_string(nvinfo,
2456 ZPOOL_CONFIG_MMP_HOSTNAME);
2457
2458 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2459 hostid = fnvlist_lookup_uint64(nvinfo,
2460 ZPOOL_CONFIG_MMP_HOSTID);
2461
2462 (void) printf(gettext(" action: The pool must be "
2463 "exported from %s (hostid=%lx)\n\tbefore it "
2464 "can be safely imported.\n"), hostname,
2465 (unsigned long) hostid);
2466 break;
2467 case ZPOOL_STATUS_HOSTID_REQUIRED:
2468 (void) printf(gettext(" action: Check the SMF "
2469 "svc:/system/hostid service.\n"));
2470 break;
2471 default:
2472 (void) printf(gettext(" action: The pool cannot be "
2473 "imported due to damaged devices or data.\n"));
2474 }
2475 }
2476
2477 /* Print the comment attached to the pool. */
2478 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2479 (void) printf(gettext("comment: %s\n"), comment);
2480
2481 /*
2482 * If the state is "closed" or "can't open", and the aux state
2483 * is "corrupt data":
2484 */
2485 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2486 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2487 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2488 if (pool_state == POOL_STATE_DESTROYED)
2489 (void) printf(gettext("\tThe pool was destroyed, "
2490 "but can be imported using the '-Df' flags.\n"));
2491 else if (pool_state != POOL_STATE_EXPORTED)
2492 (void) printf(gettext("\tThe pool may be active on "
2493 "another system, but can be imported using\n\t"
2494 "the '-f' flag.\n"));
2495 }
2496
2497 if (msgid != NULL)
2498 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
2499 msgid);
2500
2501 (void) printf(gettext(" config:\n\n"));
2502
2503 cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
2504 VDEV_NAME_TYPE_ID);
2505 if (cb.cb_namewidth < 10)
2506 cb.cb_namewidth = 10;
2507
2508 print_import_config(&cb, name, nvroot, 0);
2509
2510 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
2511 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
2512 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
2513
2514 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2515 (void) printf(gettext("\n\tAdditional devices are known to "
2516 "be part of this pool, though their\n\texact "
2517 "configuration cannot be determined.\n"));
2518 }
2519 }
2520
2521 static boolean_t
zfs_force_import_required(nvlist_t * config)2522 zfs_force_import_required(nvlist_t *config)
2523 {
2524 uint64_t state;
2525 uint64_t hostid = 0;
2526 nvlist_t *nvinfo;
2527
2528 state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
2529 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
2530
2531 if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
2532 return (B_TRUE);
2533
2534 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2535 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
2536 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
2537 ZPOOL_CONFIG_MMP_STATE);
2538
2539 if (mmp_state != MMP_STATE_INACTIVE)
2540 return (B_TRUE);
2541 }
2542
2543 return (B_FALSE);
2544 }
2545
2546 /*
2547 * Perform the import for the given configuration. This passes the heavy
2548 * lifting off to zpool_import_props(), and then mounts the datasets contained
2549 * within the pool.
2550 */
2551 static int
do_import(nvlist_t * config,const char * newname,const char * mntopts,nvlist_t * props,int flags)2552 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2553 nvlist_t *props, int flags)
2554 {
2555 int ret = 0;
2556 zpool_handle_t *zhp;
2557 char *name;
2558 uint64_t version;
2559
2560 name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
2561 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
2562
2563 if (!SPA_VERSION_IS_SUPPORTED(version)) {
2564 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2565 "is formatted using an unsupported ZFS version\n"), name);
2566 return (1);
2567 } else if (zfs_force_import_required(config) &&
2568 !(flags & ZFS_IMPORT_ANY_HOST)) {
2569 mmp_state_t mmp_state = MMP_STATE_INACTIVE;
2570 nvlist_t *nvinfo;
2571
2572 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2573 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
2574 mmp_state = fnvlist_lookup_uint64(nvinfo,
2575 ZPOOL_CONFIG_MMP_STATE);
2576
2577 if (mmp_state == MMP_STATE_ACTIVE) {
2578 char *hostname = "<unknown>";
2579 uint64_t hostid = 0;
2580
2581 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2582 hostname = fnvlist_lookup_string(nvinfo,
2583 ZPOOL_CONFIG_MMP_HOSTNAME);
2584
2585 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2586 hostid = fnvlist_lookup_uint64(nvinfo,
2587 ZPOOL_CONFIG_MMP_HOSTID);
2588
2589 (void) fprintf(stderr, gettext("cannot import '%s': "
2590 "pool is imported on %s (hostid: "
2591 "0x%lx)\nExport the pool on the other system, "
2592 "then run 'zpool import'.\n"),
2593 name, hostname, (unsigned long) hostid);
2594 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2595 (void) fprintf(stderr, gettext("Cannot import '%s': "
2596 "pool has the multihost property on and the\n"
2597 "system's hostid is not set.\n"), name);
2598 } else {
2599 char *hostname = "<unknown>";
2600 uint64_t timestamp = 0;
2601 uint64_t hostid = 0;
2602
2603 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
2604 hostname = fnvlist_lookup_string(config,
2605 ZPOOL_CONFIG_HOSTNAME);
2606
2607 if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
2608 timestamp = fnvlist_lookup_uint64(config,
2609 ZPOOL_CONFIG_TIMESTAMP);
2610
2611 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
2612 hostid = fnvlist_lookup_uint64(config,
2613 ZPOOL_CONFIG_HOSTID);
2614
2615 (void) fprintf(stderr, gettext("cannot import '%s': "
2616 "pool was previously in use from another system.\n"
2617 "Last accessed by %s (hostid=%lx) at %s"
2618 "The pool can be imported, use 'zpool import -f' "
2619 "to import the pool.\n"), name, hostname,
2620 (unsigned long)hostid, ctime((time_t *)×tamp));
2621
2622 }
2623
2624 return (1);
2625 }
2626
2627 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2628 return (1);
2629
2630 if (newname != NULL)
2631 name = (char *)newname;
2632
2633 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2634 return (1);
2635
2636 /*
2637 * Loading keys is best effort. We don't want to return immediately
2638 * if it fails but we do want to give the error to the caller.
2639 */
2640 if (flags & ZFS_IMPORT_LOAD_KEYS) {
2641 ret = zfs_crypto_attempt_load_keys(g_zfs, name);
2642 if (ret != 0)
2643 ret = 1;
2644 }
2645
2646 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2647 !(flags & ZFS_IMPORT_ONLY) &&
2648 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2649 zpool_close(zhp);
2650 return (1);
2651 }
2652
2653 zpool_close(zhp);
2654 return (ret);
2655 }
2656
2657 typedef struct target_exists_args {
2658 const char *poolname;
2659 uint64_t poolguid;
2660 } target_exists_args_t;
2661
2662 static int
name_or_guid_exists(zpool_handle_t * zhp,void * data)2663 name_or_guid_exists(zpool_handle_t *zhp, void *data)
2664 {
2665 target_exists_args_t *args = data;
2666 nvlist_t *config = zpool_get_config(zhp, NULL);
2667 int found = 0;
2668
2669 if (config == NULL)
2670 return (0);
2671
2672 if (args->poolname != NULL) {
2673 char *pool_name;
2674
2675 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2676 &pool_name) == 0);
2677 if (strcmp(pool_name, args->poolname) == 0)
2678 found = 1;
2679 } else {
2680 uint64_t pool_guid;
2681
2682 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2683 &pool_guid) == 0);
2684 if (pool_guid == args->poolguid)
2685 found = 1;
2686 }
2687 zpool_close(zhp);
2688
2689 return (found);
2690 }
2691 /*
2692 * zpool checkpoint <pool>
2693 * checkpoint --discard <pool>
2694 *
2695 * -d Discard the checkpoint from a checkpointed
2696 * --discard pool.
2697 *
2698 * Checkpoints the specified pool, by taking a "snapshot" of its
2699 * current state. A pool can only have one checkpoint at a time.
2700 */
2701 int
zpool_do_checkpoint(int argc,char ** argv)2702 zpool_do_checkpoint(int argc, char **argv)
2703 {
2704 boolean_t discard;
2705 char *pool;
2706 zpool_handle_t *zhp;
2707 int c, err;
2708
2709 struct option long_options[] = {
2710 {"discard", no_argument, NULL, 'd'},
2711 {0, 0, 0, 0}
2712 };
2713
2714 discard = B_FALSE;
2715 while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2716 switch (c) {
2717 case 'd':
2718 discard = B_TRUE;
2719 break;
2720 case '?':
2721 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2722 optopt);
2723 usage(B_FALSE);
2724 }
2725 }
2726
2727 argc -= optind;
2728 argv += optind;
2729
2730 if (argc < 1) {
2731 (void) fprintf(stderr, gettext("missing pool argument\n"));
2732 usage(B_FALSE);
2733 }
2734
2735 if (argc > 1) {
2736 (void) fprintf(stderr, gettext("too many arguments\n"));
2737 usage(B_FALSE);
2738 }
2739
2740 pool = argv[0];
2741
2742 if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2743 /* As a special case, check for use of '/' in the name */
2744 if (strchr(pool, '/') != NULL)
2745 (void) fprintf(stderr, gettext("'zpool checkpoint' "
2746 "doesn't work on datasets. To save the state "
2747 "of a dataset from a specific point in time "
2748 "please use 'zfs snapshot'\n"));
2749 return (1);
2750 }
2751
2752 if (discard)
2753 err = (zpool_discard_checkpoint(zhp) != 0);
2754 else
2755 err = (zpool_checkpoint(zhp) != 0);
2756
2757 zpool_close(zhp);
2758
2759 return (err);
2760 }
2761
2762 #define CHECKPOINT_OPT 1024
2763
2764 /*
2765 * zpool import [-d dir] [-D]
2766 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
2767 * [-d dir | -c cachefile] [-f] -a
2768 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
2769 * [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
2770 * <pool | id> [newpool]
2771 *
2772 * -c Read pool information from a cachefile instead of searching
2773 * devices.
2774 *
2775 * -d Scan in a specific directory, other than /dev/dsk. More than
2776 * one directory can be specified using multiple '-d' options.
2777 *
2778 * -D Scan for previously destroyed pools or import all or only
2779 * specified destroyed pools.
2780 *
2781 * -R Temporarily import the pool, with all mountpoints relative to
2782 * the given root. The pool will remain exported when the machine
2783 * is rebooted.
2784 *
2785 * -V Import even in the presence of faulted vdevs. This is an
2786 * intentionally undocumented option for testing purposes, and
2787 * treats the pool configuration as complete, leaving any bad
2788 * vdevs in the FAULTED state. In other words, it does verbatim
2789 * import.
2790 *
2791 * -f Force import, even if it appears that the pool is active.
2792 *
2793 * -F Attempt rewind if necessary.
2794 *
2795 * -n See if rewind would work, but don't actually rewind.
2796 *
2797 * -N Import the pool but don't mount datasets.
2798 *
2799 * -t Use newpool as a temporary pool name instead of renaming
2800 * the pool.
2801 *
2802 * -T Specify a starting txg to use for import. This option is
2803 * intentionally undocumented option for testing purposes.
2804 *
2805 * -a Import all pools found.
2806 *
2807 * -o Set property=value and/or temporary mount options (without '=').
2808 * -l Load encryption keys while importing.
2809 *
2810 * --rewind-to-checkpoint
2811 * Import the pool and revert back to the checkpoint.
2812 *
2813 * The import command scans for pools to import, and import pools based on pool
2814 * name and GUID. The pool can also be renamed as part of the import process.
2815 */
2816 int
zpool_do_import(int argc,char ** argv)2817 zpool_do_import(int argc, char **argv)
2818 {
2819 char **searchdirs = NULL;
2820 int nsearch = 0;
2821 int c;
2822 int err = 0;
2823 nvlist_t *pools = NULL;
2824 boolean_t do_all = B_FALSE;
2825 boolean_t do_destroyed = B_FALSE;
2826 char *mntopts = NULL;
2827 nvpair_t *elem;
2828 nvlist_t *config;
2829 uint64_t searchguid = 0;
2830 char *searchname = NULL;
2831 char *propval;
2832 nvlist_t *found_config;
2833 nvlist_t *policy = NULL;
2834 nvlist_t *props = NULL;
2835 boolean_t first;
2836 int flags = ZFS_IMPORT_NORMAL;
2837 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2838 boolean_t dryrun = B_FALSE;
2839 boolean_t do_rewind = B_FALSE;
2840 boolean_t xtreme_rewind = B_FALSE;
2841 boolean_t pool_exists = B_FALSE;
2842 uint64_t pool_state, txg = -1ULL;
2843 char *cachefile = NULL;
2844 importargs_t idata = { 0 };
2845 char *endptr;
2846
2847
2848 struct option long_options[] = {
2849 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2850 {0, 0, 0, 0}
2851 };
2852
2853 /* check options */
2854 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX",
2855 long_options, NULL)) != -1) {
2856 switch (c) {
2857 case 'a':
2858 do_all = B_TRUE;
2859 break;
2860 case 'c':
2861 cachefile = optarg;
2862 break;
2863 case 'd':
2864 if (searchdirs == NULL) {
2865 searchdirs = safe_malloc(sizeof (char *));
2866 } else {
2867 char **tmp = safe_malloc((nsearch + 1) *
2868 sizeof (char *));
2869 bcopy(searchdirs, tmp, nsearch *
2870 sizeof (char *));
2871 free(searchdirs);
2872 searchdirs = tmp;
2873 }
2874 searchdirs[nsearch++] = optarg;
2875 break;
2876 case 'D':
2877 do_destroyed = B_TRUE;
2878 break;
2879 case 'f':
2880 flags |= ZFS_IMPORT_ANY_HOST;
2881 break;
2882 case 'F':
2883 do_rewind = B_TRUE;
2884 break;
2885 case 'l':
2886 flags |= ZFS_IMPORT_LOAD_KEYS;
2887 break;
2888 case 'm':
2889 flags |= ZFS_IMPORT_MISSING_LOG;
2890 break;
2891 case 'n':
2892 dryrun = B_TRUE;
2893 break;
2894 case 'N':
2895 flags |= ZFS_IMPORT_ONLY;
2896 break;
2897 case 'o':
2898 if ((propval = strchr(optarg, '=')) != NULL) {
2899 *propval = '\0';
2900 propval++;
2901 if (add_prop_list(optarg, propval,
2902 &props, B_TRUE))
2903 goto error;
2904 } else {
2905 mntopts = optarg;
2906 }
2907 break;
2908 case 'R':
2909 if (add_prop_list(zpool_prop_to_name(
2910 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2911 goto error;
2912 if (add_prop_list_default(zpool_prop_to_name(
2913 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2914 goto error;
2915 break;
2916 case 't':
2917 flags |= ZFS_IMPORT_TEMP_NAME;
2918 if (add_prop_list_default(zpool_prop_to_name(
2919 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2920 goto error;
2921 break;
2922 case 'T':
2923 errno = 0;
2924 txg = strtoull(optarg, &endptr, 0);
2925 if (errno != 0 || *endptr != '\0') {
2926 (void) fprintf(stderr,
2927 gettext("invalid txg value\n"));
2928 usage(B_FALSE);
2929 }
2930 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2931 break;
2932 case 'V':
2933 flags |= ZFS_IMPORT_VERBATIM;
2934 break;
2935 case 'X':
2936 xtreme_rewind = B_TRUE;
2937 break;
2938 case CHECKPOINT_OPT:
2939 flags |= ZFS_IMPORT_CHECKPOINT;
2940 break;
2941 case ':':
2942 (void) fprintf(stderr, gettext("missing argument for "
2943 "'%c' option\n"), optopt);
2944 usage(B_FALSE);
2945 break;
2946 case '?':
2947 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2948 optopt);
2949 usage(B_FALSE);
2950 }
2951 }
2952
2953 argc -= optind;
2954 argv += optind;
2955
2956 if (cachefile && nsearch != 0) {
2957 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2958 usage(B_FALSE);
2959 }
2960
2961 if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
2962 (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
2963 usage(B_FALSE);
2964 }
2965
2966 if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
2967 (void) fprintf(stderr, gettext("-l is only meaningful during "
2968 "an import\n"));
2969 usage(B_FALSE);
2970 }
2971
2972 if ((dryrun || xtreme_rewind) && !do_rewind) {
2973 (void) fprintf(stderr,
2974 gettext("-n or -X only meaningful with -F\n"));
2975 usage(B_FALSE);
2976 }
2977 if (dryrun)
2978 rewind_policy = ZPOOL_TRY_REWIND;
2979 else if (do_rewind)
2980 rewind_policy = ZPOOL_DO_REWIND;
2981 if (xtreme_rewind)
2982 rewind_policy |= ZPOOL_EXTREME_REWIND;
2983
2984 /* In the future, we can capture further policy and include it here */
2985 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2986 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
2987 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
2988 rewind_policy) != 0)
2989 goto error;
2990
2991 if (searchdirs == NULL) {
2992 searchdirs = safe_malloc(sizeof (char *));
2993 searchdirs[0] = ZFS_DISK_ROOT;
2994 nsearch = 1;
2995 }
2996
2997 /* check argument count */
2998 if (do_all) {
2999 if (argc != 0) {
3000 (void) fprintf(stderr, gettext("too many arguments\n"));
3001 usage(B_FALSE);
3002 }
3003 } else {
3004 if (argc > 2) {
3005 (void) fprintf(stderr, gettext("too many arguments\n"));
3006 usage(B_FALSE);
3007 }
3008
3009 /*
3010 * Check for the SYS_CONFIG privilege. We do this explicitly
3011 * here because otherwise any attempt to discover pools will
3012 * silently fail.
3013 */
3014 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
3015 (void) fprintf(stderr, gettext("cannot "
3016 "discover pools: permission denied\n"));
3017 free(searchdirs);
3018 nvlist_free(policy);
3019 return (1);
3020 }
3021 }
3022
3023 /*
3024 * Depending on the arguments given, we do one of the following:
3025 *
3026 * <none> Iterate through all pools and display information about
3027 * each one.
3028 *
3029 * -a Iterate through all pools and try to import each one.
3030 *
3031 * <id> Find the pool that corresponds to the given GUID/pool
3032 * name and import that one.
3033 *
3034 * -D Above options applies only to destroyed pools.
3035 */
3036 if (argc != 0) {
3037 char *endptr;
3038
3039 errno = 0;
3040 searchguid = strtoull(argv[0], &endptr, 10);
3041 if (errno != 0 || *endptr != '\0') {
3042 searchname = argv[0];
3043 searchguid = 0;
3044 }
3045 found_config = NULL;
3046
3047 /*
3048 * User specified a name or guid. Ensure it's unique.
3049 */
3050 target_exists_args_t search = {searchname, searchguid};
3051 pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search);
3052 }
3053
3054 idata.path = searchdirs;
3055 idata.paths = nsearch;
3056 idata.poolname = searchname;
3057 idata.guid = searchguid;
3058 idata.cachefile = cachefile;
3059 idata.policy = policy;
3060
3061 pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
3062
3063 if (pools != NULL && pool_exists &&
3064 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
3065 (void) fprintf(stderr, gettext("cannot import '%s': "
3066 "a pool with that name already exists\n"),
3067 argv[0]);
3068 (void) fprintf(stderr, gettext("use the form 'zpool import "
3069 "[-t] <pool | id> <newpool>' to give it a new temporary "
3070 "or permanent name\n"));
3071 err = 1;
3072 } else if (pools == NULL && pool_exists) {
3073 (void) fprintf(stderr, gettext("cannot import '%s': "
3074 "a pool with that name is already created/imported,\n"),
3075 argv[0]);
3076 (void) fprintf(stderr, gettext("and no additional pools "
3077 "with that name were found\n"));
3078 err = 1;
3079 } else if (pools == NULL) {
3080 if (argc != 0) {
3081 (void) fprintf(stderr, gettext("cannot import '%s': "
3082 "no such pool available\n"), argv[0]);
3083 }
3084 err = 1;
3085 }
3086
3087 if (err == 1) {
3088 free(searchdirs);
3089 nvlist_free(policy);
3090 return (1);
3091 }
3092
3093 /*
3094 * At this point we have a list of import candidate configs. Even if
3095 * we were searching by pool name or guid, we still need to
3096 * post-process the list to deal with pool state and possible
3097 * duplicate names.
3098 */
3099 err = 0;
3100 elem = NULL;
3101 first = B_TRUE;
3102 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
3103
3104 verify(nvpair_value_nvlist(elem, &config) == 0);
3105
3106 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
3107 &pool_state) == 0);
3108 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
3109 continue;
3110 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
3111 continue;
3112
3113 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
3114 policy) == 0);
3115
3116 if (argc == 0) {
3117 if (first)
3118 first = B_FALSE;
3119 else if (!do_all)
3120 (void) printf("\n");
3121
3122 if (do_all) {
3123 err |= do_import(config, NULL, mntopts,
3124 props, flags);
3125 } else {
3126 show_import(config);
3127 }
3128 } else if (searchname != NULL) {
3129 char *name;
3130
3131 /*
3132 * We are searching for a pool based on name.
3133 */
3134 verify(nvlist_lookup_string(config,
3135 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
3136
3137 if (strcmp(name, searchname) == 0) {
3138 if (found_config != NULL) {
3139 (void) fprintf(stderr, gettext(
3140 "cannot import '%s': more than "
3141 "one matching pool\n"), searchname);
3142 (void) fprintf(stderr, gettext(
3143 "import by numeric ID instead\n"));
3144 err = B_TRUE;
3145 }
3146 found_config = config;
3147 }
3148 } else {
3149 uint64_t guid;
3150
3151 /*
3152 * Search for a pool by guid.
3153 */
3154 verify(nvlist_lookup_uint64(config,
3155 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
3156
3157 if (guid == searchguid)
3158 found_config = config;
3159 }
3160 }
3161
3162 /*
3163 * If we were searching for a specific pool, verify that we found a
3164 * pool, and then do the import.
3165 */
3166 if (argc != 0 && err == 0) {
3167 if (found_config == NULL) {
3168 (void) fprintf(stderr, gettext("cannot import '%s': "
3169 "no such pool available\n"), argv[0]);
3170 err = B_TRUE;
3171 } else {
3172 err |= do_import(found_config, argc == 1 ? NULL :
3173 argv[1], mntopts, props, flags);
3174 }
3175 }
3176
3177 /*
3178 * If we were just looking for pools, report an error if none were
3179 * found.
3180 */
3181 if (argc == 0 && first)
3182 (void) fprintf(stderr,
3183 gettext("no pools available to import\n"));
3184
3185 error:
3186 nvlist_free(props);
3187 nvlist_free(pools);
3188 nvlist_free(policy);
3189 free(searchdirs);
3190
3191 return (err ? 1 : 0);
3192 }
3193
3194 /*
3195 * zpool sync [-f] [pool] ...
3196 *
3197 * -f (undocumented) force uberblock (and config including zpool cache file)
3198 * update.
3199 *
3200 * Sync the specified pool(s).
3201 * Without arguments "zpool sync" will sync all pools.
3202 * This command initiates TXG sync(s) and will return after the TXG(s) commit.
3203 *
3204 */
3205 static int
zpool_do_sync(int argc,char ** argv)3206 zpool_do_sync(int argc, char **argv)
3207 {
3208 int ret;
3209 boolean_t force = B_FALSE;
3210
3211 /* check options */
3212 while ((ret = getopt(argc, argv, "f")) != -1) {
3213 switch (ret) {
3214 case 'f':
3215 force = B_TRUE;
3216 break;
3217 case '?':
3218 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3219 optopt);
3220 usage(B_FALSE);
3221 }
3222 }
3223
3224 argc -= optind;
3225 argv += optind;
3226
3227 /* if argc == 0 we will execute zpool_sync_one on all pools */
3228 ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);
3229
3230 return (ret);
3231 }
3232
3233 typedef struct iostat_cbdata {
3234 uint64_t cb_flags;
3235 int cb_name_flags;
3236 int cb_namewidth;
3237 int cb_iteration;
3238 char **cb_vdev_names; /* Only show these vdevs */
3239 unsigned int cb_vdev_names_count;
3240 boolean_t cb_verbose;
3241 boolean_t cb_literal;
3242 boolean_t cb_scripted;
3243 zpool_list_t *cb_list;
3244 } iostat_cbdata_t;
3245
3246 /* iostat labels */
3247 typedef struct name_and_columns {
3248 const char *name; /* Column name */
3249 unsigned int columns; /* Center name to this number of columns */
3250 } name_and_columns_t;
3251
3252 #define IOSTAT_MAX_LABELS 13 /* Max number of labels on one line */
3253
3254 static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
3255 {
3256 [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2},
3257 {NULL}},
3258 [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3259 {"asyncq_wait", 2}, {"scrub"}, {"trim", 1}, {NULL}},
3260 [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
3261 {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
3262 {"trimq_write", 2}, {NULL}},
3263 [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2},
3264 {"asyncq_wait", 2}, {NULL}},
3265 [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
3266 {"async_read", 2}, {"async_write", 2}, {"scrub", 2},
3267 {"trim", 2}, {NULL}},
3268
3269 };
3270
3271 /* Shorthand - if "columns" field not set, default to 1 column */
3272 static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
3273 {
3274 [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"},
3275 {"write"}, {NULL}},
3276 [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3277 {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {NULL}},
3278 [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
3279 {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"},
3280 {"pend"}, {"activ"}, {NULL}},
3281 [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
3282 {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {NULL}},
3283 [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
3284 {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, {NULL}},
3285 };
3286
3287 static const char *histo_to_title[] = {
3288 [IOS_L_HISTO] = "latency",
3289 [IOS_RQ_HISTO] = "req_size",
3290 };
3291
3292 /*
3293 * Return the number of labels in a null-terminated name_and_columns_t
3294 * array.
3295 *
3296 */
3297 static unsigned int
label_array_len(const name_and_columns_t * labels)3298 label_array_len(const name_and_columns_t *labels)
3299 {
3300 int i = 0;
3301
3302 while (labels[i].name)
3303 i++;
3304
3305 return (i);
3306 }
3307
3308 /*
3309 * Return the number of strings in a null-terminated string array.
3310 * For example:
3311 *
3312 * const char foo[] = {"bar", "baz", NULL}
3313 *
3314 * returns 2
3315 */
3316 static uint64_t
str_array_len(const char * array[])3317 str_array_len(const char *array[])
3318 {
3319 uint64_t i = 0;
3320 while (array[i])
3321 i++;
3322
3323 return (i);
3324 }
3325
3326
3327 /*
3328 * Return a default column width for default/latency/queue columns. This does
3329 * not include histograms, which have their columns autosized.
3330 */
3331 static unsigned int
default_column_width(iostat_cbdata_t * cb,enum iostat_type type)3332 default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
3333 {
3334 unsigned long column_width = 5; /* Normal niceprint */
3335 static unsigned long widths[] = {
3336 /*
3337 * Choose some sane default column sizes for printing the
3338 * raw numbers.
3339 */
3340 [IOS_DEFAULT] = 15, /* 1PB capacity */
3341 [IOS_LATENCY] = 10, /* 1B ns = 10sec */
3342 [IOS_QUEUES] = 6, /* 1M queue entries */
3343 [IOS_L_HISTO] = 10, /* 1B ns = 10sec */
3344 [IOS_RQ_HISTO] = 6, /* 1M queue entries */
3345 };
3346
3347 if (cb->cb_literal)
3348 column_width = widths[type];
3349
3350 return (column_width);
3351 }
3352
3353 /*
3354 * Print the column labels, i.e:
3355 *
3356 * capacity operations bandwidth
3357 * alloc free read write read write ...
3358 *
3359 * If force_column_width is set, use it for the column width. If not set, use
3360 * the default column width.
3361 */
3362 void
print_iostat_labels(iostat_cbdata_t * cb,unsigned int force_column_width,const name_and_columns_t labels[][IOSTAT_MAX_LABELS])3363 print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width,
3364 const name_and_columns_t labels[][IOSTAT_MAX_LABELS])
3365 {
3366 int i, idx, s;
3367 int text_start, rw_column_width, spaces_to_end;
3368 uint64_t flags = cb->cb_flags;
3369 uint64_t f;
3370 unsigned int column_width = force_column_width;
3371
3372 /* For each bit set in flags */
3373 for (f = flags; f; f &= ~(1ULL << idx)) {
3374 idx = lowbit64(f) - 1;
3375 if (!force_column_width)
3376 column_width = default_column_width(cb, idx);
3377 /* Print our top labels centered over "read write" label. */
3378 for (i = 0; i < label_array_len(labels[idx]); i++) {
3379 const char *name = labels[idx][i].name;
3380 /*
3381 * We treat labels[][].columns == 0 as shorthand
3382 * for one column. It makes writing out the label
3383 * tables more concise.
3384 */
3385 unsigned int columns = MAX(1, labels[idx][i].columns);
3386 unsigned int slen = strlen(name);
3387
3388 rw_column_width = (column_width * columns) +
3389 (2 * (columns - 1));
3390
3391 text_start = (int)((rw_column_width) / columns -
3392 slen / columns);
3393 if (text_start < 0)
3394 text_start = 0;
3395
3396 printf(" "); /* Two spaces between columns */
3397
3398 /* Space from beginning of column to label */
3399 for (s = 0; s < text_start; s++)
3400 printf(" ");
3401
3402 printf("%s", name);
3403
3404 /* Print space after label to end of column */
3405 spaces_to_end = rw_column_width - text_start - slen;
3406 if (spaces_to_end < 0)
3407 spaces_to_end = 0;
3408
3409 for (s = 0; s < spaces_to_end; s++)
3410 printf(" ");
3411 }
3412 }
3413 }
3414
3415 /*
3416 * Utility function to print out a line of dashes like:
3417 *
3418 * -------------------------------- ----- ----- ----- ----- -----
3419 *
3420 * ...or a dashed named-row line like:
3421 *
3422 * logs - - - - -
3423 *
3424 * @cb: iostat data
3425 *
3426 * @force_column_width If non-zero, use the value as the column width.
3427 * Otherwise use the default column widths.
3428 *
3429 * @name: Print a dashed named-row line starting
3430 * with @name. Otherwise, print a regular
3431 * dashed line.
3432 */
3433 static void
print_iostat_dashes(iostat_cbdata_t * cb,unsigned int force_column_width,const char * name)3434 print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width,
3435 const char *name)
3436 {
3437 int i;
3438 unsigned int namewidth;
3439 uint64_t flags = cb->cb_flags;
3440 uint64_t f;
3441 int idx;
3442 const name_and_columns_t *labels;
3443 const char *title;
3444
3445
3446 if (cb->cb_flags & IOS_ANYHISTO_M) {
3447 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3448 } else if (cb->cb_vdev_names_count) {
3449 title = "vdev";
3450 } else {
3451 title = "pool";
3452 }
3453
3454 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3455 name ? strlen(name) : 0);
3456
3457
3458 if (name) {
3459 printf("%-*s", namewidth, name);
3460 } else {
3461 for (i = 0; i < namewidth; i++)
3462 (void) printf("-");
3463 }
3464
3465 /* For each bit in flags */
3466 for (f = flags; f; f &= ~(1ULL << idx)) {
3467 unsigned int column_width;
3468 idx = lowbit64(f) - 1;
3469 if (force_column_width)
3470 column_width = force_column_width;
3471 else
3472 column_width = default_column_width(cb, idx);
3473
3474 labels = iostat_bottom_labels[idx];
3475 for (i = 0; i < label_array_len(labels); i++) {
3476 if (name)
3477 printf(" %*s-", column_width - 1, " ");
3478 else
3479 printf(" %.*s", column_width,
3480 "--------------------");
3481 }
3482 }
3483 }
3484
3485
3486 static void
print_iostat_separator_impl(iostat_cbdata_t * cb,unsigned int force_column_width)3487 print_iostat_separator_impl(iostat_cbdata_t *cb,
3488 unsigned int force_column_width)
3489 {
3490 print_iostat_dashes(cb, force_column_width, NULL);
3491 }
3492
3493 static void
print_iostat_separator(iostat_cbdata_t * cb)3494 print_iostat_separator(iostat_cbdata_t *cb)
3495 {
3496 print_iostat_separator_impl(cb, 0);
3497 }
3498
3499 static void
print_iostat_header_impl(iostat_cbdata_t * cb,unsigned int force_column_width,const char * histo_vdev_name)3500 print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width,
3501 const char *histo_vdev_name)
3502 {
3503 unsigned int namewidth;
3504 const char *title;
3505
3506 if (cb->cb_flags & IOS_ANYHISTO_M) {
3507 title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)];
3508 } else if (cb->cb_vdev_names_count) {
3509 title = "vdev";
3510 } else {
3511 title = "pool";
3512 }
3513
3514 namewidth = MAX(MAX(strlen(title), cb->cb_namewidth),
3515 histo_vdev_name ? strlen(histo_vdev_name) : 0);
3516
3517 if (histo_vdev_name)
3518 printf("%-*s", namewidth, histo_vdev_name);
3519 else
3520 printf("%*s", namewidth, "");
3521
3522
3523 print_iostat_labels(cb, force_column_width, iostat_top_labels);
3524 printf("\n");
3525
3526 printf("%-*s", namewidth, title);
3527
3528 print_iostat_labels(cb, force_column_width, iostat_bottom_labels);
3529
3530 printf("\n");
3531
3532 print_iostat_separator_impl(cb, force_column_width);
3533
3534 printf("\n");
3535 }
3536
3537 static void
print_iostat_header(iostat_cbdata_t * cb)3538 print_iostat_header(iostat_cbdata_t *cb)
3539 {
3540 print_iostat_header_impl(cb, 0, NULL);
3541 }
3542
3543 /*
3544 * Display a single statistic.
3545 */
3546 static void
print_one_stat(uint64_t value,enum zfs_nicenum_format format,unsigned int column_size,boolean_t scripted)3547 print_one_stat(uint64_t value, enum zfs_nicenum_format format,
3548 unsigned int column_size, boolean_t scripted)
3549 {
3550 char buf[64];
3551
3552 zfs_nicenum_format(value, buf, sizeof (buf), format);
3553
3554 if (scripted)
3555 printf("\t%s", buf);
3556 else
3557 printf(" %*s", column_size, buf);
3558 }
3559
3560 /*
3561 * Calculate the default vdev stats
3562 *
3563 * Subtract oldvs from newvs, apply a scaling factor, and save the resulting
3564 * stats into calcvs.
3565 */
3566 static void
calc_default_iostats(vdev_stat_t * oldvs,vdev_stat_t * newvs,vdev_stat_t * calcvs)3567 calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs,
3568 vdev_stat_t *calcvs)
3569 {
3570 int i;
3571
3572 memcpy(calcvs, newvs, sizeof (*calcvs));
3573 for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++)
3574 calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]);
3575
3576 for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++)
3577 calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]);
3578 }
3579
3580 /*
3581 * Internal representation of the extended iostats data.
3582 *
3583 * The extended iostat stats are exported in nvlists as either uint64_t arrays
3584 * or single uint64_t's. We make both look like arrays to make them easier
3585 * to process. In order to make single uint64_t's look like arrays, we set
3586 * __data to the stat data, and then set *data = &__data with count = 1. Then,
3587 * we can just use *data and count.
3588 */
3589 struct stat_array {
3590 uint64_t *data;
3591 uint_t count; /* Number of entries in data[] */
3592 uint64_t __data; /* Only used when data is a single uint64_t */
3593 };
3594
3595 static uint64_t
stat_histo_max(struct stat_array * nva,unsigned int len)3596 stat_histo_max(struct stat_array *nva, unsigned int len)
3597 {
3598 uint64_t max = 0;
3599 int i;
3600 for (i = 0; i < len; i++)
3601 max = MAX(max, array64_max(nva[i].data, nva[i].count));
3602
3603 return (max);
3604 }
3605
3606 /*
3607 * Helper function to lookup a uint64_t array or uint64_t value and store its
3608 * data as a stat_array. If the nvpair is a single uint64_t value, then we make
3609 * it look like a one element array to make it easier to process.
3610 */
3611 static int
nvpair64_to_stat_array(nvlist_t * nvl,const char * name,struct stat_array * nva)3612 nvpair64_to_stat_array(nvlist_t *nvl, const char *name,
3613 struct stat_array *nva)
3614 {
3615 nvpair_t *tmp;
3616 int ret;
3617
3618 verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0);
3619 switch (nvpair_type(tmp)) {
3620 case DATA_TYPE_UINT64_ARRAY:
3621 ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count);
3622 break;
3623 case DATA_TYPE_UINT64:
3624 ret = nvpair_value_uint64(tmp, &nva->__data);
3625 nva->data = &nva->__data;
3626 nva->count = 1;
3627 break;
3628 default:
3629 /* Not a uint64_t */
3630 ret = EINVAL;
3631 break;
3632 }
3633
3634 return (ret);
3635 }
3636
3637 /*
3638 * Given a list of nvlist names, look up the extended stats in newnv and oldnv,
3639 * subtract them, and return the results in a newly allocated stat_array.
3640 * You must free the returned array after you are done with it with
3641 * free_calc_stats().
3642 *
3643 * Additionally, you can set "oldnv" to NULL if you simply want the newnv
3644 * values.
3645 */
3646 static struct stat_array *
calc_and_alloc_stats_ex(const char ** names,unsigned int len,nvlist_t * oldnv,nvlist_t * newnv)3647 calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv,
3648 nvlist_t *newnv)
3649 {
3650 nvlist_t *oldnvx = NULL, *newnvx;
3651 struct stat_array *oldnva, *newnva, *calcnva;
3652 int i, j;
3653 unsigned int alloc_size = (sizeof (struct stat_array)) * len;
3654
3655 /* Extract our extended stats nvlist from the main list */
3656 verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3657 &newnvx) == 0);
3658 if (oldnv) {
3659 verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX,
3660 &oldnvx) == 0);
3661 }
3662
3663 newnva = safe_malloc(alloc_size);
3664 oldnva = safe_malloc(alloc_size);
3665 calcnva = safe_malloc(alloc_size);
3666
3667 for (j = 0; j < len; j++) {
3668 verify(nvpair64_to_stat_array(newnvx, names[j],
3669 &newnva[j]) == 0);
3670 calcnva[j].count = newnva[j].count;
3671 alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]);
3672 calcnva[j].data = safe_malloc(alloc_size);
3673 memcpy(calcnva[j].data, newnva[j].data, alloc_size);
3674
3675 if (oldnvx) {
3676 verify(nvpair64_to_stat_array(oldnvx, names[j],
3677 &oldnva[j]) == 0);
3678 for (i = 0; i < oldnva[j].count; i++)
3679 calcnva[j].data[i] -= oldnva[j].data[i];
3680 }
3681 }
3682 free(newnva);
3683 free(oldnva);
3684 return (calcnva);
3685 }
3686
3687 static void
free_calc_stats(struct stat_array * nva,unsigned int len)3688 free_calc_stats(struct stat_array *nva, unsigned int len)
3689 {
3690 int i;
3691 for (i = 0; i < len; i++)
3692 free(nva[i].data);
3693
3694