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) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
29 * Copyright 2016 Nexenta Systems, Inc.
30 * Copyright (c) 2017 Datto Inc.
31 * Copyright (c) 2017, Intel Corporation.
32 */
33
34 #include <solaris.h>
35 #include <assert.h>
36 #include <ctype.h>
37 #include <dirent.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <getopt.h>
41 #include <libgen.h>
42 #include <libintl.h>
43 #include <libuutil.h>
44 #include <locale.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <strings.h>
49 #include <unistd.h>
50 #include <priv.h>
51 #include <pwd.h>
52 #include <zone.h>
53 #include <sys/time.h>
54 #include <zfs_prop.h>
55 #include <sys/fs/zfs.h>
56 #include <sys/stat.h>
57 #include <sys/debug.h>
58
59 #include <libzfs.h>
60
61 #include "zpool_util.h"
62 #include "zfs_comutil.h"
63 #include "zfeature_common.h"
64
65 #include "statcommon.h"
66
67 libzfs_handle_t *g_zfs;
68
69 static int zpool_do_create(int, char **);
70 static int zpool_do_destroy(int, char **);
71
72 static int zpool_do_add(int, char **);
73 static int zpool_do_remove(int, char **);
74 static int zpool_do_labelclear(int, char **);
75
76 static int zpool_do_checkpoint(int, char **);
77
78 static int zpool_do_list(int, char **);
79 static int zpool_do_iostat(int, char **);
80 static int zpool_do_status(int, char **);
81
82 static int zpool_do_online(int, char **);
83 static int zpool_do_offline(int, char **);
84 static int zpool_do_clear(int, char **);
85 static int zpool_do_reopen(int, char **);
86
87 static int zpool_do_reguid(int, char **);
88
89 static int zpool_do_attach(int, char **);
90 static int zpool_do_detach(int, char **);
91 static int zpool_do_replace(int, char **);
92 static int zpool_do_split(int, char **);
93
94 static int zpool_do_initialize(int, char **);
95 static int zpool_do_scrub(int, char **);
96
97 static int zpool_do_import(int, char **);
98 static int zpool_do_export(int, char **);
99
100 static int zpool_do_upgrade(int, char **);
101
102 static int zpool_do_history(int, char **);
103
104 static int zpool_do_get(int, char **);
105 static int zpool_do_set(int, char **);
106
107 static int zpool_do_sync(int, char **);
108
109 /*
110 * These libumem hooks provide a reasonable set of defaults for the allocator's
111 * debugging facilities.
112 */
113
114 #ifdef DEBUG
115 const char *
_umem_debug_init(void)116 _umem_debug_init(void)
117 {
118 return ("default,verbose"); /* $UMEM_DEBUG setting */
119 }
120
121 const char *
_umem_logging_init(void)122 _umem_logging_init(void)
123 {
124 return ("fail,contents"); /* $UMEM_LOGGING setting */
125 }
126 #endif
127
128 typedef enum {
129 HELP_ADD,
130 HELP_ATTACH,
131 HELP_CLEAR,
132 HELP_CREATE,
133 HELP_CHECKPOINT,
134 HELP_DESTROY,
135 HELP_DETACH,
136 HELP_EXPORT,
137 HELP_HISTORY,
138 HELP_IMPORT,
139 HELP_IOSTAT,
140 HELP_LABELCLEAR,
141 HELP_LIST,
142 HELP_OFFLINE,
143 HELP_ONLINE,
144 HELP_REPLACE,
145 HELP_REMOVE,
146 HELP_INITIALIZE,
147 HELP_SCRUB,
148 HELP_STATUS,
149 HELP_UPGRADE,
150 HELP_GET,
151 HELP_SET,
152 HELP_SPLIT,
153 HELP_SYNC,
154 HELP_REGUID,
155 HELP_REOPEN
156 } zpool_help_t;
157
158
159 typedef struct zpool_command {
160 const char *name;
161 int (*func)(int, char **);
162 zpool_help_t usage;
163 } zpool_command_t;
164
165 /*
166 * Master command table. Each ZFS command has a name, associated function, and
167 * usage message. The usage messages need to be internationalized, so we have
168 * to have a function to return the usage message based on a command index.
169 *
170 * These commands are organized according to how they are displayed in the usage
171 * message. An empty command (one with a NULL name) indicates an empty line in
172 * the generic usage message.
173 */
174 static zpool_command_t command_table[] = {
175 { "create", zpool_do_create, HELP_CREATE },
176 { "destroy", zpool_do_destroy, HELP_DESTROY },
177 { NULL },
178 { "add", zpool_do_add, HELP_ADD },
179 { "remove", zpool_do_remove, HELP_REMOVE },
180 { NULL },
181 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
182 { NULL },
183 { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT },
184 { NULL },
185 { "list", zpool_do_list, HELP_LIST },
186 { "iostat", zpool_do_iostat, HELP_IOSTAT },
187 { "status", zpool_do_status, HELP_STATUS },
188 { NULL },
189 { "online", zpool_do_online, HELP_ONLINE },
190 { "offline", zpool_do_offline, HELP_OFFLINE },
191 { "clear", zpool_do_clear, HELP_CLEAR },
192 { "reopen", zpool_do_reopen, HELP_REOPEN },
193 { NULL },
194 { "attach", zpool_do_attach, HELP_ATTACH },
195 { "detach", zpool_do_detach, HELP_DETACH },
196 { "replace", zpool_do_replace, HELP_REPLACE },
197 { "split", zpool_do_split, HELP_SPLIT },
198 { NULL },
199 { "initialize", zpool_do_initialize, HELP_INITIALIZE },
200 { "scrub", zpool_do_scrub, HELP_SCRUB },
201 { NULL },
202 { "import", zpool_do_import, HELP_IMPORT },
203 { "export", zpool_do_export, HELP_EXPORT },
204 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
205 { "reguid", zpool_do_reguid, HELP_REGUID },
206 { NULL },
207 { "history", zpool_do_history, HELP_HISTORY },
208 { "get", zpool_do_get, HELP_GET },
209 { "set", zpool_do_set, HELP_SET },
210 { "sync", zpool_do_sync, HELP_SYNC },
211 };
212
213 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
214
215 #define VDEV_ALLOC_CLASS_LOGS "logs"
216
217 static zpool_command_t *current_command;
218 static char history_str[HIS_MAX_RECORD_LEN];
219 static boolean_t log_history = B_TRUE;
220 static uint_t timestamp_fmt = NODATE;
221
222 static const char *
get_usage(zpool_help_t idx)223 get_usage(zpool_help_t idx)
224 {
225 switch (idx) {
226 case HELP_ADD:
227 return (gettext("\tadd [-fgLnP] <pool> <vdev> ...\n"));
228 case HELP_ATTACH:
229 return (gettext("\tattach [-f] <pool> <device> "
230 "<new-device>\n"));
231 case HELP_CLEAR:
232 return (gettext("\tclear [-nF] <pool> [device]\n"));
233 case HELP_CREATE:
234 return (gettext("\tcreate [-fnd] [-B] "
235 "[-o property=value] ... \n"
236 "\t [-O file-system-property=value] ...\n"
237 "\t [-m mountpoint] [-R root] [-t tempname] "
238 "<pool> <vdev> ...\n"));
239 case HELP_CHECKPOINT:
240 return (gettext("\tcheckpoint [--discard] <pool> ...\n"));
241 case HELP_DESTROY:
242 return (gettext("\tdestroy [-f] <pool>\n"));
243 case HELP_DETACH:
244 return (gettext("\tdetach <pool> <device>\n"));
245 case HELP_EXPORT:
246 return (gettext("\texport [-f] <pool> ...\n"));
247 case HELP_HISTORY:
248 return (gettext("\thistory [-il] [<pool>] ...\n"));
249 case HELP_IMPORT:
250 return (gettext("\timport [-d dir] [-D]\n"
251 "\timport [-o mntopts] [-o property=value] ... \n"
252 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
253 "[-R root] [-F [-n]] -a\n"
254 "\timport [-o mntopts] [-o property=value] ... \n"
255 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
256 "[-R root] [-F [-n]] [-t]\n"
257 "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
258 case HELP_IOSTAT:
259 return (gettext("\tiostat [-gLPv] [-T d|u] [pool] ... "
260 "[interval [count]]\n"));
261 case HELP_LABELCLEAR:
262 return (gettext("\tlabelclear [-f] <vdev>\n"));
263 case HELP_LIST:
264 return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
265 "[-T d|u] [pool] ... [interval [count]]\n"));
266 case HELP_OFFLINE:
267 return (gettext("\toffline [-t] <pool> <device> ...\n"));
268 case HELP_ONLINE:
269 return (gettext("\tonline [-e] <pool> <device> ...\n"));
270 case HELP_REPLACE:
271 return (gettext("\treplace [-f] <pool> <device> "
272 "[new-device]\n"));
273 case HELP_REMOVE:
274 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
275 case HELP_REOPEN:
276 return (gettext("\treopen <pool>\n"));
277 case HELP_INITIALIZE:
278 return (gettext("\tinitialize [-cs] <pool> [<device> ...]\n"));
279 case HELP_SCRUB:
280 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
281 case HELP_STATUS:
282 return (gettext("\tstatus [-DgLPvx] [-T d|u] [pool] ... "
283 "[interval [count]]\n"));
284 case HELP_UPGRADE:
285 return (gettext("\tupgrade [-v]\n"
286 "\tupgrade [-V version] <-a | pool ...>\n"));
287 case HELP_GET:
288 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
289 "<\"all\" | property[,...]> <pool> ...\n"));
290 case HELP_SET:
291 return (gettext("\tset <property=value> <pool> \n"));
292 case HELP_SPLIT:
293 return (gettext("\tsplit [-gLnP] [-R altroot] [-o mntopts]\n"
294 "\t [-o property=value] <pool> <newpool> "
295 "[<device> ...]\n"));
296 case HELP_REGUID:
297 return (gettext("\treguid <pool>\n"));
298 case HELP_SYNC:
299 return (gettext("\tsync [pool] ...\n"));
300 }
301
302 abort();
303 /* NOTREACHED */
304 }
305
306
307 /*
308 * Callback routine that will print out a pool property value.
309 */
310 static int
print_prop_cb(int prop,void * cb)311 print_prop_cb(int prop, void *cb)
312 {
313 FILE *fp = cb;
314
315 (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop));
316
317 if (zpool_prop_readonly(prop))
318 (void) fprintf(fp, " NO ");
319 else
320 (void) fprintf(fp, " YES ");
321
322 if (zpool_prop_values(prop) == NULL)
323 (void) fprintf(fp, "-\n");
324 else
325 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
326
327 return (ZPROP_CONT);
328 }
329
330 /*
331 * Display usage message. If we're inside a command, display only the usage for
332 * that command. Otherwise, iterate over the entire command table and display
333 * a complete usage message.
334 */
335 void
usage(boolean_t requested)336 usage(boolean_t requested)
337 {
338 FILE *fp = requested ? stdout : stderr;
339
340 if (current_command == NULL) {
341 int i;
342
343 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
344 (void) fprintf(fp,
345 gettext("where 'command' is one of the following:\n\n"));
346
347 for (i = 0; i < NCOMMAND; i++) {
348 if (command_table[i].name == NULL)
349 (void) fprintf(fp, "\n");
350 else
351 (void) fprintf(fp, "%s",
352 get_usage(command_table[i].usage));
353 }
354 } else {
355 (void) fprintf(fp, gettext("usage:\n"));
356 (void) fprintf(fp, "%s", get_usage(current_command->usage));
357 }
358
359 if (current_command != NULL &&
360 ((strcmp(current_command->name, "set") == 0) ||
361 (strcmp(current_command->name, "get") == 0) ||
362 (strcmp(current_command->name, "list") == 0))) {
363
364 (void) fprintf(fp,
365 gettext("\nthe following properties are supported:\n"));
366
367 (void) fprintf(fp, "\n\t%-19s %s %s\n\n",
368 "PROPERTY", "EDIT", "VALUES");
369
370 /* Iterate over all properties */
371 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
372 ZFS_TYPE_POOL);
373
374 (void) fprintf(fp, "\t%-19s ", "feature@...");
375 (void) fprintf(fp, "YES disabled | enabled | active\n");
376
377 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
378 "appended with a feature name.\nSee zpool-features(7).\n"));
379 }
380
381 /*
382 * See comments at end of main().
383 */
384 if (getenv("ZFS_ABORT") != NULL) {
385 (void) printf("dumping core by request\n");
386 abort();
387 }
388
389 exit(requested ? 0 : 2);
390 }
391
392 /*
393 * print a pool vdev config for dry runs
394 */
395 static void
print_vdev_tree(zpool_handle_t * zhp,const char * name,nvlist_t * nv,int indent,const char * match,int name_flags)396 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
397 const char *match, int name_flags)
398 {
399 nvlist_t **child;
400 uint_t c, children;
401 char *vname;
402 boolean_t printed = B_FALSE;
403
404 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
405 &child, &children) != 0) {
406 if (name != NULL)
407 (void) printf("\t%*s%s\n", indent, "", name);
408 return;
409 }
410
411 for (c = 0; c < children; c++) {
412 uint64_t is_log = B_FALSE;
413 char *class = "";
414
415 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
416 &is_log);
417 if (is_log)
418 class = VDEV_ALLOC_BIAS_LOG;
419 (void) nvlist_lookup_string(child[c],
420 ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
421 if (strcmp(match, class) != 0)
422 continue;
423
424 if (!printed && name != NULL) {
425 (void) printf("\t%*s%s\n", indent, "", name);
426 printed = B_TRUE;
427 }
428 vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
429 print_vdev_tree(zhp, vname, child[c], indent + 2, "",
430 name_flags);
431 free(vname);
432 }
433 }
434
435 static boolean_t
prop_list_contains_feature(nvlist_t * proplist)436 prop_list_contains_feature(nvlist_t *proplist)
437 {
438 nvpair_t *nvp;
439 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
440 nvp = nvlist_next_nvpair(proplist, nvp)) {
441 if (zpool_prop_feature(nvpair_name(nvp)))
442 return (B_TRUE);
443 }
444 return (B_FALSE);
445 }
446
447 /*
448 * Add a property pair (name, string-value) into a property nvlist.
449 */
450 static int
add_prop_list(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)451 add_prop_list(const char *propname, char *propval, nvlist_t **props,
452 boolean_t poolprop)
453 {
454 zpool_prop_t prop = ZPROP_INVAL;
455 zfs_prop_t fprop;
456 nvlist_t *proplist;
457 const char *normnm;
458 char *strval;
459
460 if (*props == NULL &&
461 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
462 (void) fprintf(stderr,
463 gettext("internal error: out of memory\n"));
464 return (1);
465 }
466
467 proplist = *props;
468
469 if (poolprop) {
470 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
471
472 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
473 !zpool_prop_feature(propname)) {
474 (void) fprintf(stderr, gettext("property '%s' is "
475 "not a valid pool property\n"), propname);
476 return (2);
477 }
478
479 /*
480 * feature@ properties and version should not be specified
481 * at the same time.
482 */
483 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
484 nvlist_exists(proplist, vname)) ||
485 (prop == ZPOOL_PROP_VERSION &&
486 prop_list_contains_feature(proplist))) {
487 (void) fprintf(stderr, gettext("'feature@' and "
488 "'version' properties cannot be specified "
489 "together\n"));
490 return (2);
491 }
492
493
494 if (zpool_prop_feature(propname))
495 normnm = propname;
496 else
497 normnm = zpool_prop_to_name(prop);
498 } else {
499 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
500 normnm = zfs_prop_to_name(fprop);
501 } else {
502 normnm = propname;
503 }
504 }
505
506 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
507 prop != ZPOOL_PROP_CACHEFILE) {
508 (void) fprintf(stderr, gettext("property '%s' "
509 "specified multiple times\n"), propname);
510 return (2);
511 }
512
513 if (nvlist_add_string(proplist, normnm, propval) != 0) {
514 (void) fprintf(stderr, gettext("internal "
515 "error: out of memory\n"));
516 return (1);
517 }
518
519 return (0);
520 }
521
522 /*
523 * Set a default property pair (name, string-value) in a property nvlist
524 */
525 static int
add_prop_list_default(const char * propname,char * propval,nvlist_t ** props,boolean_t poolprop)526 add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
527 boolean_t poolprop)
528 {
529 char *pval;
530
531 if (nvlist_lookup_string(*props, propname, &pval) == 0)
532 return (0);
533
534 return (add_prop_list(propname, propval, props, poolprop));
535 }
536
537 /*
538 * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
539 *
540 * -f Force addition of devices, even if they appear in use
541 * -g Display guid for individual vdev name.
542 * -L Follow links when resolving vdev path name.
543 * -n Do not add the devices, but display the resulting layout if
544 * they were to be added.
545 * -P Display full path for vdev name.
546 *
547 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
548 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
549 * libzfs.
550 */
551 int
zpool_do_add(int argc,char ** argv)552 zpool_do_add(int argc, char **argv)
553 {
554 boolean_t force = B_FALSE;
555 boolean_t dryrun = B_FALSE;
556 int name_flags = 0;
557 int c;
558 nvlist_t *nvroot;
559 char *poolname;
560 zpool_boot_label_t boot_type;
561 uint64_t boot_size;
562 int ret;
563 zpool_handle_t *zhp;
564 nvlist_t *config;
565
566 /* check options */
567 while ((c = getopt(argc, argv, "fgLnP")) != -1) {
568 switch (c) {
569 case 'f':
570 force = B_TRUE;
571 break;
572 case 'g':
573 name_flags |= VDEV_NAME_GUID;
574 break;
575 case 'L':
576 name_flags |= VDEV_NAME_FOLLOW_LINKS;
577 break;
578 case 'n':
579 dryrun = B_TRUE;
580 break;
581 case 'P':
582 name_flags |= VDEV_NAME_PATH;
583 break;
584 case '?':
585 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
586 optopt);
587 usage(B_FALSE);
588 }
589 }
590
591 argc -= optind;
592 argv += optind;
593
594 /* get pool name and check number of arguments */
595 if (argc < 1) {
596 (void) fprintf(stderr, gettext("missing pool name argument\n"));
597 usage(B_FALSE);
598 }
599 if (argc < 2) {
600 (void) fprintf(stderr, gettext("missing vdev specification\n"));
601 usage(B_FALSE);
602 }
603
604 poolname = argv[0];
605
606 argc--;
607 argv++;
608
609 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
610 return (1);
611
612 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
613 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
614 poolname);
615 zpool_close(zhp);
616 return (1);
617 }
618
619 if (zpool_is_bootable(zhp))
620 boot_type = ZPOOL_COPY_BOOT_LABEL;
621 else
622 boot_type = ZPOOL_NO_BOOT_LABEL;
623
624 /* pass off to get_vdev_spec for processing */
625 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
626 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
627 boot_type, boot_size, argc, argv);
628 if (nvroot == NULL) {
629 zpool_close(zhp);
630 return (1);
631 }
632
633 if (dryrun) {
634 nvlist_t *poolnvroot;
635
636 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
637 &poolnvroot) == 0);
638
639 (void) printf(gettext("would update '%s' to the following "
640 "configuration:\n"), zpool_get_name(zhp));
641
642 /* print original main pool and new tree */
643 print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
644 name_flags | VDEV_NAME_TYPE_ID);
645 print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
646
647 /* print other classes: 'dedup', 'special', and 'log' */
648 print_vdev_tree(zhp, "dedup", poolnvroot, 0,
649 VDEV_ALLOC_BIAS_DEDUP, name_flags);
650 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP,
651 name_flags);
652
653 print_vdev_tree(zhp, "special", poolnvroot, 0,
654 VDEV_ALLOC_BIAS_SPECIAL, name_flags);
655 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL,
656 name_flags);
657
658 print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG,
659 name_flags);
660 print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG,
661 name_flags);
662
663 ret = 0;
664 } else {
665 ret = (zpool_add(zhp, nvroot) != 0);
666 }
667
668 nvlist_free(nvroot);
669 zpool_close(zhp);
670
671 return (ret);
672 }
673
674 /*
675 * zpool remove <pool> <vdev> ...
676 *
677 * Removes the given vdev from the pool.
678 */
679 int
zpool_do_remove(int argc,char ** argv)680 zpool_do_remove(int argc, char **argv)
681 {
682 char *poolname;
683 int i, ret = 0;
684 zpool_handle_t *zhp;
685 boolean_t stop = B_FALSE;
686 boolean_t noop = B_FALSE;
687 boolean_t parsable = B_FALSE;
688 char c;
689
690 /* check options */
691 while ((c = getopt(argc, argv, "nps")) != -1) {
692 switch (c) {
693 case 'n':
694 noop = B_TRUE;
695 break;
696 case 'p':
697 parsable = B_TRUE;
698 break;
699 case 's':
700 stop = B_TRUE;
701 break;
702 case '?':
703 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
704 optopt);
705 usage(B_FALSE);
706 }
707 }
708
709 argc -= optind;
710 argv += optind;
711
712 /* get pool name and check number of arguments */
713 if (argc < 1) {
714 (void) fprintf(stderr, gettext("missing pool name argument\n"));
715 usage(B_FALSE);
716 }
717
718 poolname = argv[0];
719
720 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
721 return (1);
722
723 if (stop && noop) {
724 (void) fprintf(stderr, gettext("stop request ignored\n"));
725 return (0);
726 }
727
728 if (stop) {
729 if (argc > 1) {
730 (void) fprintf(stderr, gettext("too many arguments\n"));
731 usage(B_FALSE);
732 }
733 if (zpool_vdev_remove_cancel(zhp) != 0)
734 ret = 1;
735 } else {
736 if (argc < 2) {
737 (void) fprintf(stderr, gettext("missing device\n"));
738 usage(B_FALSE);
739 }
740
741 for (i = 1; i < argc; i++) {
742 if (noop) {
743 uint64_t size;
744
745 if (zpool_vdev_indirect_size(zhp, argv[i],
746 &size) != 0) {
747 ret = 1;
748 break;
749 }
750 if (parsable) {
751 (void) printf("%s %llu\n",
752 argv[i], size);
753 } else {
754 char valstr[32];
755 zfs_nicenum(size, valstr,
756 sizeof (valstr));
757 (void) printf("Memory that will be "
758 "used after removing %s: %s\n",
759 argv[i], valstr);
760 }
761 } else {
762 if (zpool_vdev_remove(zhp, argv[i]) != 0)
763 ret = 1;
764 }
765 }
766 }
767
768 return (ret);
769 }
770
771 /*
772 * zpool labelclear [-f] <vdev>
773 *
774 * -f Force clearing the label for the vdevs which are members of
775 * the exported or foreign pools.
776 *
777 * Verifies that the vdev is not active and zeros out the label information
778 * on the device.
779 */
780 int
zpool_do_labelclear(int argc,char ** argv)781 zpool_do_labelclear(int argc, char **argv)
782 {
783 char vdev[MAXPATHLEN];
784 char *name = NULL;
785 struct stat st;
786 int c, fd, ret = 0;
787 nvlist_t *config;
788 pool_state_t state;
789 boolean_t inuse = B_FALSE;
790 boolean_t force = B_FALSE;
791
792 /* check options */
793 while ((c = getopt(argc, argv, "f")) != -1) {
794 switch (c) {
795 case 'f':
796 force = B_TRUE;
797 break;
798 default:
799 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
800 optopt);
801 usage(B_FALSE);
802 }
803 }
804
805 argc -= optind;
806 argv += optind;
807
808 /* get vdev name */
809 if (argc < 1) {
810 (void) fprintf(stderr, gettext("missing vdev name\n"));
811 usage(B_FALSE);
812 }
813 if (argc > 1) {
814 (void) fprintf(stderr, gettext("too many arguments\n"));
815 usage(B_FALSE);
816 }
817
818 /*
819 * Check if we were given absolute path and use it as is.
820 * Otherwise if the provided vdev name doesn't point to a file,
821 * try prepending dsk path and appending s0.
822 */
823 (void) strlcpy(vdev, argv[0], sizeof (vdev));
824 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
825 char *s;
826
827 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
828 #ifdef illumos
829 ZFS_DISK_ROOT, argv[0]);
830 if ((s = strrchr(argv[0], 's')) == NULL ||
831 !isdigit(*(s + 1)))
832 (void) strlcat(vdev, "s0", sizeof (vdev));
833 #else
834 "/dev", argv[0]);
835 #endif
836 if (stat(vdev, &st) != 0) {
837 (void) fprintf(stderr, gettext(
838 "failed to find device %s, try specifying absolute "
839 "path instead\n"), argv[0]);
840 return (1);
841 }
842 }
843
844 if ((fd = open(vdev, O_RDWR)) < 0) {
845 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
846 vdev, strerror(errno));
847 return (1);
848 }
849
850 if (zpool_read_label(fd, &config) != 0) {
851 (void) fprintf(stderr,
852 gettext("failed to read label from %s\n"), vdev);
853 return (1);
854 }
855 nvlist_free(config);
856
857 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
858 if (ret != 0) {
859 (void) fprintf(stderr,
860 gettext("failed to check state for %s\n"), vdev);
861 return (1);
862 }
863
864 if (!inuse)
865 goto wipe_label;
866
867 switch (state) {
868 default:
869 case POOL_STATE_ACTIVE:
870 case POOL_STATE_SPARE:
871 case POOL_STATE_L2CACHE:
872 (void) fprintf(stderr, gettext(
873 "%s is a member (%s) of pool \"%s\"\n"),
874 vdev, zpool_pool_state_to_name(state), name);
875 ret = 1;
876 goto errout;
877
878 case POOL_STATE_EXPORTED:
879 if (force)
880 break;
881 (void) fprintf(stderr, gettext(
882 "use '-f' to override the following error:\n"
883 "%s is a member of exported pool \"%s\"\n"),
884 vdev, name);
885 ret = 1;
886 goto errout;
887
888 case POOL_STATE_POTENTIALLY_ACTIVE:
889 if (force)
890 break;
891 (void) fprintf(stderr, gettext(
892 "use '-f' to override the following error:\n"
893 "%s is a member of potentially active pool \"%s\"\n"),
894 vdev, name);
895 ret = 1;
896 goto errout;
897
898 case POOL_STATE_DESTROYED:
899 /* inuse should never be set for a destroyed pool */
900 assert(0);
901 break;
902 }
903
904 wipe_label:
905 ret = zpool_clear_label(fd);
906 if (ret != 0) {
907 (void) fprintf(stderr,
908 gettext("failed to clear label for %s\n"), vdev);
909 }
910
911 errout:
912 free(name);
913 (void) close(fd);
914
915 return (ret);
916 }
917
918 /*
919 * zpool create [-fnd] [-B] [-o property=value] ...
920 * [-O file-system-property=value] ...
921 * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ...
922 *
923 * -B Create boot partition.
924 * -f Force creation, even if devices appear in use
925 * -n Do not create the pool, but display the resulting layout if it
926 * were to be created.
927 * -R Create a pool under an alternate root
928 * -m Set default mountpoint for the root dataset. By default it's
929 * '/<pool>'
930 * -t Use the temporary name until the pool is exported.
931 * -o Set property=value.
932 * -d Don't automatically enable all supported pool features
933 * (individual features can be enabled with -o).
934 * -O Set fsproperty=value in the pool's root file system
935 *
936 * Creates the named pool according to the given vdev specification. The
937 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
938 * we get the nvlist back from get_vdev_spec(), we either print out the contents
939 * (if '-n' was specified), or pass it to libzfs to do the creation.
940 */
941
942 #define SYSTEM256 (256 * 1024 * 1024)
943 int
zpool_do_create(int argc,char ** argv)944 zpool_do_create(int argc, char **argv)
945 {
946 boolean_t force = B_FALSE;
947 boolean_t dryrun = B_FALSE;
948 boolean_t enable_all_pool_feat = B_TRUE;
949 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
950 uint64_t boot_size = 0;
951 int c;
952 nvlist_t *nvroot = NULL;
953 char *poolname;
954 char *tname = NULL;
955 int ret = 1;
956 char *altroot = NULL;
957 char *mountpoint = NULL;
958 nvlist_t *fsprops = NULL;
959 nvlist_t *props = NULL;
960 char *propval;
961
962 /* check options */
963 while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) {
964 switch (c) {
965 case 'f':
966 force = B_TRUE;
967 break;
968 case 'n':
969 dryrun = B_TRUE;
970 break;
971 case 'd':
972 enable_all_pool_feat = B_FALSE;
973 break;
974 case 'B':
975 #ifdef illumos
976 /*
977 * We should create the system partition.
978 * Also make sure the size is set.
979 */
980 boot_type = ZPOOL_CREATE_BOOT_LABEL;
981 if (boot_size == 0)
982 boot_size = SYSTEM256;
983 break;
984 #else
985 (void) fprintf(stderr,
986 gettext("option '%c' is not supported\n"),
987 optopt);
988 goto badusage;
989 #endif
990 case 'R':
991 altroot = optarg;
992 if (add_prop_list(zpool_prop_to_name(
993 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
994 goto errout;
995 if (add_prop_list_default(zpool_prop_to_name(
996 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
997 goto errout;
998 break;
999 case 'm':
1000 /* Equivalent to -O mountpoint=optarg */
1001 mountpoint = optarg;
1002 break;
1003 case 'o':
1004 if ((propval = strchr(optarg, '=')) == NULL) {
1005 (void) fprintf(stderr, gettext("missing "
1006 "'=' for -o option\n"));
1007 goto errout;
1008 }
1009 *propval = '\0';
1010 propval++;
1011
1012 if (add_prop_list(optarg, propval, &props, B_TRUE))
1013 goto errout;
1014
1015 /*
1016 * Get bootsize value for make_root_vdev().
1017 */
1018 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
1019 if (zfs_nicestrtonum(g_zfs, propval,
1020 &boot_size) < 0 || boot_size == 0) {
1021 (void) fprintf(stderr,
1022 gettext("bad boot partition size "
1023 "'%s': %s\n"), propval,
1024 libzfs_error_description(g_zfs));
1025 goto errout;
1026 }
1027 }
1028
1029 /*
1030 * If the user is creating a pool that doesn't support
1031 * feature flags, don't enable any features.
1032 */
1033 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
1034 char *end;
1035 u_longlong_t ver;
1036
1037 ver = strtoull(propval, &end, 10);
1038 if (*end == '\0' &&
1039 ver < SPA_VERSION_FEATURES) {
1040 enable_all_pool_feat = B_FALSE;
1041 }
1042 }
1043 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
1044 altroot = propval;
1045 break;
1046 case 'O':
1047 if ((propval = strchr(optarg, '=')) == NULL) {
1048 (void) fprintf(stderr, gettext("missing "
1049 "'=' for -O option\n"));
1050 goto errout;
1051 }
1052 *propval = '\0';
1053 propval++;
1054
1055 /*
1056 * Mountpoints are checked and then added later.
1057 * Uniquely among properties, they can be specified
1058 * more than once, to avoid conflict with -m.
1059 */
1060 if (0 == strcmp(optarg,
1061 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
1062 mountpoint = propval;
1063 } else if (add_prop_list(optarg, propval, &fsprops,
1064 B_FALSE)) {
1065 goto errout;
1066 }
1067 break;
1068 case 't':
1069 /*
1070 * Sanity check temporary pool name.
1071 */
1072 if (strchr(optarg, '/') != NULL) {
1073 (void) fprintf(stderr, gettext("cannot create "
1074 "'%s': invalid character '/' in temporary "
1075 "name\n"), optarg);
1076 (void) fprintf(stderr, gettext("use 'zfs "
1077 "create' to create a dataset\n"));
1078 goto errout;
1079 }
1080
1081 if (add_prop_list(zpool_prop_to_name(
1082 ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
1083 goto errout;
1084 if (add_prop_list_default(zpool_prop_to_name(
1085 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1086 goto errout;
1087 tname = optarg;
1088 break;
1089 case ':':
1090 (void) fprintf(stderr, gettext("missing argument for "
1091 "'%c' option\n"), optopt);
1092 goto badusage;
1093 case '?':
1094 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1095 optopt);
1096 goto badusage;
1097 }
1098 }
1099
1100 argc -= optind;
1101 argv += optind;
1102
1103 /* get pool name and check number of arguments */
1104 if (argc < 1) {
1105 (void) fprintf(stderr, gettext("missing pool name argument\n"));
1106 goto badusage;
1107 }
1108 if (argc < 2) {
1109 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1110 goto badusage;
1111 }
1112
1113 poolname = argv[0];
1114
1115 /*
1116 * As a special case, check for use of '/' in the name, and direct the
1117 * user to use 'zfs create' instead.
1118 */
1119 if (strchr(poolname, '/') != NULL) {
1120 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1121 "character '/' in pool name\n"), poolname);
1122 (void) fprintf(stderr, gettext("use 'zfs create' to "
1123 "create a dataset\n"));
1124 goto errout;
1125 }
1126
1127 /*
1128 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1129 * and not set otherwise.
1130 */
1131 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1132 const char *propname;
1133 char *strptr, *buf = NULL;
1134 int rv;
1135
1136 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1137 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1138 (void) asprintf(&buf, "%" PRIu64, boot_size);
1139 if (buf == NULL) {
1140 (void) fprintf(stderr,
1141 gettext("internal error: out of memory\n"));
1142 goto errout;
1143 }
1144 rv = add_prop_list(propname, buf, &props, B_TRUE);
1145 free(buf);
1146 if (rv != 0)
1147 goto errout;
1148 }
1149 } else {
1150 const char *propname;
1151 char *strptr;
1152
1153 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1154 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1155 (void) fprintf(stderr, gettext("error: setting boot "
1156 "partition size requires option '-B'\n"));
1157 goto errout;
1158 }
1159 }
1160
1161 /* pass off to get_vdev_spec for bulk processing */
1162 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1163 boot_type, boot_size, argc - 1, argv + 1);
1164 if (nvroot == NULL)
1165 goto errout;
1166
1167 /* make_root_vdev() allows 0 toplevel children if there are spares */
1168 if (!zfs_allocatable_devs(nvroot)) {
1169 (void) fprintf(stderr, gettext("invalid vdev "
1170 "specification: at least one toplevel vdev must be "
1171 "specified\n"));
1172 goto errout;
1173 }
1174
1175 if (altroot != NULL && altroot[0] != '/') {
1176 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1177 "must be an absolute path\n"), altroot);
1178 goto errout;
1179 }
1180
1181 /*
1182 * Check the validity of the mountpoint and direct the user to use the
1183 * '-m' mountpoint option if it looks like its in use.
1184 * Ignore the checks if the '-f' option is given.
1185 */
1186 if (!force && (mountpoint == NULL ||
1187 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1188 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) {
1189 char buf[MAXPATHLEN];
1190 DIR *dirp;
1191
1192 if (mountpoint && mountpoint[0] != '/') {
1193 (void) fprintf(stderr, gettext("invalid mountpoint "
1194 "'%s': must be an absolute path, 'legacy', or "
1195 "'none'\n"), mountpoint);
1196 goto errout;
1197 }
1198
1199 if (mountpoint == NULL) {
1200 if (altroot != NULL)
1201 (void) snprintf(buf, sizeof (buf), "%s/%s",
1202 altroot, poolname);
1203 else
1204 (void) snprintf(buf, sizeof (buf), "/%s",
1205 poolname);
1206 } else {
1207 if (altroot != NULL)
1208 (void) snprintf(buf, sizeof (buf), "%s%s",
1209 altroot, mountpoint);
1210 else
1211 (void) snprintf(buf, sizeof (buf), "%s",
1212 mountpoint);
1213 }
1214
1215 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1216 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1217 "%s\n"), buf, strerror(errno));
1218 (void) fprintf(stderr, gettext("use '-m' "
1219 "option to provide a different default\n"));
1220 goto errout;
1221 } else if (dirp) {
1222 int count = 0;
1223
1224 while (count < 3 && readdir(dirp) != NULL)
1225 count++;
1226 (void) closedir(dirp);
1227
1228 if (count > 2) {
1229 (void) fprintf(stderr, gettext("mountpoint "
1230 "'%s' exists and is not empty\n"), buf);
1231 (void) fprintf(stderr, gettext("use '-m' "
1232 "option to provide a "
1233 "different default\n"));
1234 goto errout;
1235 }
1236 }
1237 }
1238
1239 /*
1240 * Now that the mountpoint's validity has been checked, ensure that
1241 * the property is set appropriately prior to creating the pool.
1242 */
1243 if (mountpoint != NULL) {
1244 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1245 mountpoint, &fsprops, B_FALSE);
1246 if (ret != 0)
1247 goto errout;
1248 }
1249
1250 ret = 1;
1251 if (dryrun) {
1252 /*
1253 * For a dry run invocation, print out a basic message and run
1254 * through all the vdevs in the list and print out in an
1255 * appropriate hierarchy.
1256 */
1257 (void) printf(gettext("would create '%s' with the "
1258 "following layout:\n\n"), poolname);
1259
1260 print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
1261 print_vdev_tree(NULL, "dedup", nvroot, 0,
1262 VDEV_ALLOC_BIAS_DEDUP, 0);
1263 print_vdev_tree(NULL, "special", nvroot, 0,
1264 VDEV_ALLOC_BIAS_SPECIAL, 0);
1265 print_vdev_tree(NULL, "logs", nvroot, 0,
1266 VDEV_ALLOC_BIAS_LOG, 0);
1267
1268 ret = 0;
1269 } else {
1270 /*
1271 * Hand off to libzfs.
1272 */
1273 if (enable_all_pool_feat) {
1274 spa_feature_t i;
1275 for (i = 0; i < SPA_FEATURES; i++) {
1276 char propname[MAXPATHLEN];
1277 zfeature_info_t *feat = &spa_feature_table[i];
1278
1279 (void) snprintf(propname, sizeof (propname),
1280 "feature@%s", feat->fi_uname);
1281
1282 /*
1283 * Skip feature if user specified it manually
1284 * on the command line.
1285 */
1286 if (nvlist_exists(props, propname))
1287 continue;
1288
1289 ret = add_prop_list(propname,
1290 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1291 if (ret != 0)
1292 goto errout;
1293 }
1294 }
1295
1296 ret = 1;
1297 if (zpool_create(g_zfs, poolname,
1298 nvroot, props, fsprops) == 0) {
1299 zfs_handle_t *pool = zfs_open(g_zfs,
1300 tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
1301 if (pool != NULL) {
1302 if (zfs_mount(pool, NULL, 0) == 0)
1303 ret = zfs_shareall(pool);
1304 zfs_close(pool);
1305 }
1306 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1307 (void) fprintf(stderr, gettext("pool name may have "
1308 "been omitted\n"));
1309 }
1310 }
1311
1312 errout:
1313 nvlist_free(nvroot);
1314 nvlist_free(fsprops);
1315 nvlist_free(props);
1316 return (ret);
1317 badusage:
1318 nvlist_free(fsprops);
1319 nvlist_free(props);
1320 usage(B_FALSE);
1321 return (2);
1322 }
1323
1324 /*
1325 * zpool destroy <pool>
1326 *
1327 * -f Forcefully unmount any datasets
1328 *
1329 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1330 */
1331 int
zpool_do_destroy(int argc,char ** argv)1332 zpool_do_destroy(int argc, char **argv)
1333 {
1334 boolean_t force = B_FALSE;
1335 int c;
1336 char *pool;
1337 zpool_handle_t *zhp;
1338 int ret;
1339
1340 /* check options */
1341 while ((c = getopt(argc, argv, "f")) != -1) {
1342 switch (c) {
1343 case 'f':
1344 force = B_TRUE;
1345 break;
1346 case '?':
1347 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1348 optopt);
1349 usage(B_FALSE);
1350 }
1351 }
1352
1353 argc -= optind;
1354 argv += optind;
1355
1356 /* check arguments */
1357 if (argc < 1) {
1358 (void) fprintf(stderr, gettext("missing pool argument\n"));
1359 usage(B_FALSE);
1360 }
1361 if (argc > 1) {
1362 (void) fprintf(stderr, gettext("too many arguments\n"));
1363 usage(B_FALSE);
1364 }
1365
1366 pool = argv[0];
1367
1368 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1369 /*
1370 * As a special case, check for use of '/' in the name, and
1371 * direct the user to use 'zfs destroy' instead.
1372 */
1373 if (strchr(pool, '/') != NULL)
1374 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1375 "destroy a dataset\n"));
1376 return (1);
1377 }
1378
1379 if (zpool_disable_datasets(zhp, force) != 0) {
1380 (void) fprintf(stderr, gettext("could not destroy '%s': "
1381 "could not unmount datasets\n"), zpool_get_name(zhp));
1382 return (1);
1383 }
1384
1385 /* The history must be logged as part of the export */
1386 log_history = B_FALSE;
1387
1388 ret = (zpool_destroy(zhp, history_str) != 0);
1389
1390 zpool_close(zhp);
1391
1392 return (ret);
1393 }
1394
1395 /*
1396 * zpool export [-f] <pool> ...
1397 *
1398 * -f Forcefully unmount datasets
1399 *
1400 * Export the given pools. By default, the command will attempt to cleanly
1401 * unmount any active datasets within the pool. If the '-f' flag is specified,
1402 * then the datasets will be forcefully unmounted.
1403 */
1404 int
zpool_do_export(int argc,char ** argv)1405 zpool_do_export(int argc, char **argv)
1406 {
1407 boolean_t force = B_FALSE;
1408 boolean_t hardforce = B_FALSE;
1409 int c;
1410 zpool_handle_t *zhp;
1411 int ret;
1412 int i;
1413
1414 /* check options */
1415 while ((c = getopt(argc, argv, "fF")) != -1) {
1416 switch (c) {
1417 case 'f':
1418 force = B_TRUE;
1419 break;
1420 case 'F':
1421 hardforce = B_TRUE;
1422 break;
1423 case '?':
1424 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1425 optopt);
1426 usage(B_FALSE);
1427 }
1428 }
1429
1430 argc -= optind;
1431 argv += optind;
1432
1433 /* check arguments */
1434 if (argc < 1) {
1435 (void) fprintf(stderr, gettext("missing pool argument\n"));
1436 usage(B_FALSE);
1437 }
1438
1439 ret = 0;
1440 for (i = 0; i < argc; i++) {
1441 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1442 ret = 1;
1443 continue;
1444 }
1445
1446 if (zpool_disable_datasets(zhp, force) != 0) {
1447 ret = 1;
1448 zpool_close(zhp);
1449 continue;
1450 }
1451
1452 /* The history must be logged as part of the export */
1453 log_history = B_FALSE;
1454
1455 if (hardforce) {
1456 if (zpool_export_force(zhp, history_str) != 0)
1457 ret = 1;
1458 } else if (zpool_export(zhp, force, history_str) != 0) {
1459 ret = 1;
1460 }
1461
1462 zpool_close(zhp);
1463 }
1464
1465 return (ret);
1466 }
1467
1468 /*
1469 * Given a vdev configuration, determine the maximum width needed for the device
1470 * name column.
1471 */
1472 static int
max_width(zpool_handle_t * zhp,nvlist_t * nv,int depth,int max,int name_flags)1473 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
1474 int name_flags)
1475 {
1476 char *name;
1477 nvlist_t **child;
1478 uint_t c, children;
1479 int ret;
1480
1481 name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID);
1482 if (strlen(name) + depth > max)
1483 max = strlen(name) + depth;
1484
1485 free(name);
1486
1487 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1488 &child, &children) == 0) {
1489 for (c = 0; c < children; c++)
1490 if ((ret = max_width(zhp, child[c], depth + 2,
1491 max, name_flags)) > max)
1492 max = ret;
1493 }
1494
1495 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1496 &child, &children) == 0) {
1497 for (c = 0; c < children; c++)
1498 if ((ret = max_width(zhp, child[c], depth + 2,
1499 max, name_flags)) > max)
1500 max = ret;
1501 }
1502
1503 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1504 &child, &children) == 0) {
1505 for (c = 0; c < children; c++)
1506 if ((ret = max_width(zhp, child[c], depth + 2,
1507 max, name_flags)) > max)
1508 max = ret;
1509 }
1510
1511 return (max);
1512 }
1513
1514 typedef struct spare_cbdata {
1515 uint64_t cb_guid;
1516 zpool_handle_t *cb_zhp;
1517 } spare_cbdata_t;
1518
1519 static boolean_t
find_vdev(nvlist_t * nv,uint64_t search)1520 find_vdev(nvlist_t *nv, uint64_t search)
1521 {
1522 uint64_t guid;
1523 nvlist_t **child;
1524 uint_t c, children;
1525
1526 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1527 search == guid)
1528 return (B_TRUE);
1529
1530 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1531 &child, &children) == 0) {
1532 for (c = 0; c < children; c++)
1533 if (find_vdev(child[c], search))
1534 return (B_TRUE);
1535 }
1536
1537 return (B_FALSE);
1538 }
1539
1540 static int
find_spare(zpool_handle_t * zhp,void * data)1541 find_spare(zpool_handle_t *zhp, void *data)
1542 {
1543 spare_cbdata_t *cbp = data;
1544 nvlist_t *config, *nvroot;
1545
1546 config = zpool_get_config(zhp, NULL);
1547 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1548 &nvroot) == 0);
1549
1550 if (find_vdev(nvroot, cbp->cb_guid)) {
1551 cbp->cb_zhp = zhp;
1552 return (1);
1553 }
1554
1555 zpool_close(zhp);
1556 return (0);
1557 }
1558
1559 typedef struct status_cbdata {
1560 int cb_count;
1561 int cb_name_flags;
1562 int cb_namewidth;
1563 boolean_t cb_allpools;
1564 boolean_t cb_verbose;
1565 boolean_t cb_explain;
1566 boolean_t cb_first;
1567 boolean_t cb_dedup_stats;
1568 boolean_t cb_print_status;
1569 } status_cbdata_t;
1570
1571 /*
1572 * Print out configuration state as requested by status_callback.
1573 */
1574 static void
print_status_config(zpool_handle_t * zhp,status_cbdata_t * cb,const char * name,nvlist_t * nv,int depth,boolean_t isspare)1575 print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
1576 nvlist_t *nv, int depth, boolean_t isspare)
1577 {
1578 nvlist_t **child;
1579 uint_t c, vsc, children;
1580 pool_scan_stat_t *ps = NULL;
1581 vdev_stat_t *vs;
1582 char rbuf[6], wbuf[6], cbuf[6];
1583 char *vname;
1584 uint64_t notpresent;
1585 uint64_t ashift;
1586 spare_cbdata_t spare_cb;
1587 const char *state;
1588 char *type;
1589
1590 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1591 &child, &children) != 0)
1592 children = 0;
1593
1594 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1595 (uint64_t **)&vs, &vsc) == 0);
1596
1597 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1598
1599 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1600 return;
1601
1602 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1603 if (isspare) {
1604 /*
1605 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1606 * online drives.
1607 */
1608 if (vs->vs_aux == VDEV_AUX_SPARED)
1609 state = "INUSE";
1610 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1611 state = "AVAIL";
1612 }
1613
1614 (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
1615 name, state);
1616
1617 if (!isspare) {
1618 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1619 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1620 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1621 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1622 }
1623
1624 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1625 ¬present) == 0 ||
1626 vs->vs_state <= VDEV_STATE_CANT_OPEN) {
1627 char *path;
1628 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0)
1629 (void) printf(" was %s", path);
1630 } else if (vs->vs_aux != 0) {
1631 (void) printf(" ");
1632
1633 switch (vs->vs_aux) {
1634 case VDEV_AUX_OPEN_FAILED:
1635 (void) printf(gettext("cannot open"));
1636 break;
1637
1638 case VDEV_AUX_BAD_GUID_SUM:
1639 (void) printf(gettext("missing device"));
1640 break;
1641
1642 case VDEV_AUX_NO_REPLICAS:
1643 (void) printf(gettext("insufficient replicas"));
1644 break;
1645
1646 case VDEV_AUX_VERSION_NEWER:
1647 (void) printf(gettext("newer version"));
1648 break;
1649
1650 case VDEV_AUX_UNSUP_FEAT:
1651 (void) printf(gettext("unsupported feature(s)"));
1652 break;
1653
1654 case VDEV_AUX_ASHIFT_TOO_BIG:
1655 (void) printf(gettext("unsupported minimum blocksize"));
1656 break;
1657
1658 case VDEV_AUX_SPARED:
1659 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1660 &spare_cb.cb_guid) == 0);
1661 if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
1662 if (strcmp(zpool_get_name(spare_cb.cb_zhp),
1663 zpool_get_name(zhp)) == 0)
1664 (void) printf(gettext("currently in "
1665 "use"));
1666 else
1667 (void) printf(gettext("in use by "
1668 "pool '%s'"),
1669 zpool_get_name(spare_cb.cb_zhp));
1670 zpool_close(spare_cb.cb_zhp);
1671 } else {
1672 (void) printf(gettext("currently in use"));
1673 }
1674 break;
1675
1676 case VDEV_AUX_ERR_EXCEEDED:
1677 (void) printf(gettext("too many errors"));
1678 break;
1679
1680 case VDEV_AUX_IO_FAILURE:
1681 (void) printf(gettext("experienced I/O failures"));
1682 break;
1683
1684 case VDEV_AUX_BAD_LOG:
1685 (void) printf(gettext("bad intent log"));
1686 break;
1687
1688 case VDEV_AUX_EXTERNAL:
1689 (void) printf(gettext("external device fault"));
1690 break;
1691
1692 case VDEV_AUX_SPLIT_POOL:
1693 (void) printf(gettext("split into new pool"));
1694 break;
1695
1696 case VDEV_AUX_ACTIVE:
1697 (void) printf(gettext("currently in use"));
1698 break;
1699
1700 case VDEV_AUX_CHILDREN_OFFLINE:
1701 (void) printf(gettext("all children offline"));
1702 break;
1703
1704 default:
1705 (void) printf(gettext("corrupted data"));
1706 break;
1707 }
1708 } else if (children == 0 && !isspare &&
1709 VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
1710 vs->vs_configured_ashift < vs->vs_physical_ashift) {
1711 (void) printf(
1712 gettext(" block size: %dB configured, %dB native"),
1713 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift);
1714 }
1715
1716 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1717 (uint64_t **)&ps, &c);
1718
1719 if (ps != NULL && ps->pss_state == DSS_SCANNING &&
1720 vs->vs_scan_processed != 0 && children == 0) {
1721 (void) printf(gettext(" (%s)"),
1722 (ps->pss_func == POOL_SCAN_RESILVER) ?
1723 "resilvering" : "repairing");
1724 }
1725
1726 if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE ||
1727 vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED ||
1728 vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) &&
1729 !vs->vs_scan_removing) {
1730 char zbuf[1024];
1731 char tbuf[256];
1732 struct tm zaction_ts;
1733
1734 time_t t = vs->vs_initialize_action_time;
1735 int initialize_pct = 100;
1736 if (vs->vs_initialize_state != VDEV_INITIALIZE_COMPLETE) {
1737 initialize_pct = (vs->vs_initialize_bytes_done * 100 /
1738 (vs->vs_initialize_bytes_est + 1));
1739 }
1740
1741 (void) localtime_r(&t, &zaction_ts);
1742 (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts);
1743
1744 switch (vs->vs_initialize_state) {
1745 case VDEV_INITIALIZE_SUSPENDED:
1746 (void) snprintf(zbuf, sizeof (zbuf),
1747 ", suspended, started at %s", tbuf);
1748 break;
1749 case VDEV_INITIALIZE_ACTIVE:
1750 (void) snprintf(zbuf, sizeof (zbuf),
1751 ", started at %s", tbuf);
1752 break;
1753 case VDEV_INITIALIZE_COMPLETE:
1754 (void) snprintf(zbuf, sizeof (zbuf),
1755 ", completed at %s", tbuf);
1756 break;
1757 }
1758
1759 (void) printf(gettext(" (%d%% initialized%s)"),
1760 initialize_pct, zbuf);
1761 }
1762
1763 (void) printf("\n");
1764
1765 for (c = 0; c < children; c++) {
1766 uint64_t islog = B_FALSE, ishole = B_FALSE;
1767
1768 /* Don't print logs or holes here */
1769 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1770 &islog);
1771 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1772 &ishole);
1773 if (islog || ishole)
1774 continue;
1775 /* Only print normal classes here */
1776 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
1777 continue;
1778
1779 vname = zpool_vdev_name(g_zfs, zhp, child[c],
1780 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
1781 print_status_config(zhp, cb, vname, child[c], depth + 2,
1782 isspare);
1783 free(vname);
1784 }
1785 }
1786
1787 /*
1788 * Print the configuration of an exported pool. Iterate over all vdevs in the
1789 * pool, printing out the name and status for each one.
1790 */
1791 static void
print_import_config(status_cbdata_t * cb,const char * name,nvlist_t * nv,int depth)1792 print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
1793 int depth)
1794 {
1795 nvlist_t **child;
1796 uint_t c, children;
1797 vdev_stat_t *vs;
1798 char *type, *vname;
1799
1800 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1801 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1802 strcmp(type, VDEV_TYPE_HOLE) == 0)
1803 return;
1804
1805 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1806 (uint64_t **)&vs, &c) == 0);
1807
1808 (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
1809 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1810
1811 if (vs->vs_aux != 0) {
1812 (void) printf(" ");
1813
1814 switch (vs->vs_aux) {
1815 case VDEV_AUX_OPEN_FAILED:
1816 (void) printf(gettext("cannot open"));
1817 break;
1818
1819 case VDEV_AUX_BAD_GUID_SUM:
1820 (void) printf(gettext("missing device"));
1821 break;
1822
1823 case VDEV_AUX_NO_REPLICAS:
1824 (void) printf(gettext("insufficient replicas"));
1825 break;
1826
1827 case VDEV_AUX_VERSION_NEWER:
1828 (void) printf(gettext("newer version"));
1829 break;
1830
1831 case VDEV_AUX_UNSUP_FEAT:
1832 (void) printf(gettext("unsupported feature(s)"));
1833 break;
1834
1835 case VDEV_AUX_ERR_EXCEEDED:
1836 (void) printf(gettext("too many errors"));
1837 break;
1838
1839 case VDEV_AUX_ACTIVE:
1840 (void) printf(gettext("currently in use"));
1841 break;
1842
1843 case VDEV_AUX_CHILDREN_OFFLINE:
1844 (void) printf(gettext("all children offline"));
1845 break;
1846
1847 default:
1848 (void) printf(gettext("corrupted data"));
1849 break;
1850 }
1851 }
1852 (void) printf("\n");
1853
1854 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1855 &child, &children) != 0)
1856 return;
1857
1858 for (c = 0; c < children; c++) {
1859 uint64_t is_log = B_FALSE;
1860
1861 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1862 &is_log);
1863 if (is_log)
1864 continue;
1865 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
1866 continue;
1867
1868 vname = zpool_vdev_name(g_zfs, NULL, child[c],
1869 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
1870 print_import_config(cb, vname, child[c], depth + 2);
1871 free(vname);
1872 }
1873
1874 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1875 &child, &children) == 0) {
1876 (void) printf(gettext("\tcache\n"));
1877 for (c = 0; c < children; c++) {
1878 vname = zpool_vdev_name(g_zfs, NULL, child[c],
1879 cb->cb_name_flags);
1880 (void) printf("\t %s\n", vname);
1881 free(vname);
1882 }
1883 }
1884
1885 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1886 &child, &children) == 0) {
1887 (void) printf(gettext("\tspares\n"));
1888 for (c = 0; c < children; c++) {
1889 vname = zpool_vdev_name(g_zfs, NULL, child[c],
1890 cb->cb_name_flags);
1891 (void) printf("\t %s\n", vname);
1892 free(vname);
1893 }
1894 }
1895 }
1896
1897 /*
1898 * Print specialized class vdevs.
1899 *
1900 * These are recorded as top level vdevs in the main pool child array
1901 * but with "is_log" set to 1 or an "alloc_bias" string. We use either
1902 * print_status_config() or print_import_config() to print the top level
1903 * class vdevs then any of their children (eg mirrored slogs) are printed
1904 * recursively - which works because only the top level vdev is marked.
1905 */
1906 static void
print_class_vdevs(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t * nv,const char * class)1907 print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
1908 const char *class)
1909 {
1910 uint_t c, children;
1911 nvlist_t **child;
1912 boolean_t printed = B_FALSE;
1913
1914 assert(zhp != NULL || !cb->cb_verbose);
1915
1916 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1917 &children) != 0)
1918 return;
1919
1920 for (c = 0; c < children; c++) {
1921 uint64_t is_log = B_FALSE;
1922 char *bias = NULL;
1923 char *type = NULL;
1924
1925 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1926 &is_log);
1927
1928 if (is_log) {
1929 bias = VDEV_ALLOC_CLASS_LOGS;
1930 } else {
1931 (void) nvlist_lookup_string(child[c],
1932 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
1933 (void) nvlist_lookup_string(child[c],
1934 ZPOOL_CONFIG_TYPE, &type);
1935 }
1936
1937 if (bias == NULL || strcmp(bias, class) != 0)
1938 continue;
1939 if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1940 continue;
1941
1942 if (!printed) {
1943 (void) printf("\t%s\t\n", gettext(class));
1944 printed = B_TRUE;
1945 }
1946
1947 char *name = zpool_vdev_name(g_zfs, zhp, child[c],
1948 cb->cb_name_flags | VDEV_NAME_TYPE_ID);
1949 if (cb->cb_print_status)
1950 print_status_config(zhp, cb, name, child[c], 2,
1951 B_FALSE);
1952 else
1953 print_import_config(cb, name, child[c], 2);
1954 free(name);
1955 }
1956 }
1957
1958 /*
1959 * Display the status for the given pool.
1960 */
1961 static void
show_import(nvlist_t * config)1962 show_import(nvlist_t *config)
1963 {
1964 uint64_t pool_state;
1965 vdev_stat_t *vs;
1966 char *name;
1967 uint64_t guid;
1968 uint64_t hostid = 0;
1969 char *msgid;
1970 char *hostname = "unknown";
1971 nvlist_t *nvroot, *nvinfo;
1972 int reason;
1973 const char *health;
1974 uint_t vsc;
1975 char *comment;
1976 status_cbdata_t cb = { 0 };
1977
1978 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1979 &name) == 0);
1980 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1981 &guid) == 0);
1982 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1983 &pool_state) == 0);
1984 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1985 &nvroot) == 0);
1986
1987 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1988 (uint64_t **)&vs, &vsc) == 0);
1989 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1990
1991 reason = zpool_import_status(config, &msgid);
1992
1993 (void) printf(gettext(" pool: %s\n"), name);
1994 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1995 (void) printf(gettext(" state: %s"), health);
1996 if (pool_state == POOL_STATE_DESTROYED)
1997 (void) printf(gettext(" (DESTROYED)"));
1998 (void) printf("\n");
1999
2000 switch (reason) {
2001 case ZPOOL_STATUS_MISSING_DEV_R:
2002 case ZPOOL_STATUS_MISSING_DEV_NR:
2003 case ZPOOL_STATUS_BAD_GUID_SUM:
2004 (void) printf(gettext(" status: One or more devices are "
2005 "missing from the system.\n"));
2006 break;
2007
2008 case ZPOOL_STATUS_CORRUPT_LABEL_R:
2009 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2010 (void) printf(gettext(" status: One or more devices contains "
2011 "corrupted data.\n"));
2012 break;
2013
2014 case ZPOOL_STATUS_CORRUPT_DATA:
2015 (void) printf(
2016 gettext(" status: The pool data is corrupted.\n"));
2017 break;
2018
2019 case ZPOOL_STATUS_OFFLINE_DEV:
2020 (void) printf(gettext(" status: One or more devices "
2021 "are offlined.\n"));
2022 break;
2023
2024 case ZPOOL_STATUS_CORRUPT_POOL:
2025 (void) printf(gettext(" status: The pool metadata is "
2026 "corrupted.\n"));
2027 break;
2028
2029 case ZPOOL_STATUS_VERSION_OLDER:
2030 (void) printf(gettext(" status: The pool is formatted using a "
2031 "legacy on-disk version.\n"));
2032 break;
2033
2034 case ZPOOL_STATUS_VERSION_NEWER:
2035 (void) printf(gettext(" status: The pool is formatted using an "
2036 "incompatible version.\n"));
2037 break;
2038
2039 case ZPOOL_STATUS_FEAT_DISABLED:
2040 (void) printf(gettext(" status: Some supported features are "
2041 "not enabled on the pool.\n"));
2042 break;
2043
2044 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2045 (void) printf(gettext("status: The pool uses the following "
2046 "feature(s) not supported on this system:\n"));
2047 zpool_print_unsup_feat(config);
2048 break;
2049
2050 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2051 (void) printf(gettext("status: The pool can only be accessed "
2052 "in read-only mode on this system. It\n\tcannot be "
2053 "accessed in read-write mode because it uses the "
2054 "following\n\tfeature(s) not supported on this system:\n"));
2055 zpool_print_unsup_feat(config);
2056 break;
2057
2058 case ZPOOL_STATUS_HOSTID_ACTIVE:
2059 (void) printf(gettext(" status: The pool is currently "
2060 "imported by another system.\n"));
2061 break;
2062
2063 case ZPOOL_STATUS_HOSTID_REQUIRED:
2064 (void) printf(gettext(" status: The pool has the "
2065 "multihost property on. It cannot\n\tbe safely imported "
2066 "when the system hostid is not set.\n"));
2067 break;
2068
2069 case ZPOOL_STATUS_HOSTID_MISMATCH:
2070 (void) printf(gettext(" status: The pool was last accessed by "
2071 "another system.\n"));
2072 break;
2073
2074 case ZPOOL_STATUS_FAULTED_DEV_R:
2075 case ZPOOL_STATUS_FAULTED_DEV_NR:
2076 (void) printf(gettext(" status: One or more devices are "
2077 "faulted.\n"));
2078 break;
2079
2080 case ZPOOL_STATUS_BAD_LOG:
2081 (void) printf(gettext(" status: An intent log record cannot be "
2082 "read.\n"));
2083 break;
2084
2085 case ZPOOL_STATUS_RESILVERING:
2086 (void) printf(gettext(" status: One or more devices were being "
2087 "resilvered.\n"));
2088 break;
2089
2090 case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
2091 (void) printf(gettext("status: One or more devices were "
2092 "configured to use a non-native block size.\n"
2093 "\tExpect reduced performance.\n"));
2094 break;
2095
2096 default:
2097 /*
2098 * No other status can be seen when importing pools.
2099 */
2100 assert(reason == ZPOOL_STATUS_OK);
2101 }
2102
2103 /*
2104 * Print out an action according to the overall state of the pool.
2105 */
2106 if (vs->vs_state == VDEV_STATE_HEALTHY) {
2107 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
2108 reason == ZPOOL_STATUS_FEAT_DISABLED) {
2109 (void) printf(gettext(" action: The pool can be "
2110 "imported using its name or numeric identifier, "
2111 "though\n\tsome features will not be available "
2112 "without an explicit 'zpool upgrade'.\n"));
2113 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
2114 (void) printf(gettext(" action: The pool can be "
2115 "imported using its name or numeric "
2116 "identifier and\n\tthe '-f' flag.\n"));
2117 } else {
2118 (void) printf(gettext(" action: The pool can be "
2119 "imported using its name or numeric "
2120 "identifier.\n"));
2121 }
2122 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
2123 (void) printf(gettext(" action: The pool can be imported "
2124 "despite missing or damaged devices. The\n\tfault "
2125 "tolerance of the pool may be compromised if imported.\n"));
2126 } else {
2127 switch (reason) {
2128 case ZPOOL_STATUS_VERSION_NEWER:
2129 (void) printf(gettext(" action: The pool cannot be "
2130 "imported. Access the pool on a system running "
2131 "newer\n\tsoftware, or recreate the pool from "
2132 "backup.\n"));
2133 break;
2134 case ZPOOL_STATUS_UNSUP_FEAT_READ:
2135 (void) printf(gettext("action: The pool cannot be "
2136 "imported. Access the pool on a system that "
2137 "supports\n\tthe required feature(s), or recreate "
2138 "the pool from backup.\n"));
2139 break;
2140 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
2141 (void) printf(gettext("action: The pool cannot be "
2142 "imported in read-write mode. Import the pool "
2143 "with\n"
2144 "\t\"-o readonly=on\", access the pool on a system "
2145 "that supports the\n\trequired feature(s), or "
2146 "recreate the pool from backup.\n"));
2147 break;
2148 case ZPOOL_STATUS_MISSING_DEV_R:
2149 case ZPOOL_STATUS_MISSING_DEV_NR:
2150 case ZPOOL_STATUS_BAD_GUID_SUM:
2151 (void) printf(gettext(" action: The pool cannot be "
2152 "imported. Attach the missing\n\tdevices and try "
2153 "again.\n"));
2154 break;
2155 case ZPOOL_STATUS_HOSTID_ACTIVE:
2156 VERIFY0(nvlist_lookup_nvlist(config,
2157 ZPOOL_CONFIG_LOAD_INFO, &nvinfo));
2158
2159 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2160 hostname = fnvlist_lookup_string(nvinfo,
2161 ZPOOL_CONFIG_MMP_HOSTNAME);
2162
2163 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2164 hostid = fnvlist_lookup_uint64(nvinfo,
2165 ZPOOL_CONFIG_MMP_HOSTID);
2166
2167 (void) printf(gettext(" action: The pool must be "
2168 "exported from %s (hostid=%lx)\n\tbefore it "
2169 "can be safely imported.\n"), hostname,
2170 (unsigned long) hostid);
2171 break;
2172 case ZPOOL_STATUS_HOSTID_REQUIRED:
2173 (void) printf(gettext(" action: Check the SMF "
2174 "svc:/system/hostid service.\n"));
2175 break;
2176 default:
2177 (void) printf(gettext(" action: The pool cannot be "
2178 "imported due to damaged devices or data.\n"));
2179 }
2180 }
2181
2182 /* Print the comment attached to the pool. */
2183 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
2184 (void) printf(gettext("comment: %s\n"), comment);
2185
2186 /*
2187 * If the state is "closed" or "can't open", and the aux state
2188 * is "corrupt data":
2189 */
2190 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
2191 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
2192 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
2193 if (pool_state == POOL_STATE_DESTROYED)
2194 (void) printf(gettext("\tThe pool was destroyed, "
2195 "but can be imported using the '-Df' flags.\n"));
2196 else if (pool_state != POOL_STATE_EXPORTED)
2197 (void) printf(gettext("\tThe pool may be active on "
2198 "another system, but can be imported using\n\t"
2199 "the '-f' flag.\n"));
2200 }
2201
2202 if (msgid != NULL)
2203 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
2204 msgid);
2205
2206 (void) printf(gettext(" config:\n\n"));
2207
2208 cb.cb_namewidth = max_width(NULL, nvroot, 0, 0, 0);
2209 if (cb.cb_namewidth < 10)
2210 cb.cb_namewidth = 10;
2211
2212 print_import_config(&cb, name, nvroot, 0);
2213
2214 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
2215 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
2216 print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
2217
2218 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2219 (void) printf(gettext("\n\tAdditional devices are known to "
2220 "be part of this pool, though their\n\texact "
2221 "configuration cannot be determined.\n"));
2222 }
2223 }
2224
2225 static boolean_t
zfs_force_import_required(nvlist_t * config)2226 zfs_force_import_required(nvlist_t *config)
2227 {
2228 uint64_t state;
2229 uint64_t hostid = 0;
2230 nvlist_t *nvinfo;
2231
2232 state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE);
2233 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
2234
2235 if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid())
2236 return (B_TRUE);
2237
2238 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2239 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) {
2240 mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo,
2241 ZPOOL_CONFIG_MMP_STATE);
2242
2243 if (mmp_state != MMP_STATE_INACTIVE)
2244 return (B_TRUE);
2245 }
2246
2247 return (B_FALSE);
2248 }
2249
2250 /*
2251 * Perform the import for the given configuration. This passes the heavy
2252 * lifting off to zpool_import_props(), and then mounts the datasets contained
2253 * within the pool.
2254 */
2255 static int
do_import(nvlist_t * config,const char * newname,const char * mntopts,nvlist_t * props,int flags)2256 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2257 nvlist_t *props, int flags)
2258 {
2259 zpool_handle_t *zhp;
2260 char *name;
2261 uint64_t version;
2262
2263 name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
2264 version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION);
2265
2266 if (!SPA_VERSION_IS_SUPPORTED(version)) {
2267 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2268 "is formatted using an unsupported ZFS version\n"), name);
2269 return (1);
2270 } else if (zfs_force_import_required(config) &&
2271 !(flags & ZFS_IMPORT_ANY_HOST)) {
2272 mmp_state_t mmp_state = MMP_STATE_INACTIVE;
2273 nvlist_t *nvinfo;
2274
2275 nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO);
2276 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE))
2277 mmp_state = fnvlist_lookup_uint64(nvinfo,
2278 ZPOOL_CONFIG_MMP_STATE);
2279
2280 if (mmp_state == MMP_STATE_ACTIVE) {
2281 char *hostname = "<unknown>";
2282 uint64_t hostid = 0;
2283
2284 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME))
2285 hostname = fnvlist_lookup_string(nvinfo,
2286 ZPOOL_CONFIG_MMP_HOSTNAME);
2287
2288 if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID))
2289 hostid = fnvlist_lookup_uint64(nvinfo,
2290 ZPOOL_CONFIG_MMP_HOSTID);
2291
2292 (void) fprintf(stderr, gettext("cannot import '%s': "
2293 "pool is imported on %s (hostid: "
2294 "0x%lx)\nExport the pool on the other system, "
2295 "then run 'zpool import'.\n"),
2296 name, hostname, (unsigned long) hostid);
2297 } else if (mmp_state == MMP_STATE_NO_HOSTID) {
2298 (void) fprintf(stderr, gettext("Cannot import '%s': "
2299 "pool has the multihost property on and the\n"
2300 "system's hostid is not set.\n"), name);
2301 } else {
2302 char *hostname = "<unknown>";
2303 uint64_t timestamp = 0;
2304 uint64_t hostid = 0;
2305
2306 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME))
2307 hostname = fnvlist_lookup_string(config,
2308 ZPOOL_CONFIG_HOSTNAME);
2309
2310 if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP))
2311 timestamp = fnvlist_lookup_uint64(config,
2312 ZPOOL_CONFIG_TIMESTAMP);
2313
2314 if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID))
2315 hostid = fnvlist_lookup_uint64(config,
2316 ZPOOL_CONFIG_HOSTID);
2317
2318 (void) fprintf(stderr, gettext("cannot import '%s': "
2319 "pool was previously in use from another system.\n"
2320 "Last accessed by %s (hostid=%lx) at %s"
2321 "The pool can be imported, use 'zpool import -f' "
2322 "to import the pool.\n"), name, hostname,
2323 (unsigned long)hostid, ctime((time_t *)×tamp));
2324
2325 }
2326
2327 return (1);
2328 }
2329
2330 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2331 return (1);
2332
2333 if (newname != NULL)
2334 name = (char *)newname;
2335
2336 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2337 return (1);
2338
2339 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2340 !(flags & ZFS_IMPORT_ONLY) &&
2341 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2342 zpool_close(zhp);
2343 return (1);
2344 }
2345
2346 zpool_close(zhp);
2347 return (0);
2348 }
2349
2350 /*
2351 * zpool checkpoint <pool>
2352 * checkpoint --discard <pool>
2353 *
2354 * -d Discard the checkpoint from a checkpointed
2355 * --discard pool.
2356 *
2357 * Checkpoints the specified pool, by taking a "snapshot" of its
2358 * current state. A pool can only have one checkpoint at a time.
2359 */
2360 int
zpool_do_checkpoint(int argc,char ** argv)2361 zpool_do_checkpoint(int argc, char **argv)
2362 {
2363 boolean_t discard;
2364 char *pool;
2365 zpool_handle_t *zhp;
2366 int c, err;
2367
2368 struct option long_options[] = {
2369 {"discard", no_argument, NULL, 'd'},
2370 {0, 0, 0, 0}
2371 };
2372
2373 discard = B_FALSE;
2374 while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) {
2375 switch (c) {
2376 case 'd':
2377 discard = B_TRUE;
2378 break;
2379 case '?':
2380 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2381 optopt);
2382 usage(B_FALSE);
2383 }
2384 }
2385
2386 argc -= optind;
2387 argv += optind;
2388
2389 if (argc < 1) {
2390 (void) fprintf(stderr, gettext("missing pool argument\n"));
2391 usage(B_FALSE);
2392 }
2393
2394 if (argc > 1) {
2395 (void) fprintf(stderr, gettext("too many arguments\n"));
2396 usage(B_FALSE);
2397 }
2398
2399 pool = argv[0];
2400
2401 if ((zhp = zpool_open(g_zfs, pool)) == NULL) {
2402 /* As a special case, check for use of '/' in the name */
2403 if (strchr(pool, '/') != NULL)
2404 (void) fprintf(stderr, gettext("'zpool checkpoint' "
2405 "doesn't work on datasets. To save the state "
2406 "of a dataset from a specific point in time "
2407 "please use 'zfs snapshot'\n"));
2408 return (1);
2409 }
2410
2411 if (discard)
2412 err = (zpool_discard_checkpoint(zhp) != 0);
2413 else
2414 err = (zpool_checkpoint(zhp) != 0);
2415
2416 zpool_close(zhp);
2417
2418 return (err);
2419 }
2420
2421 #define CHECKPOINT_OPT 1024
2422
2423 /*
2424 * zpool import [-d dir] [-D]
2425 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2426 * [-d dir | -c cachefile] [-f] -a
2427 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2428 * [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
2429 * <pool | id> [newpool]
2430 *
2431 * -c Read pool information from a cachefile instead of searching
2432 * devices.
2433 *
2434 * -d Scan in a specific directory, other than /dev/dsk. More than
2435 * one directory can be specified using multiple '-d' options.
2436 *
2437 * -D Scan for previously destroyed pools or import all or only
2438 * specified destroyed pools.
2439 *
2440 * -R Temporarily import the pool, with all mountpoints relative to
2441 * the given root. The pool will remain exported when the machine
2442 * is rebooted.
2443 *
2444 * -V Import even in the presence of faulted vdevs. This is an
2445 * intentionally undocumented option for testing purposes, and
2446 * treats the pool configuration as complete, leaving any bad
2447 * vdevs in the FAULTED state. In other words, it does verbatim
2448 * import.
2449 *
2450 * -f Force import, even if it appears that the pool is active.
2451 *
2452 * -F Attempt rewind if necessary.
2453 *
2454 * -n See if rewind would work, but don't actually rewind.
2455 *
2456 * -N Import the pool but don't mount datasets.
2457 *
2458 * -t Use newpool as a temporary pool name instead of renaming
2459 * the pool.
2460 *
2461 * -T Specify a starting txg to use for import. This option is
2462 * intentionally undocumented option for testing purposes.
2463 *
2464 * -a Import all pools found.
2465 *
2466 * -o Set property=value and/or temporary mount options (without '=').
2467 *
2468 * --rewind-to-checkpoint
2469 * Import the pool and revert back to the checkpoint.
2470 *
2471 * The import command scans for pools to import, and import pools based on pool
2472 * name and GUID. The pool can also be renamed as part of the import process.
2473 */
2474 int
zpool_do_import(int argc,char ** argv)2475 zpool_do_import(int argc, char **argv)
2476 {
2477 char **searchdirs = NULL;
2478 int nsearch = 0;
2479 int c;
2480 int err = 0;
2481 nvlist_t *pools = NULL;
2482 boolean_t do_all = B_FALSE;
2483 boolean_t do_destroyed = B_FALSE;
2484 char *mntopts = NULL;
2485 nvpair_t *elem;
2486 nvlist_t *config;
2487 uint64_t searchguid = 0;
2488 char *searchname = NULL;
2489 char *propval;
2490 nvlist_t *found_config;
2491 nvlist_t *policy = NULL;
2492 nvlist_t *props = NULL;
2493 boolean_t first;
2494 int flags = ZFS_IMPORT_NORMAL;
2495 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2496 boolean_t dryrun = B_FALSE;
2497 boolean_t do_rewind = B_FALSE;
2498 boolean_t xtreme_rewind = B_FALSE;
2499 uint64_t pool_state, txg = -1ULL;
2500 char *cachefile = NULL;
2501 importargs_t idata = { 0 };
2502 char *endptr;
2503
2504
2505 struct option long_options[] = {
2506 {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
2507 {0, 0, 0, 0}
2508 };
2509
2510 /* check options */
2511 while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:tT:VX",
2512 long_options, NULL)) != -1) {
2513 switch (c) {
2514 case 'a':
2515 do_all = B_TRUE;
2516 break;
2517 case 'c':
2518 cachefile = optarg;
2519 break;
2520 case 'd':
2521 if (searchdirs == NULL) {
2522 searchdirs = safe_malloc(sizeof (char *));
2523 } else {
2524 char **tmp = safe_malloc((nsearch + 1) *
2525 sizeof (char *));
2526 bcopy(searchdirs, tmp, nsearch *
2527 sizeof (char *));
2528 free(searchdirs);
2529 searchdirs = tmp;
2530 }
2531 searchdirs[nsearch++] = optarg;
2532 break;
2533 case 'D':
2534 do_destroyed = B_TRUE;
2535 break;
2536 case 'f':
2537 flags |= ZFS_IMPORT_ANY_HOST;
2538 break;
2539 case 'F':
2540 do_rewind = B_TRUE;
2541 break;
2542 case 'm':
2543 flags |= ZFS_IMPORT_MISSING_LOG;
2544 break;
2545 case 'n':
2546 dryrun = B_TRUE;
2547 break;
2548 case 'N':
2549 flags |= ZFS_IMPORT_ONLY;
2550 break;
2551 case 'o':
2552 if ((propval = strchr(optarg, '=')) != NULL) {
2553 *propval = '\0';
2554 propval++;
2555 if (add_prop_list(optarg, propval,
2556 &props, B_TRUE))
2557 goto error;
2558 } else {
2559 mntopts = optarg;
2560 }
2561 break;
2562 case 'R':
2563 if (add_prop_list(zpool_prop_to_name(
2564 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2565 goto error;
2566 if (add_prop_list_default(zpool_prop_to_name(
2567 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2568 goto error;
2569 break;
2570 case 't':
2571 flags |= ZFS_IMPORT_TEMP_NAME;
2572 if (add_prop_list_default(zpool_prop_to_name(
2573 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2574 goto error;
2575 break;
2576 case 'T':
2577 errno = 0;
2578 txg = strtoull(optarg, &endptr, 0);
2579 if (errno != 0 || *endptr != '\0') {
2580 (void) fprintf(stderr,
2581 gettext("invalid txg value\n"));
2582 usage(B_FALSE);
2583 }
2584 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2585 break;
2586 case 'V':
2587 flags |= ZFS_IMPORT_VERBATIM;
2588 break;
2589 case 'X':
2590 xtreme_rewind = B_TRUE;
2591 break;
2592 case CHECKPOINT_OPT:
2593 flags |= ZFS_IMPORT_CHECKPOINT;
2594 break;
2595 case ':':
2596 (void) fprintf(stderr, gettext("missing argument for "
2597 "'%c' option\n"), optopt);
2598 usage(B_FALSE);
2599 break;
2600 case '?':
2601 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2602 optopt);
2603 usage(B_FALSE);
2604 }
2605 }
2606
2607 argc -= optind;
2608 argv += optind;
2609
2610 if (cachefile && nsearch != 0) {
2611 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2612 usage(B_FALSE);
2613 }
2614
2615 if ((dryrun || xtreme_rewind) && !do_rewind) {
2616 (void) fprintf(stderr,
2617 gettext("-n or -X only meaningful with -F\n"));
2618 usage(B_FALSE);
2619 }
2620 if (dryrun)
2621 rewind_policy = ZPOOL_TRY_REWIND;
2622 else if (do_rewind)
2623 rewind_policy = ZPOOL_DO_REWIND;
2624 if (xtreme_rewind)
2625 rewind_policy |= ZPOOL_EXTREME_REWIND;
2626
2627 /* In the future, we can capture further policy and include it here */
2628 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2629 nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 ||
2630 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
2631 rewind_policy) != 0)
2632 goto error;
2633
2634 if (searchdirs == NULL) {
2635 searchdirs = safe_malloc(sizeof (char *));
2636 searchdirs[0] = "/dev";
2637 nsearch = 1;
2638 }
2639
2640 /* check argument count */
2641 if (do_all) {
2642 if (argc != 0) {
2643 (void) fprintf(stderr, gettext("too many arguments\n"));
2644 usage(B_FALSE);
2645 }
2646 } else {
2647 if (argc > 2) {
2648 (void) fprintf(stderr, gettext("too many arguments\n"));
2649 usage(B_FALSE);
2650 }
2651
2652 /*
2653 * Check for the SYS_CONFIG privilege. We do this explicitly
2654 * here because otherwise any attempt to discover pools will
2655 * silently fail.
2656 */
2657 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2658 (void) fprintf(stderr, gettext("cannot "
2659 "discover pools: permission denied\n"));
2660 free(searchdirs);
2661 nvlist_free(policy);
2662 return (1);
2663 }
2664 }
2665
2666 /*
2667 * Depending on the arguments given, we do one of the following:
2668 *
2669 * <none> Iterate through all pools and display information about
2670 * each one.
2671 *
2672 * -a Iterate through all pools and try to import each one.
2673 *
2674 * <id> Find the pool that corresponds to the given GUID/pool
2675 * name and import that one.
2676 *
2677 * -D Above options applies only to destroyed pools.
2678 */
2679 if (argc != 0) {
2680 char *endptr;
2681
2682 errno = 0;
2683 searchguid = strtoull(argv[0], &endptr, 10);
2684 if (errno != 0 || *endptr != '\0') {
2685 searchname = argv[0];
2686 searchguid = 0;
2687 }
2688 found_config = NULL;
2689
2690 /*
2691 * User specified a name or guid. Ensure it's unique.
2692 */
2693 idata.unique = B_TRUE;
2694 }
2695
2696
2697 idata.path = searchdirs;
2698 idata.paths = nsearch;
2699 idata.poolname = searchname;
2700 idata.guid = searchguid;
2701 idata.cachefile = cachefile;
2702 idata.policy = policy;
2703
2704 pools = zpool_search_import(g_zfs, &idata);
2705
2706 if (pools != NULL && idata.exists &&
2707 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2708 (void) fprintf(stderr, gettext("cannot import '%s': "
2709 "a pool with that name already exists\n"),
2710 argv[0]);
2711 (void) fprintf(stderr, gettext("use the form 'zpool import "
2712 "[-t] <pool | id> <newpool>' to give it a new temporary "
2713 "or permanent name\n"));
2714 err = 1;
2715 } else if (pools == NULL && idata.exists) {
2716 (void) fprintf(stderr, gettext("cannot import '%s': "
2717 "a pool with that name is already created/imported,\n"),
2718 argv[0]);
2719 (void) fprintf(stderr, gettext("and no additional pools "
2720 "with that name were found\n"));
2721 err = 1;
2722 } else if (pools == NULL) {
2723 if (argc != 0) {
2724 (void) fprintf(stderr, gettext("cannot import '%s': "
2725 "no such pool available\n"), argv[0]);
2726 }
2727 err = 1;
2728 }
2729
2730 if (err == 1) {
2731 free(searchdirs);
2732 nvlist_free(policy);
2733 return (1);
2734 }
2735
2736 /*
2737 * At this point we have a list of import candidate configs. Even if
2738 * we were searching by pool name or guid, we still need to
2739 * post-process the list to deal with pool state and possible
2740 * duplicate names.
2741 */
2742 err = 0;
2743 elem = NULL;
2744 first = B_TRUE;
2745 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2746
2747 verify(nvpair_value_nvlist(elem, &config) == 0);
2748
2749 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2750 &pool_state) == 0);
2751 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2752 continue;
2753 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2754 continue;
2755
2756 verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
2757 policy) == 0);
2758
2759 if (argc == 0) {
2760 if (first)
2761 first = B_FALSE;
2762 else if (!do_all)
2763 (void) printf("\n");
2764
2765 if (do_all) {
2766 err |= do_import(config, NULL, mntopts,
2767 props, flags);
2768 } else {
2769 show_import(config);
2770 }
2771 } else if (searchname != NULL) {
2772 char *name;
2773
2774 /*
2775 * We are searching for a pool based on name.
2776 */
2777 verify(nvlist_lookup_string(config,
2778 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2779
2780 if (strcmp(name, searchname) == 0) {
2781 if (found_config != NULL) {
2782 (void) fprintf(stderr, gettext(
2783 "cannot import '%s': more than "
2784 "one matching pool\n"), searchname);
2785 (void) fprintf(stderr, gettext(
2786 "import by numeric ID instead\n"));
2787 err = B_TRUE;
2788 }
2789 found_config = config;
2790 }
2791 } else {
2792 uint64_t guid;
2793
2794 /*
2795 * Search for a pool by guid.
2796 */
2797 verify(nvlist_lookup_uint64(config,
2798 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2799
2800 if (guid == searchguid)
2801 found_config = config;
2802 }
2803 }
2804
2805 /*
2806 * If we were searching for a specific pool, verify that we found a
2807 * pool, and then do the import.
2808 */
2809 if (argc != 0 && err == 0) {
2810 if (found_config == NULL) {
2811 (void) fprintf(stderr, gettext("cannot import '%s': "
2812 "no such pool available\n"), argv[0]);
2813 err = B_TRUE;
2814 } else {
2815 err |= do_import(found_config, argc == 1 ? NULL :
2816 argv[1], mntopts, props, flags);
2817 }
2818 }
2819
2820 /*
2821 * If we were just looking for pools, report an error if none were
2822 * found.
2823 */
2824 if (argc == 0 && first)
2825 (void) fprintf(stderr,
2826 gettext("no pools available to import\n"));
2827
2828 error:
2829 nvlist_free(props);
2830 nvlist_free(pools);
2831 nvlist_free(policy);
2832 free(searchdirs);
2833
2834 return (err ? 1 : 0);
2835 }
2836
2837 /*
2838 * zpool sync [-f] [pool] ...
2839 *
2840 * -f (undocumented) force uberblock (and config including zpool cache file)
2841 * update.
2842 *
2843 * Sync the specified pool(s).
2844 * Without arguments "zpool sync" will sync all pools.
2845 * This command initiates TXG sync(s) and will return after the TXG(s) commit.
2846 *
2847 */
2848 static int
zpool_do_sync(int argc,char ** argv)2849 zpool_do_sync(int argc, char **argv)
2850 {
2851 int ret;
2852 boolean_t force = B_FALSE;
2853
2854 /* check options */
2855 while ((ret = getopt(argc, argv, "f")) != -1) {
2856 switch (ret) {
2857 case 'f':
2858 force = B_TRUE;
2859 break;
2860 case '?':
2861 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2862 optopt);
2863 usage(B_FALSE);
2864 }
2865 }
2866
2867 argc -= optind;
2868 argv += optind;
2869
2870 /* if argc == 0 we will execute zpool_sync_one on all pools */
2871 ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);
2872
2873 return (ret);
2874 }
2875
2876 typedef struct iostat_cbdata {
2877 boolean_t cb_verbose;
2878 int cb_name_flags;
2879 int cb_namewidth;
2880 int cb_iteration;
2881 boolean_t cb_scripted;
2882 zpool_list_t *cb_list;
2883 } iostat_cbdata_t;
2884
2885 static void
print_iostat_separator(iostat_cbdata_t * cb)2886 print_iostat_separator(iostat_cbdata_t *cb)
2887 {
2888 int i = 0;
2889
2890 for (i = 0; i < cb->cb_namewidth; i++)
2891 (void) printf("-");
2892 (void) printf(" ----- ----- ----- ----- ----- -----\n");
2893 }
2894
2895 static void
print_iostat_header(iostat_cbdata_t * cb)2896 print_iostat_header(iostat_cbdata_t *cb)
2897 {
2898 (void) printf("%*s capacity operations bandwidth\n",
2899 cb->cb_namewidth, "");
2900 (void) printf("%-*s alloc free read write read write\n",
2901 cb->cb_namewidth, "pool");
2902 print_iostat_separator(cb);
2903 }
2904
2905 /*
2906 * Display a single statistic.
2907 */
2908 static void
print_one_stat(uint64_t value)2909 print_one_stat(uint64_t value)
2910 {
2911 char buf[64];
2912
2913 zfs_nicenum(value, buf, sizeof (buf));
2914 (void) printf(" %5s", buf);
2915 }
2916
2917 static const char *class_name[] = {
2918 VDEV_ALLOC_BIAS_DEDUP,
2919 VDEV_ALLOC_BIAS_SPECIAL,
2920 VDEV_ALLOC_CLASS_LOGS
2921 };
2922
2923 /*
2924 * Print out all the statistics for the given vdev. This can either be the
2925 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2926 * is a verbose output, and we don't want to display the toplevel pool stats.
2927 *
2928 * Returns the number of stat lines printed.
2929 */
2930 static unsigned int
print_vdev_stats(zpool_handle_t * zhp,const char * name,nvlist_t * oldnv,nvlist_t * newnv,iostat_cbdata_t * cb,int depth)2931 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2932 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2933 {
2934 nvlist_t **oldchild, **newchild;
2935 uint_t c, children;
2936 vdev_stat_t *oldvs, *newvs;
2937 vdev_stat_t zerovs = { 0 };
2938 char *vname;
2939 int ret = 0;
2940 uint64_t tdelta;
2941 double scale;
2942
2943 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2944 return (ret);
2945
2946 if (oldnv != NULL) {
2947 verify(nvlist_lookup_uint64_array(oldnv,
2948 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2949 } else {
2950 oldvs = &zerovs;
2951 }
2952
2953 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2954 (uint64_t **)&newvs, &c) == 0);
2955
2956 if (strlen(name) + depth > cb->cb_namewidth)
2957 (void) printf("%*s%s", depth, "", name);
2958 else
2959 (void) printf("%*s%s%*s", depth, "", name,
2960 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2961
2962 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2963
2964 if (tdelta == 0)
2965 scale = 1.0;
2966 else
2967 scale = (double)NANOSEC / tdelta;
2968
2969 /* only toplevel vdevs have capacity stats */
2970 if (newvs->vs_space == 0) {
2971 (void) printf(" - -");
2972 } else {
2973 print_one_stat(newvs->vs_alloc);
2974 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2975 }
2976
2977 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2978 oldvs->vs_ops[ZIO_TYPE_READ])));
2979
2980 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2981 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2982
2983 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2984 oldvs->vs_bytes[ZIO_TYPE_READ])));
2985
2986 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2987 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2988
2989 (void) printf("\n");
2990
2991 if (!cb->cb_verbose)
2992 return (ret);
2993
2994 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2995 &newchild, &children) != 0)
2996 return (ret);
2997
2998 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2999 &oldchild, &c) != 0)
3000 return (ret);
3001
3002 /*
3003 * print normal top-level devices
3004 */
3005 for (c = 0; c < children; c++) {
3006 uint64_t ishole = B_FALSE, islog = B_FALSE;
3007
3008 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
3009 &ishole);
3010
3011 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
3012 &islog);
3013
3014 if (ishole || islog)
3015 continue;
3016
3017 if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
3018 continue;
3019
3020 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
3021 cb->cb_name_flags);
3022 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
3023 newchild[c], cb, depth + 2);
3024 free(vname);
3025 }
3026
3027 /*
3028 * print all other top-level devices
3029 */
3030 for (uint_t n = 0; n < 3; n++) {
3031 for (c = 0; c < children; c++) {
3032 uint64_t islog = B_FALSE;
3033 char *bias = NULL;
3034 char *type = NULL;
3035
3036 (void) nvlist_lookup_uint64(newchild[c],
3037 ZPOOL_CONFIG_IS_LOG, &islog);
3038 if (islog) {
3039 bias = VDEV_ALLOC_CLASS_LOGS;
3040 } else {
3041 (void) nvlist_lookup_string(newchild[c],
3042 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
3043 (void) nvlist_lookup_string(newchild[c],
3044 ZPOOL_CONFIG_TYPE, &type);
3045 }
3046 if (bias == NULL || strcmp(bias, class_name[n]) != 0)
3047 continue;
3048 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
3049 continue;
3050
3051 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
3052 cb->cb_name_flags);
3053 ret += print_vdev_stats(zhp, vname, oldnv ?
3054 oldchild[c] : NULL, newchild[c], cb, depth + 2);
3055 free(vname);
3056 }
3057
3058 }
3059
3060 /*
3061 * Include level 2 ARC devices in iostat output
3062 */
3063 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
3064 &newchild, &children) != 0)
3065 return (ret);
3066
3067 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
3068 &oldchild, &c) != 0)
3069 return (ret);
3070
3071 if (children > 0) {
3072 (void) printf("%-*s - - - - - "
3073 "-\n", cb->cb_namewidth, "cache");
3074 for (c = 0; c < children; c++) {
3075 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
3076 cb->cb_name_flags);
3077 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
3078 newchild[c], cb, depth + 2);
3079 free(vname);
3080 }
3081 }
3082
3083 return (ret);
3084 }
3085
3086 static int
refresh_iostat(zpool_handle_t * zhp,void * data)3087 refresh_iostat(zpool_handle_t *zhp, void *data)
3088 {
3089 iostat_cbdata_t *cb = data;
3090 boolean_t missing;
3091
3092 /*
3093 * If the pool has disappeared, remove it from the list and continue.
3094 */
3095 if (zpool_refresh_stats(zhp, &missing) != 0)
3096 return (-1);
3097
3098 if (missing)
3099 pool_list_remove(cb->cb_list, zhp);
3100
3101 return (0);
3102 }
3103
3104 /*
3105 * Callback to print out the iostats for the given pool.
3106 */
3107 int
print_iostat(zpool_handle_t * zhp,void * data)3108 print_iostat(zpool_handle_t *zhp, void *data)
3109 {
3110 iostat_cbdata_t *cb = data;
3111 nvlist_t *oldconfig, *newconfig;
3112 nvlist_t *oldnvroot, *newnvroot;
3113
3114 newconfig = zpool_get_config(zhp, &oldconfig);
3115
3116 if (cb->cb_iteration == 1)
3117 oldconfig = NULL;
3118
3119 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
3120 &newnvroot) == 0);
3121
3122 if (oldconfig == NULL)
3123 oldnvroot = NULL;
3124 else
3125 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
3126 &oldnvroot) == 0);
3127
3128 /*
3129 * Print out the statistics for the pool.
3130 */
3131 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
3132
3133 if (cb->cb_verbose)
3134 print_iostat_separator(cb);
3135
3136 return (0);
3137 }
3138
3139 int
get_namewidth(zpool_handle_t * zhp,void * data)3140 get_namewidth(zpool_handle_t *zhp, void *data)
3141 {
3142 iostat_cbdata_t *cb = data;
3143 nvlist_t *config, *nvroot;
3144
3145 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
3146 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3147 &nvroot) == 0);
3148 if (!cb->cb_verbose)
3149 cb->cb_namewidth = strlen(zpool_get_name(zhp));
3150 else
3151 cb->cb_namewidth = max_width(zhp, nvroot, 0,
3152 cb->cb_namewidth, cb->cb_name_flags);
3153 }
3154
3155 /*
3156 * The width must fall into the range [10,38]. The upper limit is the
3157 * maximum we can have and still fit in 80 columns.
3158 */
3159 if (cb->cb_namewidth < 10)
3160 cb->cb_namewidth = 10;
3161 if (cb->cb_namewidth > 38)
3162 cb->cb_namewidth = 38;
3163
3164 return (0);
3165 }
3166
3167 /*
3168 * Parse the input string, get the 'interval' and 'count' value if there is one.
3169 */
3170 static void
get_interval_count(int * argcp,char ** argv,unsigned long * iv,unsigned long * cnt)3171 get_interval_count(int *argcp, char **argv, unsigned long *iv,
3172 unsigned long *cnt)
3173 {
3174 unsigned long interval = 0, count = 0;
3175 int argc = *argcp, errno;
3176
3177 /*
3178 * Determine if the last argument is an integer or a pool name
3179 */
3180 if (argc > 0 && isdigit(argv[argc - 1][0])) {
3181 char *end;
3182
3183 errno = 0;
3184 interval = strtoul(argv[argc - 1], &end, 10);
3185
3186 if (*end == '\0' && errno == 0) {
3187 if (interval == 0) {
3188 (void) fprintf(stderr, gettext("interval "
3189 "cannot be zero\n"));
3190 usage(B_FALSE);
3191 }
3192 /*
3193 * Ignore the last parameter
3194 */
3195 argc--;
3196 } else {
3197 /*
3198 * If this is not a valid number, just plow on. The
3199 * user will get a more informative error message later
3200 * on.
3201 */
3202 interval = 0;
3203 }
3204 }
3205
3206 /*
3207 * If the last argument is also an integer, then we have both a count
3208 * and an interval.
3209 */
3210 if (argc > 0 && isdigit(argv[argc - 1][0])) {
3211 char *end;
3212
3213 errno = 0;
3214 count = interval;
3215 interval = strtoul(argv[argc - 1], &end, 10);
3216
3217 if (*end == '\0' && errno == 0) {
3218 if (interval == 0) {
3219 (void) fprintf(stderr, gettext("interval "
3220 "cannot be zero\n"));
3221 usage(B_FALSE);
3222 }
3223
3224 /*
3225 * Ignore the last parameter
3226 */
3227 argc--;
3228 } else {
3229 interval = 0;
3230 }
3231 }
3232
3233 *iv = interval;
3234 *cnt = count;
3235 *argcp = argc;
3236 }
3237
3238 static void
get_timestamp_arg(char c)3239 get_timestamp_arg(char c)
3240 {
3241 if (c == 'u')
3242 timestamp_fmt = UDATE;
3243 else if (c == 'd')
3244 timestamp_fmt = DDATE;
3245 else
3246 usage(B_FALSE);
3247 }
3248
3249 /*
3250 * zpool iostat [-gLPv] [-T d|u] [pool] ... [interval [count]]
3251 *
3252 * -g Display guid for individual vdev name.
3253 * -L Follow links when resolving vdev path name.
3254 * -P Display full path for vdev name.
3255 * -v Display statistics for individual vdevs
3256 * -T Display a timestamp in date(1) or Unix format
3257 *
3258 * This command can be tricky because we want to be able to deal with pool
3259 * creation/destruction as well as vdev configuration changes. The bulk of this
3260 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
3261 * on pool_list_update() to detect the addition of new pools. Configuration
3262 * changes are all handled within libzfs.
3263 */
3264 int
zpool_do_iostat(int argc,char ** argv)3265 zpool_do_iostat(int argc, char **argv)
3266 {
3267 int c;
3268 int ret;
3269 int npools;
3270 unsigned long interval = 0, count = 0;
3271 zpool_list_t *list;
3272 boolean_t verbose = B_FALSE;
3273 boolean_t guid = B_FALSE;
3274 boolean_t follow_links = B_FALSE;
3275 boolean_t full_name = B_FALSE;
3276 iostat_cbdata_t cb = { 0 };
3277
3278 /* check options */
3279 while ((c = getopt(argc, argv, "gLPT:v")) != -1) {
3280 switch (c) {
3281 case 'g':
3282 guid = B_TRUE;
3283 break;
3284 case 'L':
3285 follow_links = B_TRUE;
3286 break;
3287 case 'P':
3288 full_name = B_TRUE;
3289 break;
3290 case 'T':
3291 get_timestamp_arg(*optarg);
3292 break;
3293 case 'v':
3294 verbose = B_TRUE;
3295 break;
3296 case '?':
3297 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3298 optopt);
3299 usage(B_FALSE);
3300 }
3301 }
3302
3303 argc -= optind;
3304 argv += optind;
3305
3306 get_interval_count(&argc, argv, &interval, &count);
3307
3308 /*
3309 * Construct the list of all interesting pools.
3310 */
3311 ret = 0;
3312 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
3313 return (1);
3314
3315 if (pool_list_count(list) == 0 && argc != 0) {
3316 pool_list_free(list);
3317 return (1);
3318 }
3319
3320 if (pool_list_count(list) == 0 && interval == 0) {
3321 pool_list_free(list);
3322 (void) fprintf(stderr, gettext("no pools available\n"));
3323 return (1);
3324 }
3325
3326 /*
3327 * Enter the main iostat loop.
3328 */
3329 cb.cb_list = list;
3330 cb.cb_verbose = verbose;
3331 if (guid)
3332 cb.cb_name_flags |= VDEV_NAME_GUID;
3333 if (follow_links)
3334 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
3335 if (full_name)
3336 cb.cb_name_flags |= VDEV_NAME_PATH;
3337 cb.cb_iteration = 0;
3338 cb.cb_namewidth = 0;
3339
3340 for (;;) {
3341 pool_list_update(list);
3342
3343 if ((npools = pool_list_count(list)) == 0)
3344 break;
3345
3346 /*
3347 * Refresh all statistics. This is done as an explicit step
3348 * before calculating the maximum name width, so that any
3349 * configuration changes are properly accounted for.
3350 */
3351 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
3352
3353 /*
3354 * Iterate over all pools to determine the maximum width
3355 * for the pool / device name column across all pools.
3356 */
3357 cb.cb_namewidth = 0;
3358 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3359
3360 if (timestamp_fmt != NODATE)
3361 print_timestamp(timestamp_fmt);
3362
3363 /*
3364 * If it's the first time, or verbose mode, print the header.
3365 */
3366 if (++cb.cb_iteration == 1 || verbose)
3367 print_iostat_header(&cb);
3368
3369 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
3370
3371 /*
3372 * If there's more than one pool, and we're not in verbose mode
3373 * (which prints a separator for us), then print a separator.
3374 */
3375 if (npools > 1 && !verbose)
3376 print_iostat_separator(&cb);
3377
3378 if (verbose)
3379 (void) printf("\n");
3380
3381 /*
3382 * Flush the output so that redirection to a file isn't buffered
3383 * indefinitely.
3384 */
3385 (void) fflush(stdout);
3386
3387 if (interval == 0)
3388 break;
3389
3390 if (count != 0 && --count == 0)
3391 break;
3392
3393 (void) sleep(interval);
3394 }
3395
3396 pool_list_free(list);
3397
3398 return (ret);
3399 }
3400
3401 typedef struct list_cbdata {
3402 boolean_t cb_verbose;
3403 int cb_name_flags;
3404 int cb_namewidth;
3405 boolean_t cb_scripted;
3406 zprop_list_t *cb_proplist;
3407 boolean_t cb_literal;
3408 } list_cbdata_t;
3409
3410
3411 /*
3412 * Given a list of columns to display, output appropriate headers for each one.
3413 */
3414 static void
print_header(list_cbdata_t * cb)3415 print_header(list_cbdata_t *cb)
3416 {
3417 zprop_list_t *pl = cb->cb_proplist;
3418 char headerbuf[ZPOOL_MAXPROPLEN];
3419 const char *header;
3420 boolean_t first = B_TRUE;
3421 boolean_t right_justify;
3422 size_t width = 0;
3423
3424 for (; pl != NULL; pl = pl->pl_next) {
3425 width = pl->pl_width;
3426 if (first && cb->cb_verbose) {
3427 /*
3428 * Reset the width to accommodate the verbose listing
3429 * of devices.
3430 */
3431 width = cb->cb_namewidth;
3432 }
3433
3434 if (!first)
3435 (void) printf(" ");
3436 else
3437 first = B_FALSE;
3438
3439 right_justify = B_FALSE;
3440 if (pl->pl_prop != ZPROP_INVAL) {
3441 header = zpool_prop_column_name(pl->pl_prop);
3442 right_justify = zpool_prop_align_right(pl->pl_prop);
3443 } else {
3444 int i;
3445
3446 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
3447 headerbuf[i] = toupper(pl->pl_user_prop[i]);
3448 headerbuf[i] = '\0';
3449 header = headerbuf;
3450 }
3451
3452 if (pl->pl_next == NULL && !right_justify)
3453 (void) printf("%s", header);
3454 else if (right_justify)
3455 (void) printf("%*s", width, header);
3456 else
3457 (void) printf("%-*s", width, header);
3458
3459 }
3460
3461 (void) printf("\n");
3462 }
3463
3464 /*
3465 * Given a pool and a list of properties, print out all the properties according
3466 * to the described layout. Used by zpool_do_list().
3467 */
3468 static void
print_pool(zpool_handle_t * zhp,list_cbdata_t * cb)3469 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
3470 {
3471 zprop_list_t *pl = cb->cb_proplist;
3472 boolean_t first = B_TRUE;
3473 char property[ZPOOL_MAXPROPLEN];
3474 char *propstr;
3475 boolean_t right_justify;
3476 size_t width;
3477
3478 for (; pl != NULL; pl = pl->pl_next) {
3479
3480 width = pl->pl_width;
3481 if (first && cb->cb_verbose) {
3482 /*
3483 * Reset the width to accommodate the verbose listing
3484 * of devices.
3485 */
3486 width = cb->cb_namewidth;
3487 }
3488
3489 if (!first) {
3490 if (cb->cb_scripted)
3491 (void) printf("\t");
3492 else
3493 (void) printf(" ");
3494 } else {
3495 first = B_FALSE;
3496 }
3497
3498 right_justify = B_FALSE;
3499 if (pl->pl_prop != ZPROP_INVAL) {
3500 if (zpool_get_prop(zhp, pl->pl_prop, property,
3501 sizeof (property), NULL, cb->cb_literal) != 0)
3502 propstr = "-";
3503 else
3504 propstr = property;
3505
3506 right_justify = zpool_prop_align_right(pl->pl_prop);
3507 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
3508 zpool_prop_unsupported(pl->pl_user_prop)) &&
3509 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3510 sizeof (property)) == 0) {
3511 propstr = property;
3512 } else {
3513 propstr = "-";
3514 }
3515
3516
3517 /*
3518 * If this is being called in scripted mode, or if this is the
3519 * last column and it is left-justified, don't include a width
3520 * format specifier.
3521 */
3522 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3523 (void) printf("%s", propstr);
3524 else if (right_justify)
3525 (void) printf("%*s", width, propstr);
3526 else
3527 (void) printf("%-*s", width, propstr);
3528 }
3529
3530 (void) printf("\n");
3531 }
3532
3533 static void
print_one_column(zpool_prop_t prop,uint64_t value,boolean_t scripted,boolean_t valid)3534 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3535 boolean_t valid)
3536 {
3537 char propval[64];
3538 boolean_t fixed;
3539 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3540
3541 switch (prop) {
3542 case ZPOOL_PROP_EXPANDSZ:
3543 case ZPOOL_PROP_CHECKPOINT:
3544 if (value == 0)
3545 (void) strlcpy(propval, "-", sizeof (propval));
3546 else
3547 zfs_nicenum(value, propval, sizeof (propval));
3548 break;
3549 case ZPOOL_PROP_FRAGMENTATION:
3550 if (value == ZFS_FRAG_INVALID) {
3551 (void) strlcpy(propval, "-", sizeof (propval));
3552 } else {
3553 (void) snprintf(propval, sizeof (propval), "%llu%%",
3554 value);
3555 }
3556 break;
3557 case ZPOOL_PROP_CAPACITY:
3558 (void) snprintf(propval, sizeof (propval),
3559 value < 1000 ? "%1.2f%%" : value < 10000 ?
3560 "%2.1f%%" : "%3.0f%%", value / 100.0);
3561 break;
3562 default:
3563 zfs_nicenum(value, propval, sizeof (propval));
3564 }
3565
3566 if (!valid)
3567 (void) strlcpy(propval, "-", sizeof (propval));
3568
3569 if (scripted)
3570 (void) printf("\t%s", propval);
3571 else
3572 (void) printf(" %*s", width, propval);
3573 }
3574
3575 /*
3576 * print static default line per vdev
3577 */
3578 void
print_list_stats(zpool_handle_t * zhp,const char * name,nvlist_t * nv,list_cbdata_t * cb,int depth)3579 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3580 list_cbdata_t *cb, int depth)
3581 {
3582 nvlist_t **child;
3583 vdev_stat_t *vs;
3584 uint_t c, children;
3585 char *vname;
3586 boolean_t scripted = cb->cb_scripted;
3587 uint64_t islog = B_FALSE;
3588 char *dashes = "%-*s - - - - - -\n";
3589
3590 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3591 (uint64_t **)&vs, &c) == 0);
3592
3593 if (name != NULL) {
3594 boolean_t toplevel = (vs->vs_space != 0);
3595 uint64_t cap;
3596
3597 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3598 return;
3599
3600 if (scripted)
3601 (void) printf("\t%s", name);
3602 else if (strlen(name) + depth > cb->cb_namewidth)
3603 (void) printf("%*s%s", depth, "", name);
3604 else
3605 (void) printf("%*s%s%*s", depth, "", name,
3606 (int)(cb->cb_namewidth - strlen(name) - depth), "");
3607
3608 /*
3609 * Print the properties for the individual vdevs. Some
3610 * properties are only applicable to toplevel vdevs. The
3611 * 'toplevel' boolean value is passed to the print_one_column()
3612 * to indicate that the value is valid.
3613 */
3614 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3615 toplevel);
3616 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3617 toplevel);
3618 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3619 scripted, toplevel);
3620 print_one_column(ZPOOL_PROP_CHECKPOINT,
3621 vs->vs_checkpoint_space, scripted, toplevel);
3622 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3623 B_TRUE);
3624 print_one_column(ZPOOL_PROP_FRAGMENTATION,
3625 vs->vs_fragmentation, scripted,
3626 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3627 cap = (vs->vs_space == 0) ? 0 :
3628 (vs->vs_alloc * 10000 / vs->vs_space);
3629 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3630 (void) printf("\n");
3631 }
3632
3633 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3634 &child, &children) != 0)
3635 return;
3636
3637 /* list the normal vdevs first */
3638 for (c = 0; c < children; c++) {
3639 uint64_t ishole = B_FALSE;
3640
3641 if (nvlist_lookup_uint64(child[c],
3642 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3643 continue;
3644
3645 if (nvlist_lookup_uint64(child[c],
3646 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog)
3647 continue;
3648
3649 if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
3650 continue;
3651
3652 vname = zpool_vdev_name(g_zfs, zhp, child[c],
3653 cb->cb_name_flags);
3654 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3655 free(vname);
3656 }
3657
3658 /* list the classes: 'logs', 'dedup', and 'special' */
3659 for (uint_t n = 0; n < 3; n++) {
3660 boolean_t printed = B_FALSE;
3661
3662 for (c = 0; c < children; c++) {
3663 char *bias = NULL;
3664 char *type = NULL;
3665
3666 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3667 &islog) == 0 && islog) {
3668 bias = VDEV_ALLOC_CLASS_LOGS;
3669 } else {
3670 (void) nvlist_lookup_string(child[c],
3671 ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
3672 (void) nvlist_lookup_string(child[c],
3673 ZPOOL_CONFIG_TYPE, &type);
3674 }
3675 if (bias == NULL || strcmp(bias, class_name[n]) != 0)
3676 continue;
3677 if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
3678 continue;
3679
3680 if (!printed) {
3681 /* LINTED E_SEC_PRINTF_VAR_FMT */
3682 (void) printf(dashes, cb->cb_namewidth,
3683 class_name[n]);
3684 printed = B_TRUE;
3685 }
3686 vname = zpool_vdev_name(g_zfs, zhp, child[c],
3687 cb->cb_name_flags);
3688 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3689 free(vname);
3690 }
3691 }
3692
3693 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3694 &child, &children) == 0 && children > 0) {
3695 /* LINTED E_SEC_PRINTF_VAR_FMT */
3696 (void) printf(dashes, cb->cb_namewidth, "cache");
3697 for (c = 0; c < children; c++) {
3698 vname = zpool_vdev_name(g_zfs, zhp, child[c],
3699 cb->cb_name_flags);
3700 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3701 free(vname);
3702 }
3703 }
3704
3705 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3706 &children) == 0 && children > 0) {
3707 /* LINTED E_SEC_PRINTF_VAR_FMT */
3708 (void) printf(dashes, cb->cb_namewidth, "spare");
3709 for (c = 0; c < children; c++) {
3710 vname = zpool_vdev_name(g_zfs, zhp, child[c],
3711 cb->cb_name_flags);
3712 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3713 free(vname);
3714 }
3715 }
3716 }
3717
3718 /*
3719 * Generic callback function to list a pool.
3720 */
3721 int
list_callback(zpool_handle_t * zhp,void * data)3722 list_callback(zpool_handle_t *zhp, void *data)
3723 {
3724 list_cbdata_t *cbp = data;
3725 nvlist_t *config;
3726 nvlist_t *nvroot;
3727
3728 config = zpool_get_config(zhp, NULL);
3729
3730 if (cbp->cb_verbose) {
3731 config = zpool_get_config(zhp, NULL);
3732
3733 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3734 &nvroot) == 0);
3735 }
3736
3737 if (cbp->cb_verbose)
3738 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
3739 cbp->cb_name_flags);
3740
3741 print_pool(zhp, cbp);
3742
3743 if (cbp->cb_verbose)
3744 print_list_stats(zhp, NULL, nvroot, cbp, 0);
3745
3746 return (0);
3747 }
3748
3749 /*
3750 * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3751 *
3752 * -g Display guid for individual vdev name.
3753 * -H Scripted mode. Don't display headers, and separate properties
3754 * by a single tab.
3755 * -L Follow links when resolving vdev path name.
3756 * -o List of properties to display. Defaults to
3757 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
3758 * "dedupratio,health,altroot"
3759 * -p Diplay values in parsable (exact) format.
3760 * -P Display full path for vdev name.
3761 * -T Display a timestamp in date(1) or Unix format
3762 *
3763 * List all pools in the system, whether or not they're healthy. Output space
3764 * statistics for each one, as well as health status summary.
3765 */
3766 int
zpool_do_list(int argc,char ** argv)3767 zpool_do_list(int argc, char **argv)
3768 {
3769 int c;
3770 int ret;
3771 list_cbdata_t cb = { 0 };
3772 static char default_props[] =
3773 "name,size,allocated,free,checkpoint,expandsize,fragmentation,"
3774 "capacity,dedupratio,health,altroot";
3775 char *props = default_props;
3776 unsigned long interval = 0, count = 0;
3777 zpool_list_t *list;
3778 boolean_t first = B_TRUE;
3779
3780 /* check options */
3781 while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
3782 switch (c) {
3783 case 'g':
3784 cb.cb_name_flags |= VDEV_NAME_GUID;
3785 break;
3786 case 'H':
3787 cb.cb_scripted = B_TRUE;
3788 break;
3789 case 'L':
3790 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
3791 break;
3792 case 'o':
3793 props = optarg;
3794 break;
3795 case 'P':
3796 cb.cb_name_flags |= VDEV_NAME_PATH;
3797 break;
3798 case 'p':
3799 cb.cb_literal = B_TRUE;
3800 break;
3801 case 'T':
3802 get_timestamp_arg(*optarg);
3803 break;
3804 case 'v':
3805 cb.cb_verbose = B_TRUE;
3806 cb.cb_namewidth = 8; /* 8 until precalc is avail */
3807 break;
3808 case ':':
3809 (void) fprintf(stderr, gettext("missing argument for "
3810 "'%c' option\n"), optopt);
3811 usage(B_FALSE);
3812 break;
3813 case '?':
3814 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3815 optopt);
3816 usage(B_FALSE);
3817 }
3818 }
3819
3820 argc -= optind;
3821 argv += optind;
3822
3823 get_interval_count(&argc, argv, &interval, &count);
3824
3825 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3826 usage(B_FALSE);
3827
3828 for (;;) {
3829 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3830 &ret)) == NULL)
3831 return (1);
3832
3833 if (pool_list_count(list) == 0)
3834 break;
3835
3836 cb.cb_namewidth = 0;
3837 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3838
3839 if (timestamp_fmt != NODATE)
3840 print_timestamp(timestamp_fmt);
3841
3842 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3843 print_header(&cb);
3844 first = B_FALSE;
3845 }
3846 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3847
3848 if (interval == 0)
3849 break;
3850
3851 if (count != 0 && --count == 0)
3852 break;
3853
3854 pool_list_free(list);
3855 (void) sleep(interval);
3856 }
3857
3858 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3859 (void) printf(gettext("no pools available\n"));
3860 ret = 0;
3861 }
3862
3863 pool_list_free(list);
3864 zprop_free_list(cb.cb_proplist);
3865 return (ret);
3866 }
3867
3868 static int
zpool_do_attach_or_replace(int argc,char ** argv,int replacing)3869 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3870 {
3871 boolean_t force = B_FALSE;
3872 int c;
3873 nvlist_t *nvroot;
3874 char *poolname, *old_disk, *new_disk;
3875 zpool_handle_t *zhp;
3876 zpool_boot_label_t boot_type;
3877 uint64_t boot_size;
3878 int ret;
3879
3880 /* check options */
3881 while ((c = getopt(argc, argv, "f")) != -1) {
3882 switch (c) {
3883 case 'f':
3884 force = B_TRUE;
3885 break;
3886 case '?':
3887 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3888 optopt);
3889 usage(B_FALSE);
3890 }
3891 }
3892
3893 argc -= optind;
3894 argv += optind;
3895
3896 /* get pool name and check number of arguments */
3897 if (argc < 1) {
3898 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3899 usage(B_FALSE);
3900 }
3901
3902 poolname = argv[0];
3903
3904 if (argc < 2) {
3905 (void) fprintf(stderr,
3906 gettext("missing <device> specification\n"));
3907 usage(B_FALSE);
3908 }
3909
3910 old_disk = argv[1];
3911
3912 if (argc < 3) {
3913 if (!replacing) {
3914 (void) fprintf(stderr,
3915 gettext("missing <new_device> specification\n"));
3916 usage(B_FALSE);
3917 }
3918 new_disk = old_disk;
3919 argc -= 1;
3920 argv += 1;
3921 } else {
3922 new_disk = argv[2];
3923 argc -= 2;
3924 argv += 2;
3925 }
3926
3927 if (argc > 1) {
3928 (void) fprintf(stderr, gettext("too many arguments\n"));
3929 usage(B_FALSE);
3930 }
3931
3932 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3933 return (1);
3934
3935 if (zpool_get_config(zhp, NULL) == NULL) {
3936 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3937 poolname);
3938 zpool_close(zhp);
3939 return (1);
3940 }
3941
3942 if (zpool_is_bootable(zhp))
3943 boot_type = ZPOOL_COPY_BOOT_LABEL;
3944 else
3945 boot_type = ZPOOL_NO_BOOT_LABEL;
3946
3947 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3948 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3949 boot_type, boot_size, argc, argv);
3950 if (nvroot == NULL) {
3951 zpool_close(zhp);
3952 return (1);
3953 }
3954
3955 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3956
3957 nvlist_free(nvroot);
3958 zpool_close(zhp);
3959
3960 return (ret);
3961 }
3962
3963 /*
3964 * zpool replace [-f] <pool> <device> <new_device>
3965 *
3966 * -f Force attach, even if <new_device> appears to be in use.
3967 *
3968 * Replace <device> with <new_device>.
3969 */
3970 /* ARGSUSED */
3971 int
zpool_do_replace(int argc,char ** argv)3972 zpool_do_replace(int argc, char **argv)
3973 {
3974 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3975 }
3976
3977 /*
3978 * zpool attach [-f] <pool> <device> <new_device>
3979 *
3980 * -f Force attach, even if <new_device> appears to be in use.
3981 *
3982 * Attach <new_device> to the mirror containing <device>. If <device> is not
3983 * part of a mirror, then <device> will be transformed into a mirror of
3984 * <device> and <new_device>. In either case, <new_device> will begin life
3985 * with a DTL of [0, now], and will immediately begin to resilver itself.
3986 */
3987 int
zpool_do_attach(int argc,char ** argv)3988 zpool_do_attach(int argc, char **argv)
3989 {
3990 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3991 }
3992
3993 /*
3994 * zpool detach [-f] <pool> <device>
3995 *
3996 * -f Force detach of <device>, even if DTLs argue against it
3997 * (not supported yet)
3998 *
3999 * Detach a device from a mirror. The operation will be refused if <device>
4000 * is the last device in the mirror, or if the DTLs indicate that this device
4001 * has the only valid copy of some data.
4002 */
4003 /* ARGSUSED */
4004 int
zpool_do_detach(int argc,char ** argv)4005 zpool_do_detach(int argc, char **argv)
4006 {
4007 int c;
4008 char *poolname, *path;
4009 zpool_handle_t *zhp;
4010 int ret;
4011
4012 /* check options */
4013 while ((c = getopt(argc, argv, "f")) != -1) {
4014 switch (c) {
4015 case 'f':
4016 case '?':
4017 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4018 optopt);
4019 usage(B_FALSE);
4020 }
4021 }
4022
4023 argc -= optind;
4024 argv += optind;
4025
4026 /* get pool name and check number of arguments */
4027 if (argc < 1) {
4028 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4029 usage(B_FALSE);
4030 }
4031
4032 if (argc < 2) {
4033 (void) fprintf(stderr,
4034 gettext("missing <device> specification\n"));
4035 usage(B_FALSE);
4036 }
4037
4038 poolname = argv[0];
4039 path = argv[1];
4040
4041 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4042 return (1);
4043
4044 ret = zpool_vdev_detach(zhp, path);
4045
4046 zpool_close(zhp);
4047
4048 return (ret);
4049 }
4050
4051 /*
4052 * zpool split [-gLnP] [-o prop=val] ...
4053 * [-o mntopt] ...
4054 * [-R altroot] <pool> <newpool> [<device> ...]
4055 *
4056 * -g Display guid for individual vdev name.
4057 * -L Follow links when resolving vdev path name.
4058 * -n Do not split the pool, but display the resulting layout if
4059 * it were to be split.
4060 * -o Set property=value, or set mount options.
4061 * -P Display full path for vdev name.
4062 * -R Mount the split-off pool under an alternate root.
4063 *
4064 * Splits the named pool and gives it the new pool name. Devices to be split
4065 * off may be listed, provided that no more than one device is specified
4066 * per top-level vdev mirror. The newly split pool is left in an exported
4067 * state unless -R is specified.
4068 *
4069 * Restrictions: the top-level of the pool pool must only be made up of
4070 * mirrors; all devices in the pool must be healthy; no device may be
4071 * undergoing a resilvering operation.
4072 */
4073 int
zpool_do_split(int argc,char ** argv)4074 zpool_do_split(int argc, char **argv)
4075 {
4076 char *srcpool, *newpool, *propval;
4077 char *mntopts = NULL;
4078 splitflags_t flags;
4079 int c, ret = 0;
4080 zpool_handle_t *zhp;
4081 nvlist_t *config, *props = NULL;
4082
4083 flags.dryrun = B_FALSE;
4084 flags.import = B_FALSE;
4085 flags.name_flags = 0;
4086
4087 /* check options */
4088 while ((c = getopt(argc, argv, ":gLR:no:P")) != -1) {
4089 switch (c) {
4090 case 'g':
4091 flags.name_flags |= VDEV_NAME_GUID;
4092 break;
4093 case 'L':
4094 flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
4095 break;
4096 case 'R':
4097 flags.import = B_TRUE;
4098 if (add_prop_list(
4099 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
4100 &props, B_TRUE) != 0) {
4101 nvlist_free(props);
4102 usage(B_FALSE);
4103 }
4104 break;
4105 case 'n':
4106 flags.dryrun = B_TRUE;
4107 break;
4108 case 'o':
4109 if ((propval = strchr(optarg, '=')) != NULL) {
4110 *propval = '\0';
4111 propval++;
4112 if (add_prop_list(optarg, propval,
4113 &props, B_TRUE) != 0) {
4114 nvlist_free(props);
4115 usage(B_FALSE);
4116 }
4117 } else {
4118 mntopts = optarg;
4119 }
4120 break;
4121 case 'P':
4122 flags.name_flags |= VDEV_NAME_PATH;
4123 break;
4124 case ':':
4125 (void) fprintf(stderr, gettext("missing argument for "
4126 "'%c' option\n"), optopt);
4127 usage(B_FALSE);
4128 break;
4129 case '?':
4130 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4131 optopt);
4132 usage(B_FALSE);
4133 break;
4134 }
4135 }
4136
4137 if (!flags.import && mntopts != NULL) {
4138 (void) fprintf(stderr, gettext("setting mntopts is only "
4139 "valid when importing the pool\n"));
4140 usage(B_FALSE);
4141 }
4142
4143 argc -= optind;
4144 argv += optind;
4145
4146 if (argc < 1) {
4147 (void) fprintf(stderr, gettext("Missing pool name\n"));
4148 usage(B_FALSE);
4149 }
4150 if (argc < 2) {
4151 (void) fprintf(stderr, gettext("Missing new pool name\n"));
4152 usage(B_FALSE);
4153 }
4154
4155 srcpool = argv[0];
4156 newpool = argv[1];
4157
4158 argc -= 2;
4159 argv += 2;
4160
4161 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
4162 return (1);
4163
4164 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
4165 if (config == NULL) {
4166 ret = 1;
4167 } else {
4168 if (flags.dryrun) {
4169 (void) printf(gettext("would create '%s' with the "
4170 "following layout:\n\n"), newpool);
4171 print_vdev_tree(NULL, newpool, config, 0, "",
4172 flags.name_flags);
4173 }
4174 nvlist_free(config);
4175 }
4176
4177 zpool_close(zhp);
4178
4179 if (ret != 0 || flags.dryrun || !flags.import)
4180 return (ret);
4181
4182 /*
4183 * The split was successful. Now we need to open the new
4184 * pool and import it.
4185 */
4186 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
4187 return (1);
4188 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
4189 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
4190 ret = 1;
4191 (void) fprintf(stderr, gettext("Split was successful, but "
4192 "the datasets could not all be mounted\n"));
4193 (void) fprintf(stderr, gettext("Try doing '%s' with a "
4194 "different altroot\n"), "zpool import");
4195 }
4196 zpool_close(zhp);
4197
4198 return (ret);
4199 }
4200
4201
4202
4203 /*
4204 * zpool online <pool> <device> ...
4205 */
4206 int
zpool_do_online(int argc,char ** argv)4207 zpool_do_online(int argc, char **argv)
4208 {
4209 int c, i;
4210 char *poolname;
4211 zpool_handle_t *zhp;
4212 int ret = 0;
4213 vdev_state_t newstate;
4214 int flags = 0;
4215
4216 /* check options */
4217 while ((c = getopt(argc, argv, "et")) != -1) {
4218 switch (c) {
4219 case 'e':
4220 flags |= ZFS_ONLINE_EXPAND;
4221 break;
4222 case 't':
4223 case '?':
4224 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4225 optopt);
4226 usage(B_FALSE);
4227 }
4228 }
4229
4230 argc -= optind;
4231 argv += optind;
4232
4233 /* get pool name and check number of arguments */
4234 if (argc < 1) {
4235 (void) fprintf(stderr, gettext("missing pool name\n"));
4236 usage(B_FALSE);
4237 }
4238 if (argc < 2) {
4239 (void) fprintf(stderr, gettext("missing device name\n"));
4240 usage(B_FALSE);
4241 }
4242
4243 poolname = argv[0];
4244
4245 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4246 return (1);
4247
4248 for (i = 1; i < argc; i++) {
4249 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
4250 if (newstate != VDEV_STATE_HEALTHY) {
4251 (void) printf(gettext("warning: device '%s' "
4252 "onlined, but remains in faulted state\n"),
4253 argv[i]);
4254 if (newstate == VDEV_STATE_FAULTED)
4255 (void) printf(gettext("use 'zpool "
4256 "clear' to restore a faulted "
4257 "device\n"));
4258 else
4259 (void) printf(gettext("use 'zpool "
4260 "replace' to replace devices "
4261 "that are no longer present\n"));
4262 }
4263 } else {
4264 ret = 1;
4265 }
4266 }
4267
4268 zpool_close(zhp);
4269
4270 return (ret);
4271 }
4272
4273 /*
4274 * zpool offline [-ft] <pool> <device> ...
4275 *
4276 * -f Force the device into the offline state, even if doing
4277 * so would appear to compromise pool availability.
4278 * (not supported yet)
4279 *
4280 * -t Only take the device off-line temporarily. The offline
4281 * state will not be persistent across reboots.
4282 */
4283 /* ARGSUSED */
4284 int
zpool_do_offline(int argc,char ** argv)4285 zpool_do_offline(int argc, char **argv)
4286 {
4287 int c, i;
4288 char *poolname;
4289 zpool_handle_t *zhp;
4290 int ret = 0;
4291 boolean_t istmp = B_FALSE;
4292
4293 /* check options */
4294 while ((c = getopt(argc, argv, "ft")) != -1) {
4295 switch (c) {
4296 case 't':
4297 istmp = B_TRUE;
4298 break;
4299 case 'f':
4300 case '?':
4301 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4302 optopt);
4303 usage(B_FALSE);
4304 }
4305 }
4306
4307 argc -= optind;
4308 argv += optind;
4309
4310 /* get pool name and check number of arguments */
4311 if (argc < 1) {
4312 (void) fprintf(stderr, gettext("missing pool name\n"));
4313 usage(B_FALSE);
4314 }
4315 if (argc < 2) {
4316 (void) fprintf(stderr, gettext("missing device name\n"));
4317 usage(B_FALSE);
4318 }
4319
4320 poolname = argv[0];
4321
4322 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4323 return (1);
4324
4325 for (i = 1; i < argc; i++) {
4326 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
4327 ret = 1;
4328 }
4329
4330 zpool_close(zhp);
4331
4332 return (ret);
4333 }
4334
4335 /*
4336 * zpool clear <pool> [device]
4337 *
4338 * Clear all errors associated with a pool or a particular device.
4339 */
4340 int
zpool_do_clear(int argc,char ** argv)4341 zpool_do_clear(int argc, char **argv)
4342 {
4343 int c;
4344 int ret = 0;
4345 boolean_t dryrun = B_FALSE;
4346 boolean_t do_rewind = B_FALSE;
4347 boolean_t xtreme_rewind = B_FALSE;
4348 uint32_t rewind_policy = ZPOOL_NO_REWIND;
4349 nvlist_t *policy = NULL;
4350 zpool_handle_t *zhp;
4351 char *pool, *device;
4352
4353 /* check options */
4354 while ((c = getopt(argc, argv, "FnX")) != -1) {
4355 switch (c) {
4356 case 'F':
4357 do_rewind = B_TRUE;
4358 break;
4359 case 'n':
4360 dryrun = B_TRUE;
4361 break;
4362 case 'X':
4363 xtreme_rewind = B_TRUE;
4364 break;
4365 case '?':
4366 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4367 optopt);
4368 usage(B_FALSE);
4369 }
4370 }
4371
4372 argc -= optind;
4373 argv += optind;
4374
4375 if (argc < 1) {
4376 (void) fprintf(stderr, gettext("missing pool name\n"));
4377 usage(B_FALSE);
4378 }
4379
4380 if (argc > 2) {
4381 (void) fprintf(stderr, gettext("too many arguments\n"));
4382 usage(B_FALSE);
4383 }
4384
4385 if ((dryrun || xtreme_rewind) && !do_rewind) {
4386 (void) fprintf(stderr,
4387 gettext("-n or -X only meaningful with -F\n"));
4388 usage(B_FALSE);
4389 }
4390 if (dryrun)
4391 rewind_policy = ZPOOL_TRY_REWIND;
4392 else if (do_rewind)
4393 rewind_policy = ZPOOL_DO_REWIND;
4394 if (xtreme_rewind)
4395 rewind_policy |= ZPOOL_EXTREME_REWIND;
4396
4397 /* In future, further rewind policy choices can be passed along here */
4398 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
4399 nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY,
4400 rewind_policy) != 0) {
4401 return (1);
4402 }
4403
4404 pool = argv[0];
4405 device = argc == 2 ? argv[1] : NULL;
4406
4407 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
4408 nvlist_free(policy);
4409 return (1);
4410 }
4411
4412 if (zpool_clear(zhp, device, policy) != 0)
4413 ret = 1;
4414
4415 zpool_close(zhp);
4416
4417 nvlist_free(policy);
4418
4419 return (ret);
4420 }
4421
4422 /*
4423 * zpool reguid <pool>
4424 */
4425 int
zpool_do_reguid(int argc,char ** argv)4426 zpool_do_reguid(int argc, char **argv)
4427 {
4428 int c;
4429 char *poolname;
4430 zpool_handle_t *zhp;
4431 int ret = 0;
4432
4433 /* check options */
4434 while ((c = getopt(argc, argv, "")) != -1) {
4435 switch (c) {
4436 case '?':
4437 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4438 optopt);
4439 usage(B_FALSE);
4440 }
4441 }
4442
4443 argc -= optind;
4444 argv += optind;
4445
4446 /* get pool name and check number of arguments */
4447 if (argc < 1) {
4448 (void) fprintf(stderr, gettext("missing pool name\n"));
4449 usage(B_FALSE);
4450 }
4451
4452 if (argc > 1) {
4453 (void) fprintf(stderr, gettext("too many arguments\n"));
4454 usage(B_FALSE);
4455 }
4456
4457 poolname = argv[0];
4458 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
4459 return (1);
4460
4461 ret = zpool_reguid(zhp);
4462
4463 zpool_close(zhp);
4464 return (ret);
4465 }
4466
4467
4468 /*
4469 * zpool reopen <pool>
4470 *
4471 * Reopen the pool so that the kernel can update the sizes of all vdevs.
4472 */
4473 int
zpool_do_reopen(int argc,char ** argv)4474 zpool_do_reopen(int argc, char **argv)
4475 {
4476 int c;
4477 int ret = 0;
4478 zpool_handle_t *zhp;
4479 char *pool;
4480
4481 /* check options */
4482 while ((c = getopt(argc, argv, "")) != -1) {
4483 switch (c) {
4484 case '?':
4485 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4486 optopt);
4487 usage(B_FALSE);
4488 }
4489 }
4490
4491 argc--;
4492 argv++;
4493
4494 if (argc < 1) {
4495 (void) fprintf(stderr, gettext("missing pool name\n"));
4496 usage(B_FALSE);
4497 }
4498
4499 if (argc > 1) {
4500 (void) fprintf(stderr, gettext("too many arguments\n"));
4501 usage(B_FALSE);
4502 }
4503
4504 pool = argv[0];
4505 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
4506 return (1);
4507
4508 ret = zpool_reopen(zhp);
4509 zpool_close(zhp);
4510 return (ret);
4511 }
4512
4513 typedef struct scrub_cbdata {
4514 int cb_type;
4515 int cb_argc;
4516 char **cb_argv;
4517 pool_scrub_cmd_t cb_scrub_cmd;
4518 } scrub_cbdata_t;
4519
4520 static boolean_t
zpool_has_checkpoint(zpool_handle_t * zhp)4521 zpool_has_checkpoint(zpool_handle_t *zhp)
4522 {
4523 nvlist_t *config, *nvroot;
4524
4525 config = zpool_get_config(zhp, NULL);
4526
4527 if (config != NULL) {
4528 pool_checkpoint_stat_t *pcs = NULL;
4529 uint_t c;
4530
4531 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4532 (void) nvlist_lookup_uint64_array(nvroot,
4533 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
4534
4535 if (pcs == NULL || pcs->pcs_state == CS_NONE)
4536 return (B_FALSE);
4537
4538 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS ||
4539 pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
4540 return (B_TRUE);
4541 }
4542
4543 return (B_FALSE);
4544 }
4545
4546 int
scrub_callback(zpool_handle_t * zhp,void * data)4547 scrub_callback(zpool_handle_t *zhp, void *data)
4548 {
4549 scrub_cbdata_t *cb = data;
4550 int err;
4551
4552 /*
4553 * Ignore faulted pools.
4554 */
4555 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4556 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4557 "currently unavailable\n"), zpool_get_name(zhp));
4558 return (1);
4559 }
4560
4561 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4562
4563 if (err == 0 && zpool_has_checkpoint(zhp) &&
4564 cb->cb_type == POOL_SCAN_SCRUB) {
4565 (void) printf(gettext("warning: will not scrub state that "
4566 "belongs to the checkpoint of pool '%s'\n"),
4567 zpool_get_name(zhp));
4568 }
4569
4570 return (err != 0);
4571 }
4572
4573 /*
4574 * zpool scrub [-s | -p] <pool> ...
4575 *
4576 * -s Stop. Stops any in-progress scrub.
4577 * -p Pause. Pause in-progress scrub.
4578 */
4579 int
zpool_do_scrub(int argc,char ** argv)4580 zpool_do_scrub(int argc, char **argv)
4581 {
4582 int c;
4583 scrub_cbdata_t cb;
4584
4585 cb.cb_type = POOL_SCAN_SCRUB;
4586 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4587
4588 /* check options */
4589 while ((c = getopt(argc, argv, "sp")) != -1) {
4590 switch (c) {
4591 case 's':
4592 cb.cb_type = POOL_SCAN_NONE;
4593 break;
4594 case 'p':
4595 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4596 break;
4597 case '?':
4598 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4599 optopt);
4600 usage(B_FALSE);
4601 }
4602 }
4603
4604 if (cb.cb_type == POOL_SCAN_NONE &&
4605 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4606 (void) fprintf(stderr, gettext("invalid option combination: "
4607 "-s and -p are mutually exclusive\n"));
4608 usage(B_FALSE);
4609 }
4610
4611 cb.cb_argc = argc;
4612 cb.cb_argv = argv;
4613 argc -= optind;
4614 argv += optind;
4615
4616 if (argc < 1) {
4617 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4618 usage(B_FALSE);
4619 }
4620
4621 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4622 }
4623
4624 static void
zpool_collect_leaves(zpool_handle_t * zhp,nvlist_t * nvroot,nvlist_t * res)4625 zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
4626 {
4627 uint_t children = 0;
4628 nvlist_t **child;
4629 uint_t i;
4630
4631 (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4632 &child, &children);
4633
4634 if (children == 0) {
4635 char *path = zpool_vdev_name(g_zfs, zhp, nvroot, B_FALSE);
4636 fnvlist_add_boolean(res, path);
4637 free(path);
4638 return;
4639 }
4640
4641 for (i = 0; i < children; i++) {
4642 zpool_collect_leaves(zhp, child[i], res);
4643 }
4644 }
4645
4646 /*
4647 * zpool initialize [-cs] <pool> [<vdev> ...]
4648 * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
4649 * if none specified.
4650 *
4651 * -c Cancel. Ends active initializing.
4652 * -s Suspend. Initializing can then be restarted with no flags.
4653 */
4654 int
zpool_do_initialize(int argc,char ** argv)4655 zpool_do_initialize(int argc, char **argv)
4656 {
4657 int c;
4658 char *poolname;
4659 zpool_handle_t *zhp;
4660 nvlist_t *vdevs;
4661 int err = 0;
4662
4663 struct option long_options[] = {
4664 {"cancel", no_argument, NULL, 'c'},
4665 {"suspend", no_argument, NULL, 's'},
4666 {0, 0, 0, 0}
4667 };
4668
4669 pool_initialize_func_t cmd_type = POOL_INITIALIZE_DO;
4670 while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) {
4671 switch (c) {
4672 case 'c':
4673 if (cmd_type != POOL_INITIALIZE_DO) {
4674 (void) fprintf(stderr, gettext("-c cannot be "
4675 "combined with other options\n"));
4676 usage(B_FALSE);
4677 }
4678 cmd_type = POOL_INITIALIZE_CANCEL;
4679 break;
4680 case 's':
4681 if (cmd_type != POOL_INITIALIZE_DO) {
4682 (void) fprintf(stderr, gettext("-s cannot be "
4683 "combined with other options\n"));
4684 usage(B_FALSE);
4685 }
4686 cmd_type = POOL_INITIALIZE_SUSPEND;
4687 break;
4688 case '?':
4689 if (optopt != 0) {
4690 (void) fprintf(stderr,
4691 gettext("invalid option '%c'\n"), optopt);
4692 } else {
4693 (void) fprintf(stderr,
4694 gettext("invalid option '%s'\n"),
4695 argv[optind - 1]);
4696 }
4697 usage(B_FALSE);
4698 }
4699 }
4700
4701 argc -= optind;
4702 argv += optind;
4703
4704 if (argc < 1) {
4705 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4706 usage(B_FALSE);
4707 return (-1);
4708 }
4709
4710 poolname = argv[0];
4711 zhp = zpool_open(g_zfs, poolname);
4712 if (zhp == NULL)
4713 return (-1);
4714
4715 vdevs = fnvlist_alloc();
4716 if (argc == 1) {
4717 /* no individual leaf vdevs specified, so add them all */
4718 nvlist_t *config = zpool_get_config(zhp, NULL);
4719 nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
4720 ZPOOL_CONFIG_VDEV_TREE);
4721 zpool_collect_leaves(zhp, nvroot, vdevs);
4722 } else {
4723 int i;
4724 for (i = 1; i < argc; i++) {
4725 fnvlist_add_boolean(vdevs, argv[i]);
4726 }
4727 }
4728
4729 err = zpool_initialize(zhp, cmd_type, vdevs);
4730
4731 fnvlist_free(vdevs);
4732 zpool_close(zhp);
4733
4734 return (err);
4735 }
4736
4737 /*
4738 * Print out detailed scrub status.
4739 */
4740 static void
print_scan_status(pool_scan_stat_t * ps)4741 print_scan_status(pool_scan_stat_t *ps)
4742 {
4743 time_t start, end, pause;
4744 uint64_t total_secs_left;
4745 uint64_t elapsed, secs_left, mins_left, hours_left, days_left;
4746 uint64_t pass_scanned, scanned, pass_issued, issued, total;
4747 uint_t scan_rate, issue_rate;
4748 double fraction_done;
4749 char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7];
4750 char srate_buf[7], irate_buf[7];
4751
4752 (void) printf(gettext(" scan: "));
4753
4754 /* If there's never been a scan, there's not much to say. */
4755 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4756 ps->pss_func >= POOL_SCAN_FUNCS) {
4757 (void) printf(gettext("none requested\n"));
4758 return;
4759 }
4760
4761 start = ps->pss_start_time;
4762 end = ps->pss_end_time;
4763 pause = ps->pss_pass_scrub_pause;
4764
4765 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4766
4767 assert(ps->pss_func == POOL_SCAN_SCRUB ||
4768 ps->pss_func == POOL_SCAN_RESILVER);
4769
4770 /* Scan is finished or canceled. */
4771 if (ps->pss_state == DSS_FINISHED) {
4772 total_secs_left = end - start;
4773 days_left = total_secs_left / 60 / 60 / 24;
4774 hours_left = (total_secs_left / 60 / 60) % 24;
4775 mins_left = (total_secs_left / 60) % 60;
4776 secs_left = (total_secs_left % 60);
4777
4778 if (ps->pss_func == POOL_SCAN_SCRUB) {
4779 (void) printf(gettext("scrub repaired %s "
4780 "in %llu days %02llu:%02llu:%02llu "
4781 "with %llu errors on %s"), processed_buf,
4782 (u_longlong_t)days_left, (u_longlong_t)hours_left,
4783 (u_longlong_t)mins_left, (u_longlong_t)secs_left,
4784 (u_longlong_t)ps->pss_errors, ctime(&end));
4785 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4786 (void) printf(gettext("resilvered %s "
4787 "in %llu days %02llu:%02llu:%02llu "
4788 "with %llu errors on %s"), processed_buf,
4789 (u_longlong_t)days_left, (u_longlong_t)hours_left,
4790 (u_longlong_t)mins_left, (u_longlong_t)secs_left,
4791 (u_longlong_t)ps->pss_errors, ctime(&end));
4792
4793 }
4794
4795 return;
4796 } else if (ps->pss_state == DSS_CANCELED) {
4797 if (ps->pss_func == POOL_SCAN_SCRUB) {
4798 (void) printf(gettext("scrub canceled on %s"),
4799 ctime(&end));
4800 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4801 (void) printf(gettext("resilver canceled on %s"),
4802 ctime(&end));
4803 }
4804 return;
4805 }
4806
4807 assert(ps->pss_state == DSS_SCANNING);
4808
4809 /* Scan is in progress. Resilvers can't be paused. */
4810 if (ps->pss_func == POOL_SCAN_SCRUB) {
4811 if (pause == 0) {
4812 (void) printf(gettext("scrub in progress since %s"),
4813 ctime(&start));
4814 } else {
4815 (void) printf(gettext("scrub paused since %s"),
4816 ctime(&pause));
4817 (void) printf(gettext("\tscrub started on %s"),
4818 ctime(&start));
4819 }
4820 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4821 (void) printf(gettext("resilver in progress since %s"),
4822 ctime(&start));
4823 }
4824
4825 scanned = ps->pss_examined;
4826 pass_scanned = ps->pss_pass_exam;
4827 issued = ps->pss_issued;
4828 pass_issued = ps->pss_pass_issued;
4829 total = ps->pss_to_examine;
4830
4831 /* we are only done with a block once we have issued the IO for it */
4832 fraction_done = (double)issued / total;
4833
4834 /* elapsed time for this pass, rounding up to 1 if it's 0 */
4835 elapsed = time(NULL) - ps->pss_pass_start;
4836 elapsed -= ps->pss_pass_scrub_spent_paused;
4837 elapsed = (elapsed != 0) ? elapsed : 1;
4838
4839 scan_rate = pass_scanned / elapsed;
4840 issue_rate = pass_issued / elapsed;
4841 total_secs_left = (issue_rate != 0) ?
4842 ((total - issued) / issue_rate) : UINT64_MAX;
4843
4844 days_left = total_secs_left / 60 / 60 / 24;
4845 hours_left = (total_secs_left / 60 / 60) % 24;
4846 mins_left = (total_secs_left / 60) % 60;
4847 secs_left = (total_secs_left % 60);
4848
4849 /* format all of the numbers we will be reporting */
4850 zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf));
4851 zfs_nicenum(issued, issued_buf, sizeof (issued_buf));
4852 zfs_nicenum(total, total_buf, sizeof (total_buf));
4853 zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf));
4854 zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf));
4855
4856 /* doo not print estimated time if we have a paused scrub */
4857 if (pause == 0) {
4858 (void) printf(gettext("\t%s scanned at %s/s, "
4859 "%s issued at %s/s, %s total\n"),
4860 scanned_buf, srate_buf, issued_buf, irate_buf, total_buf);
4861 } else {
4862 (void) printf(gettext("\t%s scanned, %s issued, %s total\n"),
4863 scanned_buf, issued_buf, total_buf);
4864 }
4865
4866 if (ps->pss_func == POOL_SCAN_RESILVER) {
4867 (void) printf(gettext("\t%s resilvered, %.2f%% done"),
4868 processed_buf, 100 * fraction_done);
4869 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4870 (void) printf(gettext("\t%s repaired, %.2f%% done"),
4871 processed_buf, 100 * fraction_done);
4872 }
4873
4874 if (pause == 0) {
4875 if (issue_rate >= 10 * 1024 * 1024) {
4876 (void) printf(gettext(", %llu days "
4877 "%02llu:%02llu:%02llu to go\n"),
4878 (u_longlong_t)days_left, (u_longlong_t)hours_left,
4879 (u_longlong_t)mins_left, (u_longlong_t)secs_left);
4880 } else {
4881 (void) printf(gettext(", no estimated "
4882 "completion time\n"));
4883 }
4884 } else {
4885 (void) printf(gettext("\n"));
4886 }
4887 }
4888
4889 /*
4890 * As we don't scrub checkpointed blocks, we want to warn the
4891 * user that we skipped scanning some blocks if a checkpoint exists
4892 * or existed at any time during the scan.
4893 */
4894 static void
print_checkpoint_scan_warning(pool_scan_stat_t * ps,pool_checkpoint_stat_t * pcs)4895 print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs)
4896 {
4897 if (ps == NULL || pcs == NULL)
4898 return;
4899
4900 if (pcs->pcs_state == CS_NONE ||
4901 pcs->pcs_state == CS_CHECKPOINT_DISCARDING)
4902 return;
4903
4904 assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS);
4905
4906 if (ps->pss_state == DSS_NONE)
4907 return;
4908
4909 if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) &&
4910 ps->pss_end_time < pcs->pcs_start_time)
4911 return;
4912
4913 if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) {
4914 (void) printf(gettext(" scan warning: skipped blocks "
4915 "that are only referenced by the checkpoint.\n"));
4916 } else {
4917 assert(ps->pss_state == DSS_SCANNING);
4918 (void) printf(gettext(" scan warning: skipping blocks "
4919 "that are only referenced by the checkpoint.\n"));
4920 }
4921 }
4922
4923 /*
4924 * Print out detailed removal status.
4925 */
4926 static void
print_removal_status(zpool_handle_t * zhp,pool_removal_stat_t * prs)4927 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4928 {
4929 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4930 time_t start, end;
4931 nvlist_t *config, *nvroot;
4932 nvlist_t **child;
4933 uint_t children;
4934 char *vdev_name;
4935
4936 if (prs == NULL || prs->prs_state == DSS_NONE)
4937 return;
4938
4939 /*
4940 * Determine name of vdev.
4941 */
4942 config = zpool_get_config(zhp, NULL);
4943 nvroot = fnvlist_lookup_nvlist(config,
4944 ZPOOL_CONFIG_VDEV_TREE);
4945 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4946 &child, &children) == 0);
4947 assert(prs->prs_removing_vdev < children);
4948 vdev_name = zpool_vdev_name(g_zfs, zhp,
4949 child[prs->prs_removing_vdev], B_TRUE);
4950
4951 (void) printf(gettext("remove: "));
4952
4953 start = prs->prs_start_time;
4954 end = prs->prs_end_time;
4955 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4956
4957 /*
4958 * Removal is finished or canceled.
4959 */
4960 if (prs->prs_state == DSS_FINISHED) {
4961 uint64_t minutes_taken = (end - start) / 60;
4962
4963 (void) printf(gettext("Removal of vdev %llu copied %s "
4964 "in %lluh%um, completed on %s"),
4965 (longlong_t)prs->prs_removing_vdev,
4966 copied_buf,
4967 (u_longlong_t)(minutes_taken / 60),
4968 (uint_t)(minutes_taken % 60),
4969 ctime((time_t *)&end));
4970 } else if (prs->prs_state == DSS_CANCELED) {
4971 (void) printf(gettext("Removal of %s canceled on %s"),
4972 vdev_name, ctime(&end));
4973 } else {
4974 uint64_t copied, total, elapsed, mins_left, hours_left;
4975 double fraction_done;
4976 uint_t rate;
4977
4978 assert(prs->prs_state == DSS_SCANNING);
4979
4980 /*
4981 * Removal is in progress.
4982 */
4983 (void) printf(gettext(
4984 "Evacuation of %s in progress since %s"),
4985 vdev_name, ctime(&start));
4986
4987 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4988 total = prs->prs_to_copy;
4989 fraction_done = (double)copied / total;
4990
4991 /* elapsed time for this pass */
4992 elapsed = time(NULL) - prs->prs_start_time;
4993 elapsed = elapsed > 0 ? elapsed : 1;
4994 rate = copied / elapsed;
4995 rate = rate > 0 ? rate : 1;
4996 mins_left = ((total - copied) / rate) / 60;
4997 hours_left = mins_left / 60;
4998
4999 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
5000 zfs_nicenum(total, total_buf, sizeof (total_buf));
5001 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
5002
5003 /*
5004 * do not print estimated time if hours_left is more than
5005 * 30 days
5006 */
5007 (void) printf(gettext(" %s copied out of %s at %s/s, "
5008 "%.2f%% done"),
5009 examined_buf, total_buf, rate_buf, 100 * fraction_done);
5010 if (hours_left < (30 * 24)) {
5011 (void) printf(gettext(", %lluh%um to go\n"),
5012 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
5013 } else {
5014 (void) printf(gettext(
5015 ", (copy is slow, no estimated time)\n"));
5016 }
5017 }
5018
5019 if (prs->prs_mapping_memory > 0) {
5020 char mem_buf[7];
5021 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
5022 (void) printf(gettext(" %s memory used for "
5023 "removed device mappings\n"),
5024 mem_buf);
5025 }
5026 }
5027
5028 static void
print_checkpoint_status(pool_checkpoint_stat_t * pcs)5029 print_checkpoint_status(pool_checkpoint_stat_t *pcs)
5030 {
5031 time_t start;
5032 char space_buf[7];
5033
5034 if (pcs == NULL || pcs->pcs_state == CS_NONE)
5035 return;
5036
5037 (void) printf(gettext("checkpoint: "));
5038
5039 start = pcs->pcs_start_time;
5040 zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf));
5041
5042 if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) {
5043 char *date = ctime(&start);
5044
5045 /*
5046 * ctime() adds a newline at the end of the generated
5047 * string, thus the weird format specifier and the
5048 * strlen() call used to chop it off from the output.
5049 */
5050 (void) printf(gettext("created %.*s, consumes %s\n"),
5051 strlen(date) - 1, date, space_buf);
5052 return;
5053 }
5054
5055 assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING);
5056
5057 (void) printf(gettext("discarding, %s remaining.\n"),
5058 space_buf);
5059 }
5060
5061 static void
print_error_log(zpool_handle_t * zhp)5062 print_error_log(zpool_handle_t *zhp)
5063 {
5064 nvlist_t *nverrlist = NULL;
5065 nvpair_t *elem;
5066 char *pathname;
5067 size_t len = MAXPATHLEN * 2;
5068
5069 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
5070 (void) printf("errors: List of errors unavailable "
5071 "(insufficient privileges)\n");
5072 return;
5073 }
5074
5075 (void) printf("errors: Permanent errors have been "
5076 "detected in the following files:\n\n");
5077
5078 pathname = safe_malloc(len);
5079 elem = NULL;
5080 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
5081 nvlist_t *nv;
5082 uint64_t dsobj, obj;
5083
5084 verify(nvpair_value_nvlist(elem, &nv) == 0);
5085 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
5086 &dsobj) == 0);
5087 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
5088 &obj) == 0);
5089 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
5090 (void) printf("%7s %s\n", "", pathname);
5091 }
5092 free(pathname);
5093 nvlist_free(nverrlist);
5094 }
5095
5096 static void
print_spares(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t ** spares,uint_t nspares)5097 print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
5098 uint_t nspares)
5099 {
5100 uint_t i;
5101 char *name;
5102
5103 if (nspares == 0)
5104 return;
5105
5106 (void) printf(gettext("\tspares\n"));
5107
5108 for (i = 0; i < nspares; i++) {
5109 name = zpool_vdev_name(g_zfs, zhp, spares[i],
5110 cb->cb_name_flags);
5111 print_status_config(zhp, cb, name, spares[i], 2, B_TRUE);
5112 free(name);
5113 }
5114 }
5115
5116 static void
print_l2cache(zpool_handle_t * zhp,status_cbdata_t * cb,nvlist_t ** l2cache,uint_t nl2cache)5117 print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
5118 uint_t nl2cache)
5119 {
5120 uint_t i;
5121 char *name;
5122
5123 if (nl2cache == 0)
5124 return;
5125
5126 (void) printf(gettext("\tcache\n"));
5127
5128 for (i = 0; i < nl2cache; i++) {
5129 name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
5130 cb->cb_name_flags);
5131 print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE);
5132 free(name);
5133 }
5134 }
5135
5136 static void
print_dedup_stats(nvlist_t * config)5137 print_dedup_stats(nvlist_t *config)
5138 {
5139 ddt_histogram_t *ddh;
5140 ddt_stat_t *dds;
5141 ddt_object_t *ddo;
5142 uint_t c;
5143
5144 /*
5145 * If the pool was faulted then we may not have been able to
5146 * obtain the config. Otherwise, if we have anything in the dedup
5147 * table continue processing the stats.
5148 */
5149 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
5150 (uint64_t **)&ddo, &c) != 0)
5151 return;
5152
5153 (void) printf("\n");
5154 (void) printf(gettext(" dedup: "));
5155 if (ddo->ddo_count == 0) {
5156 (void) printf(gettext("no DDT entries\n"));
5157 return;
5158 }
5159
5160 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
5161 (u_longlong_t)ddo->ddo_count,
5162 (u_longlong_t)ddo->ddo_dspace,
5163 (u_longlong_t)ddo->ddo_mspace);
5164
5165 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
5166 (uint64_t **)&dds, &c) == 0);
5167 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
5168 (uint64_t **)&ddh, &c) == 0);
5169 zpool_dump_ddt(dds, ddh);
5170 }
5171
5172 /*
5173 * Display a summary of pool status. Displays a summary such as:
5174 *
5175 * pool: tank
5176 * status: DEGRADED
5177 * reason: One or more devices ...
5178 * see: http://illumos.org/msg/ZFS-xxxx-01
5179 * config:
5180 * mirror DEGRADED
5181 * c1t0d0 OK
5182 * c2t0d0 UNAVAIL
5183 *
5184 * When given the '-v' option, we print out the complete config. If the '-e'
5185 * option is specified, then we print out error rate information as well.
5186 */
5187 int
status_callback(zpool_handle_t * zhp,void * data)5188 status_callback(zpool_handle_t *zhp, void *data)
5189 {
5190 status_cbdata_t *cbp = data;
5191 nvlist_t *config, *nvroot;
5192 char *msgid;
5193 int reason;
5194 const char *health;
5195 uint_t c;
5196 vdev_stat_t *vs;
5197
5198 config = zpool_get_config(zhp, NULL);
5199 reason = zpool_get_status(zhp, &msgid);
5200
5201 cbp->cb_count++;
5202
5203 /*
5204 * If we were given 'zpool status -x', only report those pools with
5205 * problems.
5206 */
5207 if (cbp->cb_explain &&
5208 (reason == ZPOOL_STATUS_OK ||
5209 reason == ZPOOL_STATUS_VERSION_OLDER ||
5210 reason == ZPOOL_STATUS_NON_NATIVE_ASHIFT ||
5211 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
5212 if (!cbp->cb_allpools) {
5213 (void) printf(gettext("pool '%s' is healthy\n"),
5214 zpool_get_name(zhp));
5215 if (cbp->cb_first)
5216 cbp->cb_first = B_FALSE;
5217 }
5218 return (0);
5219 }
5220
5221 if (cbp->cb_first)
5222 cbp->cb_first = B_FALSE;
5223 else
5224 (void) printf("\n");
5225
5226 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
5227 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
5228 (uint64_t **)&vs, &c) == 0);
5229 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
5230
5231 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
5232 (void) printf(gettext(" state: %s\n"), health);
5233
5234 switch (reason) {
5235 case ZPOOL_STATUS_MISSING_DEV_R:
5236 (void) printf(gettext("status: One or more devices could not "
5237 "be opened. Sufficient replicas exist for\n\tthe pool to "
5238 "continue functioning in a degraded state.\n"));
5239 (void) printf(gettext("action: Attach the missing device and "
5240 "online it using 'zpool online'.\n"));
5241 break;
5242
5243 case ZPOOL_STATUS_MISSING_DEV_NR:
5244 (void) printf(gettext("status: One or more devices could not "
5245 "be opened. There are insufficient\n\treplicas for the "
5246 "pool to continue functioning.\n"));
5247 (void) printf(gettext("action: Attach the missing device and "
5248 "online it using 'zpool online'.\n"));
5249 break;
5250
5251 case ZPOOL_STATUS_CORRUPT_LABEL_R:
5252 (void) printf(gettext("status: One or more devices could not "
5253 "be used because the label is missing or\n\tinvalid. "
5254 "Sufficient replicas exist for the pool to continue\n\t"
5255 "functioning in a degraded state.\n"));
5256 (void) printf(gettext("action: Replace the device using "
5257 "'zpool replace'.\n"));
5258 break;
5259
5260 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
5261 (void) printf(gettext("status: One or more devices could not "
5262 "be used because the label is missing \n\tor invalid. "
5263 "There are insufficient replicas for the pool to "
5264 "continue\n\tfunctioning.\n"));
5265 zpool_explain_recover(zpool_get_handle(zhp),
5266 zpool_get_name(zhp), reason, config);
5267 break;
5268
5269 case ZPOOL_STATUS_FAILING_DEV:
5270 (void) printf(gettext("status: One or more devices has "
5271 "experienced an unrecoverable error. An\n\tattempt was "
5272 "made to correct the error. Applications are "
5273 "unaffected.\n"));
5274 (void) printf(gettext("action: Determine if the device needs "
5275 "to be replaced, and clear the errors\n\tusing "
5276 "'zpool clear' or replace the device with 'zpool "
5277 "replace'.\n"));
5278 break;
5279
5280 case ZPOOL_STATUS_OFFLINE_DEV:
5281 (void) printf(gettext("status: One or more devices has "
5282 "been taken offline by the administrator.\n\tSufficient "
5283 "replicas exist for the pool to continue functioning in "
5284 "a\n\tdegraded state.\n"));
5285 (void) printf(gettext("action: Online the device using "
5286 "'zpool online' or replace the device with\n\t'zpool "
5287 "replace'.\n"));
5288 break;
5289
5290 case ZPOOL_STATUS_REMOVED_DEV:
5291 (void) printf(gettext("status: One or more devices has "
5292 "been removed by the administrator.\n\tSufficient "
5293 "replicas exist for the pool to continue functioning in "
5294 "a\n\tdegraded state.\n"));
5295 (void) printf(gettext("action: Online the device using "
5296 "'zpool online' or replace the device with\n\t'zpool "
5297 "replace'.\n"));
5298 break;
5299
5300 case ZPOOL_STATUS_RESILVERING:
5301 (void) printf(gettext("status: One or more devices is "
5302 "currently being resilvered. The pool will\n\tcontinue "
5303 "to function, possibly in a degraded state.\n"));
5304 (void) printf(gettext("action: Wait for the resilver to "
5305 "complete.\n"));
5306 break;
5307
5308 case ZPOOL_STATUS_CORRUPT_DATA:
5309 (void) printf(gettext("status: One or more devices has "
5310 "experienced an error resulting in data\n\tcorruption. "
5311 "Applications may be affected.\n"));
5312 (void) printf(gettext("action: Restore the file in question "
5313 "if possible. Otherwise restore the\n\tentire pool from "
5314 "backup.\n"));
5315 break;
5316
5317 case ZPOOL_STATUS_CORRUPT_POOL:
5318 (void) printf(gettext("status: The pool metadata is corrupted "
5319 "and the pool cannot be opened.\n"));
5320 zpool_explain_recover(zpool_get_handle(zhp),
5321 zpool_get_name(zhp), reason, config);
5322 break;
5323
5324 case ZPOOL_STATUS_VERSION_OLDER:
5325 (void) printf(gettext("status: The pool is formatted using a "
5326 "legacy on-disk format. The pool can\n\tstill be used, "
5327 "but some features are unavailable.\n"));
5328 (void) printf(gettext("action: Upgrade the pool using 'zpool "
5329 "upgrade'. Once this is done, the\n\tpool will no longer "
5330 "be accessible on software that does not support feature\n"
5331 "\tflags.\n"));
5332 break;
5333
5334 case ZPOOL_STATUS_VERSION_NEWER:
5335 (void) printf(gettext("status: The pool has been upgraded to a "
5336 "newer, incompatible on-disk version.\n\tThe pool cannot "
5337 "be accessed on this system.\n"));
5338 (void) printf(gettext("action: Access the pool from a system "
5339 "running more recent software, or\n\trestore the pool from "
5340 "backup.\n"));
5341 break;
5342
5343 case ZPOOL_STATUS_FEAT_DISABLED:
5344 (void) printf(gettext("status: Some supported features are not "
5345 "enabled on the pool. The pool can\n\tstill be used, but "
5346 "some features are unavailable.\n"));
5347 (void) printf(gettext("action: Enable all features using "
5348 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
5349 "longer be accessible by software that does not support\n\t"
5350 "the features. See zpool-features(7) for details.\n"));
5351 break;
5352
5353 case ZPOOL_STATUS_UNSUP_FEAT_READ:
5354 (void) printf(gettext("status: The pool cannot be accessed on "
5355 "this system because it uses the\n\tfollowing feature(s) "
5356 "not supported on this system:\n"));
5357 zpool_print_unsup_feat(config);
5358 (void) printf("\n");
5359 (void) printf(gettext("action: Access the pool from a system "
5360 "that supports the required feature(s),\n\tor restore the "
5361 "pool from backup.\n"));
5362 break;
5363
5364 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
5365 (void) printf(gettext("status: The pool can only be accessed "
5366 "in read-only mode on this system. It\n\tcannot be "
5367 "accessed in read-write mode because it uses the "
5368 "following\n\tfeature(s) not supported on this system:\n"));
5369 zpool_print_unsup_feat(config);
5370 (void) printf("\n");
5371 (void) printf(gettext("action: The pool cannot be accessed in "
5372 "read-write mode. Import the pool with\n"
5373 "\t\"-o readonly=on\", access the pool from a system that "
5374 "supports the\n\trequired feature(s), or restore the "
5375 "pool from backup.\n"));
5376 break;
5377
5378 case ZPOOL_STATUS_FAULTED_DEV_R:
5379 (void) printf(gettext("status: One or more devices are "
5380 "faulted in response to persistent errors.\n\tSufficient "
5381 "replicas exist for the pool to continue functioning "
5382 "in a\n\tdegraded state.\n"));
5383 (void) printf(gettext("action: Replace the faulted device, "
5384 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
5385 break;
5386
5387 case ZPOOL_STATUS_FAULTED_DEV_NR:
5388 (void) printf(gettext("status: One or more devices are "
5389 "faulted in response to persistent errors. There are "
5390 "insufficient replicas for the pool to\n\tcontinue "
5391 "functioning.\n"));
5392 (void) printf(gettext("action: Destroy and re-create the pool "
5393 "from a backup source. Manually marking the device\n"
5394 "\trepaired using 'zpool clear' may allow some data "
5395 "to be recovered.\n"));
5396 break;
5397
5398 case ZPOOL_STATUS_IO_FAILURE_MMP:
5399 (void) printf(gettext("status: The pool is suspended because "
5400 "multihost writes failed or were delayed;\n\tanother "
5401 "system could import the pool undetected.\n"));
5402 (void) printf(gettext("action: Make sure the pool's devices "
5403 "are connected, then reboot your system and\n\timport the "
5404 "pool.\n"));
5405 break;
5406
5407 case ZPOOL_STATUS_IO_FAILURE_WAIT:
5408 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
5409 (void) printf(gettext("status: One or more devices are "
5410 "faulted in response to IO failures.\n"));
5411 (void) printf(gettext("action: Make sure the affected devices "
5412 "are connected, then run 'zpool clear'.\n"));
5413 break;
5414
5415 case ZPOOL_STATUS_BAD_LOG:
5416 (void) printf(gettext("status: An intent log record "
5417 "could not be read.\n"
5418 "\tWaiting for adminstrator intervention to fix the "
5419 "faulted pool.\n"));
5420 (void) printf(gettext("action: Either restore the affected "
5421 "device(s) and run 'zpool online',\n"
5422 "\tor ignore the intent log records by running "
5423 "'zpool clear'.\n"));
5424 break;
5425
5426 case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
5427 (void) printf(gettext("status: One or more devices are "
5428 "configured to use a non-native block size.\n"
5429 "\tExpect reduced performance.\n"));
5430 (void) printf(gettext("action: Replace affected devices with "
5431 "devices that support the\n\tconfigured block size, or "
5432 "migrate data to a properly configured\n\tpool.\n"));
5433 break;
5434
5435 default:
5436 /*
5437 * The remaining errors can't actually be generated, yet.
5438 */
5439 assert(reason == ZPOOL_STATUS_OK);
5440 }
5441
5442 if (msgid != NULL)
5443 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
5444 msgid);
5445
5446 if (config != NULL) {
5447 uint64_t nerr;
5448 nvlist_t **spares, **l2cache;
5449 uint_t nspares, nl2cache;
5450 pool_checkpoint_stat_t *pcs = NULL;
5451 pool_scan_stat_t *ps = NULL;
5452 pool_removal_stat_t *prs = NULL;
5453
5454 (void) nvlist_lookup_uint64_array(nvroot,
5455 ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c);
5456 (void) nvlist_lookup_uint64_array(nvroot,
5457 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
5458 (void) nvlist_lookup_uint64_array(nvroot,
5459 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
5460
5461 print_scan_status(ps);
5462 print_checkpoint_scan_warning(ps, pcs);
5463 print_removal_status(zhp, prs);
5464 print_checkpoint_status(pcs);
5465
5466 cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
5467 cbp->cb_name_flags);
5468 if (cbp->cb_namewidth < 10)
5469 cbp->cb_namewidth = 10;
5470
5471 (void) printf(gettext("config:\n\n"));
5472 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"),
5473 cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
5474 "CKSUM");
5475
5476 print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
5477 B_FALSE);
5478
5479 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
5480 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
5481 print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
5482
5483 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5484 &l2cache, &nl2cache) == 0)
5485 print_l2cache(zhp, cbp, l2cache, nl2cache);
5486
5487 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5488 &spares, &nspares) == 0)
5489 print_spares(zhp, cbp, spares, nspares);
5490
5491 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5492 &nerr) == 0) {
5493 nvlist_t *nverrlist = NULL;
5494
5495 /*
5496 * If the approximate error count is small, get a
5497 * precise count by fetching the entire log and
5498 * uniquifying the results.
5499 */
5500 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
5501 zpool_get_errlog(zhp, &nverrlist) == 0) {
5502 nvpair_t *elem;
5503
5504 elem = NULL;
5505 nerr = 0;
5506 while ((elem = nvlist_next_nvpair(nverrlist,
5507 elem)) != NULL) {
5508 nerr++;
5509 }
5510 }
5511 nvlist_free(nverrlist);
5512
5513 (void) printf("\n");
5514
5515 if (nerr == 0)
5516 (void) printf(gettext("errors: No known data "
5517 "errors\n"));
5518 else if (!cbp->cb_verbose)
5519 (void) printf(gettext("errors: %llu data "
5520 "errors, use '-v' for a list\n"),
5521 (u_longlong_t)nerr);
5522 else
5523 print_error_log(zhp);
5524 }
5525
5526 if (cbp->cb_dedup_stats)
5527 print_dedup_stats(config);
5528 } else {
5529 (void) printf(gettext("config: The configuration cannot be "
5530 "determined.\n"));
5531 }
5532
5533 return (0);
5534 }
5535
5536 /*
5537 * zpool status [-gLPvx] [-T d|u] [pool] ... [interval [count]]
5538 *
5539 * -g Display guid for individual vdev name.
5540 * -L Follow links when resolving vdev path name.
5541 * -P Display full path for vdev name.
5542 * -v Display complete error logs
5543 * -x Display only pools with potential problems
5544 * -D Display dedup status (undocumented)
5545 * -T Display a timestamp in date(1) or Unix format
5546 *
5547 * Describes the health status of all pools or some subset.
5548 */
5549 int
zpool_do_status(int argc,char ** argv)5550 zpool_do_status(int argc, char **argv)
5551 {
5552 int c;
5553 int ret;
5554 unsigned long interval = 0, count = 0;
5555 status_cbdata_t cb = { 0 };
5556
5557 /* check options */
5558 while ((c = getopt(argc, argv, "gLPvxDT:")) != -1) {
5559 switch (c) {
5560 case 'g':
5561 cb.cb_name_flags |= VDEV_NAME_GUID;
5562 break;
5563 case 'L':
5564 cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
5565 break;
5566 case 'P':
5567 cb.cb_name_flags |= VDEV_NAME_PATH;
5568 break;
5569 case 'v':
5570 cb.cb_verbose = B_TRUE;
5571 break;
5572 case 'x':
5573 cb.cb_explain = B_TRUE;
5574 break;
5575 case 'D':
5576 cb.cb_dedup_stats = B_TRUE;
5577 break;
5578 case 'T':
5579 get_timestamp_arg(*optarg);
5580 break;
5581 case '?':
5582 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5583 optopt);
5584 usage(B_FALSE);
5585 }
5586 }
5587
5588 argc -= optind;
5589 argv += optind;
5590
5591 get_interval_count(&argc, argv, &interval, &count);
5592
5593 if (argc == 0)
5594 cb.cb_allpools = B_TRUE;
5595
5596 cb.cb_first = B_TRUE;
5597 cb.cb_print_status = B_TRUE;
5598
5599 for (;;) {
5600 if (timestamp_fmt != NODATE)
5601 print_timestamp(timestamp_fmt);
5602
5603 ret = for_each_pool(argc, argv, B_TRUE, NULL,
5604 status_callback, &cb);
5605
5606 if (argc == 0 && cb.cb_count == 0)
5607 (void) printf(gettext("no pools available\n"));
5608 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
5609 (void) printf(gettext("all pools are healthy\n"));
5610
5611 if (ret != 0)
5612 return (ret);
5613
5614 if (interval == 0)
5615 break;
5616
5617 if (count != 0 && --count == 0)
5618 break;
5619
5620 (void) sleep(interval);
5621 }
5622
5623 return (0);
5624 }
5625
5626 typedef struct upgrade_cbdata {
5627 boolean_t cb_first;
5628 boolean_t cb_unavail;
5629 char cb_poolname[ZFS_MAX_DATASET_NAME_LEN];
5630 int cb_argc;
5631 uint64_t cb_version;
5632 char **cb_argv;
5633 } upgrade_cbdata_t;
5634
5635 #ifdef __FreeBSD__
5636 static int
is_root_pool(zpool_handle_t * zhp)5637 is_root_pool(zpool_handle_t *zhp)
5638 {
5639 static struct statfs sfs;
5640 static char *poolname = NULL;
5641 static boolean_t stated = B_FALSE;
5642 char *slash;
5643
5644 if (!stated) {
5645 stated = B_TRUE;
5646 if (statfs("/", &sfs) == -1) {
5647 (void) fprintf(stderr,
5648 "Unable to stat root file system: %s.\n",
5649 strerror(errno));
5650 return (0);
5651 }
5652 if (strcmp(sfs.f_fstypename, "zfs") != 0)
5653 return (0);
5654 poolname = sfs.f_mntfromname;
5655 if ((slash = strchr(poolname, '/')) != NULL)
5656 *slash = '\0';
5657 }
5658 return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0);
5659 }
5660
5661 static void
root_pool_upgrade_check(zpool_handle_t * zhp,char * poolname,int size)5662 root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
5663 {
5664
5665 if (poolname[0] == '\0' && is_root_pool(zhp))
5666 (void) strlcpy(poolname, zpool_get_name(zhp), size);
5667 }
5668 #endif /* FreeBSD */
5669
5670 static int
upgrade_version(zpool_handle_t * zhp,uint64_t version)5671 upgrade_version(zpool_handle_t *zhp, uint64_t version)
5672 {
5673 int ret;
5674 nvlist_t *config;
5675 uint64_t oldversion;
5676
5677 config = zpool_get_config(zhp, NULL);
5678 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5679 &oldversion) == 0);
5680
5681 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
5682 assert(oldversion < version);
5683
5684 ret = zpool_upgrade(zhp, version);
5685 if (ret != 0)
5686 return (ret);
5687
5688 if (version >= SPA_VERSION_FEATURES) {
5689 (void) printf(gettext("Successfully upgraded "
5690 "'%s' from version %llu to feature flags.\n"),
5691 zpool_get_name(zhp), oldversion);
5692 } else {
5693 (void) printf(gettext("Successfully upgraded "
5694 "'%s' from version %llu to version %llu.\n"),
5695 zpool_get_name(zhp), oldversion, version);
5696 }
5697
5698 return (0);
5699 }
5700
5701 static int
upgrade_enable_all(zpool_handle_t * zhp,int * countp)5702 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5703 {
5704 int i, ret, count;
5705 boolean_t firstff = B_TRUE;
5706 nvlist_t *enabled = zpool_get_features(zhp);
5707
5708 count = 0;
5709 for (i = 0; i < SPA_FEATURES; i++) {
5710 const char *fname = spa_feature_table[i].fi_uname;
5711 const char *fguid = spa_feature_table[i].fi_guid;
5712 if (!nvlist_exists(enabled, fguid)) {
5713 char *propname;
5714 verify(-1 != asprintf(&propname, "feature@%s", fname));
5715 ret = zpool_set_prop(zhp, propname,
5716 ZFS_FEATURE_ENABLED);
5717 if (ret != 0) {
5718 free(propname);
5719 return (ret);
5720 }
5721 count++;
5722
5723 if (firstff) {
5724 (void) printf(gettext("Enabled the "
5725 "following features on '%s':\n"),
5726 zpool_get_name(zhp));
5727 firstff = B_FALSE;
5728 }
5729 (void) printf(gettext(" %s\n"), fname);
5730 free(propname);
5731 }
5732 }
5733
5734 if (countp != NULL)
5735 *countp = count;
5736 return (0);
5737 }
5738
5739 static int
upgrade_cb(zpool_handle_t * zhp,void * arg)5740 upgrade_cb(zpool_handle_t *zhp, void *arg)
5741 {
5742 upgrade_cbdata_t *cbp = arg;
5743 nvlist_t *config;
5744 uint64_t version;
5745 boolean_t printnl = B_FALSE;
5746 int ret;
5747
5748 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5749 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5750 "currently unavailable.\n\n"), zpool_get_name(zhp));
5751 cbp->cb_unavail = B_TRUE;
5752 /* Allow iteration to continue. */
5753 return (0);
5754 }
5755
5756 config = zpool_get_config(zhp, NULL);
5757 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5758 &version) == 0);
5759
5760 assert(SPA_VERSION_IS_SUPPORTED(version));
5761
5762 if (version < cbp->cb_version) {
5763 cbp->cb_first = B_FALSE;
5764 ret = upgrade_version(zhp, cbp->cb_version);
5765 if (ret != 0)
5766 return (ret);
5767 #ifdef __FreeBSD__
5768 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5769 sizeof(cbp->cb_poolname));
5770 #endif /* __FreeBSD__ */
5771 printnl = B_TRUE;
5772
5773 #ifdef illumos
5774 /*
5775 * If they did "zpool upgrade -a", then we could
5776 * be doing ioctls to different pools. We need
5777 * to log this history once to each pool, and bypass
5778 * the normal history logging that happens in main().
5779 */
5780 (void) zpool_log_history(g_zfs, history_str);
5781 log_history = B_FALSE;
5782 #endif
5783 }
5784
5785 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5786 int count;
5787 ret = upgrade_enable_all(zhp, &count);
5788 if (ret != 0)
5789 return (ret);
5790
5791 if (count > 0) {
5792 cbp->cb_first = B_FALSE;
5793 printnl = B_TRUE;
5794 #ifdef __FreeBSD__
5795 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5796 sizeof(cbp->cb_poolname));
5797 #endif /* __FreeBSD__ */
5798 /*
5799 * If they did "zpool upgrade -a", then we could
5800 * be doing ioctls to different pools. We need
5801 * to log this history once to each pool, and bypass
5802 * the normal history logging that happens in main().
5803 */
5804 (void) zpool_log_history(g_zfs, history_str);
5805 log_history = B_FALSE;
5806 }
5807 }
5808
5809 if (printnl) {
5810 (void) printf(gettext("\n"));
5811 }
5812
5813 return (0);
5814 }
5815
5816 static int
upgrade_list_unavail(zpool_handle_t * zhp,void * arg)5817 upgrade_list_unavail(zpool_handle_t *zhp, void *arg)
5818 {
5819 upgrade_cbdata_t *cbp = arg;
5820
5821 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5822 if (cbp->cb_first) {
5823 (void) fprintf(stderr, gettext("The following pools "
5824 "are unavailable and cannot be upgraded as this "
5825 "time.\n\n"));
5826 (void) fprintf(stderr, gettext("POOL\n"));
5827 (void) fprintf(stderr, gettext("------------\n"));
5828 cbp->cb_first = B_FALSE;
5829 }
5830 (void) printf(gettext("%s\n"), zpool_get_name(zhp));
5831 cbp->cb_unavail = B_TRUE;
5832 }
5833 return (0);
5834 }
5835
5836 static int
upgrade_list_older_cb(zpool_handle_t * zhp,void * arg)5837 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
5838 {
5839 upgrade_cbdata_t *cbp = arg;
5840 nvlist_t *config;
5841 uint64_t version;
5842
5843 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5844 /*
5845 * This will have been reported by upgrade_list_unavail so
5846 * just allow iteration to continue.
5847 */
5848 cbp->cb_unavail = B_TRUE;
5849 return (0);
5850 }
5851
5852 config = zpool_get_config(zhp, NULL);
5853 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5854 &version) == 0);
5855
5856 assert(SPA_VERSION_IS_SUPPORTED(version));
5857
5858 if (version < SPA_VERSION_FEATURES) {
5859 if (cbp->cb_first) {
5860 (void) printf(gettext("The following pools are "
5861 "formatted with legacy version numbers and can\n"
5862 "be upgraded to use feature flags. After "
5863 "being upgraded, these pools\nwill no "
5864 "longer be accessible by software that does not "
5865 "support feature\nflags.\n\n"));
5866 (void) printf(gettext("VER POOL\n"));
5867 (void) printf(gettext("--- ------------\n"));
5868 cbp->cb_first = B_FALSE;
5869 }
5870
5871 (void) printf("%2llu %s\n", (u_longlong_t)version,
5872 zpool_get_name(zhp));
5873 }
5874
5875 return (0);
5876 }
5877
5878 static int
upgrade_list_disabled_cb(zpool_handle_t * zhp,void * arg)5879 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
5880 {
5881 upgrade_cbdata_t *cbp = arg;
5882 nvlist_t *config;
5883 uint64_t version;
5884
5885 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5886 /*
5887 * This will have been reported by upgrade_list_unavail so
5888 * just allow iteration to continue.
5889 */
5890 cbp->cb_unavail = B_TRUE;
5891 return (0);
5892 }
5893
5894 config = zpool_get_config(zhp, NULL);
5895 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
5896 &version) == 0);
5897
5898 if (version >= SPA_VERSION_FEATURES) {
5899 int i;
5900 boolean_t poolfirst = B_TRUE;
5901 nvlist_t *enabled = zpool_get_features(zhp);
5902
5903 for (i = 0; i < SPA_FEATURES; i++) {
5904 const char *fguid = spa_feature_table[i].fi_guid;
5905 const char *fname = spa_feature_table[i].fi_uname;
5906 if (!nvlist_exists(enabled, fguid)) {
5907 if (cbp->cb_first) {
5908 (void) printf(gettext("\nSome "
5909 "supported features are not "
5910 "enabled on the following pools. "
5911 "Once a\nfeature is enabled the "
5912 "pool may become incompatible with "
5913 "software\nthat does not support "
5914 "the feature. See "
5915 "zpool-features(7) for "
5916 "details.\n\n"));
5917 (void) printf(gettext("POOL "
5918 "FEATURE\n"));
5919 (void) printf(gettext("------"
5920 "---------\n"));
5921 cbp->cb_first = B_FALSE;
5922 }
5923
5924 if (poolfirst) {
5925 (void) printf(gettext("%s\n"),
5926 zpool_get_name(zhp));
5927 poolfirst = B_FALSE;
5928 }
5929
5930 (void) printf(gettext(" %s\n"), fname);
5931 }
5932 }
5933 }
5934
5935 return (0);
5936 }
5937
5938 /* ARGSUSED */
5939 static int
upgrade_one(zpool_handle_t * zhp,void * data)5940 upgrade_one(zpool_handle_t *zhp, void *data)
5941 {
5942 boolean_t printnl = B_FALSE;
5943 upgrade_cbdata_t *cbp = data;
5944 uint64_t cur_version;
5945 int ret;
5946
5947 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
5948 (void) fprintf(stderr, gettext("cannot upgrade '%s': pool is "
5949 "is currently unavailable.\n\n"), zpool_get_name(zhp));
5950 cbp->cb_unavail = B_TRUE;
5951 return (1);
5952 }
5953
5954 if (strcmp("log", zpool_get_name(zhp)) == 0) {
5955 (void) printf(gettext("'log' is now a reserved word\n"
5956 "Pool 'log' must be renamed using export and import"
5957 " to upgrade.\n\n"));
5958 return (1);
5959 }
5960
5961 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5962 if (cur_version > cbp->cb_version) {
5963 (void) printf(gettext("Pool '%s' is already formatted "
5964 "using more current version '%llu'.\n\n"),
5965 zpool_get_name(zhp), cur_version);
5966 return (0);
5967 }
5968
5969 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5970 (void) printf(gettext("Pool '%s' is already formatted "
5971 "using version %llu.\n\n"), zpool_get_name(zhp),
5972 cbp->cb_version);
5973 return (0);
5974 }
5975
5976 if (cur_version != cbp->cb_version) {
5977 printnl = B_TRUE;
5978 ret = upgrade_version(zhp, cbp->cb_version);
5979 if (ret != 0)
5980 return (ret);
5981 #ifdef __FreeBSD__
5982 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5983 sizeof(cbp->cb_poolname));
5984 #endif /* __FreeBSD__ */
5985 }
5986
5987 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5988 int count = 0;
5989 ret = upgrade_enable_all(zhp, &count);
5990 if (ret != 0)
5991 return (ret);
5992
5993 if (count != 0) {
5994 printnl = B_TRUE;
5995 #ifdef __FreeBSD__
5996 root_pool_upgrade_check(zhp, cbp->cb_poolname,
5997 sizeof(cbp->cb_poolname));
5998 #endif /* __FreeBSD __*/
5999 } else if (cur_version == SPA_VERSION) {
6000 (void) printf(gettext("Pool '%s' already has all "
6001 "supported features enabled.\n\n"),
6002 zpool_get_name(zhp));
6003 }
6004 }
6005
6006 if (printnl) {
6007 (void) printf(gettext("\n"));
6008 }
6009
6010 return (0);
6011 }
6012
6013 /*
6014 * zpool upgrade
6015 * zpool upgrade -v
6016 * zpool upgrade [-V version] <-a | pool ...>
6017 *
6018 * With no arguments, display downrev'd ZFS pool available for upgrade.
6019 * Individual pools can be upgraded by specifying the pool, and '-a' will
6020 * upgrade all pools.
6021 */
6022 int
zpool_do_upgrade(int argc,char ** argv)6023 zpool_do_upgrade(int argc, char **argv)
6024 {
6025 int c;
6026 upgrade_cbdata_t cb = { 0 };
6027 int ret = 0;
6028 boolean_t showversions = B_FALSE;
6029 boolean_t upgradeall = B_FALSE;
6030 char *end;
6031
6032
6033 /* check options */
6034 while ((c = getopt(argc, argv, ":avV:")) != -1) {
6035 switch (c) {
6036 case 'a':
6037 upgradeall = B_TRUE;
6038 break;
6039 case 'v':
6040 showversions = B_TRUE;
6041 break;
6042 case 'V':
6043 cb.cb_version = strtoll(optarg, &end, 10);
6044 if (*end != '\0' ||
6045 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
6046 (void) fprintf(stderr,
6047 gettext("invalid version '%s'\n"), optarg);
6048 usage(B_FALSE);
6049 }
6050 break;
6051 case ':':
6052 (void) fprintf(stderr, gettext("missing argument for "
6053 "'%c' option\n"), optopt);
6054 usage(B_FALSE);
6055 break;
6056 case '?':
6057 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6058 optopt);
6059 usage(B_FALSE);
6060 }
6061 }
6062
6063 cb.cb_argc = argc;
6064 cb.cb_argv = argv;
6065 argc -= optind;
6066 argv += optind;
6067
6068 if (cb.cb_version == 0) {
6069 cb.cb_version = SPA_VERSION;
6070 } else if (!upgradeall && argc == 0) {
6071 (void) fprintf(stderr, gettext("-V option is "
6072 "incompatible with other arguments\n"));
6073 usage(B_FALSE);
6074 }
6075
6076 if (showversions) {
6077 if (upgradeall || argc != 0) {
6078 (void) fprintf(stderr, gettext("-v option is "
6079 "incompatible with other arguments\n"));
6080 usage(B_FALSE);
6081 }
6082 } else if (upgradeall) {
6083 if (argc != 0) {
6084 (void) fprintf(stderr, gettext("-a option should not "
6085 "be used along with a pool name\n"));
6086 usage(B_FALSE);
6087 }
6088 }
6089
6090 (void) printf(gettext("This system supports ZFS pool feature "
6091 "flags.\n\n"));
6092 if (showversions) {
6093 int i;
6094
6095 (void) printf(gettext("The following features are "
6096 "supported:\n\n"));
6097 (void) printf(gettext("FEAT DESCRIPTION\n"));
6098 (void) printf("----------------------------------------------"
6099 "---------------\n");
6100 for (i = 0; i < SPA_FEATURES; i++) {
6101 zfeature_info_t *fi = &spa_feature_table[i];
6102 const char *ro =
6103 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
6104 " (read-only compatible)" : "";
6105
6106 (void) printf("%-37s%s\n", fi->fi_uname, ro);
6107 (void) printf(" %s\n", fi->fi_desc);
6108 }
6109 (void) printf("\n");
6110
6111 (void) printf(gettext("The following legacy versions are also "
6112 "supported:\n\n"));
6113 (void) printf(gettext("VER DESCRIPTION\n"));
6114 (void) printf("--- -----------------------------------------"
6115 "---------------\n");
6116 (void) printf(gettext(" 1 Initial ZFS version\n"));
6117 (void) printf(gettext(" 2 Ditto blocks "
6118 "(replicated metadata)\n"));
6119 (void) printf(gettext(" 3 Hot spares and double parity "
6120 "RAID-Z\n"));
6121 (void) printf(gettext(" 4 zpool history\n"));
6122 (void) printf(gettext(" 5 Compression using the gzip "
6123 "algorithm\n"));
6124 (void) printf(gettext(" 6 bootfs pool property\n"));
6125 (void) printf(gettext(" 7 Separate intent log devices\n"));
6126 (void) printf(gettext(" 8 Delegated administration\n"));
6127 (void) printf(gettext(" 9 refquota and refreservation "
6128 "properties\n"));
6129 (void) printf(gettext(" 10 Cache devices\n"));
6130 (void) printf(gettext(" 11 Improved scrub performance\n"));
6131 (void) printf(gettext(" 12 Snapshot properties\n"));
6132 (void) printf(gettext(" 13 snapused property\n"));
6133 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
6134 (void) printf(gettext(" 15 user/group space accounting\n"));
6135 (void) printf(gettext(" 16 stmf property support\n"));
6136 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
6137 (void) printf(gettext(" 18 Snapshot user holds\n"));
6138 (void) printf(gettext(" 19 Log device removal\n"));
6139 (void) printf(gettext(" 20 Compression using zle "
6140 "(zero-length encoding)\n"));
6141 (void) printf(gettext(" 21 Deduplication\n"));
6142 (void) printf(gettext(" 22 Received properties\n"));
6143 (void) printf(gettext(" 23 Slim ZIL\n"));
6144 (void) printf(gettext(" 24 System attributes\n"));
6145 (void) printf(gettext(" 25 Improved scrub stats\n"));
6146 (void) printf(gettext(" 26 Improved snapshot deletion "
6147 "performance\n"));
6148 (void) printf(gettext(" 27 Improved snapshot creation "
6149 "performance\n"));
6150 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
6151 (void) printf(gettext("\nFor more information on a particular "
6152 "version, including supported releases,\n"));
6153 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
6154 } else if (argc == 0 && upgradeall) {
6155 cb.cb_first = B_TRUE;
6156 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
6157 if (ret == 0 && cb.cb_first) {
6158 if (cb.cb_version == SPA_VERSION) {
6159 (void) printf(gettext("All %spools are already "
6160 "formatted using feature flags.\n\n"),
6161 cb.cb_unavail ? gettext("available ") : "");
6162 (void) printf(gettext("Every %sfeature flags "
6163 "pool already has all supported features "
6164 "enabled.\n"),
6165 cb.cb_unavail ? gettext("available ") : "");
6166 } else {
6167 (void) printf(gettext("All pools are already "
6168 "formatted with version %llu or higher.\n"),
6169 cb.cb_version);
6170 }
6171 }
6172 } else if (argc == 0) {
6173 cb.cb_first = B_TRUE;
6174 ret = zpool_iter(g_zfs, upgrade_list_unavail, &cb);
6175 assert(ret == 0);
6176
6177 if (!cb.cb_first) {
6178 (void) fprintf(stderr, "\n");
6179 }
6180
6181 cb.cb_first = B_TRUE;
6182 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
6183 assert(ret == 0);
6184
6185 if (cb.cb_first) {
6186 (void) printf(gettext("All %spools are formatted using "
6187 "feature flags.\n\n"), cb.cb_unavail ?
6188 gettext("available ") : "");
6189 } else {
6190 (void) printf(gettext("\nUse 'zpool upgrade -v' "
6191 "for a list of available legacy versions.\n"));
6192 }
6193
6194 cb.cb_first = B_TRUE;
6195 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
6196 assert(ret == 0);
6197
6198 if (cb.cb_first) {
6199 (void) printf(gettext("Every %sfeature flags pool has "
6200 "all supported features enabled.\n"),
6201 cb.cb_unavail ? gettext("available ") : "");
6202 } else {
6203 (void) printf(gettext("\n"));
6204 }
6205 } else {
6206 ret = for_each_pool(argc, argv, B_TRUE, NULL,
6207 upgrade_one, &cb);
6208 }
6209
6210 if (cb.cb_poolname[0] != '\0') {
6211 (void) printf(
6212 "If you boot from pool '%s', don't forget to update boot code.\n"
6213 "Assuming you use GPT partitioning and da0 is your boot disk\n"
6214 "the following command will do it:\n"
6215 "\n"
6216 "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n",
6217 cb.cb_poolname);
6218 }
6219
6220 return (ret);
6221 }
6222
6223 typedef struct hist_cbdata {
6224 boolean_t first;
6225 boolean_t longfmt;
6226 boolean_t internal;
6227 } hist_cbdata_t;
6228
6229 static void
print_history_records(nvlist_t * nvhis,hist_cbdata_t * cb)6230 print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb)
6231 {
6232 nvlist_t **records;
6233 uint_t numrecords;
6234 int i;
6235
6236 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
6237 &records, &numrecords) == 0);
6238 for (i = 0; i < numrecords; i++) {
6239 nvlist_t *rec = records[i];
6240 char tbuf[30] = "";
6241
6242 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
6243 time_t tsec;
6244 struct tm t;
6245
6246 tsec = fnvlist_lookup_uint64(records[i],
6247 ZPOOL_HIST_TIME);
6248 (void) localtime_r(&tsec, &t);
6249 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
6250 }
6251
6252 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
6253 (void) printf("%s %s", tbuf,
6254 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
6255 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
6256 int ievent =
6257 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
6258 if (!cb->internal)
6259 continue;
6260 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
6261 (void) printf("%s unrecognized record:\n",
6262 tbuf);
6263 dump_nvlist(rec, 4);
6264 continue;
6265 }
6266 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
6267 zfs_history_event_names[ievent],
6268 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
6269 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
6270 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
6271 if (!cb->internal)
6272 continue;
6273 (void) printf("%s [txg:%lld] %s", tbuf,
6274 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
6275 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
6276 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
6277 (void) printf(" %s (%llu)",
6278 fnvlist_lookup_string(rec,
6279 ZPOOL_HIST_DSNAME),
6280 fnvlist_lookup_uint64(rec,
6281 ZPOOL_HIST_DSID));
6282 }
6283 (void) printf(" %s", fnvlist_lookup_string(rec,
6284 ZPOOL_HIST_INT_STR));
6285 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
6286 if (!cb->internal)
6287 continue;
6288 (void) printf("%s ioctl %s\n", tbuf,
6289 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
6290 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
6291 (void) printf(" input:\n");
6292 dump_nvlist(fnvlist_lookup_nvlist(rec,
6293 ZPOOL_HIST_INPUT_NVL), 8);
6294 }
6295 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
6296 (void) printf(" output:\n");
6297 dump_nvlist(fnvlist_lookup_nvlist(rec,
6298 ZPOOL_HIST_OUTPUT_NVL), 8);
6299 }
6300 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
6301 (void) printf(" errno: %lld\n",
6302 fnvlist_lookup_int64(rec,
6303 ZPOOL_HIST_ERRNO));
6304 }
6305 } else {
6306 if (!cb->internal)
6307 continue;
6308 (void) printf("%s unrecognized record:\n", tbuf);
6309 dump_nvlist(rec, 4);
6310 }
6311
6312 if (!cb->longfmt) {
6313 (void) printf("\n");
6314 continue;
6315 }
6316 (void) printf(" [");
6317 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
6318 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
6319 struct passwd *pwd = getpwuid(who);
6320 (void) printf("user %d ", (int)who);
6321 if (pwd != NULL)
6322 (void) printf("(%s) ", pwd->pw_name);
6323 }
6324 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
6325 (void) printf("on %s",
6326 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
6327 }
6328 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
6329 (void) printf(":%s",
6330 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
6331 }
6332 (void) printf("]");
6333 (void) printf("\n");
6334 }
6335 }
6336
6337 /*
6338 * Print out the command history for a specific pool.
6339 */
6340 static int
get_history_one(zpool_handle_t * zhp,void * data)6341 get_history_one(zpool_handle_t *zhp, void *data)
6342 {
6343 nvlist_t *nvhis;
6344 int ret;
6345 hist_cbdata_t *cb = (hist_cbdata_t *)data;
6346 uint64_t off = 0;
6347 boolean_t eof = B_FALSE;
6348
6349 cb->first = B_FALSE;
6350
6351 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
6352
6353 while (!eof) {
6354 if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0)
6355 return (ret);
6356
6357 print_history_records(nvhis, cb);
6358 nvlist_free(nvhis);
6359 }
6360 (void) printf("\n");
6361
6362 return (ret);
6363 }
6364
6365 /*
6366 * zpool history <pool>
6367 *
6368 * Displays the history of commands that modified pools.
6369 */
6370 int
zpool_do_history(int argc,char ** argv)6371 zpool_do_history(int argc, char **argv)
6372 {
6373 hist_cbdata_t cbdata = { 0 };
6374 int ret;
6375 int c;
6376
6377 cbdata.first = B_TRUE;
6378 /* check options */
6379 while ((c = getopt(argc, argv, "li")) != -1) {
6380 switch (c) {
6381 case 'l':
6382 cbdata.longfmt = B_TRUE;
6383 break;
6384 case 'i':
6385 cbdata.internal = B_TRUE;
6386 break;
6387 case '?':
6388 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6389 optopt);
6390 usage(B_FALSE);
6391 }
6392 }
6393 argc -= optind;
6394 argv += optind;
6395
6396 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
6397 &cbdata);
6398
6399 if (argc == 0 && cbdata.first == B_TRUE) {
6400 (void) printf(gettext("no pools available\n"));
6401 return (0);
6402 }
6403
6404 return (ret);
6405 }
6406
6407 static int
get_callback(zpool_handle_t * zhp,void * data)6408 get_callback(zpool_handle_t *zhp, void *data)
6409 {
6410 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
6411 char value[MAXNAMELEN];
6412 zprop_source_t srctype;
6413 zprop_list_t *pl;
6414
6415 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
6416
6417 /*
6418 * Skip the special fake placeholder. This will also skip
6419 * over the name property when 'all' is specified.
6420 */
6421 if (pl->pl_prop == ZPOOL_PROP_NAME &&
6422 pl == cbp->cb_proplist)
6423 continue;
6424
6425 if (pl->pl_prop == ZPROP_INVAL &&
6426 (zpool_prop_feature(pl->pl_user_prop) ||
6427 zpool_prop_unsupported(pl->pl_user_prop))) {
6428 srctype = ZPROP_SRC_LOCAL;
6429
6430 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
6431 value, sizeof (value)) == 0) {
6432 zprop_print_one_property(zpool_get_name(zhp),
6433 cbp, pl->pl_user_prop, value, srctype,
6434 NULL, NULL);
6435 }
6436 } else {
6437 if (zpool_get_prop(zhp, pl->pl_prop, value,
6438 sizeof (value), &srctype, cbp->cb_literal) != 0)
6439 continue;
6440
6441 zprop_print_one_property(zpool_get_name(zhp), cbp,
6442 zpool_prop_to_name(pl->pl_prop), value, srctype,
6443 NULL, NULL);
6444 }
6445 }
6446 return (0);
6447 }
6448
6449 /*
6450 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
6451 *
6452 * -H Scripted mode. Don't display headers, and separate properties
6453 * by a single tab.
6454 * -o List of columns to display. Defaults to
6455 * "name,property,value,source".
6456 * -p Diplay values in parsable (exact) format.
6457 *
6458 * Get properties of pools in the system. Output space statistics
6459 * for each one as well as other attributes.
6460 */
6461 int
zpool_do_get(int argc,char ** argv)6462 zpool_do_get(int argc, char **argv)
6463 {
6464 zprop_get_cbdata_t cb = { 0 };
6465 zprop_list_t fake_name = { 0 };
6466 int ret;
6467 int c, i;
6468 char *value;
6469
6470 cb.cb_first = B_TRUE;
6471
6472 /*
6473 * Set up default columns and sources.
6474 */
6475 cb.cb_sources = ZPROP_SRC_ALL;
6476 cb.cb_columns[0] = GET_COL_NAME;
6477 cb.cb_columns[1] = GET_COL_PROPERTY;
6478 cb.cb_columns[2] = GET_COL_VALUE;
6479 cb.cb_columns[3] = GET_COL_SOURCE;
6480 cb.cb_type = ZFS_TYPE_POOL;
6481
6482 /* check options */
6483 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
6484 switch (c) {
6485 case 'p':
6486 cb.cb_literal = B_TRUE;
6487 break;
6488 case 'H':
6489 cb.cb_scripted = B_TRUE;
6490 break;
6491 case 'o':
6492 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
6493 i = 0;
6494 while (*optarg != '\0') {
6495 static char *col_subopts[] =
6496 { "name", "property", "value", "source",
6497 "all", NULL };
6498
6499 if (i == ZFS_GET_NCOLS) {
6500 (void) fprintf(stderr, gettext("too "
6501 "many fields given to -o "
6502 "option\n"));
6503 usage(B_FALSE);
6504 }
6505
6506 switch (getsubopt(&optarg, col_subopts,
6507 &value)) {
6508 case 0:
6509 cb.cb_columns[i++] = GET_COL_NAME;
6510 break;
6511 case 1:
6512 cb.cb_columns[i++] = GET_COL_PROPERTY;
6513 break;
6514 case 2:
6515 cb.cb_columns[i++] = GET_COL_VALUE;
6516 break;
6517 case 3:
6518 cb.cb_columns[i++] = GET_COL_SOURCE;
6519 break;
6520 case 4:
6521 if (i > 0) {
6522 (void) fprintf(stderr,
6523 gettext("\"all\" conflicts "
6524 "with specific fields "
6525 "given to -o option\n"));
6526 usage(B_FALSE);
6527 }
6528 cb.cb_columns[0] = GET_COL_NAME;
6529 cb.cb_columns[1] = GET_COL_PROPERTY;
6530 cb.cb_columns[2] = GET_COL_VALUE;
6531 cb.cb_columns[3] = GET_COL_SOURCE;
6532 i = ZFS_GET_NCOLS;
6533 break;
6534 default:
6535 (void) fprintf(stderr,
6536 gettext("invalid column name "
6537 "'%s'\n"), suboptarg);
6538 usage(B_FALSE);
6539 }
6540 }
6541 break;
6542 case '?':
6543 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6544 optopt);
6545 usage(B_FALSE);
6546 }
6547 }
6548
6549 argc -= optind;
6550 argv += optind;
6551
6552 if (argc < 1) {
6553 (void) fprintf(stderr, gettext("missing property "
6554 "argument\n"));
6555 usage(B_FALSE);
6556 }
6557
6558 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
6559 ZFS_TYPE_POOL) != 0)
6560 usage(B_FALSE);
6561
6562 argc--;
6563 argv++;
6564
6565 if (cb.cb_proplist != NULL) {
6566 fake_name.pl_prop = ZPOOL_PROP_NAME;
6567 fake_name.pl_width = strlen(gettext("NAME"));
6568 fake_name.pl_next = cb.cb_proplist;
6569 cb.cb_proplist = &fake_name;
6570 }
6571
6572 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
6573 get_callback, &cb);
6574
6575 if (cb.cb_proplist == &fake_name)
6576 zprop_free_list(fake_name.pl_next);
6577 else
6578 zprop_free_list(cb.cb_proplist);
6579
6580 return (ret);
6581 }
6582
6583 typedef struct set_cbdata {
6584 char *cb_propname;
6585 char *cb_value;
6586 boolean_t cb_any_successful;
6587 } set_cbdata_t;
6588
6589 int
set_callback(zpool_handle_t * zhp,void * data)6590 set_callback(zpool_handle_t *zhp, void *data)
6591 {
6592 int error;
6593 set_cbdata_t *cb = (set_cbdata_t *)data;
6594
6595 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
6596
6597 if (!error)
6598 cb->cb_any_successful = B_TRUE;
6599
6600 return (error);
6601 }
6602
6603 int
zpool_do_set(int argc,char ** argv)6604 zpool_do_set(int argc, char **argv)
6605 {
6606 set_cbdata_t cb = { 0 };
6607 int error;
6608
6609 if (argc > 1 && argv[1][0] == '-') {
6610 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6611 argv[1][1]);
6612 usage(B_FALSE);
6613 }
6614
6615 if (argc < 2) {
6616 (void) fprintf(stderr, gettext("missing property=value "
6617 "argument\n"));
6618 usage(B_FALSE);
6619 }
6620
6621 if (argc < 3) {
6622 (void) fprintf(stderr, gettext("missing pool name\n"));
6623 usage(B_FALSE);
6624 }
6625
6626 if (argc > 3) {
6627 (void) fprintf(stderr, gettext("too many pool names\n"));
6628 usage(B_FALSE);
6629 }
6630
6631 cb.cb_propname = argv[1];
6632 cb.cb_value = strchr(cb.cb_propname, '=');
6633 if (cb.cb_value == NULL) {
6634 (void) fprintf(stderr, gettext("missing value in "
6635 "property=value argument\n"));
6636 usage(B_FALSE);
6637 }
6638
6639 *(cb.cb_value) = '\0';
6640 cb.cb_value++;
6641
6642 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6643 set_callback, &cb);
6644
6645 return (error);
6646 }
6647
6648 static int
find_command_idx(char * command,int * idx)6649 find_command_idx(char *command, int *idx)
6650 {
6651 int i;
6652
6653 for (i = 0; i < NCOMMAND; i++) {
6654 if (command_table[i].name == NULL)
6655 continue;
6656
6657 if (strcmp(command, command_table[i].name) == 0) {
6658 *idx = i;
6659 return (0);
6660 }
6661 }
6662 return (1);
6663 }
6664
6665 int
main(int argc,char ** argv)6666 main(int argc, char **argv)
6667 {
6668 int ret = 0;
6669 int i;
6670 char *cmdname;
6671
6672 (void) setlocale(LC_ALL, "");
6673 (void) textdomain(TEXT_DOMAIN);
6674
6675 if ((g_zfs = libzfs_init()) == NULL) {
6676 (void) fprintf(stderr, gettext("internal error: failed to "
6677 "initialize ZFS library\n"));
6678 return (1);
6679 }
6680
6681 libzfs_print_on_error(g_zfs, B_TRUE);
6682
6683 opterr = 0;
6684
6685 /*
6686 * Make sure the user has specified some command.
6687 */
6688 if (argc < 2) {
6689 (void) fprintf(stderr, gettext("missing command\n"));
6690 usage(B_FALSE);
6691 }
6692
6693 cmdname = argv[1];
6694
6695 /*
6696 * Special case '-?'
6697 */
6698 if (strcmp(cmdname, "-?") == 0)
6699 usage(B_TRUE);
6700
6701 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6702
6703 /*
6704 * Run the appropriate command.
6705 */
6706 if (find_command_idx(cmdname, &i) == 0) {
6707 current_command = &command_table[i];
6708 ret = command_table[i].func(argc - 1, argv + 1);
6709 } else if (strchr(cmdname, '=')) {
6710 verify(find_command_idx("set", &i) == 0);
6711 current_command = &command_table[i];
6712 ret = command_table[i].func(argc, argv);
6713 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6714 /*
6715 * 'freeze' is a vile debugging abomination, so we treat
6716 * it as such.
6717 */
6718 zfs_cmd_t zc = { 0 };
6719 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name));
6720 return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc));
6721 } else {
6722 (void) fprintf(stderr, gettext("unrecognized "
6723 "command '%s'\n"), cmdname);
6724 usage(B_FALSE);
6725 }
6726
6727 if (ret == 0 && log_history)
6728 (void) zpool_log_history(g_zfs, history_str);
6729
6730 libzfs_fini(g_zfs);
6731
6732 /*
6733 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
6734 * for the purposes of running ::findleaks.
6735 */
6736 if (getenv("ZFS_ABORT") != NULL) {
6737 (void) printf("dumping core by request\n");
6738 abort();
6739 }
6740
6741 return (ret);
6742 }
6743