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