]> git.proxmox.com Git - mirror_zfs.git/blame - zfs/zcmd/zpool/zpool_main.c
Initial Linux ZFS GIT Repo
[mirror_zfs.git] / zfs / zcmd / zpool / zpool_main.c
CommitLineData
34dc7c2f
BB
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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident "@(#)zpool_main.c 1.54 08/02/13 SMI"
28
29#include <assert.h>
30#include <ctype.h>
31#include <dirent.h>
32#include <errno.h>
33#include <fcntl.h>
34#include <libgen.h>
35#include <libintl.h>
36#include <libuutil.h>
37#include <locale.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <strings.h>
42#include <unistd.h>
43#include <priv.h>
44#include <pwd.h>
45#include <zone.h>
46#include <sys/fs/zfs.h>
47
48#include <sys/stat.h>
49
50#include <libzfs.h>
51
52#include "zpool_util.h"
53#include "zfs_comutil.h"
54
55static int zpool_do_create(int, char **);
56static int zpool_do_destroy(int, char **);
57
58static int zpool_do_add(int, char **);
59static int zpool_do_remove(int, char **);
60
61static int zpool_do_list(int, char **);
62static int zpool_do_iostat(int, char **);
63static int zpool_do_status(int, char **);
64
65static int zpool_do_online(int, char **);
66static int zpool_do_offline(int, char **);
67static int zpool_do_clear(int, char **);
68
69static int zpool_do_attach(int, char **);
70static int zpool_do_detach(int, char **);
71static int zpool_do_replace(int, char **);
72
73static int zpool_do_scrub(int, char **);
74
75static int zpool_do_import(int, char **);
76static int zpool_do_export(int, char **);
77
78static int zpool_do_upgrade(int, char **);
79
80static int zpool_do_history(int, char **);
81
82static int zpool_do_get(int, char **);
83static int zpool_do_set(int, char **);
84
85/*
86 * These libumem hooks provide a reasonable set of defaults for the allocator's
87 * debugging facilities.
88 */
89const char *
90_umem_debug_init(void)
91{
92 return ("default,verbose"); /* $UMEM_DEBUG setting */
93}
94
95const char *
96_umem_logging_init(void)
97{
98 return ("fail,contents"); /* $UMEM_LOGGING setting */
99}
100
101typedef enum {
102 HELP_ADD,
103 HELP_ATTACH,
104 HELP_CLEAR,
105 HELP_CREATE,
106 HELP_DESTROY,
107 HELP_DETACH,
108 HELP_EXPORT,
109 HELP_HISTORY,
110 HELP_IMPORT,
111 HELP_IOSTAT,
112 HELP_LIST,
113 HELP_OFFLINE,
114 HELP_ONLINE,
115 HELP_REPLACE,
116 HELP_REMOVE,
117 HELP_SCRUB,
118 HELP_STATUS,
119 HELP_UPGRADE,
120 HELP_GET,
121 HELP_SET
122} zpool_help_t;
123
124
125typedef struct zpool_command {
126 const char *name;
127 int (*func)(int, char **);
128 zpool_help_t usage;
129} zpool_command_t;
130
131/*
132 * Master command table. Each ZFS command has a name, associated function, and
133 * usage message. The usage messages need to be internationalized, so we have
134 * to have a function to return the usage message based on a command index.
135 *
136 * These commands are organized according to how they are displayed in the usage
137 * message. An empty command (one with a NULL name) indicates an empty line in
138 * the generic usage message.
139 */
140static zpool_command_t command_table[] = {
141 { "create", zpool_do_create, HELP_CREATE },
142 { "destroy", zpool_do_destroy, HELP_DESTROY },
143 { NULL },
144 { "add", zpool_do_add, HELP_ADD },
145 { "remove", zpool_do_remove, HELP_REMOVE },
146 { NULL },
147 { "list", zpool_do_list, HELP_LIST },
148 { "iostat", zpool_do_iostat, HELP_IOSTAT },
149 { "status", zpool_do_status, HELP_STATUS },
150 { NULL },
151 { "online", zpool_do_online, HELP_ONLINE },
152 { "offline", zpool_do_offline, HELP_OFFLINE },
153 { "clear", zpool_do_clear, HELP_CLEAR },
154 { NULL },
155 { "attach", zpool_do_attach, HELP_ATTACH },
156 { "detach", zpool_do_detach, HELP_DETACH },
157 { "replace", zpool_do_replace, HELP_REPLACE },
158 { NULL },
159 { "scrub", zpool_do_scrub, HELP_SCRUB },
160 { NULL },
161 { "import", zpool_do_import, HELP_IMPORT },
162 { "export", zpool_do_export, HELP_EXPORT },
163 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
164 { NULL },
165 { "history", zpool_do_history, HELP_HISTORY },
166 { "get", zpool_do_get, HELP_GET },
167 { "set", zpool_do_set, HELP_SET },
168};
169
170#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
171
172zpool_command_t *current_command;
173static char history_str[HIS_MAX_RECORD_LEN];
174
175static const char *
176get_usage(zpool_help_t idx) {
177 switch (idx) {
178 case HELP_ADD:
179 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
180 case HELP_ATTACH:
181 return (gettext("\tattach [-f] <pool> <device> "
182 "<new-device>\n"));
183 case HELP_CLEAR:
184 return (gettext("\tclear <pool> [device]\n"));
185 case HELP_CREATE:
186 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
187 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
188 case HELP_DESTROY:
189 return (gettext("\tdestroy [-f] <pool>\n"));
190 case HELP_DETACH:
191 return (gettext("\tdetach <pool> <device>\n"));
192 case HELP_EXPORT:
193 return (gettext("\texport [-f] <pool> ...\n"));
194 case HELP_HISTORY:
195 return (gettext("\thistory [-il] [<pool>] ...\n"));
196 case HELP_IMPORT:
197 return (gettext("\timport [-d dir] [-D]\n"
198 "\timport [-o mntopts] [-o property=value] ... \n"
199 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
200 "\timport [-o mntopts] [-o property=value] ... \n"
201 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] "
202 "<pool | id> [newpool]\n"));
203 case HELP_IOSTAT:
204 return (gettext("\tiostat [-v] [pool] ... [interval "
205 "[count]]\n"));
206 case HELP_LIST:
207 return (gettext("\tlist [-H] [-o property[,...]] "
208 "[pool] ...\n"));
209 case HELP_OFFLINE:
210 return (gettext("\toffline [-t] <pool> <device> ...\n"));
211 case HELP_ONLINE:
212 return (gettext("\tonline <pool> <device> ...\n"));
213 case HELP_REPLACE:
214 return (gettext("\treplace [-f] <pool> <device> "
215 "[new-device]\n"));
216 case HELP_REMOVE:
217 return (gettext("\tremove <pool> <device> ...\n"));
218 case HELP_SCRUB:
219 return (gettext("\tscrub [-s] <pool> ...\n"));
220 case HELP_STATUS:
221 return (gettext("\tstatus [-vx] [pool] ...\n"));
222 case HELP_UPGRADE:
223 return (gettext("\tupgrade\n"
224 "\tupgrade -v\n"
225 "\tupgrade [-V version] <-a | pool ...>\n"));
226 case HELP_GET:
227 return (gettext("\tget <\"all\" | property[,...]> "
228 "<pool> ...\n"));
229 case HELP_SET:
230 return (gettext("\tset <property=value> <pool> \n"));
231 }
232
233 abort();
234 /* NOTREACHED */
235}
236
237
238/*
239 * Callback routine that will print out a pool property value.
240 */
241static int
242print_prop_cb(int prop, void *cb)
243{
244 FILE *fp = cb;
245
246 (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop));
247
248 if (zpool_prop_readonly(prop))
249 (void) fprintf(fp, " NO ");
250 else
251 (void) fprintf(fp, " YES ");
252
253 if (zpool_prop_values(prop) == NULL)
254 (void) fprintf(fp, "-\n");
255 else
256 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
257
258 return (ZPROP_CONT);
259}
260
261/*
262 * Display usage message. If we're inside a command, display only the usage for
263 * that command. Otherwise, iterate over the entire command table and display
264 * a complete usage message.
265 */
266void
267usage(boolean_t requested)
268{
269 FILE *fp = requested ? stdout : stderr;
270
271 if (current_command == NULL) {
272 int i;
273
274 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
275 (void) fprintf(fp,
276 gettext("where 'command' is one of the following:\n\n"));
277
278 for (i = 0; i < NCOMMAND; i++) {
279 if (command_table[i].name == NULL)
280 (void) fprintf(fp, "\n");
281 else
282 (void) fprintf(fp, "%s",
283 get_usage(command_table[i].usage));
284 }
285 } else {
286 (void) fprintf(fp, gettext("usage:\n"));
287 (void) fprintf(fp, "%s", get_usage(current_command->usage));
288 }
289
290 if (current_command != NULL &&
291 ((strcmp(current_command->name, "set") == 0) ||
292 (strcmp(current_command->name, "get") == 0) ||
293 (strcmp(current_command->name, "list") == 0))) {
294
295 (void) fprintf(fp,
296 gettext("\nthe following properties are supported:\n"));
297
298 (void) fprintf(fp, "\n\t%-13s %s %s\n\n",
299 "PROPERTY", "EDIT", "VALUES");
300
301 /* Iterate over all properties */
302 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
303 ZFS_TYPE_POOL);
304 }
305
306 /*
307 * See comments at end of main().
308 */
309 if (getenv("ZFS_ABORT") != NULL) {
310 (void) printf("dumping core by request\n");
311 abort();
312 }
313
314 exit(requested ? 0 : 2);
315}
316
317void
318print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
319 boolean_t print_logs)
320{
321 nvlist_t **child;
322 uint_t c, children;
323 char *vname;
324
325 if (name != NULL)
326 (void) printf("\t%*s%s\n", indent, "", name);
327
328 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
329 &child, &children) != 0)
330 return;
331
332 for (c = 0; c < children; c++) {
333 uint64_t is_log = B_FALSE;
334
335 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
336 &is_log);
337 if ((is_log && !print_logs) || (!is_log && print_logs))
338 continue;
339
340 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
341 print_vdev_tree(zhp, vname, child[c], indent + 2,
342 B_FALSE);
343 free(vname);
344 }
345}
346
347/*
348 * Add a property pair (name, string-value) into a property nvlist.
349 */
350static int
351add_prop_list(const char *propname, char *propval, nvlist_t **props)
352{
353 char *strval;
354 nvlist_t *proplist;
355 zpool_prop_t prop;
356
357 if (*props == NULL &&
358 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
359 (void) fprintf(stderr,
360 gettext("internal error: out of memory\n"));
361 return (1);
362 }
363
364 proplist = *props;
365
366 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
367 (void) fprintf(stderr, gettext("property '%s' is "
368 "not a valid pool property\n"), propname);
369 return (2);
370 }
371
372 /* Use normalized property name for nvlist operations */
373 if (nvlist_lookup_string(proplist, zpool_prop_to_name(prop),
374 &strval) == 0 && prop != ZPOOL_PROP_CACHEFILE) {
375 (void) fprintf(stderr, gettext("property '%s' "
376 "specified multiple times\n"), propname);
377 return (2);
378 }
379
380 if (nvlist_add_string(proplist, zpool_prop_to_name(prop),
381 propval) != 0) {
382 (void) fprintf(stderr, gettext("internal "
383 "error: out of memory\n"));
384 return (1);
385 }
386
387 return (0);
388}
389
390/*
391 * zpool add [-fn] <pool> <vdev> ...
392 *
393 * -f Force addition of devices, even if they appear in use
394 * -n Do not add the devices, but display the resulting layout if
395 * they were to be added.
396 *
397 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
398 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
399 * libzfs.
400 */
401int
402zpool_do_add(int argc, char **argv)
403{
404 boolean_t force = B_FALSE;
405 boolean_t dryrun = B_FALSE;
406 int c;
407 nvlist_t *nvroot;
408 char *poolname;
409 int ret;
410 zpool_handle_t *zhp;
411 nvlist_t *config;
412
413 /* check options */
414 while ((c = getopt(argc, argv, "fn")) != -1) {
415 switch (c) {
416 case 'f':
417 force = B_TRUE;
418 break;
419 case 'n':
420 dryrun = B_TRUE;
421 break;
422 case '?':
423 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
424 optopt);
425 usage(B_FALSE);
426 }
427 }
428
429 argc -= optind;
430 argv += optind;
431
432 /* get pool name and check number of arguments */
433 if (argc < 1) {
434 (void) fprintf(stderr, gettext("missing pool name argument\n"));
435 usage(B_FALSE);
436 }
437 if (argc < 2) {
438 (void) fprintf(stderr, gettext("missing vdev specification\n"));
439 usage(B_FALSE);
440 }
441
442 poolname = argv[0];
443
444 argc--;
445 argv++;
446
447 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
448 return (1);
449
450 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
451 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
452 poolname);
453 zpool_close(zhp);
454 return (1);
455 }
456
457 /* pass off to get_vdev_spec for processing */
458 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, argc, argv);
459 if (nvroot == NULL) {
460 zpool_close(zhp);
461 return (1);
462 }
463
464 if (dryrun) {
465 nvlist_t *poolnvroot;
466
467 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
468 &poolnvroot) == 0);
469
470 (void) printf(gettext("would update '%s' to the following "
471 "configuration:\n"), zpool_get_name(zhp));
472
473 /* print original main pool and new tree */
474 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
475 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
476
477 /* Do the same for the logs */
478 if (num_logs(poolnvroot) > 0) {
479 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
480 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
481 } else if (num_logs(nvroot) > 0) {
482 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
483 }
484
485 ret = 0;
486 } else {
487 ret = (zpool_add(zhp, nvroot) != 0);
488 }
489
490 nvlist_free(nvroot);
491 zpool_close(zhp);
492
493 return (ret);
494}
495
496/*
497 * zpool remove <pool> <vdev> ...
498 *
499 * Removes the given vdev from the pool. Currently, this only supports removing
500 * spares and cache devices from the pool. Eventually, we'll want to support
501 * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
502 */
503int
504zpool_do_remove(int argc, char **argv)
505{
506 char *poolname;
507 int i, ret = 0;
508 zpool_handle_t *zhp;
509
510 argc--;
511 argv++;
512
513 /* get pool name and check number of arguments */
514 if (argc < 1) {
515 (void) fprintf(stderr, gettext("missing pool name argument\n"));
516 usage(B_FALSE);
517 }
518 if (argc < 2) {
519 (void) fprintf(stderr, gettext("missing device\n"));
520 usage(B_FALSE);
521 }
522
523 poolname = argv[0];
524
525 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
526 return (1);
527
528 for (i = 1; i < argc; i++) {
529 if (zpool_vdev_remove(zhp, argv[i]) != 0)
530 ret = 1;
531 }
532
533 return (ret);
534}
535
536/*
537 * zpool create [-fn] [-o property=value] ... [-R root] [-m mountpoint]
538 * <pool> <dev> ...
539 *
540 * -f Force creation, even if devices appear in use
541 * -n Do not create the pool, but display the resulting layout if it
542 * were to be created.
543 * -R Create a pool under an alternate root
544 * -m Set default mountpoint for the root dataset. By default it's
545 * '/<pool>'
546 * -o Set property=value.
547 *
548 * Creates the named pool according to the given vdev specification. The
549 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
550 * we get the nvlist back from get_vdev_spec(), we either print out the contents
551 * (if '-n' was specified), or pass it to libzfs to do the creation.
552 */
553int
554zpool_do_create(int argc, char **argv)
555{
556 boolean_t force = B_FALSE;
557 boolean_t dryrun = B_FALSE;
558 int c;
559 nvlist_t *nvroot = NULL;
560 char *poolname;
561 int ret = 1;
562 char *altroot = NULL;
563 char *mountpoint = NULL;
564 nvlist_t *props = NULL;
565 char *propval;
566
567 /* check options */
568 while ((c = getopt(argc, argv, ":fnR:m:o:")) != -1) {
569 switch (c) {
570 case 'f':
571 force = B_TRUE;
572 break;
573 case 'n':
574 dryrun = B_TRUE;
575 break;
576 case 'R':
577 altroot = optarg;
578 if (add_prop_list(zpool_prop_to_name(
579 ZPOOL_PROP_ALTROOT), optarg, &props))
580 goto errout;
581 if (nvlist_lookup_string(props,
582 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
583 &propval) == 0)
584 break;
585 if (add_prop_list(zpool_prop_to_name(
586 ZPOOL_PROP_CACHEFILE), "none", &props))
587 goto errout;
588 break;
589 case 'm':
590 mountpoint = optarg;
591 break;
592 case 'o':
593 if ((propval = strchr(optarg, '=')) == NULL) {
594 (void) fprintf(stderr, gettext("missing "
595 "'=' for -o option\n"));
596 goto errout;
597 }
598 *propval = '\0';
599 propval++;
600
601 if (add_prop_list(optarg, propval, &props))
602 goto errout;
603 break;
604 case ':':
605 (void) fprintf(stderr, gettext("missing argument for "
606 "'%c' option\n"), optopt);
607 goto badusage;
608 case '?':
609 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
610 optopt);
611 goto badusage;
612 }
613 }
614
615 argc -= optind;
616 argv += optind;
617
618 /* get pool name and check number of arguments */
619 if (argc < 1) {
620 (void) fprintf(stderr, gettext("missing pool name argument\n"));
621 goto badusage;
622 }
623 if (argc < 2) {
624 (void) fprintf(stderr, gettext("missing vdev specification\n"));
625 goto badusage;
626 }
627
628 poolname = argv[0];
629
630 /*
631 * As a special case, check for use of '/' in the name, and direct the
632 * user to use 'zfs create' instead.
633 */
634 if (strchr(poolname, '/') != NULL) {
635 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
636 "character '/' in pool name\n"), poolname);
637 (void) fprintf(stderr, gettext("use 'zfs create' to "
638 "create a dataset\n"));
639 goto errout;
640 }
641
642 /* pass off to get_vdev_spec for bulk processing */
643 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, argc - 1,
644 argv + 1);
645 if (nvroot == NULL)
646 return (1);
647
648 /* make_root_vdev() allows 0 toplevel children if there are spares */
649 if (!zfs_allocatable_devs(nvroot)) {
650 (void) fprintf(stderr, gettext("invalid vdev "
651 "specification: at least one toplevel vdev must be "
652 "specified\n"));
653 goto errout;
654 }
655
656
657 if (altroot != NULL && altroot[0] != '/') {
658 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
659 "must be an absolute path\n"), altroot);
660 goto errout;
661 }
662
663 /*
664 * Check the validity of the mountpoint and direct the user to use the
665 * '-m' mountpoint option if it looks like its in use.
666 */
667 if (mountpoint == NULL ||
668 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
669 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
670 char buf[MAXPATHLEN];
671 DIR *dirp;
672
673 if (mountpoint && mountpoint[0] != '/') {
674 (void) fprintf(stderr, gettext("invalid mountpoint "
675 "'%s': must be an absolute path, 'legacy', or "
676 "'none'\n"), mountpoint);
677 goto errout;
678 }
679
680 if (mountpoint == NULL) {
681 if (altroot != NULL)
682 (void) snprintf(buf, sizeof (buf), "%s/%s",
683 altroot, poolname);
684 else
685 (void) snprintf(buf, sizeof (buf), "/%s",
686 poolname);
687 } else {
688 if (altroot != NULL)
689 (void) snprintf(buf, sizeof (buf), "%s%s",
690 altroot, mountpoint);
691 else
692 (void) snprintf(buf, sizeof (buf), "%s",
693 mountpoint);
694 }
695
696 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
697 (void) fprintf(stderr, gettext("mountpoint '%s' : "
698 "%s\n"), buf, strerror(errno));
699 (void) fprintf(stderr, gettext("use '-m' "
700 "option to provide a different default\n"));
701 goto errout;
702 } else if (dirp) {
703 int count = 0;
704
705 while (count < 3 && readdir(dirp) != NULL)
706 count++;
707 (void) closedir(dirp);
708
709 if (count > 2) {
710 (void) fprintf(stderr, gettext("mountpoint "
711 "'%s' exists and is not empty\n"), buf);
712 (void) fprintf(stderr, gettext("use '-m' "
713 "option to provide a "
714 "different default\n"));
715 goto errout;
716 }
717 }
718 }
719
720 if (dryrun) {
721 /*
722 * For a dry run invocation, print out a basic message and run
723 * through all the vdevs in the list and print out in an
724 * appropriate hierarchy.
725 */
726 (void) printf(gettext("would create '%s' with the "
727 "following layout:\n\n"), poolname);
728
729 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
730 if (num_logs(nvroot) > 0)
731 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
732
733 ret = 0;
734 } else {
735 /*
736 * Hand off to libzfs.
737 */
738 if (zpool_create(g_zfs, poolname, nvroot, props) == 0) {
739 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
740 ZFS_TYPE_FILESYSTEM);
741 if (pool != NULL) {
742 if (mountpoint != NULL)
743 verify(zfs_prop_set(pool,
744 zfs_prop_to_name(
745 ZFS_PROP_MOUNTPOINT),
746 mountpoint) == 0);
747 if (zfs_mount(pool, NULL, 0) == 0)
748 ret = zfs_shareall(pool);
749 zfs_close(pool);
750 }
751 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
752 (void) fprintf(stderr, gettext("pool name may have "
753 "been omitted\n"));
754 }
755 }
756
757errout:
758 nvlist_free(nvroot);
759 nvlist_free(props);
760 return (ret);
761badusage:
762 nvlist_free(props);
763 usage(B_FALSE);
764 return (2);
765}
766
767/*
768 * zpool destroy <pool>
769 *
770 * -f Forcefully unmount any datasets
771 *
772 * Destroy the given pool. Automatically unmounts any datasets in the pool.
773 */
774int
775zpool_do_destroy(int argc, char **argv)
776{
777 boolean_t force = B_FALSE;
778 int c;
779 char *pool;
780 zpool_handle_t *zhp;
781 int ret;
782
783 /* check options */
784 while ((c = getopt(argc, argv, "f")) != -1) {
785 switch (c) {
786 case 'f':
787 force = B_TRUE;
788 break;
789 case '?':
790 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
791 optopt);
792 usage(B_FALSE);
793 }
794 }
795
796 argc -= optind;
797 argv += optind;
798
799 /* check arguments */
800 if (argc < 1) {
801 (void) fprintf(stderr, gettext("missing pool argument\n"));
802 usage(B_FALSE);
803 }
804 if (argc > 1) {
805 (void) fprintf(stderr, gettext("too many arguments\n"));
806 usage(B_FALSE);
807 }
808
809 pool = argv[0];
810
811 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
812 /*
813 * As a special case, check for use of '/' in the name, and
814 * direct the user to use 'zfs destroy' instead.
815 */
816 if (strchr(pool, '/') != NULL)
817 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
818 "destroy a dataset\n"));
819 return (1);
820 }
821
822 if (zpool_disable_datasets(zhp, force) != 0) {
823 (void) fprintf(stderr, gettext("could not destroy '%s': "
824 "could not unmount datasets\n"), zpool_get_name(zhp));
825 return (1);
826 }
827
828 ret = (zpool_destroy(zhp) != 0);
829
830 zpool_close(zhp);
831
832 return (ret);
833}
834
835/*
836 * zpool export [-f] <pool> ...
837 *
838 * -f Forcefully unmount datasets
839 *
840 * Export the given pools. By default, the command will attempt to cleanly
841 * unmount any active datasets within the pool. If the '-f' flag is specified,
842 * then the datasets will be forcefully unmounted.
843 */
844int
845zpool_do_export(int argc, char **argv)
846{
847 boolean_t force = B_FALSE;
848 int c;
849 zpool_handle_t *zhp;
850 int ret;
851 int i;
852
853 /* check options */
854 while ((c = getopt(argc, argv, "f")) != -1) {
855 switch (c) {
856 case 'f':
857 force = B_TRUE;
858 break;
859 case '?':
860 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
861 optopt);
862 usage(B_FALSE);
863 }
864 }
865
866 argc -= optind;
867 argv += optind;
868
869 /* check arguments */
870 if (argc < 1) {
871 (void) fprintf(stderr, gettext("missing pool argument\n"));
872 usage(B_FALSE);
873 }
874
875 ret = 0;
876 for (i = 0; i < argc; i++) {
877 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
878 ret = 1;
879 continue;
880 }
881
882 if (zpool_disable_datasets(zhp, force) != 0) {
883 ret = 1;
884 zpool_close(zhp);
885 continue;
886 }
887
888 if (zpool_export(zhp) != 0)
889 ret = 1;
890
891 zpool_close(zhp);
892 }
893
894 return (ret);
895}
896
897/*
898 * Given a vdev configuration, determine the maximum width needed for the device
899 * name column.
900 */
901static int
902max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
903{
904 char *name = zpool_vdev_name(g_zfs, zhp, nv);
905 nvlist_t **child;
906 uint_t c, children;
907 int ret;
908
909 if (strlen(name) + depth > max)
910 max = strlen(name) + depth;
911
912 free(name);
913
914 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
915 &child, &children) == 0) {
916 for (c = 0; c < children; c++)
917 if ((ret = max_width(zhp, child[c], depth + 2,
918 max)) > max)
919 max = ret;
920 }
921
922 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
923 &child, &children) == 0) {
924 for (c = 0; c < children; c++)
925 if ((ret = max_width(zhp, child[c], depth + 2,
926 max)) > max)
927 max = ret;
928 }
929
930 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
931 &child, &children) == 0) {
932 for (c = 0; c < children; c++)
933 if ((ret = max_width(zhp, child[c], depth + 2,
934 max)) > max)
935 max = ret;
936 }
937
938
939 return (max);
940}
941
942
943/*
944 * Print the configuration of an exported pool. Iterate over all vdevs in the
945 * pool, printing out the name and status for each one.
946 */
947void
948print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
949 boolean_t print_logs)
950{
951 nvlist_t **child;
952 uint_t c, children;
953 vdev_stat_t *vs;
954 char *type, *vname;
955
956 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
957 if (strcmp(type, VDEV_TYPE_MISSING) == 0)
958 return;
959
960 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
961 (uint64_t **)&vs, &c) == 0);
962
963 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
964 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
965
966 if (vs->vs_aux != 0) {
967 (void) printf(" ");
968
969 switch (vs->vs_aux) {
970 case VDEV_AUX_OPEN_FAILED:
971 (void) printf(gettext("cannot open"));
972 break;
973
974 case VDEV_AUX_BAD_GUID_SUM:
975 (void) printf(gettext("missing device"));
976 break;
977
978 case VDEV_AUX_NO_REPLICAS:
979 (void) printf(gettext("insufficient replicas"));
980 break;
981
982 case VDEV_AUX_VERSION_NEWER:
983 (void) printf(gettext("newer version"));
984 break;
985
986 case VDEV_AUX_ERR_EXCEEDED:
987 (void) printf(gettext("too many errors"));
988 break;
989
990 default:
991 (void) printf(gettext("corrupted data"));
992 break;
993 }
994 }
995 (void) printf("\n");
996
997 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
998 &child, &children) != 0)
999 return;
1000
1001 for (c = 0; c < children; c++) {
1002 uint64_t is_log = B_FALSE;
1003
1004 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1005 &is_log);
1006 if ((is_log && !print_logs) || (!is_log && print_logs))
1007 continue;
1008
1009 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1010 print_import_config(vname, child[c],
1011 namewidth, depth + 2, B_FALSE);
1012 free(vname);
1013 }
1014
1015 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1016 &child, &children) == 0) {
1017 (void) printf(gettext("\tcache\n"));
1018 for (c = 0; c < children; c++) {
1019 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1020 (void) printf("\t %s\n", vname);
1021 free(vname);
1022 }
1023 }
1024
1025 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1026 &child, &children) == 0) {
1027 (void) printf(gettext("\tspares\n"));
1028 for (c = 0; c < children; c++) {
1029 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1030 (void) printf("\t %s\n", vname);
1031 free(vname);
1032 }
1033 }
1034}
1035
1036/*
1037 * Display the status for the given pool.
1038 */
1039static void
1040show_import(nvlist_t *config)
1041{
1042 uint64_t pool_state;
1043 vdev_stat_t *vs;
1044 char *name;
1045 uint64_t guid;
1046 char *msgid;
1047 nvlist_t *nvroot;
1048 int reason;
1049 const char *health;
1050 uint_t vsc;
1051 int namewidth;
1052
1053 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1054 &name) == 0);
1055 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1056 &guid) == 0);
1057 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1058 &pool_state) == 0);
1059 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1060 &nvroot) == 0);
1061
1062 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1063 (uint64_t **)&vs, &vsc) == 0);
1064 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1065
1066 reason = zpool_import_status(config, &msgid);
1067
1068 (void) printf(gettext(" pool: %s\n"), name);
1069 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1070 (void) printf(gettext(" state: %s"), health);
1071 if (pool_state == POOL_STATE_DESTROYED)
1072 (void) printf(gettext(" (DESTROYED)"));
1073 (void) printf("\n");
1074
1075 switch (reason) {
1076 case ZPOOL_STATUS_MISSING_DEV_R:
1077 case ZPOOL_STATUS_MISSING_DEV_NR:
1078 case ZPOOL_STATUS_BAD_GUID_SUM:
1079 (void) printf(gettext("status: One or more devices are missing "
1080 "from the system.\n"));
1081 break;
1082
1083 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1084 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1085 (void) printf(gettext("status: One or more devices contains "
1086 "corrupted data.\n"));
1087 break;
1088
1089 case ZPOOL_STATUS_CORRUPT_DATA:
1090 (void) printf(gettext("status: The pool data is corrupted.\n"));
1091 break;
1092
1093 case ZPOOL_STATUS_OFFLINE_DEV:
1094 (void) printf(gettext("status: One or more devices "
1095 "are offlined.\n"));
1096 break;
1097
1098 case ZPOOL_STATUS_CORRUPT_POOL:
1099 (void) printf(gettext("status: The pool metadata is "
1100 "corrupted.\n"));
1101 break;
1102
1103 case ZPOOL_STATUS_VERSION_OLDER:
1104 (void) printf(gettext("status: The pool is formatted using an "
1105 "older on-disk version.\n"));
1106 break;
1107
1108 case ZPOOL_STATUS_VERSION_NEWER:
1109 (void) printf(gettext("status: The pool is formatted using an "
1110 "incompatible version.\n"));
1111 break;
1112 case ZPOOL_STATUS_HOSTID_MISMATCH:
1113 (void) printf(gettext("status: The pool was last accessed by "
1114 "another system.\n"));
1115 break;
1116 case ZPOOL_STATUS_FAULTED_DEV_R:
1117 case ZPOOL_STATUS_FAULTED_DEV_NR:
1118 (void) printf(gettext("status: One or more devices are "
1119 "faulted.\n"));
1120 break;
1121
1122 default:
1123 /*
1124 * No other status can be seen when importing pools.
1125 */
1126 assert(reason == ZPOOL_STATUS_OK);
1127 }
1128
1129 /*
1130 * Print out an action according to the overall state of the pool.
1131 */
1132 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1133 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1134 (void) printf(gettext("action: The pool can be "
1135 "imported using its name or numeric identifier, "
1136 "though\n\tsome features will not be available "
1137 "without an explicit 'zpool upgrade'.\n"));
1138 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1139 (void) printf(gettext("action: The pool can be "
1140 "imported using its name or numeric "
1141 "identifier and\n\tthe '-f' flag.\n"));
1142 else
1143 (void) printf(gettext("action: The pool can be "
1144 "imported using its name or numeric "
1145 "identifier.\n"));
1146 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1147 (void) printf(gettext("action: The pool can be imported "
1148 "despite missing or damaged devices. The\n\tfault "
1149 "tolerance of the pool may be compromised if imported.\n"));
1150 } else {
1151 switch (reason) {
1152 case ZPOOL_STATUS_VERSION_NEWER:
1153 (void) printf(gettext("action: The pool cannot be "
1154 "imported. Access the pool on a system running "
1155 "newer\n\tsoftware, or recreate the pool from "
1156 "backup.\n"));
1157 break;
1158 case ZPOOL_STATUS_MISSING_DEV_R:
1159 case ZPOOL_STATUS_MISSING_DEV_NR:
1160 case ZPOOL_STATUS_BAD_GUID_SUM:
1161 (void) printf(gettext("action: The pool cannot be "
1162 "imported. Attach the missing\n\tdevices and try "
1163 "again.\n"));
1164 break;
1165 default:
1166 (void) printf(gettext("action: The pool cannot be "
1167 "imported due to damaged devices or data.\n"));
1168 }
1169 }
1170
1171 /*
1172 * If the state is "closed" or "can't open", and the aux state
1173 * is "corrupt data":
1174 */
1175 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1176 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1177 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1178 if (pool_state == POOL_STATE_DESTROYED)
1179 (void) printf(gettext("\tThe pool was destroyed, "
1180 "but can be imported using the '-Df' flags.\n"));
1181 else if (pool_state != POOL_STATE_EXPORTED)
1182 (void) printf(gettext("\tThe pool may be active on "
1183 "another system, but can be imported using\n\t"
1184 "the '-f' flag.\n"));
1185 }
1186
1187 if (msgid != NULL)
1188 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
1189 msgid);
1190
1191 (void) printf(gettext("config:\n\n"));
1192
1193 namewidth = max_width(NULL, nvroot, 0, 0);
1194 if (namewidth < 10)
1195 namewidth = 10;
1196
1197 print_import_config(name, nvroot, namewidth, 0, B_FALSE);
1198 if (num_logs(nvroot) > 0) {
1199 (void) printf(gettext("\tlogs\n"));
1200 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1201 }
1202
1203 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1204 (void) printf(gettext("\n\tAdditional devices are known to "
1205 "be part of this pool, though their\n\texact "
1206 "configuration cannot be determined.\n"));
1207 }
1208}
1209
1210/*
1211 * Perform the import for the given configuration. This passes the heavy
1212 * lifting off to zpool_import_props(), and then mounts the datasets contained
1213 * within the pool.
1214 */
1215static int
1216do_import(nvlist_t *config, const char *newname, const char *mntopts,
1217 int force, nvlist_t *props)
1218{
1219 zpool_handle_t *zhp;
1220 char *name;
1221 uint64_t state;
1222 uint64_t version;
1223 int error = 0;
1224
1225 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1226 &name) == 0);
1227
1228 verify(nvlist_lookup_uint64(config,
1229 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1230 verify(nvlist_lookup_uint64(config,
1231 ZPOOL_CONFIG_VERSION, &version) == 0);
1232 if (version > SPA_VERSION) {
1233 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1234 "is formatted using a newer ZFS version\n"), name);
1235 return (1);
1236 } else if (state != POOL_STATE_EXPORTED && !force) {
1237 uint64_t hostid;
1238
1239 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1240 &hostid) == 0) {
1241 if ((unsigned long)hostid != gethostid()) {
1242 char *hostname;
1243 uint64_t timestamp;
1244 time_t t;
1245
1246 verify(nvlist_lookup_string(config,
1247 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1248 verify(nvlist_lookup_uint64(config,
1249 ZPOOL_CONFIG_TIMESTAMP, &timestamp) == 0);
1250 t = timestamp;
1251 (void) fprintf(stderr, gettext("cannot import "
1252 "'%s': pool may be in use from other "
1253 "system, it was last accessed by %s "
1254 "(hostid: 0x%lx) on %s"), name, hostname,
1255 (unsigned long)hostid,
1256 asctime(localtime(&t)));
1257 (void) fprintf(stderr, gettext("use '-f' to "
1258 "import anyway\n"));
1259 return (1);
1260 }
1261 } else {
1262 (void) fprintf(stderr, gettext("cannot import '%s': "
1263 "pool may be in use from other system\n"), name);
1264 (void) fprintf(stderr, gettext("use '-f' to import "
1265 "anyway\n"));
1266 return (1);
1267 }
1268 }
1269
1270 if (zpool_import_props(g_zfs, config, newname, props) != 0)
1271 return (1);
1272
1273 if (newname != NULL)
1274 name = (char *)newname;
1275
1276 verify((zhp = zpool_open(g_zfs, name)) != NULL);
1277
1278 if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1279 zpool_close(zhp);
1280 return (1);
1281 }
1282
1283 zpool_close(zhp);
1284 return (error);
1285}
1286
1287/*
1288 * zpool import [-d dir] [-D]
1289 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1290 * [-d dir | -c cachefile] [-f] -a
1291 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1292 * [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1293 *
1294 * -c Read pool information from a cachefile instead of searching
1295 * devices.
1296 *
1297 * -d Scan in a specific directory, other than /dev/dsk. More than
1298 * one directory can be specified using multiple '-d' options.
1299 *
1300 * -D Scan for previously destroyed pools or import all or only
1301 * specified destroyed pools.
1302 *
1303 * -R Temporarily import the pool, with all mountpoints relative to
1304 * the given root. The pool will remain exported when the machine
1305 * is rebooted.
1306 *
1307 * -f Force import, even if it appears that the pool is active.
1308 *
1309 * -a Import all pools found.
1310 *
1311 * -o Set property=value and/or temporary mount options (without '=').
1312 *
1313 * The import command scans for pools to import, and import pools based on pool
1314 * name and GUID. The pool can also be renamed as part of the import process.
1315 */
1316int
1317zpool_do_import(int argc, char **argv)
1318{
1319 char **searchdirs = NULL;
1320 int nsearch = 0;
1321 int c;
1322 int err;
1323 nvlist_t *pools = NULL;
1324 boolean_t do_all = B_FALSE;
1325 boolean_t do_destroyed = B_FALSE;
1326 char *mntopts = NULL;
1327 boolean_t do_force = B_FALSE;
1328 nvpair_t *elem;
1329 nvlist_t *config;
1330 uint64_t searchguid;
1331 char *searchname;
1332 char *propval;
1333 nvlist_t *found_config;
1334 nvlist_t *props = NULL;
1335 boolean_t first;
1336 uint64_t pool_state;
1337 char *cachefile = NULL;
1338
1339 /* check options */
1340 while ((c = getopt(argc, argv, ":afc:d:Do:p:R:")) != -1) {
1341 switch (c) {
1342 case 'a':
1343 do_all = B_TRUE;
1344 break;
1345 case 'c':
1346 cachefile = optarg;
1347 break;
1348 case 'd':
1349 if (searchdirs == NULL) {
1350 searchdirs = safe_malloc(sizeof (char *));
1351 } else {
1352 char **tmp = safe_malloc((nsearch + 1) *
1353 sizeof (char *));
1354 bcopy(searchdirs, tmp, nsearch *
1355 sizeof (char *));
1356 free(searchdirs);
1357 searchdirs = tmp;
1358 }
1359 searchdirs[nsearch++] = optarg;
1360 break;
1361 case 'D':
1362 do_destroyed = B_TRUE;
1363 break;
1364 case 'f':
1365 do_force = B_TRUE;
1366 break;
1367 case 'o':
1368 if ((propval = strchr(optarg, '=')) != NULL) {
1369 *propval = '\0';
1370 propval++;
1371 if (add_prop_list(optarg, propval, &props))
1372 goto error;
1373 } else {
1374 mntopts = optarg;
1375 }
1376 break;
1377 case 'R':
1378 if (add_prop_list(zpool_prop_to_name(
1379 ZPOOL_PROP_ALTROOT), optarg, &props))
1380 goto error;
1381 if (nvlist_lookup_string(props,
1382 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1383 &propval) == 0)
1384 break;
1385 if (add_prop_list(zpool_prop_to_name(
1386 ZPOOL_PROP_CACHEFILE), "none", &props))
1387 goto error;
1388 break;
1389 case ':':
1390 (void) fprintf(stderr, gettext("missing argument for "
1391 "'%c' option\n"), optopt);
1392 usage(B_FALSE);
1393 break;
1394 case '?':
1395 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1396 optopt);
1397 usage(B_FALSE);
1398 }
1399 }
1400
1401 argc -= optind;
1402 argv += optind;
1403
1404 if (cachefile && nsearch != 0) {
1405 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1406 usage(B_FALSE);
1407 }
1408
1409 if (searchdirs == NULL) {
1410 searchdirs = safe_malloc(sizeof (char *));
1411 searchdirs[0] = "/dev/dsk";
1412 nsearch = 1;
1413 }
1414
1415 /* check argument count */
1416 if (do_all) {
1417 if (argc != 0) {
1418 (void) fprintf(stderr, gettext("too many arguments\n"));
1419 usage(B_FALSE);
1420 }
1421 } else {
1422 if (argc > 2) {
1423 (void) fprintf(stderr, gettext("too many arguments\n"));
1424 usage(B_FALSE);
1425 }
1426
1427 /*
1428 * Check for the SYS_CONFIG privilege. We do this explicitly
1429 * here because otherwise any attempt to discover pools will
1430 * silently fail.
1431 */
1432 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1433 (void) fprintf(stderr, gettext("cannot "
1434 "discover pools: permission denied\n"));
1435 free(searchdirs);
1436 return (1);
1437 }
1438 }
1439
1440 if (cachefile)
1441 pools = zpool_find_import_cached(g_zfs, cachefile, B_FALSE);
1442 else
1443 pools = zpool_find_import(g_zfs, nsearch, searchdirs, B_FALSE);
1444
1445 if (pools == NULL) {
1446 free(searchdirs);
1447 return (1);
1448 }
1449
1450 /*
1451 * We now have a list of all available pools in the given directories.
1452 * Depending on the arguments given, we do one of the following:
1453 *
1454 * <none> Iterate through all pools and display information about
1455 * each one.
1456 *
1457 * -a Iterate through all pools and try to import each one.
1458 *
1459 * <id> Find the pool that corresponds to the given GUID/pool
1460 * name and import that one.
1461 *
1462 * -D Above options applies only to destroyed pools.
1463 */
1464 if (argc != 0) {
1465 char *endptr;
1466
1467 errno = 0;
1468 searchguid = strtoull(argv[0], &endptr, 10);
1469 if (errno != 0 || *endptr != '\0')
1470 searchname = argv[0];
1471 else
1472 searchname = NULL;
1473 found_config = NULL;
1474 }
1475
1476 err = 0;
1477 elem = NULL;
1478 first = B_TRUE;
1479 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1480
1481 verify(nvpair_value_nvlist(elem, &config) == 0);
1482
1483 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1484 &pool_state) == 0);
1485 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1486 continue;
1487 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1488 continue;
1489
1490 if (argc == 0) {
1491 if (first)
1492 first = B_FALSE;
1493 else if (!do_all)
1494 (void) printf("\n");
1495
1496 if (do_all)
1497 err |= do_import(config, NULL, mntopts,
1498 do_force, props);
1499 else
1500 show_import(config);
1501 } else if (searchname != NULL) {
1502 char *name;
1503
1504 /*
1505 * We are searching for a pool based on name.
1506 */
1507 verify(nvlist_lookup_string(config,
1508 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1509
1510 if (strcmp(name, searchname) == 0) {
1511 if (found_config != NULL) {
1512 (void) fprintf(stderr, gettext(
1513 "cannot import '%s': more than "
1514 "one matching pool\n"), searchname);
1515 (void) fprintf(stderr, gettext(
1516 "import by numeric ID instead\n"));
1517 err = B_TRUE;
1518 }
1519 found_config = config;
1520 }
1521 } else {
1522 uint64_t guid;
1523
1524 /*
1525 * Search for a pool by guid.
1526 */
1527 verify(nvlist_lookup_uint64(config,
1528 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1529
1530 if (guid == searchguid)
1531 found_config = config;
1532 }
1533 }
1534
1535 /*
1536 * If we were searching for a specific pool, verify that we found a
1537 * pool, and then do the import.
1538 */
1539 if (argc != 0 && err == 0) {
1540 if (found_config == NULL) {
1541 (void) fprintf(stderr, gettext("cannot import '%s': "
1542 "no such pool available\n"), argv[0]);
1543 err = B_TRUE;
1544 } else {
1545 err |= do_import(found_config, argc == 1 ? NULL :
1546 argv[1], mntopts, do_force, props);
1547 }
1548 }
1549
1550 /*
1551 * If we were just looking for pools, report an error if none were
1552 * found.
1553 */
1554 if (argc == 0 && first)
1555 (void) fprintf(stderr,
1556 gettext("no pools available to import\n"));
1557
1558error:
1559 nvlist_free(props);
1560 nvlist_free(pools);
1561 free(searchdirs);
1562
1563 return (err ? 1 : 0);
1564}
1565
1566typedef struct iostat_cbdata {
1567 zpool_list_t *cb_list;
1568 int cb_verbose;
1569 int cb_iteration;
1570 int cb_namewidth;
1571} iostat_cbdata_t;
1572
1573static void
1574print_iostat_separator(iostat_cbdata_t *cb)
1575{
1576 int i = 0;
1577
1578 for (i = 0; i < cb->cb_namewidth; i++)
1579 (void) printf("-");
1580 (void) printf(" ----- ----- ----- ----- ----- -----\n");
1581}
1582
1583static void
1584print_iostat_header(iostat_cbdata_t *cb)
1585{
1586 (void) printf("%*s capacity operations bandwidth\n",
1587 cb->cb_namewidth, "");
1588 (void) printf("%-*s used avail read write read write\n",
1589 cb->cb_namewidth, "pool");
1590 print_iostat_separator(cb);
1591}
1592
1593/*
1594 * Display a single statistic.
1595 */
1596static void
1597print_one_stat(uint64_t value)
1598{
1599 char buf[64];
1600
1601 zfs_nicenum(value, buf, sizeof (buf));
1602 (void) printf(" %5s", buf);
1603}
1604
1605/*
1606 * Print out all the statistics for the given vdev. This can either be the
1607 * toplevel configuration, or called recursively. If 'name' is NULL, then this
1608 * is a verbose output, and we don't want to display the toplevel pool stats.
1609 */
1610void
1611print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1612 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1613{
1614 nvlist_t **oldchild, **newchild;
1615 uint_t c, children;
1616 vdev_stat_t *oldvs, *newvs;
1617 vdev_stat_t zerovs = { 0 };
1618 uint64_t tdelta;
1619 double scale;
1620 char *vname;
1621
1622 if (oldnv != NULL) {
1623 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1624 (uint64_t **)&oldvs, &c) == 0);
1625 } else {
1626 oldvs = &zerovs;
1627 }
1628
1629 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1630 (uint64_t **)&newvs, &c) == 0);
1631
1632 if (strlen(name) + depth > cb->cb_namewidth)
1633 (void) printf("%*s%s", depth, "", name);
1634 else
1635 (void) printf("%*s%s%*s", depth, "", name,
1636 (int)(cb->cb_namewidth - strlen(name) - depth), "");
1637
1638 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1639
1640 if (tdelta == 0)
1641 scale = 1.0;
1642 else
1643 scale = (double)NANOSEC / tdelta;
1644
1645 /* only toplevel vdevs have capacity stats */
1646 if (newvs->vs_space == 0) {
1647 (void) printf(" - -");
1648 } else {
1649 print_one_stat(newvs->vs_alloc);
1650 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1651 }
1652
1653 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1654 oldvs->vs_ops[ZIO_TYPE_READ])));
1655
1656 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1657 oldvs->vs_ops[ZIO_TYPE_WRITE])));
1658
1659 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1660 oldvs->vs_bytes[ZIO_TYPE_READ])));
1661
1662 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1663 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1664
1665 (void) printf("\n");
1666
1667 if (!cb->cb_verbose)
1668 return;
1669
1670 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1671 &newchild, &children) != 0)
1672 return;
1673
1674 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1675 &oldchild, &c) != 0)
1676 return;
1677
1678 for (c = 0; c < children; c++) {
1679 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1680 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1681 newchild[c], cb, depth + 2);
1682 free(vname);
1683 }
1684
1685 /*
1686 * Include level 2 ARC devices in iostat output
1687 */
1688 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1689 &newchild, &children) != 0)
1690 return;
1691
1692 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1693 &oldchild, &c) != 0)
1694 return;
1695
1696 if (children > 0) {
1697 (void) printf("%-*s - - - - - "
1698 "-\n", cb->cb_namewidth, "cache");
1699 for (c = 0; c < children; c++) {
1700 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1701 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1702 newchild[c], cb, depth + 2);
1703 free(vname);
1704 }
1705 }
1706}
1707
1708static int
1709refresh_iostat(zpool_handle_t *zhp, void *data)
1710{
1711 iostat_cbdata_t *cb = data;
1712 boolean_t missing;
1713
1714 /*
1715 * If the pool has disappeared, remove it from the list and continue.
1716 */
1717 if (zpool_refresh_stats(zhp, &missing) != 0)
1718 return (-1);
1719
1720 if (missing)
1721 pool_list_remove(cb->cb_list, zhp);
1722
1723 return (0);
1724}
1725
1726/*
1727 * Callback to print out the iostats for the given pool.
1728 */
1729int
1730print_iostat(zpool_handle_t *zhp, void *data)
1731{
1732 iostat_cbdata_t *cb = data;
1733 nvlist_t *oldconfig, *newconfig;
1734 nvlist_t *oldnvroot, *newnvroot;
1735
1736 newconfig = zpool_get_config(zhp, &oldconfig);
1737
1738 if (cb->cb_iteration == 1)
1739 oldconfig = NULL;
1740
1741 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1742 &newnvroot) == 0);
1743
1744 if (oldconfig == NULL)
1745 oldnvroot = NULL;
1746 else
1747 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1748 &oldnvroot) == 0);
1749
1750 /*
1751 * Print out the statistics for the pool.
1752 */
1753 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1754
1755 if (cb->cb_verbose)
1756 print_iostat_separator(cb);
1757
1758 return (0);
1759}
1760
1761int
1762get_namewidth(zpool_handle_t *zhp, void *data)
1763{
1764 iostat_cbdata_t *cb = data;
1765 nvlist_t *config, *nvroot;
1766
1767 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1768 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1769 &nvroot) == 0);
1770 if (!cb->cb_verbose)
1771 cb->cb_namewidth = strlen(zpool_get_name(zhp));
1772 else
1773 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1774 }
1775
1776 /*
1777 * The width must fall into the range [10,38]. The upper limit is the
1778 * maximum we can have and still fit in 80 columns.
1779 */
1780 if (cb->cb_namewidth < 10)
1781 cb->cb_namewidth = 10;
1782 if (cb->cb_namewidth > 38)
1783 cb->cb_namewidth = 38;
1784
1785 return (0);
1786}
1787
1788/*
1789 * zpool iostat [-v] [pool] ... [interval [count]]
1790 *
1791 * -v Display statistics for individual vdevs
1792 *
1793 * This command can be tricky because we want to be able to deal with pool
1794 * creation/destruction as well as vdev configuration changes. The bulk of this
1795 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
1796 * on pool_list_update() to detect the addition of new pools. Configuration
1797 * changes are all handled within libzfs.
1798 */
1799int
1800zpool_do_iostat(int argc, char **argv)
1801{
1802 int c;
1803 int ret;
1804 int npools;
1805 unsigned long interval = 0, count = 0;
1806 zpool_list_t *list;
1807 boolean_t verbose = B_FALSE;
1808 iostat_cbdata_t cb;
1809
1810 /* check options */
1811 while ((c = getopt(argc, argv, "v")) != -1) {
1812 switch (c) {
1813 case 'v':
1814 verbose = B_TRUE;
1815 break;
1816 case '?':
1817 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1818 optopt);
1819 usage(B_FALSE);
1820 }
1821 }
1822
1823 argc -= optind;
1824 argv += optind;
1825
1826 /*
1827 * Determine if the last argument is an integer or a pool name
1828 */
1829 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1830 char *end;
1831
1832 errno = 0;
1833 interval = strtoul(argv[argc - 1], &end, 10);
1834
1835 if (*end == '\0' && errno == 0) {
1836 if (interval == 0) {
1837 (void) fprintf(stderr, gettext("interval "
1838 "cannot be zero\n"));
1839 usage(B_FALSE);
1840 }
1841
1842 /*
1843 * Ignore the last parameter
1844 */
1845 argc--;
1846 } else {
1847 /*
1848 * If this is not a valid number, just plow on. The
1849 * user will get a more informative error message later
1850 * on.
1851 */
1852 interval = 0;
1853 }
1854 }
1855
1856 /*
1857 * If the last argument is also an integer, then we have both a count
1858 * and an integer.
1859 */
1860 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1861 char *end;
1862
1863 errno = 0;
1864 count = interval;
1865 interval = strtoul(argv[argc - 1], &end, 10);
1866
1867 if (*end == '\0' && errno == 0) {
1868 if (interval == 0) {
1869 (void) fprintf(stderr, gettext("interval "
1870 "cannot be zero\n"));
1871 usage(B_FALSE);
1872 }
1873
1874 /*
1875 * Ignore the last parameter
1876 */
1877 argc--;
1878 } else {
1879 interval = 0;
1880 }
1881 }
1882
1883 /*
1884 * Construct the list of all interesting pools.
1885 */
1886 ret = 0;
1887 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1888 return (1);
1889
1890 if (pool_list_count(list) == 0 && argc != 0) {
1891 pool_list_free(list);
1892 return (1);
1893 }
1894
1895 if (pool_list_count(list) == 0 && interval == 0) {
1896 pool_list_free(list);
1897 (void) fprintf(stderr, gettext("no pools available\n"));
1898 return (1);
1899 }
1900
1901 /*
1902 * Enter the main iostat loop.
1903 */
1904 cb.cb_list = list;
1905 cb.cb_verbose = verbose;
1906 cb.cb_iteration = 0;
1907 cb.cb_namewidth = 0;
1908
1909 for (;;) {
1910 pool_list_update(list);
1911
1912 if ((npools = pool_list_count(list)) == 0)
1913 break;
1914
1915 /*
1916 * Refresh all statistics. This is done as an explicit step
1917 * before calculating the maximum name width, so that any
1918 * configuration changes are properly accounted for.
1919 */
1920 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1921
1922 /*
1923 * Iterate over all pools to determine the maximum width
1924 * for the pool / device name column across all pools.
1925 */
1926 cb.cb_namewidth = 0;
1927 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
1928
1929 /*
1930 * If it's the first time, or verbose mode, print the header.
1931 */
1932 if (++cb.cb_iteration == 1 || verbose)
1933 print_iostat_header(&cb);
1934
1935 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
1936
1937 /*
1938 * If there's more than one pool, and we're not in verbose mode
1939 * (which prints a separator for us), then print a separator.
1940 */
1941 if (npools > 1 && !verbose)
1942 print_iostat_separator(&cb);
1943
1944 if (verbose)
1945 (void) printf("\n");
1946
1947 /*
1948 * Flush the output so that redirection to a file isn't buffered
1949 * indefinitely.
1950 */
1951 (void) fflush(stdout);
1952
1953 if (interval == 0)
1954 break;
1955
1956 if (count != 0 && --count == 0)
1957 break;
1958
1959 (void) sleep(interval);
1960 }
1961
1962 pool_list_free(list);
1963
1964 return (ret);
1965}
1966
1967typedef struct list_cbdata {
1968 boolean_t cb_scripted;
1969 boolean_t cb_first;
1970 zprop_list_t *cb_proplist;
1971} list_cbdata_t;
1972
1973/*
1974 * Given a list of columns to display, output appropriate headers for each one.
1975 */
1976static void
1977print_header(zprop_list_t *pl)
1978{
1979 const char *header;
1980 boolean_t first = B_TRUE;
1981 boolean_t right_justify;
1982
1983 for (; pl != NULL; pl = pl->pl_next) {
1984 if (pl->pl_prop == ZPROP_INVAL)
1985 continue;
1986
1987 if (!first)
1988 (void) printf(" ");
1989 else
1990 first = B_FALSE;
1991
1992 header = zpool_prop_column_name(pl->pl_prop);
1993 right_justify = zpool_prop_align_right(pl->pl_prop);
1994
1995 if (pl->pl_next == NULL && !right_justify)
1996 (void) printf("%s", header);
1997 else if (right_justify)
1998 (void) printf("%*s", pl->pl_width, header);
1999 else
2000 (void) printf("%-*s", pl->pl_width, header);
2001 }
2002
2003 (void) printf("\n");
2004}
2005
2006/*
2007 * Given a pool and a list of properties, print out all the properties according
2008 * to the described layout.
2009 */
2010static void
2011print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2012{
2013 boolean_t first = B_TRUE;
2014 char property[ZPOOL_MAXPROPLEN];
2015 char *propstr;
2016 boolean_t right_justify;
2017 int width;
2018
2019 for (; pl != NULL; pl = pl->pl_next) {
2020 if (!first) {
2021 if (scripted)
2022 (void) printf("\t");
2023 else
2024 (void) printf(" ");
2025 } else {
2026 first = B_FALSE;
2027 }
2028
2029 right_justify = B_FALSE;
2030 if (pl->pl_prop != ZPROP_INVAL) {
2031 if (zpool_get_prop(zhp, pl->pl_prop, property,
2032 sizeof (property), NULL) != 0)
2033 propstr = "-";
2034 else
2035 propstr = property;
2036
2037 right_justify = zpool_prop_align_right(pl->pl_prop);
2038 } else {
2039 propstr = "-";
2040 }
2041
2042 width = pl->pl_width;
2043
2044 /*
2045 * If this is being called in scripted mode, or if this is the
2046 * last column and it is left-justified, don't include a width
2047 * format specifier.
2048 */
2049 if (scripted || (pl->pl_next == NULL && !right_justify))
2050 (void) printf("%s", propstr);
2051 else if (right_justify)
2052 (void) printf("%*s", width, propstr);
2053 else
2054 (void) printf("%-*s", width, propstr);
2055 }
2056
2057 (void) printf("\n");
2058}
2059
2060/*
2061 * Generic callback function to list a pool.
2062 */
2063int
2064list_callback(zpool_handle_t *zhp, void *data)
2065{
2066 list_cbdata_t *cbp = data;
2067
2068 if (cbp->cb_first) {
2069 if (!cbp->cb_scripted)
2070 print_header(cbp->cb_proplist);
2071 cbp->cb_first = B_FALSE;
2072 }
2073
2074 print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2075
2076 return (0);
2077}
2078
2079/*
2080 * zpool list [-H] [-o prop[,prop]*] [pool] ...
2081 *
2082 * -H Scripted mode. Don't display headers, and separate properties
2083 * by a single tab.
2084 * -o List of properties to display. Defaults to
2085 * "name,size,used,available,capacity,health,altroot"
2086 *
2087 * List all pools in the system, whether or not they're healthy. Output space
2088 * statistics for each one, as well as health status summary.
2089 */
2090int
2091zpool_do_list(int argc, char **argv)
2092{
2093 int c;
2094 int ret;
2095 list_cbdata_t cb = { 0 };
2096 static char default_props[] =
2097 "name,size,used,available,capacity,health,altroot";
2098 char *props = default_props;
2099
2100 /* check options */
2101 while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2102 switch (c) {
2103 case 'H':
2104 cb.cb_scripted = B_TRUE;
2105 break;
2106 case 'o':
2107 props = optarg;
2108 break;
2109 case ':':
2110 (void) fprintf(stderr, gettext("missing argument for "
2111 "'%c' option\n"), optopt);
2112 usage(B_FALSE);
2113 break;
2114 case '?':
2115 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2116 optopt);
2117 usage(B_FALSE);
2118 }
2119 }
2120
2121 argc -= optind;
2122 argv += optind;
2123
2124 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2125 usage(B_FALSE);
2126
2127 cb.cb_first = B_TRUE;
2128
2129 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2130 list_callback, &cb);
2131
2132 zprop_free_list(cb.cb_proplist);
2133
2134 if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2135 (void) printf(gettext("no pools available\n"));
2136 return (0);
2137 }
2138
2139 return (ret);
2140}
2141
2142static nvlist_t *
2143zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2144{
2145 nvlist_t **child;
2146 uint_t c, children;
2147 nvlist_t *match;
2148 char *path;
2149
2150 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2151 &child, &children) != 0) {
2152 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2153 if (strncmp(name, "/dev/dsk/", 9) == 0)
2154 name += 9;
2155 if (strncmp(path, "/dev/dsk/", 9) == 0)
2156 path += 9;
2157 if (strcmp(name, path) == 0)
2158 return (nv);
2159 return (NULL);
2160 }
2161
2162 for (c = 0; c < children; c++)
2163 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2164 return (match);
2165
2166 return (NULL);
2167}
2168
2169static int
2170zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2171{
2172 boolean_t force = B_FALSE;
2173 int c;
2174 nvlist_t *nvroot;
2175 char *poolname, *old_disk, *new_disk;
2176 zpool_handle_t *zhp;
2177 int ret;
2178
2179 /* check options */
2180 while ((c = getopt(argc, argv, "f")) != -1) {
2181 switch (c) {
2182 case 'f':
2183 force = B_TRUE;
2184 break;
2185 case '?':
2186 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2187 optopt);
2188 usage(B_FALSE);
2189 }
2190 }
2191
2192 argc -= optind;
2193 argv += optind;
2194
2195 /* get pool name and check number of arguments */
2196 if (argc < 1) {
2197 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2198 usage(B_FALSE);
2199 }
2200
2201 poolname = argv[0];
2202
2203 if (argc < 2) {
2204 (void) fprintf(stderr,
2205 gettext("missing <device> specification\n"));
2206 usage(B_FALSE);
2207 }
2208
2209 old_disk = argv[1];
2210
2211 if (argc < 3) {
2212 if (!replacing) {
2213 (void) fprintf(stderr,
2214 gettext("missing <new_device> specification\n"));
2215 usage(B_FALSE);
2216 }
2217 new_disk = old_disk;
2218 argc -= 1;
2219 argv += 1;
2220 } else {
2221 new_disk = argv[2];
2222 argc -= 2;
2223 argv += 2;
2224 }
2225
2226 if (argc > 1) {
2227 (void) fprintf(stderr, gettext("too many arguments\n"));
2228 usage(B_FALSE);
2229 }
2230
2231 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2232 return (1);
2233
2234 if (zpool_get_config(zhp, NULL) == NULL) {
2235 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2236 poolname);
2237 zpool_close(zhp);
2238 return (1);
2239 }
2240
2241 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, argc, argv);
2242 if (nvroot == NULL) {
2243 zpool_close(zhp);
2244 return (1);
2245 }
2246
2247 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2248
2249 nvlist_free(nvroot);
2250 zpool_close(zhp);
2251
2252 return (ret);
2253}
2254
2255/*
2256 * zpool replace [-f] <pool> <device> <new_device>
2257 *
2258 * -f Force attach, even if <new_device> appears to be in use.
2259 *
2260 * Replace <device> with <new_device>.
2261 */
2262/* ARGSUSED */
2263int
2264zpool_do_replace(int argc, char **argv)
2265{
2266 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2267}
2268
2269/*
2270 * zpool attach [-f] <pool> <device> <new_device>
2271 *
2272 * -f Force attach, even if <new_device> appears to be in use.
2273 *
2274 * Attach <new_device> to the mirror containing <device>. If <device> is not
2275 * part of a mirror, then <device> will be transformed into a mirror of
2276 * <device> and <new_device>. In either case, <new_device> will begin life
2277 * with a DTL of [0, now], and will immediately begin to resilver itself.
2278 */
2279int
2280zpool_do_attach(int argc, char **argv)
2281{
2282 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2283}
2284
2285/*
2286 * zpool detach [-f] <pool> <device>
2287 *
2288 * -f Force detach of <device>, even if DTLs argue against it
2289 * (not supported yet)
2290 *
2291 * Detach a device from a mirror. The operation will be refused if <device>
2292 * is the last device in the mirror, or if the DTLs indicate that this device
2293 * has the only valid copy of some data.
2294 */
2295/* ARGSUSED */
2296int
2297zpool_do_detach(int argc, char **argv)
2298{
2299 int c;
2300 char *poolname, *path;
2301 zpool_handle_t *zhp;
2302 int ret;
2303
2304 /* check options */
2305 while ((c = getopt(argc, argv, "f")) != -1) {
2306 switch (c) {
2307 case 'f':
2308 case '?':
2309 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2310 optopt);
2311 usage(B_FALSE);
2312 }
2313 }
2314
2315 argc -= optind;
2316 argv += optind;
2317
2318 /* get pool name and check number of arguments */
2319 if (argc < 1) {
2320 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2321 usage(B_FALSE);
2322 }
2323
2324 if (argc < 2) {
2325 (void) fprintf(stderr,
2326 gettext("missing <device> specification\n"));
2327 usage(B_FALSE);
2328 }
2329
2330 poolname = argv[0];
2331 path = argv[1];
2332
2333 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2334 return (1);
2335
2336 ret = zpool_vdev_detach(zhp, path);
2337
2338 zpool_close(zhp);
2339
2340 return (ret);
2341}
2342
2343/*
2344 * zpool online <pool> <device> ...
2345 */
2346int
2347zpool_do_online(int argc, char **argv)
2348{
2349 int c, i;
2350 char *poolname;
2351 zpool_handle_t *zhp;
2352 int ret = 0;
2353 vdev_state_t newstate;
2354
2355 /* check options */
2356 while ((c = getopt(argc, argv, "t")) != -1) {
2357 switch (c) {
2358 case 't':
2359 case '?':
2360 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2361 optopt);
2362 usage(B_FALSE);
2363 }
2364 }
2365
2366 argc -= optind;
2367 argv += optind;
2368
2369 /* get pool name and check number of arguments */
2370 if (argc < 1) {
2371 (void) fprintf(stderr, gettext("missing pool name\n"));
2372 usage(B_FALSE);
2373 }
2374 if (argc < 2) {
2375 (void) fprintf(stderr, gettext("missing device name\n"));
2376 usage(B_FALSE);
2377 }
2378
2379 poolname = argv[0];
2380
2381 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2382 return (1);
2383
2384 for (i = 1; i < argc; i++) {
2385 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2386 if (newstate != VDEV_STATE_HEALTHY) {
2387 (void) printf(gettext("warning: device '%s' "
2388 "onlined, but remains in faulted state\n"),
2389 argv[i]);
2390 if (newstate == VDEV_STATE_FAULTED)
2391 (void) printf(gettext("use 'zpool "
2392 "clear' to restore a faulted "
2393 "device\n"));
2394 else
2395 (void) printf(gettext("use 'zpool "
2396 "replace' to replace devices "
2397 "that are no longer present\n"));
2398 }
2399 } else {
2400 ret = 1;
2401 }
2402 }
2403
2404 zpool_close(zhp);
2405
2406 return (ret);
2407}
2408
2409/*
2410 * zpool offline [-ft] <pool> <device> ...
2411 *
2412 * -f Force the device into the offline state, even if doing
2413 * so would appear to compromise pool availability.
2414 * (not supported yet)
2415 *
2416 * -t Only take the device off-line temporarily. The offline
2417 * state will not be persistent across reboots.
2418 */
2419/* ARGSUSED */
2420int
2421zpool_do_offline(int argc, char **argv)
2422{
2423 int c, i;
2424 char *poolname;
2425 zpool_handle_t *zhp;
2426 int ret = 0;
2427 boolean_t istmp = B_FALSE;
2428
2429 /* check options */
2430 while ((c = getopt(argc, argv, "ft")) != -1) {
2431 switch (c) {
2432 case 't':
2433 istmp = B_TRUE;
2434 break;
2435 case 'f':
2436 case '?':
2437 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2438 optopt);
2439 usage(B_FALSE);
2440 }
2441 }
2442
2443 argc -= optind;
2444 argv += optind;
2445
2446 /* get pool name and check number of arguments */
2447 if (argc < 1) {
2448 (void) fprintf(stderr, gettext("missing pool name\n"));
2449 usage(B_FALSE);
2450 }
2451 if (argc < 2) {
2452 (void) fprintf(stderr, gettext("missing device name\n"));
2453 usage(B_FALSE);
2454 }
2455
2456 poolname = argv[0];
2457
2458 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2459 return (1);
2460
2461 for (i = 1; i < argc; i++) {
2462 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2463 ret = 1;
2464 }
2465
2466 zpool_close(zhp);
2467
2468 return (ret);
2469}
2470
2471/*
2472 * zpool clear <pool> [device]
2473 *
2474 * Clear all errors associated with a pool or a particular device.
2475 */
2476int
2477zpool_do_clear(int argc, char **argv)
2478{
2479 int ret = 0;
2480 zpool_handle_t *zhp;
2481 char *pool, *device;
2482
2483 if (argc < 2) {
2484 (void) fprintf(stderr, gettext("missing pool name\n"));
2485 usage(B_FALSE);
2486 }
2487
2488 if (argc > 3) {
2489 (void) fprintf(stderr, gettext("too many arguments\n"));
2490 usage(B_FALSE);
2491 }
2492
2493 pool = argv[1];
2494 device = argc == 3 ? argv[2] : NULL;
2495
2496 if ((zhp = zpool_open(g_zfs, pool)) == NULL)
2497 return (1);
2498
2499 if (zpool_clear(zhp, device) != 0)
2500 ret = 1;
2501
2502 zpool_close(zhp);
2503
2504 return (ret);
2505}
2506
2507typedef struct scrub_cbdata {
2508 int cb_type;
2509 int cb_argc;
2510 char **cb_argv;
2511} scrub_cbdata_t;
2512
2513int
2514scrub_callback(zpool_handle_t *zhp, void *data)
2515{
2516 scrub_cbdata_t *cb = data;
2517 int err;
2518
2519 /*
2520 * Ignore faulted pools.
2521 */
2522 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2523 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2524 "currently unavailable\n"), zpool_get_name(zhp));
2525 return (1);
2526 }
2527
2528 err = zpool_scrub(zhp, cb->cb_type);
2529
2530 return (err != 0);
2531}
2532
2533/*
2534 * zpool scrub [-s] <pool> ...
2535 *
2536 * -s Stop. Stops any in-progress scrub.
2537 */
2538int
2539zpool_do_scrub(int argc, char **argv)
2540{
2541 int c;
2542 scrub_cbdata_t cb;
2543
2544 cb.cb_type = POOL_SCRUB_EVERYTHING;
2545
2546 /* check options */
2547 while ((c = getopt(argc, argv, "s")) != -1) {
2548 switch (c) {
2549 case 's':
2550 cb.cb_type = POOL_SCRUB_NONE;
2551 break;
2552 case '?':
2553 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2554 optopt);
2555 usage(B_FALSE);
2556 }
2557 }
2558
2559 cb.cb_argc = argc;
2560 cb.cb_argv = argv;
2561 argc -= optind;
2562 argv += optind;
2563
2564 if (argc < 1) {
2565 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2566 usage(B_FALSE);
2567 }
2568
2569 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2570}
2571
2572typedef struct status_cbdata {
2573 int cb_count;
2574 boolean_t cb_allpools;
2575 boolean_t cb_verbose;
2576 boolean_t cb_explain;
2577 boolean_t cb_first;
2578} status_cbdata_t;
2579
2580/*
2581 * Print out detailed scrub status.
2582 */
2583void
2584print_scrub_status(nvlist_t *nvroot)
2585{
2586 vdev_stat_t *vs;
2587 uint_t vsc;
2588 time_t start, end, now;
2589 double fraction_done;
2590 uint64_t examined, total, minutes_left, minutes_taken;
2591 char *scrub_type;
2592
2593 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2594 (uint64_t **)&vs, &vsc) == 0);
2595
2596 /*
2597 * If there's never been a scrub, there's not much to say.
2598 */
2599 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2600 (void) printf(gettext("none requested\n"));
2601 return;
2602 }
2603
2604 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2605 "resilver" : "scrub";
2606
2607 start = vs->vs_scrub_start;
2608 end = vs->vs_scrub_end;
2609 now = time(NULL);
2610 examined = vs->vs_scrub_examined;
2611 total = vs->vs_alloc;
2612
2613 if (end != 0) {
2614 minutes_taken = (uint64_t)((end - start) / 60);
2615
2616 (void) printf(gettext("%s %s after %lluh%um with %llu errors "
2617 "on %s"),
2618 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2619 (u_longlong_t)(minutes_taken / 60),
2620 (uint_t)(minutes_taken % 60),
2621 (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2622 return;
2623 }
2624
2625 if (examined == 0)
2626 examined = 1;
2627 if (examined > total)
2628 total = examined;
2629
2630 fraction_done = (double)examined / total;
2631 minutes_left = (uint64_t)((now - start) *
2632 (1 - fraction_done) / fraction_done / 60);
2633 minutes_taken = (uint64_t)((now - start) / 60);
2634
2635 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
2636 "%lluh%um to go\n"),
2637 scrub_type, (u_longlong_t)(minutes_taken / 60),
2638 (uint_t)(minutes_taken % 60), 100 * fraction_done,
2639 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2640}
2641
2642typedef struct spare_cbdata {
2643 uint64_t cb_guid;
2644 zpool_handle_t *cb_zhp;
2645} spare_cbdata_t;
2646
2647static boolean_t
2648find_vdev(nvlist_t *nv, uint64_t search)
2649{
2650 uint64_t guid;
2651 nvlist_t **child;
2652 uint_t c, children;
2653
2654 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2655 search == guid)
2656 return (B_TRUE);
2657
2658 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2659 &child, &children) == 0) {
2660 for (c = 0; c < children; c++)
2661 if (find_vdev(child[c], search))
2662 return (B_TRUE);
2663 }
2664
2665 return (B_FALSE);
2666}
2667
2668static int
2669find_spare(zpool_handle_t *zhp, void *data)
2670{
2671 spare_cbdata_t *cbp = data;
2672 nvlist_t *config, *nvroot;
2673
2674 config = zpool_get_config(zhp, NULL);
2675 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2676 &nvroot) == 0);
2677
2678 if (find_vdev(nvroot, cbp->cb_guid)) {
2679 cbp->cb_zhp = zhp;
2680 return (1);
2681 }
2682
2683 zpool_close(zhp);
2684 return (0);
2685}
2686
2687/*
2688 * Print out configuration state as requested by status_callback.
2689 */
2690void
2691print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2692 int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2693{
2694 nvlist_t **child;
2695 uint_t c, children;
2696 vdev_stat_t *vs;
2697 char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2698 char *vname;
2699 uint64_t notpresent;
2700 spare_cbdata_t cb;
2701 char *state;
2702
2703 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2704 (uint64_t **)&vs, &c) == 0);
2705
2706 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2707 &child, &children) != 0)
2708 children = 0;
2709
2710 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2711 if (isspare) {
2712 /*
2713 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2714 * online drives.
2715 */
2716 if (vs->vs_aux == VDEV_AUX_SPARED)
2717 state = "INUSE";
2718 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2719 state = "AVAIL";
2720 }
2721
2722 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
2723 name, state);
2724
2725 if (!isspare) {
2726 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2727 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2728 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2729 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2730 }
2731
2732 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2733 &notpresent) == 0) {
2734 char *path;
2735 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2736 (void) printf(" was %s", path);
2737 } else if (vs->vs_aux != 0) {
2738 (void) printf(" ");
2739
2740 switch (vs->vs_aux) {
2741 case VDEV_AUX_OPEN_FAILED:
2742 (void) printf(gettext("cannot open"));
2743 break;
2744
2745 case VDEV_AUX_BAD_GUID_SUM:
2746 (void) printf(gettext("missing device"));
2747 break;
2748
2749 case VDEV_AUX_NO_REPLICAS:
2750 (void) printf(gettext("insufficient replicas"));
2751 break;
2752
2753 case VDEV_AUX_VERSION_NEWER:
2754 (void) printf(gettext("newer version"));
2755 break;
2756
2757 case VDEV_AUX_SPARED:
2758 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2759 &cb.cb_guid) == 0);
2760 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2761 if (strcmp(zpool_get_name(cb.cb_zhp),
2762 zpool_get_name(zhp)) == 0)
2763 (void) printf(gettext("currently in "
2764 "use"));
2765 else
2766 (void) printf(gettext("in use by "
2767 "pool '%s'"),
2768 zpool_get_name(cb.cb_zhp));
2769 zpool_close(cb.cb_zhp);
2770 } else {
2771 (void) printf(gettext("currently in use"));
2772 }
2773 break;
2774
2775 case VDEV_AUX_ERR_EXCEEDED:
2776 (void) printf(gettext("too many errors"));
2777 break;
2778
2779 default:
2780 (void) printf(gettext("corrupted data"));
2781 break;
2782 }
2783 } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2784 /*
2785 * Report bytes resilvered/repaired on leaf devices.
2786 */
2787 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2788 (void) printf(gettext(" %s %s"), repaired,
2789 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2790 "resilvered" : "repaired");
2791 }
2792
2793 (void) printf("\n");
2794
2795 for (c = 0; c < children; c++) {
2796 uint64_t is_log = B_FALSE;
2797
2798 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2799 &is_log);
2800 if ((is_log && !print_logs) || (!is_log && print_logs))
2801 continue;
2802 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2803 print_status_config(zhp, vname, child[c],
2804 namewidth, depth + 2, isspare, B_FALSE);
2805 free(vname);
2806 }
2807}
2808
2809static void
2810print_error_log(zpool_handle_t *zhp)
2811{
2812 nvlist_t *nverrlist = NULL;
2813 nvpair_t *elem;
2814 char *pathname;
2815 size_t len = MAXPATHLEN * 2;
2816
2817 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2818 (void) printf("errors: List of errors unavailable "
2819 "(insufficient privileges)\n");
2820 return;
2821 }
2822
2823 (void) printf("errors: Permanent errors have been "
2824 "detected in the following files:\n\n");
2825
2826 pathname = safe_malloc(len);
2827 elem = NULL;
2828 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2829 nvlist_t *nv;
2830 uint64_t dsobj, obj;
2831
2832 verify(nvpair_value_nvlist(elem, &nv) == 0);
2833 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2834 &dsobj) == 0);
2835 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2836 &obj) == 0);
2837 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2838 (void) printf("%7s %s\n", "", pathname);
2839 }
2840 free(pathname);
2841 nvlist_free(nverrlist);
2842}
2843
2844static void
2845print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2846 int namewidth)
2847{
2848 uint_t i;
2849 char *name;
2850
2851 if (nspares == 0)
2852 return;
2853
2854 (void) printf(gettext("\tspares\n"));
2855
2856 for (i = 0; i < nspares; i++) {
2857 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2858 print_status_config(zhp, name, spares[i],
2859 namewidth, 2, B_TRUE, B_FALSE);
2860 free(name);
2861 }
2862}
2863
2864static void
2865print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2866 int namewidth)
2867{
2868 uint_t i;
2869 char *name;
2870
2871 if (nl2cache == 0)
2872 return;
2873
2874 (void) printf(gettext("\tcache\n"));
2875
2876 for (i = 0; i < nl2cache; i++) {
2877 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2878 print_status_config(zhp, name, l2cache[i],
2879 namewidth, 2, B_FALSE, B_FALSE);
2880 free(name);
2881 }
2882}
2883
2884/*
2885 * Display a summary of pool status. Displays a summary such as:
2886 *
2887 * pool: tank
2888 * status: DEGRADED
2889 * reason: One or more devices ...
2890 * see: http://www.sun.com/msg/ZFS-xxxx-01
2891 * config:
2892 * mirror DEGRADED
2893 * c1t0d0 OK
2894 * c2t0d0 UNAVAIL
2895 *
2896 * When given the '-v' option, we print out the complete config. If the '-e'
2897 * option is specified, then we print out error rate information as well.
2898 */
2899int
2900status_callback(zpool_handle_t *zhp, void *data)
2901{
2902 status_cbdata_t *cbp = data;
2903 nvlist_t *config, *nvroot;
2904 char *msgid;
2905 int reason;
2906 const char *health;
2907 uint_t c;
2908 vdev_stat_t *vs;
2909
2910 config = zpool_get_config(zhp, NULL);
2911 reason = zpool_get_status(zhp, &msgid);
2912
2913 cbp->cb_count++;
2914
2915 /*
2916 * If we were given 'zpool status -x', only report those pools with
2917 * problems.
2918 */
2919 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
2920 if (!cbp->cb_allpools) {
2921 (void) printf(gettext("pool '%s' is healthy\n"),
2922 zpool_get_name(zhp));
2923 if (cbp->cb_first)
2924 cbp->cb_first = B_FALSE;
2925 }
2926 return (0);
2927 }
2928
2929 if (cbp->cb_first)
2930 cbp->cb_first = B_FALSE;
2931 else
2932 (void) printf("\n");
2933
2934 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2935 &nvroot) == 0);
2936 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2937 (uint64_t **)&vs, &c) == 0);
2938 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2939
2940 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
2941 (void) printf(gettext(" state: %s\n"), health);
2942
2943 switch (reason) {
2944 case ZPOOL_STATUS_MISSING_DEV_R:
2945 (void) printf(gettext("status: One or more devices could not "
2946 "be opened. Sufficient replicas exist for\n\tthe pool to "
2947 "continue functioning in a degraded state.\n"));
2948 (void) printf(gettext("action: Attach the missing device and "
2949 "online it using 'zpool online'.\n"));
2950 break;
2951
2952 case ZPOOL_STATUS_MISSING_DEV_NR:
2953 (void) printf(gettext("status: One or more devices could not "
2954 "be opened. There are insufficient\n\treplicas for the "
2955 "pool to continue functioning.\n"));
2956 (void) printf(gettext("action: Attach the missing device and "
2957 "online it using 'zpool online'.\n"));
2958 break;
2959
2960 case ZPOOL_STATUS_CORRUPT_LABEL_R:
2961 (void) printf(gettext("status: One or more devices could not "
2962 "be used because the label is missing or\n\tinvalid. "
2963 "Sufficient replicas exist for the pool to continue\n\t"
2964 "functioning in a degraded state.\n"));
2965 (void) printf(gettext("action: Replace the device using "
2966 "'zpool replace'.\n"));
2967 break;
2968
2969 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
2970 (void) printf(gettext("status: One or more devices could not "
2971 "be used because the label is missing \n\tor invalid. "
2972 "There are insufficient replicas for the pool to "
2973 "continue\n\tfunctioning.\n"));
2974 (void) printf(gettext("action: Destroy and re-create the pool "
2975 "from a backup source.\n"));
2976 break;
2977
2978 case ZPOOL_STATUS_FAILING_DEV:
2979 (void) printf(gettext("status: One or more devices has "
2980 "experienced an unrecoverable error. An\n\tattempt was "
2981 "made to correct the error. Applications are "
2982 "unaffected.\n"));
2983 (void) printf(gettext("action: Determine if the device needs "
2984 "to be replaced, and clear the errors\n\tusing "
2985 "'zpool clear' or replace the device with 'zpool "
2986 "replace'.\n"));
2987 break;
2988
2989 case ZPOOL_STATUS_OFFLINE_DEV:
2990 (void) printf(gettext("status: One or more devices has "
2991 "been taken offline by the administrator.\n\tSufficient "
2992 "replicas exist for the pool to continue functioning in "
2993 "a\n\tdegraded state.\n"));
2994 (void) printf(gettext("action: Online the device using "
2995 "'zpool online' or replace the device with\n\t'zpool "
2996 "replace'.\n"));
2997 break;
2998
2999 case ZPOOL_STATUS_RESILVERING:
3000 (void) printf(gettext("status: One or more devices is "
3001 "currently being resilvered. The pool will\n\tcontinue "
3002 "to function, possibly in a degraded state.\n"));
3003 (void) printf(gettext("action: Wait for the resilver to "
3004 "complete.\n"));
3005 break;
3006
3007 case ZPOOL_STATUS_CORRUPT_DATA:
3008 (void) printf(gettext("status: One or more devices has "
3009 "experienced an error resulting in data\n\tcorruption. "
3010 "Applications may be affected.\n"));
3011 (void) printf(gettext("action: Restore the file in question "
3012 "if possible. Otherwise restore the\n\tentire pool from "
3013 "backup.\n"));
3014 break;
3015
3016 case ZPOOL_STATUS_CORRUPT_POOL:
3017 (void) printf(gettext("status: The pool metadata is corrupted "
3018 "and the pool cannot be opened.\n"));
3019 (void) printf(gettext("action: Destroy and re-create the pool "
3020 "from a backup source.\n"));
3021 break;
3022
3023 case ZPOOL_STATUS_VERSION_OLDER:
3024 (void) printf(gettext("status: The pool is formatted using an "
3025 "older on-disk format. The pool can\n\tstill be used, but "
3026 "some features are unavailable.\n"));
3027 (void) printf(gettext("action: Upgrade the pool using 'zpool "
3028 "upgrade'. Once this is done, the\n\tpool will no longer "
3029 "be accessible on older software versions.\n"));
3030 break;
3031
3032 case ZPOOL_STATUS_VERSION_NEWER:
3033 (void) printf(gettext("status: The pool has been upgraded to a "
3034 "newer, incompatible on-disk version.\n\tThe pool cannot "
3035 "be accessed on this system.\n"));
3036 (void) printf(gettext("action: Access the pool from a system "
3037 "running more recent software, or\n\trestore the pool from "
3038 "backup.\n"));
3039 break;
3040
3041 case ZPOOL_STATUS_FAULTED_DEV_R:
3042 (void) printf(gettext("status: One or more devices are "
3043 "faulted in response to persistent errors.\n\tSufficient "
3044 "replicas exist for the pool to continue functioning "
3045 "in a\n\tdegraded state.\n"));
3046 (void) printf(gettext("action: Replace the faulted device, "
3047 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3048 break;
3049
3050 case ZPOOL_STATUS_FAULTED_DEV_NR:
3051 (void) printf(gettext("status: One or more devices are "
3052 "faulted in response to persistent errors. There are "
3053 "insufficient replicas for the pool to\n\tcontinue "
3054 "functioning.\n"));
3055 (void) printf(gettext("action: Destroy and re-create the pool "
3056 "from a backup source. Manually marking the device\n"
3057 "\trepaired using 'zpool clear' may allow some data "
3058 "to be recovered.\n"));
3059 break;
3060
3061 default:
3062 /*
3063 * The remaining errors can't actually be generated, yet.
3064 */
3065 assert(reason == ZPOOL_STATUS_OK);
3066 }
3067
3068 if (msgid != NULL)
3069 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
3070 msgid);
3071
3072 if (config != NULL) {
3073 int namewidth;
3074 uint64_t nerr;
3075 nvlist_t **spares, **l2cache;
3076 uint_t nspares, nl2cache;
3077
3078
3079 (void) printf(gettext(" scrub: "));
3080 print_scrub_status(nvroot);
3081
3082 namewidth = max_width(zhp, nvroot, 0, 0);
3083 if (namewidth < 10)
3084 namewidth = 10;
3085
3086 (void) printf(gettext("config:\n\n"));
3087 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
3088 "NAME", "STATE", "READ", "WRITE", "CKSUM");
3089 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3090 namewidth, 0, B_FALSE, B_FALSE);
3091 if (num_logs(nvroot) > 0)
3092 print_status_config(zhp, "logs", nvroot, namewidth, 0,
3093 B_FALSE, B_TRUE);
3094
3095 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3096 &l2cache, &nl2cache) == 0)
3097 print_l2cache(zhp, l2cache, nl2cache, namewidth);
3098
3099 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3100 &spares, &nspares) == 0)
3101 print_spares(zhp, spares, nspares, namewidth);
3102
3103 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3104 &nerr) == 0) {
3105 nvlist_t *nverrlist = NULL;
3106
3107 /*
3108 * If the approximate error count is small, get a
3109 * precise count by fetching the entire log and
3110 * uniquifying the results.
3111 */
3112 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
3113 zpool_get_errlog(zhp, &nverrlist) == 0) {
3114 nvpair_t *elem;
3115
3116 elem = NULL;
3117 nerr = 0;
3118 while ((elem = nvlist_next_nvpair(nverrlist,
3119 elem)) != NULL) {
3120 nerr++;
3121 }
3122 }
3123 nvlist_free(nverrlist);
3124
3125 (void) printf("\n");
3126
3127 if (nerr == 0)
3128 (void) printf(gettext("errors: No known data "
3129 "errors\n"));
3130 else if (!cbp->cb_verbose)
3131 (void) printf(gettext("errors: %llu data "
3132 "errors, use '-v' for a list\n"),
3133 (u_longlong_t)nerr);
3134 else
3135 print_error_log(zhp);
3136 }
3137 } else {
3138 (void) printf(gettext("config: The configuration cannot be "
3139 "determined.\n"));
3140 }
3141
3142 return (0);
3143}
3144
3145/*
3146 * zpool status [-vx] [pool] ...
3147 *
3148 * -v Display complete error logs
3149 * -x Display only pools with potential problems
3150 *
3151 * Describes the health status of all pools or some subset.
3152 */
3153int
3154zpool_do_status(int argc, char **argv)
3155{
3156 int c;
3157 int ret;
3158 status_cbdata_t cb = { 0 };
3159
3160 /* check options */
3161 while ((c = getopt(argc, argv, "vx")) != -1) {
3162 switch (c) {
3163 case 'v':
3164 cb.cb_verbose = B_TRUE;
3165 break;
3166 case 'x':
3167 cb.cb_explain = B_TRUE;
3168 break;
3169 case '?':
3170 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3171 optopt);
3172 usage(B_FALSE);
3173 }
3174 }
3175
3176 argc -= optind;
3177 argv += optind;
3178
3179 cb.cb_first = B_TRUE;
3180
3181 if (argc == 0)
3182 cb.cb_allpools = B_TRUE;
3183
3184 ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3185
3186 if (argc == 0 && cb.cb_count == 0)
3187 (void) printf(gettext("no pools available\n"));
3188 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3189 (void) printf(gettext("all pools are healthy\n"));
3190
3191 return (ret);
3192}
3193
3194typedef struct upgrade_cbdata {
3195 int cb_all;
3196 int cb_first;
3197 int cb_newer;
3198 int cb_argc;
3199 uint64_t cb_version;
3200 char **cb_argv;
3201} upgrade_cbdata_t;
3202
3203static int
3204upgrade_cb(zpool_handle_t *zhp, void *arg)
3205{
3206 upgrade_cbdata_t *cbp = arg;
3207 nvlist_t *config;
3208 uint64_t version;
3209 int ret = 0;
3210
3211 config = zpool_get_config(zhp, NULL);
3212 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3213 &version) == 0);
3214
3215 if (!cbp->cb_newer && version < SPA_VERSION) {
3216 if (!cbp->cb_all) {
3217 if (cbp->cb_first) {
3218 (void) printf(gettext("The following pools are "
3219 "out of date, and can be upgraded. After "
3220 "being\nupgraded, these pools will no "
3221 "longer be accessible by older software "
3222 "versions.\n\n"));
3223 (void) printf(gettext("VER POOL\n"));
3224 (void) printf(gettext("--- ------------\n"));
3225 cbp->cb_first = B_FALSE;
3226 }
3227
3228 (void) printf("%2llu %s\n", (u_longlong_t)version,
3229 zpool_get_name(zhp));
3230 } else {
3231 cbp->cb_first = B_FALSE;
3232 ret = zpool_upgrade(zhp, cbp->cb_version);
3233 if (!ret) {
3234 (void) printf(gettext("Successfully upgraded "
3235 "'%s'\n\n"), zpool_get_name(zhp));
3236 }
3237 }
3238 } else if (cbp->cb_newer && version > SPA_VERSION) {
3239 assert(!cbp->cb_all);
3240
3241 if (cbp->cb_first) {
3242 (void) printf(gettext("The following pools are "
3243 "formatted using a newer software version and\n"
3244 "cannot be accessed on the current system.\n\n"));
3245 (void) printf(gettext("VER POOL\n"));
3246 (void) printf(gettext("--- ------------\n"));
3247 cbp->cb_first = B_FALSE;
3248 }
3249
3250 (void) printf("%2llu %s\n", (u_longlong_t)version,
3251 zpool_get_name(zhp));
3252 }
3253
3254 zpool_close(zhp);
3255 return (ret);
3256}
3257
3258/* ARGSUSED */
3259static int
3260upgrade_one(zpool_handle_t *zhp, void *data)
3261{
3262 upgrade_cbdata_t *cbp = data;
3263 uint64_t cur_version;
3264 int ret;
3265
3266 if (strcmp("log", zpool_get_name(zhp)) == 0) {
3267 (void) printf(gettext("'log' is now a reserved word\n"
3268 "Pool 'log' must be renamed using export and import"
3269 " to upgrade.\n"));
3270 return (1);
3271 }
3272
3273 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3274 if (cur_version > cbp->cb_version) {
3275 (void) printf(gettext("Pool '%s' is already formatted "
3276 "using more current version '%llu'.\n"),
3277 zpool_get_name(zhp), cur_version);
3278 return (0);
3279 }
3280 if (cur_version == cbp->cb_version) {
3281 (void) printf(gettext("Pool '%s' is already formatted "
3282 "using the current version.\n"), zpool_get_name(zhp));
3283 return (0);
3284 }
3285
3286 ret = zpool_upgrade(zhp, cbp->cb_version);
3287
3288 if (!ret) {
3289 (void) printf(gettext("Successfully upgraded '%s' "
3290 "from version %llu to version %llu\n\n"),
3291 zpool_get_name(zhp), (u_longlong_t)cur_version,
3292 (u_longlong_t)cbp->cb_version);
3293 }
3294
3295 return (ret != 0);
3296}
3297
3298/*
3299 * zpool upgrade
3300 * zpool upgrade -v
3301 * zpool upgrade [-V version] <-a | pool ...>
3302 *
3303 * With no arguments, display downrev'd ZFS pool available for upgrade.
3304 * Individual pools can be upgraded by specifying the pool, and '-a' will
3305 * upgrade all pools.
3306 */
3307int
3308zpool_do_upgrade(int argc, char **argv)
3309{
3310 int c;
3311 upgrade_cbdata_t cb = { 0 };
3312 int ret = 0;
3313 boolean_t showversions = B_FALSE;
3314 char *end;
3315
3316
3317 /* check options */
3318 while ((c = getopt(argc, argv, "avV:")) != -1) {
3319 switch (c) {
3320 case 'a':
3321 cb.cb_all = B_TRUE;
3322 break;
3323 case 'v':
3324 showversions = B_TRUE;
3325 break;
3326 case 'V':
3327 cb.cb_version = strtoll(optarg, &end, 10);
3328 if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3329 cb.cb_version < SPA_VERSION_1) {
3330 (void) fprintf(stderr,
3331 gettext("invalid version '%s'\n"), optarg);
3332 usage(B_FALSE);
3333 }
3334 break;
3335 case '?':
3336 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3337 optopt);
3338 usage(B_FALSE);
3339 }
3340 }
3341
3342 cb.cb_argc = argc;
3343 cb.cb_argv = argv;
3344 argc -= optind;
3345 argv += optind;
3346
3347 if (cb.cb_version == 0) {
3348 cb.cb_version = SPA_VERSION;
3349 } else if (!cb.cb_all && argc == 0) {
3350 (void) fprintf(stderr, gettext("-V option is "
3351 "incompatible with other arguments\n"));
3352 usage(B_FALSE);
3353 }
3354
3355 if (showversions) {
3356 if (cb.cb_all || argc != 0) {
3357 (void) fprintf(stderr, gettext("-v option is "
3358 "incompatible with other arguments\n"));
3359 usage(B_FALSE);
3360 }
3361 } else if (cb.cb_all) {
3362 if (argc != 0) {
3363 (void) fprintf(stderr, gettext("-a option should not "
3364 "be used along with a pool name\n"));
3365 usage(B_FALSE);
3366 }
3367 }
3368
3369 (void) printf(gettext("This system is currently running "
3370 "ZFS pool version %llu.\n\n"), SPA_VERSION);
3371 cb.cb_first = B_TRUE;
3372 if (showversions) {
3373 (void) printf(gettext("The following versions are "
3374 "supported:\n\n"));
3375 (void) printf(gettext("VER DESCRIPTION\n"));
3376 (void) printf("--- -----------------------------------------"
3377 "---------------\n");
3378 (void) printf(gettext(" 1 Initial ZFS version\n"));
3379 (void) printf(gettext(" 2 Ditto blocks "
3380 "(replicated metadata)\n"));
3381 (void) printf(gettext(" 3 Hot spares and double parity "
3382 "RAID-Z\n"));
3383 (void) printf(gettext(" 4 zpool history\n"));
3384 (void) printf(gettext(" 5 Compression using the gzip "
3385 "algorithm\n"));
3386 (void) printf(gettext(" 6 bootfs pool property\n"));
3387 (void) printf(gettext(" 7 Separate intent log devices\n"));
3388 (void) printf(gettext(" 8 Delegated administration\n"));
3389 (void) printf(gettext(" 9 refquota and refreservation "
3390 "properties\n"));
3391 (void) printf(gettext(" 10 Cache devices\n"));
3392 (void) printf(gettext("For more information on a particular "
3393 "version, including supported releases, see:\n\n"));
3394 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3395 "version/N\n\n");
3396 (void) printf(gettext("Where 'N' is the version number.\n"));
3397 } else if (argc == 0) {
3398 int notfound;
3399
3400 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3401 notfound = cb.cb_first;
3402
3403 if (!cb.cb_all && ret == 0) {
3404 if (!cb.cb_first)
3405 (void) printf("\n");
3406 cb.cb_first = B_TRUE;
3407 cb.cb_newer = B_TRUE;
3408 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3409 if (!cb.cb_first) {
3410 notfound = B_FALSE;
3411 (void) printf("\n");
3412 }
3413 }
3414
3415 if (ret == 0) {
3416 if (notfound)
3417 (void) printf(gettext("All pools are formatted "
3418 "using this version.\n"));
3419 else if (!cb.cb_all)
3420 (void) printf(gettext("Use 'zpool upgrade -v' "
3421 "for a list of available versions and "
3422 "their associated\nfeatures.\n"));
3423 }
3424 } else {
3425 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3426 upgrade_one, &cb);
3427 }
3428
3429 return (ret);
3430}
3431
3432typedef struct hist_cbdata {
3433 boolean_t first;
3434 int longfmt;
3435 int internal;
3436} hist_cbdata_t;
3437
3438char *hist_event_table[LOG_END] = {
3439 "invalid event",
3440 "pool create",
3441 "vdev add",
3442 "pool remove",
3443 "pool destroy",
3444 "pool export",
3445 "pool import",
3446 "vdev attach",
3447 "vdev replace",
3448 "vdev detach",
3449 "vdev online",
3450 "vdev offline",
3451 "vdev upgrade",
3452 "pool clear",
3453 "pool scrub",
3454 "pool property set",
3455 "create",
3456 "clone",
3457 "destroy",
3458 "destroy_begin_sync",
3459 "inherit",
3460 "property set",
3461 "quota set",
3462 "permission update",
3463 "permission remove",
3464 "permission who remove",
3465 "promote",
3466 "receive",
3467 "rename",
3468 "reservation set",
3469 "replay_inc_sync",
3470 "replay_full_sync",
3471 "rollback",
3472 "snapshot",
3473 "filesystem version upgrade",
3474 "refquota set",
3475 "refreservation set",
3476};
3477
3478/*
3479 * Print out the command history for a specific pool.
3480 */
3481static int
3482get_history_one(zpool_handle_t *zhp, void *data)
3483{
3484 nvlist_t *nvhis;
3485 nvlist_t **records;
3486 uint_t numrecords;
3487 char *cmdstr;
3488 char *pathstr;
3489 uint64_t dst_time;
3490 time_t tsec;
3491 struct tm t;
3492 char tbuf[30];
3493 int ret, i;
3494 uint64_t who;
3495 struct passwd *pwd;
3496 char *hostname;
3497 char *zonename;
3498 char internalstr[MAXPATHLEN];
3499 hist_cbdata_t *cb = (hist_cbdata_t *)data;
3500 uint64_t txg;
3501 uint64_t ievent;
3502
3503 cb->first = B_FALSE;
3504
3505 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3506
3507 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3508 return (ret);
3509
3510 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3511 &records, &numrecords) == 0);
3512 for (i = 0; i < numrecords; i++) {
3513 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3514 &dst_time) != 0)
3515 continue;
3516
3517 /* is it an internal event or a standard event? */
3518 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3519 &cmdstr) != 0) {
3520 if (cb->internal == 0)
3521 continue;
3522
3523 if (nvlist_lookup_uint64(records[i],
3524 ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3525 continue;
3526 verify(nvlist_lookup_uint64(records[i],
3527 ZPOOL_HIST_TXG, &txg) == 0);
3528 verify(nvlist_lookup_string(records[i],
3529 ZPOOL_HIST_INT_STR, &pathstr) == 0);
3530 if (ievent > LOG_END)
3531 continue;
3532 (void) snprintf(internalstr,
3533 sizeof (internalstr),
3534 "[internal %s txg:%lld] %s",
3535 hist_event_table[ievent], txg,
3536 pathstr);
3537 cmdstr = internalstr;
3538 }
3539 tsec = dst_time;
3540 (void) localtime_r(&tsec, &t);
3541 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3542 (void) printf("%s %s", tbuf, cmdstr);
3543
3544 if (!cb->longfmt) {
3545 (void) printf("\n");
3546 continue;
3547 }
3548 (void) printf(" [");
3549 if (nvlist_lookup_uint64(records[i],
3550 ZPOOL_HIST_WHO, &who) == 0) {
3551 pwd = getpwuid((uid_t)who);
3552 if (pwd)
3553 (void) printf("user %s on",
3554 pwd->pw_name);
3555 else
3556 (void) printf("user %d on",
3557 (int)who);
3558 } else {
3559 (void) printf(gettext("no info]\n"));
3560 continue;
3561 }
3562 if (nvlist_lookup_string(records[i],
3563 ZPOOL_HIST_HOST, &hostname) == 0) {
3564 (void) printf(" %s", hostname);
3565 }
3566 if (nvlist_lookup_string(records[i],
3567 ZPOOL_HIST_ZONE, &zonename) == 0) {
3568 (void) printf(":%s", zonename);
3569 }
3570
3571 (void) printf("]");
3572 (void) printf("\n");
3573 }
3574 (void) printf("\n");
3575 nvlist_free(nvhis);
3576
3577 return (ret);
3578}
3579
3580/*
3581 * zpool history <pool>
3582 *
3583 * Displays the history of commands that modified pools.
3584 */
3585
3586
3587int
3588zpool_do_history(int argc, char **argv)
3589{
3590 hist_cbdata_t cbdata = { 0 };
3591 int ret;
3592 int c;
3593
3594 cbdata.first = B_TRUE;
3595 /* check options */
3596 while ((c = getopt(argc, argv, "li")) != -1) {
3597 switch (c) {
3598 case 'l':
3599 cbdata.longfmt = 1;
3600 break;
3601 case 'i':
3602 cbdata.internal = 1;
3603 break;
3604 case '?':
3605 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3606 optopt);
3607 usage(B_FALSE);
3608 }
3609 }
3610 argc -= optind;
3611 argv += optind;
3612
3613 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
3614 &cbdata);
3615
3616 if (argc == 0 && cbdata.first == B_TRUE) {
3617 (void) printf(gettext("no pools available\n"));
3618 return (0);
3619 }
3620
3621 return (ret);
3622}
3623
3624static int
3625get_callback(zpool_handle_t *zhp, void *data)
3626{
3627 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3628 char value[MAXNAMELEN];
3629 zprop_source_t srctype;
3630 zprop_list_t *pl;
3631
3632 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3633
3634 /*
3635 * Skip the special fake placeholder. This will also skip
3636 * over the name property when 'all' is specified.
3637 */
3638 if (pl->pl_prop == ZPOOL_PROP_NAME &&
3639 pl == cbp->cb_proplist)
3640 continue;
3641
3642 if (zpool_get_prop(zhp, pl->pl_prop,
3643 value, sizeof (value), &srctype) != 0)
3644 continue;
3645
3646 zprop_print_one_property(zpool_get_name(zhp), cbp,
3647 zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3648 }
3649 return (0);
3650}
3651
3652int
3653zpool_do_get(int argc, char **argv)
3654{
3655 zprop_get_cbdata_t cb = { 0 };
3656 zprop_list_t fake_name = { 0 };
3657 int ret;
3658
3659 if (argc < 3)
3660 usage(B_FALSE);
3661
3662 cb.cb_first = B_TRUE;
3663 cb.cb_sources = ZPROP_SRC_ALL;
3664 cb.cb_columns[0] = GET_COL_NAME;
3665 cb.cb_columns[1] = GET_COL_PROPERTY;
3666 cb.cb_columns[2] = GET_COL_VALUE;
3667 cb.cb_columns[3] = GET_COL_SOURCE;
3668 cb.cb_type = ZFS_TYPE_POOL;
3669
3670 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
3671 ZFS_TYPE_POOL) != 0)
3672 usage(B_FALSE);
3673
3674 if (cb.cb_proplist != NULL) {
3675 fake_name.pl_prop = ZPOOL_PROP_NAME;
3676 fake_name.pl_width = strlen(gettext("NAME"));
3677 fake_name.pl_next = cb.cb_proplist;
3678 cb.cb_proplist = &fake_name;
3679 }
3680
3681 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3682 get_callback, &cb);
3683
3684 if (cb.cb_proplist == &fake_name)
3685 zprop_free_list(fake_name.pl_next);
3686 else
3687 zprop_free_list(cb.cb_proplist);
3688
3689 return (ret);
3690}
3691
3692typedef struct set_cbdata {
3693 char *cb_propname;
3694 char *cb_value;
3695 boolean_t cb_any_successful;
3696} set_cbdata_t;
3697
3698int
3699set_callback(zpool_handle_t *zhp, void *data)
3700{
3701 int error;
3702 set_cbdata_t *cb = (set_cbdata_t *)data;
3703
3704 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3705
3706 if (!error)
3707 cb->cb_any_successful = B_TRUE;
3708
3709 return (error);
3710}
3711
3712int
3713zpool_do_set(int argc, char **argv)
3714{
3715 set_cbdata_t cb = { 0 };
3716 int error;
3717
3718 if (argc > 1 && argv[1][0] == '-') {
3719 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3720 argv[1][1]);
3721 usage(B_FALSE);
3722 }
3723
3724 if (argc < 2) {
3725 (void) fprintf(stderr, gettext("missing property=value "
3726 "argument\n"));
3727 usage(B_FALSE);
3728 }
3729
3730 if (argc < 3) {
3731 (void) fprintf(stderr, gettext("missing pool name\n"));
3732 usage(B_FALSE);
3733 }
3734
3735 if (argc > 3) {
3736 (void) fprintf(stderr, gettext("too many pool names\n"));
3737 usage(B_FALSE);
3738 }
3739
3740 cb.cb_propname = argv[1];
3741 cb.cb_value = strchr(cb.cb_propname, '=');
3742 if (cb.cb_value == NULL) {
3743 (void) fprintf(stderr, gettext("missing value in "
3744 "property=value argument\n"));
3745 usage(B_FALSE);
3746 }
3747
3748 *(cb.cb_value) = '\0';
3749 cb.cb_value++;
3750
3751 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3752 set_callback, &cb);
3753
3754 return (error);
3755}
3756
3757static int
3758find_command_idx(char *command, int *idx)
3759{
3760 int i;
3761
3762 for (i = 0; i < NCOMMAND; i++) {
3763 if (command_table[i].name == NULL)
3764 continue;
3765
3766 if (strcmp(command, command_table[i].name) == 0) {
3767 *idx = i;
3768 return (0);
3769 }
3770 }
3771 return (1);
3772}
3773
3774int
3775main(int argc, char **argv)
3776{
3777 int ret;
3778 int i;
3779 char *cmdname;
3780
3781 (void) setlocale(LC_ALL, "");
3782 (void) textdomain(TEXT_DOMAIN);
3783
3784 if ((g_zfs = libzfs_init()) == NULL) {
3785 (void) fprintf(stderr, gettext("internal error: failed to "
3786 "initialize ZFS library\n"));
3787 return (1);
3788 }
3789
3790 libzfs_print_on_error(g_zfs, B_TRUE);
3791
3792 opterr = 0;
3793
3794 /*
3795 * Make sure the user has specified some command.
3796 */
3797 if (argc < 2) {
3798 (void) fprintf(stderr, gettext("missing command\n"));
3799 usage(B_FALSE);
3800 }
3801
3802 cmdname = argv[1];
3803
3804 /*
3805 * Special case '-?'
3806 */
3807 if (strcmp(cmdname, "-?") == 0)
3808 usage(B_TRUE);
3809
3810 zpool_set_history_str("zpool", argc, argv, history_str);
3811 verify(zpool_stage_history(g_zfs, history_str) == 0);
3812
3813 /*
3814 * Run the appropriate command.
3815 */
3816 if (find_command_idx(cmdname, &i) == 0) {
3817 current_command = &command_table[i];
3818 ret = command_table[i].func(argc - 1, argv + 1);
3819 } else if (strchr(cmdname, '=')) {
3820 verify(find_command_idx("set", &i) == 0);
3821 current_command = &command_table[i];
3822 ret = command_table[i].func(argc, argv);
3823 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3824 /*
3825 * 'freeze' is a vile debugging abomination, so we treat
3826 * it as such.
3827 */
3828 char buf[16384];
3829 int fd = open(ZFS_DEV, O_RDWR);
3830 (void) strcpy((void *)buf, argv[2]);
3831 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
3832 } else {
3833 (void) fprintf(stderr, gettext("unrecognized "
3834 "command '%s'\n"), cmdname);
3835 usage(B_FALSE);
3836 }
3837
3838 libzfs_fini(g_zfs);
3839
3840 /*
3841 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3842 * for the purposes of running ::findleaks.
3843 */
3844 if (getenv("ZFS_ABORT") != NULL) {
3845 (void) printf("dumping core by request\n");
3846 abort();
3847 }
3848
3849 return (ret);
3850}