Print this page




  63 static int zpool_do_online(int, char **);
  64 static int zpool_do_offline(int, char **);
  65 static int zpool_do_clear(int, char **);
  66 
  67 static int zpool_do_attach(int, char **);
  68 static int zpool_do_detach(int, char **);
  69 static int zpool_do_replace(int, char **);
  70 
  71 static int zpool_do_scrub(int, char **);
  72 
  73 static int zpool_do_import(int, char **);
  74 static int zpool_do_export(int, char **);
  75 
  76 static int zpool_do_upgrade(int, char **);
  77 
  78 static int zpool_do_history(int, char **);
  79 
  80 static int zpool_do_get(int, char **);
  81 static int zpool_do_set(int, char **);
  82 


  83 /*
  84  * These libumem hooks provide a reasonable set of defaults for the allocator's
  85  * debugging facilities.
  86  */
  87 
  88 #ifdef DEBUG
  89 const char *
  90 _umem_debug_init(void)
  91 {
  92         return ("default,verbose"); /* $UMEM_DEBUG setting */
  93 }
  94 
  95 const char *
  96 _umem_logging_init(void)
  97 {
  98         return ("fail,contents"); /* $UMEM_LOGGING setting */
  99 }
 100 #endif
 101 
 102 typedef enum {
 103         HELP_ADD,
 104         HELP_ATTACH,
 105         HELP_CLEAR,
 106         HELP_CREATE,
 107         HELP_DESTROY,
 108         HELP_DETACH,
 109         HELP_EXPORT,
 110         HELP_HISTORY,
 111         HELP_IMPORT,
 112         HELP_IOSTAT,
 113         HELP_LIST,
 114         HELP_OFFLINE,
 115         HELP_ONLINE,
 116         HELP_REPLACE,
 117         HELP_REMOVE,
 118         HELP_SCRUB,
 119         HELP_STATUS,
 120         HELP_UPGRADE,
 121         HELP_GET,
 122         HELP_SET

 123 } zpool_help_t;
 124 
 125 
 126 typedef struct zpool_command {
 127         const char      *name;
 128         int             (*func)(int, char **);
 129         zpool_help_t    usage;
 130 } zpool_command_t;
 131 
 132 /*
 133  * Master command table.  Each ZFS command has a name, associated function, and
 134  * usage message.  The usage messages need to be internationalized, so we have
 135  * to have a function to return the usage message based on a command index.
 136  *
 137  * These commands are organized according to how they are displayed in the usage
 138  * message.  An empty command (one with a NULL name) indicates an empty line in
 139  * the generic usage message.
 140  */
 141 static zpool_command_t command_table[] = {
 142         { "create",     zpool_do_create,        HELP_CREATE             },


 149         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 150         { "status",     zpool_do_status,        HELP_STATUS             },
 151         { NULL },
 152         { "online",     zpool_do_online,        HELP_ONLINE             },
 153         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 154         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 155         { NULL },
 156         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 157         { "detach",     zpool_do_detach,        HELP_DETACH             },
 158         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 159         { NULL },
 160         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 161         { NULL },
 162         { "import",     zpool_do_import,        HELP_IMPORT             },
 163         { "export",     zpool_do_export,        HELP_EXPORT             },
 164         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 165         { NULL },
 166         { "history",    zpool_do_history,       HELP_HISTORY            },
 167         { "get",        zpool_do_get,           HELP_GET                },
 168         { "set",        zpool_do_set,           HELP_SET                },


 169 };
 170 
 171 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 172 
 173 zpool_command_t *current_command;
 174 static char history_str[HIS_MAX_RECORD_LEN];
 175 
 176 static const char *
 177 get_usage(zpool_help_t idx) {
 178         switch (idx) {
 179         case HELP_ADD:
 180                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 181         case HELP_ATTACH:
 182                 return (gettext("\tattach [-f] <pool> <device> "
 183                     "<new-device>\n"));
 184         case HELP_CLEAR:
 185                 return (gettext("\tclear <pool> [device]\n"));
 186         case HELP_CREATE:
 187                 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
 188                     "\t    [-O file-system-property=value] ... \n"


 213         case HELP_ONLINE:
 214                 return (gettext("\tonline <pool> <device> ...\n"));
 215         case HELP_REPLACE:
 216                 return (gettext("\treplace [-f] <pool> <device> "
 217                     "[new-device]\n"));
 218         case HELP_REMOVE:
 219                 return (gettext("\tremove <pool> <device> ...\n"));
 220         case HELP_SCRUB:
 221                 return (gettext("\tscrub [-s] <pool> ...\n"));
 222         case HELP_STATUS:
 223                 return (gettext("\tstatus [-vx] [pool] ...\n"));
 224         case HELP_UPGRADE:
 225                 return (gettext("\tupgrade\n"
 226                     "\tupgrade -v\n"
 227                     "\tupgrade [-V version] <-a | pool ...>\n"));
 228         case HELP_GET:
 229                 return (gettext("\tget <\"all\" | property[,...]> "
 230                     "<pool> ...\n"));
 231         case HELP_SET:
 232                 return (gettext("\tset <property=value> <pool> \n"));



 233         }
 234 
 235         abort();
 236         /* NOTREACHED */
 237 }
 238 
 239 
 240 /*
 241  * Callback routine that will print out a pool property value.
 242  */
 243 static int
 244 print_prop_cb(int prop, void *cb)
 245 {
 246         FILE *fp = cb;
 247 
 248         (void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
 249 
 250         if (zpool_prop_readonly(prop))
 251                 (void) fprintf(fp, "  NO   ");
 252         else


 790         nvlist_free(props);
 791         return (ret);
 792 badusage:
 793         nvlist_free(fsprops);
 794         nvlist_free(props);
 795         usage(B_FALSE);
 796         return (2);
 797 }
 798 
 799 /*
 800  * zpool destroy <pool>
 801  *
 802  *      -f      Forcefully unmount any datasets
 803  *
 804  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
 805  */
 806 int
 807 zpool_do_destroy(int argc, char **argv)
 808 {
 809         boolean_t force = B_FALSE;

 810         int c;
 811         char *pool;
 812         zpool_handle_t *zhp;
 813         int ret;
 814 
 815         /* check options */
 816         while ((c = getopt(argc, argv, "f")) != -1) {
 817                 switch (c) {
 818                 case 'f':
 819                         force = B_TRUE;
 820                         break;
 821                 case '?':
 822                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 823                             optopt);
 824                         usage(B_FALSE);
 825                 }
 826         }
 827 
 828         argc -= optind;
 829         argv += optind;


 834                 usage(B_FALSE);
 835         }
 836         if (argc > 1) {
 837                 (void) fprintf(stderr, gettext("too many arguments\n"));
 838                 usage(B_FALSE);
 839         }
 840 
 841         pool = argv[0];
 842 
 843         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
 844                 /*
 845                  * As a special case, check for use of '/' in the name, and
 846                  * direct the user to use 'zfs destroy' instead.
 847                  */
 848                 if (strchr(pool, '/') != NULL)
 849                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
 850                             "destroy a dataset\n"));
 851                 return (1);
 852         }
 853 
 854         if (zpool_disable_datasets(zhp, force) != 0) {
 855                 (void) fprintf(stderr, gettext("could not destroy '%s': "
 856                     "could not unmount datasets\n"), zpool_get_name(zhp));
 857                 return (1);
 858         }
 859 
 860         ret = (zpool_destroy(zhp) != 0);
 861 
 862         zpool_close(zhp);
 863 
 864         return (ret);
 865 }
 866 
 867 /*
 868  * zpool export [-f] <pool> ...
 869  *
 870  *      -f      Forcefully unmount datasets
 871  *
 872  * Export the given pools.  By default, the command will attempt to cleanly
 873  * unmount any active datasets within the pool.  If the '-f' flag is specified,
 874  * then the datasets will be forcefully unmounted.
 875  */
 876 int
 877 zpool_do_export(int argc, char **argv)
 878 {
 879         boolean_t force = B_FALSE;
 880         boolean_t hardforce = B_FALSE;

 881         int c;
 882         zpool_handle_t *zhp;
 883         int ret;
 884         int i;
 885 
 886         /* check options */
 887         while ((c = getopt(argc, argv, "fF")) != -1) {
 888                 switch (c) {
 889                 case 'f':
 890                         force = B_TRUE;
 891                         break;
 892                 case 'F':
 893                         hardforce = B_TRUE;
 894                         break;
 895                 case '?':
 896                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 897                             optopt);
 898                         usage(B_FALSE);
 899                 }
 900         }
 901 
 902         argc -= optind;
 903         argv += optind;
 904 
 905         /* check arguments */
 906         if (argc < 1) {
 907                 (void) fprintf(stderr, gettext("missing pool argument\n"));
 908                 usage(B_FALSE);
 909         }
 910 
 911         ret = 0;
 912         for (i = 0; i < argc; i++) {
 913                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
 914                         ret = 1;
 915                         continue;
 916                 }
 917 
 918                 if (zpool_disable_datasets(zhp, force) != 0) {
 919                         ret = 1;
 920                         zpool_close(zhp);
 921                         continue;
 922                 }
 923 
 924                 if (hardforce) {
 925                         if (zpool_export_force(zhp) != 0)
 926                                 ret = 1;
 927                 } else if (zpool_export(zhp, force) != 0) {
 928                         ret = 1;
 929                 }
 930 
 931                 zpool_close(zhp);
 932         }
 933 
 934         return (ret);
 935 }
 936 
 937 /*
 938  * Given a vdev configuration, determine the maximum width needed for the device


1246                 (void) printf(gettext("\tlogs\n"));
1247                 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1248         }
1249 
1250         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1251                 (void) printf(gettext("\n\tAdditional devices are known to "
1252                     "be part of this pool, though their\n\texact "
1253                     "configuration cannot be determined.\n"));
1254         }
1255 }
1256 
1257 /*
1258  * Perform the import for the given configuration.  This passes the heavy
1259  * lifting off to zpool_import_props(), and then mounts the datasets contained
1260  * within the pool.
1261  */
1262 static int
1263 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1264     int force, nvlist_t *props, boolean_t allowfaulted)
1265 {

1266         zpool_handle_t *zhp;
1267         char *name;
1268         uint64_t state;
1269         uint64_t version;
1270         int error = 0;
1271 
1272         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1273             &name) == 0);
1274 
1275         verify(nvlist_lookup_uint64(config,
1276             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1277         verify(nvlist_lookup_uint64(config,
1278             ZPOOL_CONFIG_VERSION, &version) == 0);
1279         if (version > SPA_VERSION) {
1280                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1281                     "is formatted using a newer ZFS version\n"), name);
1282                 return (1);
1283         } else if (state != POOL_STATE_EXPORTED && !force) {
1284                 uint64_t hostid;
1285 


1306                                 return (1);
1307                         }
1308                 } else {
1309                         (void) fprintf(stderr, gettext("cannot import '%s': "
1310                             "pool may be in use from other system\n"), name);
1311                         (void) fprintf(stderr, gettext("use '-f' to import "
1312                             "anyway\n"));
1313                         return (1);
1314                 }
1315         }
1316 
1317         if (zpool_import_props(g_zfs, config, newname, props,
1318             allowfaulted) != 0)
1319                 return (1);
1320 
1321         if (newname != NULL)
1322                 name = (char *)newname;
1323 
1324         verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1325 






















1326         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1327             zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1328                 zpool_close(zhp);
1329                 return (1);
1330         }
1331 
1332         zpool_close(zhp);
1333         return (error);
1334 }
1335 
1336 /*
1337  * zpool import [-d dir] [-D]
1338  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1339  *              [-d dir | -c cachefile] [-f] -a
1340  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1341  *              [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1342  *
1343  *       -c     Read pool information from a cachefile instead of searching
1344  *              devices.
1345  *
1346  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
1347  *              one directory can be specified using multiple '-d' options.
1348  *
1349  *       -D     Scan for previously destroyed pools or import all or only
1350  *              specified destroyed pools.
1351  *
1352  *       -R     Temporarily import the pool, with all mountpoints relative to
1353  *              the given root.  The pool will remain exported when the machine


2973  *      reason: One or more devices ...
2974  *         see: http://www.sun.com/msg/ZFS-xxxx-01
2975  *      config:
2976  *              mirror          DEGRADED
2977  *                c1t0d0        OK
2978  *                c2t0d0        UNAVAIL
2979  *
2980  * When given the '-v' option, we print out the complete config.  If the '-e'
2981  * option is specified, then we print out error rate information as well.
2982  */
2983 int
2984 status_callback(zpool_handle_t *zhp, void *data)
2985 {
2986         status_cbdata_t *cbp = data;
2987         nvlist_t *config, *nvroot;
2988         char *msgid;
2989         int reason;
2990         const char *health;
2991         uint_t c;
2992         vdev_stat_t *vs;


2993 
2994         config = zpool_get_config(zhp, NULL);
2995         reason = zpool_get_status(zhp, &msgid);
2996 
2997         cbp->cb_count++;
2998 
2999         /*
3000          * If we were given 'zpool status -x', only report those pools with
3001          * problems.
3002          */
3003         if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3004                 if (!cbp->cb_allpools) {
3005                         (void) printf(gettext("pool '%s' is healthy\n"),
3006                             zpool_get_name(zhp));
3007                         if (cbp->cb_first)
3008                                 cbp->cb_first = B_FALSE;
3009                 }
3010                 return (0);
3011         }
3012 
3013         if (cbp->cb_first)
3014                 cbp->cb_first = B_FALSE;
3015         else
3016                 (void) printf("\n");
3017 
3018         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3019             &nvroot) == 0);
3020         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3021             (uint64_t **)&vs, &c) == 0);
3022         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3023 
3024         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3025         (void) printf(gettext(" state: %s\n"), health);
3026 





3027         switch (reason) {
3028         case ZPOOL_STATUS_MISSING_DEV_R:
3029                 (void) printf(gettext("status: One or more devices could not "
3030                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
3031                     "continue functioning in a degraded state.\n"));
3032                 (void) printf(gettext("action: Attach the missing device and "
3033                     "online it using 'zpool online'.\n"));
3034                 break;
3035 
3036         case ZPOOL_STATUS_MISSING_DEV_NR:
3037                 (void) printf(gettext("status: One or more devices could not "
3038                     "be opened.  There are insufficient\n\treplicas for the "
3039                     "pool to continue functioning.\n"));
3040                 (void) printf(gettext("action: Attach the missing device and "
3041                     "online it using 'zpool online'.\n"));
3042                 break;
3043 
3044         case ZPOOL_STATUS_CORRUPT_LABEL_R:
3045                 (void) printf(gettext("status: One or more devices could not "
3046                     "be used because the label is missing or\n\tinvalid.  "


3480                     "---------------\n");
3481                 (void) printf(gettext(" 1   Initial ZFS version\n"));
3482                 (void) printf(gettext(" 2   Ditto blocks "
3483                     "(replicated metadata)\n"));
3484                 (void) printf(gettext(" 3   Hot spares and double parity "
3485                     "RAID-Z\n"));
3486                 (void) printf(gettext(" 4   zpool history\n"));
3487                 (void) printf(gettext(" 5   Compression using the gzip "
3488                     "algorithm\n"));
3489                 (void) printf(gettext(" 6   bootfs pool property\n"));
3490                 (void) printf(gettext(" 7   Separate intent log devices\n"));
3491                 (void) printf(gettext(" 8   Delegated administration\n"));
3492                 (void) printf(gettext(" 9   refquota and refreservation "
3493                     "properties\n"));
3494                 (void) printf(gettext(" 10  Cache devices\n"));
3495                 (void) printf(gettext(" 11  Improved scrub performance\n"));
3496                 (void) printf(gettext(" 12  Snapshot properties\n"));
3497                 (void) printf(gettext(" 13  snapused property\n"));
3498                 (void) printf(gettext(" 14  passthrough-x aclinherit "
3499                     "support\n"));

3500                 (void) printf(gettext("For more information on a particular "
3501                     "version, including supported releases, see:\n\n"));
3502                 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3503                     "version/N\n\n");
3504                 (void) printf(gettext("Where 'N' is the version number.\n"));
3505         } else if (argc == 0) {
3506                 int notfound;
3507 
3508                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3509                 notfound = cb.cb_first;
3510 
3511                 if (!cb.cb_all && ret == 0) {
3512                         if (!cb.cb_first)
3513                                 (void) printf("\n");
3514                         cb.cb_first = B_TRUE;
3515                         cb.cb_newer = B_TRUE;
3516                         ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3517                         if (!cb.cb_first) {
3518                                 notfound = B_FALSE;
3519                                 (void) printf("\n");


3565         "destroy",
3566         "destroy_begin_sync",
3567         "inherit",
3568         "property set",
3569         "quota set",
3570         "permission update",
3571         "permission remove",
3572         "permission who remove",
3573         "promote",
3574         "receive",
3575         "rename",
3576         "reservation set",
3577         "replay_inc_sync",
3578         "replay_full_sync",
3579         "rollback",
3580         "snapshot",
3581         "filesystem version upgrade",
3582         "refquota set",
3583         "refreservation set",
3584         "pool scrub done",

3585 };
3586 
3587 /*
3588  * Print out the command history for a specific pool.
3589  */
3590 static int
3591 get_history_one(zpool_handle_t *zhp, void *data)
3592 {
3593         nvlist_t *nvhis;
3594         nvlist_t **records;
3595         uint_t numrecords;
3596         char *cmdstr;
3597         char *pathstr;
3598         uint64_t dst_time;
3599         time_t tsec;
3600         struct tm t;
3601         char tbuf[30];
3602         int ret, i;
3603         uint64_t who;
3604         struct passwd *pwd;


3794                 zprop_free_list(fake_name.pl_next);
3795         else
3796                 zprop_free_list(cb.cb_proplist);
3797 
3798         return (ret);
3799 }
3800 
3801 typedef struct set_cbdata {
3802         char *cb_propname;
3803         char *cb_value;
3804         boolean_t cb_any_successful;
3805 } set_cbdata_t;
3806 
3807 int
3808 set_callback(zpool_handle_t *zhp, void *data)
3809 {
3810         int error;
3811         set_cbdata_t *cb = (set_cbdata_t *)data;
3812 
3813         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3814 
3815         if (!error)
3816                 cb->cb_any_successful = B_TRUE;
3817 
3818         return (error);
3819 }
3820 
3821 int
3822 zpool_do_set(int argc, char **argv)
3823 {
3824         set_cbdata_t cb = { 0 };
3825         int error;
3826 
3827         if (argc > 1 && argv[1][0] == '-') {
3828                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3829                     argv[1][1]);
3830                 usage(B_FALSE);
3831         }
3832 
3833         if (argc < 2) {
3834                 (void) fprintf(stderr, gettext("missing property=value "


3846                 usage(B_FALSE);
3847         }
3848 
3849         cb.cb_propname = argv[1];
3850         cb.cb_value = strchr(cb.cb_propname, '=');
3851         if (cb.cb_value == NULL) {
3852                 (void) fprintf(stderr, gettext("missing value in "
3853                     "property=value argument\n"));
3854                 usage(B_FALSE);
3855         }
3856 
3857         *(cb.cb_value) = '\0';
3858         cb.cb_value++;
3859 
3860         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3861             set_callback, &cb);
3862 
3863         return (error);
3864 }
3865 





























































































































































3866 static int
3867 find_command_idx(char *command, int *idx)
3868 {
3869         int i;
3870 
3871         for (i = 0; i < NCOMMAND; i++) {
3872                 if (command_table[i].name == NULL)
3873                         continue;
3874 
3875                 if (strcmp(command, command_table[i].name) == 0) {
3876                         *idx = i;
3877                         return (0);
3878                 }
3879         }
3880         return (1);
3881 }
3882 
3883 int
3884 main(int argc, char **argv)
3885 {




  63 static int zpool_do_online(int, char **);
  64 static int zpool_do_offline(int, char **);
  65 static int zpool_do_clear(int, char **);
  66 
  67 static int zpool_do_attach(int, char **);
  68 static int zpool_do_detach(int, char **);
  69 static int zpool_do_replace(int, char **);
  70 
  71 static int zpool_do_scrub(int, char **);
  72 
  73 static int zpool_do_import(int, char **);
  74 static int zpool_do_export(int, char **);
  75 
  76 static int zpool_do_upgrade(int, char **);
  77 
  78 static int zpool_do_history(int, char **);
  79 
  80 static int zpool_do_get(int, char **);
  81 static int zpool_do_set(int, char **);
  82 
  83 static int zpool_do_key(int, char **);
  84 
  85 /*
  86  * These libumem hooks provide a reasonable set of defaults for the allocator's
  87  * debugging facilities.
  88  */
  89 
  90 #ifdef DEBUG
  91 const char *
  92 _umem_debug_init(void)
  93 {
  94         return ("default,verbose"); /* $UMEM_DEBUG setting */
  95 }
  96 
  97 const char *
  98 _umem_logging_init(void)
  99 {
 100         return ("fail,contents"); /* $UMEM_LOGGING setting */
 101 }
 102 #endif
 103 
 104 typedef enum {
 105         HELP_ADD,
 106         HELP_ATTACH,
 107         HELP_CLEAR,
 108         HELP_CREATE,
 109         HELP_DESTROY,
 110         HELP_DETACH,
 111         HELP_EXPORT,
 112         HELP_HISTORY,
 113         HELP_IMPORT,
 114         HELP_IOSTAT,
 115         HELP_LIST,
 116         HELP_OFFLINE,
 117         HELP_ONLINE,
 118         HELP_REPLACE,
 119         HELP_REMOVE,
 120         HELP_SCRUB,
 121         HELP_STATUS,
 122         HELP_UPGRADE,
 123         HELP_GET,
 124         HELP_SET,
 125         HELP_KEY
 126 } zpool_help_t;
 127 
 128 
 129 typedef struct zpool_command {
 130         const char      *name;
 131         int             (*func)(int, char **);
 132         zpool_help_t    usage;
 133 } zpool_command_t;
 134 
 135 /*
 136  * Master command table.  Each ZFS command has a name, associated function, and
 137  * usage message.  The usage messages need to be internationalized, so we have
 138  * to have a function to return the usage message based on a command index.
 139  *
 140  * These commands are organized according to how they are displayed in the usage
 141  * message.  An empty command (one with a NULL name) indicates an empty line in
 142  * the generic usage message.
 143  */
 144 static zpool_command_t command_table[] = {
 145         { "create",     zpool_do_create,        HELP_CREATE             },


 152         { "iostat",     zpool_do_iostat,        HELP_IOSTAT             },
 153         { "status",     zpool_do_status,        HELP_STATUS             },
 154         { NULL },
 155         { "online",     zpool_do_online,        HELP_ONLINE             },
 156         { "offline",    zpool_do_offline,       HELP_OFFLINE            },
 157         { "clear",      zpool_do_clear,         HELP_CLEAR              },
 158         { NULL },
 159         { "attach",     zpool_do_attach,        HELP_ATTACH             },
 160         { "detach",     zpool_do_detach,        HELP_DETACH             },
 161         { "replace",    zpool_do_replace,       HELP_REPLACE            },
 162         { NULL },
 163         { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 164         { NULL },
 165         { "import",     zpool_do_import,        HELP_IMPORT             },
 166         { "export",     zpool_do_export,        HELP_EXPORT             },
 167         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 168         { NULL },
 169         { "history",    zpool_do_history,       HELP_HISTORY            },
 170         { "get",        zpool_do_get,           HELP_GET                },
 171         { "set",        zpool_do_set,           HELP_SET                },
 172         { NULL },
 173         { "key",        zpool_do_key,           HELP_KEY                },
 174 };
 175 
 176 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 177 
 178 zpool_command_t *current_command;
 179 static char history_str[HIS_MAX_RECORD_LEN];
 180 
 181 static const char *
 182 get_usage(zpool_help_t idx) {
 183         switch (idx) {
 184         case HELP_ADD:
 185                 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
 186         case HELP_ATTACH:
 187                 return (gettext("\tattach [-f] <pool> <device> "
 188                     "<new-device>\n"));
 189         case HELP_CLEAR:
 190                 return (gettext("\tclear <pool> [device]\n"));
 191         case HELP_CREATE:
 192                 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
 193                     "\t    [-O file-system-property=value] ... \n"


 218         case HELP_ONLINE:
 219                 return (gettext("\tonline <pool> <device> ...\n"));
 220         case HELP_REPLACE:
 221                 return (gettext("\treplace [-f] <pool> <device> "
 222                     "[new-device]\n"));
 223         case HELP_REMOVE:
 224                 return (gettext("\tremove <pool> <device> ...\n"));
 225         case HELP_SCRUB:
 226                 return (gettext("\tscrub [-s] <pool> ...\n"));
 227         case HELP_STATUS:
 228                 return (gettext("\tstatus [-vx] [pool] ...\n"));
 229         case HELP_UPGRADE:
 230                 return (gettext("\tupgrade\n"
 231                     "\tupgrade -v\n"
 232                     "\tupgrade [-V version] <-a | pool ...>\n"));
 233         case HELP_GET:
 234                 return (gettext("\tget <\"all\" | property[,...]> "
 235                     "<pool> ...\n"));
 236         case HELP_SET:
 237                 return (gettext("\tset <property=value> <pool> \n"));
 238         case HELP_KEY:
 239                 return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
 240                     "<-a | pool>\n"));
 241         }
 242 
 243         abort();
 244         /* NOTREACHED */
 245 }
 246 
 247 
 248 /*
 249  * Callback routine that will print out a pool property value.
 250  */
 251 static int
 252 print_prop_cb(int prop, void *cb)
 253 {
 254         FILE *fp = cb;
 255 
 256         (void) fprintf(fp, "\t%-13s  ", zpool_prop_to_name(prop));
 257 
 258         if (zpool_prop_readonly(prop))
 259                 (void) fprintf(fp, "  NO   ");
 260         else


 798         nvlist_free(props);
 799         return (ret);
 800 badusage:
 801         nvlist_free(fsprops);
 802         nvlist_free(props);
 803         usage(B_FALSE);
 804         return (2);
 805 }
 806 
 807 /*
 808  * zpool destroy <pool>
 809  *
 810  *      -f      Forcefully unmount any datasets
 811  *
 812  * Destroy the given pool.  Automatically unmounts any datasets in the pool.
 813  */
 814 int
 815 zpool_do_destroy(int argc, char **argv)
 816 {
 817         boolean_t force = B_FALSE;
 818         boolean_t encrypted_only = B_FALSE;
 819         int c;
 820         char *pool;
 821         zpool_handle_t *zhp;
 822         int ret;
 823 
 824         /* check options */
 825         while ((c = getopt(argc, argv, "f")) != -1) {
 826                 switch (c) {
 827                 case 'f':
 828                         force = B_TRUE;
 829                         break;
 830                 case '?':
 831                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 832                             optopt);
 833                         usage(B_FALSE);
 834                 }
 835         }
 836 
 837         argc -= optind;
 838         argv += optind;


 843                 usage(B_FALSE);
 844         }
 845         if (argc > 1) {
 846                 (void) fprintf(stderr, gettext("too many arguments\n"));
 847                 usage(B_FALSE);
 848         }
 849 
 850         pool = argv[0];
 851 
 852         if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
 853                 /*
 854                  * As a special case, check for use of '/' in the name, and
 855                  * direct the user to use 'zfs destroy' instead.
 856                  */
 857                 if (strchr(pool, '/') != NULL)
 858                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
 859                             "destroy a dataset\n"));
 860                 return (1);
 861         }
 862 
 863         if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
 864                 (void) fprintf(stderr, gettext("could not destroy '%s': "
 865                     "could not unmount datasets\n"), zpool_get_name(zhp));
 866                 return (1);
 867         }
 868 
 869         ret = (zpool_destroy(zhp) != 0);
 870 
 871         zpool_close(zhp);
 872 
 873         return (ret);
 874 }
 875 
 876 /*
 877  * zpool export [-f] <pool> ...
 878  *
 879  *      -f      Forcefully unmount datasets
 880  *
 881  * Export the given pools.  By default, the command will attempt to cleanly
 882  * unmount any active datasets within the pool.  If the '-f' flag is specified,
 883  * then the datasets will be forcefully unmounted.
 884  */
 885 int
 886 zpool_do_export(int argc, char **argv)
 887 {
 888         boolean_t force = B_FALSE;
 889         boolean_t hardforce = B_FALSE;
 890         boolean_t encrypted_only = B_FALSE;
 891         int c;
 892         zpool_handle_t *zhp;
 893         int ret;
 894         int i;
 895 
 896         /* check options */
 897         while ((c = getopt(argc, argv, "fF")) != -1) {
 898                 switch (c) {
 899                 case 'f':
 900                         force = B_TRUE;
 901                         break;
 902                 case 'F':
 903                         hardforce = B_TRUE;
 904                         break;
 905                 case '?':
 906                         (void) fprintf(stderr, gettext("invalid option '%c'\n"),
 907                             optopt);
 908                         usage(B_FALSE);
 909                 }
 910         }
 911 
 912         argc -= optind;
 913         argv += optind;
 914 
 915         /* check arguments */
 916         if (argc < 1) {
 917                 (void) fprintf(stderr, gettext("missing pool argument\n"));
 918                 usage(B_FALSE);
 919         }
 920 
 921         ret = 0;
 922         for (i = 0; i < argc; i++) {
 923                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
 924                         ret = 1;
 925                         continue;
 926                 }
 927 
 928                 if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
 929                         ret = 1;
 930                         zpool_close(zhp);
 931                         continue;
 932                 }
 933 
 934                 if (hardforce) {
 935                         if (zpool_export_force(zhp) != 0)
 936                                 ret = 1;
 937                 } else if (zpool_export(zhp, force) != 0) {
 938                         ret = 1;
 939                 }
 940 
 941                 zpool_close(zhp);
 942         }
 943 
 944         return (ret);
 945 }
 946 
 947 /*
 948  * Given a vdev configuration, determine the maximum width needed for the device


1256                 (void) printf(gettext("\tlogs\n"));
1257                 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1258         }
1259 
1260         if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1261                 (void) printf(gettext("\n\tAdditional devices are known to "
1262                     "be part of this pool, though their\n\texact "
1263                     "configuration cannot be determined.\n"));
1264         }
1265 }
1266 
1267 /*
1268  * Perform the import for the given configuration.  This passes the heavy
1269  * lifting off to zpool_import_props(), and then mounts the datasets contained
1270  * within the pool.
1271  */
1272 static int
1273 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1274     int force, nvlist_t *props, boolean_t allowfaulted)
1275 {
1276         boolean_t encrypted_only = B_FALSE;
1277         zpool_handle_t *zhp;
1278         char *name;
1279         uint64_t state;
1280         uint64_t version;
1281         int error = 0;
1282 
1283         verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1284             &name) == 0);
1285 
1286         verify(nvlist_lookup_uint64(config,
1287             ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1288         verify(nvlist_lookup_uint64(config,
1289             ZPOOL_CONFIG_VERSION, &version) == 0);
1290         if (version > SPA_VERSION) {
1291                 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1292                     "is formatted using a newer ZFS version\n"), name);
1293                 return (1);
1294         } else if (state != POOL_STATE_EXPORTED && !force) {
1295                 uint64_t hostid;
1296 


1317                                 return (1);
1318                         }
1319                 } else {
1320                         (void) fprintf(stderr, gettext("cannot import '%s': "
1321                             "pool may be in use from other system\n"), name);
1322                         (void) fprintf(stderr, gettext("use '-f' to import "
1323                             "anyway\n"));
1324                         return (1);
1325                 }
1326         }
1327 
1328         if (zpool_import_props(g_zfs, config, newname, props,
1329             allowfaulted) != 0)
1330                 return (1);
1331 
1332         if (newname != NULL)
1333                 name = (char *)newname;
1334 
1335         verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1336 
1337         /*
1338          * Attempt to load the crypto keys before mounting up the datasets
1339          * Note that depending on the value of the keysource property
1340          * this could cause us to go interactive.
1341          * We don't mind if this falls though and continue to enable what
1342          * datasets we can if it does.
1343          *
1344          * Use zpool_load_key() and tell it we are doing an import rather than
1345          * zpool_cmd_key_load().
1346          *
1347          * We then attempt enable all datasets not just the encrypted ones.
1348          */
1349 
1350         error = zpool_load_key(zhp, B_TRUE);
1351         if (error != 0 && error != ENOTSUP) {
1352                 libzfs_handle_t *zpool_hdl = zpool_get_handle(zhp);
1353                 (void) fprintf(stderr, gettext(
1354                     "%s.\nEncrypted datasets with keyscope=pool "
1355                     "will not be mounted.\n"),
1356                     libzfs_error_description(zpool_hdl));
1357         }
1358 
1359         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1360             zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
1361                 zpool_close(zhp);
1362                 return (1);
1363         }
1364 
1365         zpool_close(zhp);
1366         return (0);
1367 }
1368 
1369 /*
1370  * zpool import [-d dir] [-D]
1371  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1372  *              [-d dir | -c cachefile] [-f] -a
1373  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1374  *              [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1375  *
1376  *       -c     Read pool information from a cachefile instead of searching
1377  *              devices.
1378  *
1379  *       -d     Scan in a specific directory, other than /dev/dsk.  More than
1380  *              one directory can be specified using multiple '-d' options.
1381  *
1382  *       -D     Scan for previously destroyed pools or import all or only
1383  *              specified destroyed pools.
1384  *
1385  *       -R     Temporarily import the pool, with all mountpoints relative to
1386  *              the given root.  The pool will remain exported when the machine


3006  *      reason: One or more devices ...
3007  *         see: http://www.sun.com/msg/ZFS-xxxx-01
3008  *      config:
3009  *              mirror          DEGRADED
3010  *                c1t0d0        OK
3011  *                c2t0d0        UNAVAIL
3012  *
3013  * When given the '-v' option, we print out the complete config.  If the '-e'
3014  * option is specified, then we print out error rate information as well.
3015  */
3016 int
3017 status_callback(zpool_handle_t *zhp, void *data)
3018 {
3019         status_cbdata_t *cbp = data;
3020         nvlist_t *config, *nvroot;
3021         char *msgid;
3022         int reason;
3023         const char *health;
3024         uint_t c;
3025         vdev_stat_t *vs;
3026         char keystatus[MAXNAMELEN];
3027         zprop_source_t srctype;
3028 
3029         config = zpool_get_config(zhp, NULL);
3030         reason = zpool_get_status(zhp, &msgid);
3031 
3032         cbp->cb_count++;
3033 
3034         /*
3035          * If we were given 'zpool status -x', only report those pools with
3036          * problems.
3037          */
3038         if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3039                 if (!cbp->cb_allpools) {
3040                         (void) printf(gettext("pool '%s' is healthy\n"),
3041                             zpool_get_name(zhp));
3042                         if (cbp->cb_first)
3043                                 cbp->cb_first = B_FALSE;
3044                 }
3045                 return (0);
3046         }
3047 
3048         if (cbp->cb_first)
3049                 cbp->cb_first = B_FALSE;
3050         else
3051                 (void) printf("\n");
3052 
3053         verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3054             &nvroot) == 0);
3055         verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3056             (uint64_t **)&vs, &c) == 0);
3057         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3058 
3059         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3060         (void) printf(gettext(" state: %s\n"), health);
3061 
3062         (void) zpool_get_prop(zhp, ZPOOL_PROP_KEYSTATUS, keystatus,
3063             sizeof (keystatus), &srctype);
3064 
3065         (void) printf(gettext("   key: %s\n"), keystatus);
3066 
3067         switch (reason) {
3068         case ZPOOL_STATUS_MISSING_DEV_R:
3069                 (void) printf(gettext("status: One or more devices could not "
3070                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
3071                     "continue functioning in a degraded state.\n"));
3072                 (void) printf(gettext("action: Attach the missing device and "
3073                     "online it using 'zpool online'.\n"));
3074                 break;
3075 
3076         case ZPOOL_STATUS_MISSING_DEV_NR:
3077                 (void) printf(gettext("status: One or more devices could not "
3078                     "be opened.  There are insufficient\n\treplicas for the "
3079                     "pool to continue functioning.\n"));
3080                 (void) printf(gettext("action: Attach the missing device and "
3081                     "online it using 'zpool online'.\n"));
3082                 break;
3083 
3084         case ZPOOL_STATUS_CORRUPT_LABEL_R:
3085                 (void) printf(gettext("status: One or more devices could not "
3086                     "be used because the label is missing or\n\tinvalid.  "


3520                     "---------------\n");
3521                 (void) printf(gettext(" 1   Initial ZFS version\n"));
3522                 (void) printf(gettext(" 2   Ditto blocks "
3523                     "(replicated metadata)\n"));
3524                 (void) printf(gettext(" 3   Hot spares and double parity "
3525                     "RAID-Z\n"));
3526                 (void) printf(gettext(" 4   zpool history\n"));
3527                 (void) printf(gettext(" 5   Compression using the gzip "
3528                     "algorithm\n"));
3529                 (void) printf(gettext(" 6   bootfs pool property\n"));
3530                 (void) printf(gettext(" 7   Separate intent log devices\n"));
3531                 (void) printf(gettext(" 8   Delegated administration\n"));
3532                 (void) printf(gettext(" 9   refquota and refreservation "
3533                     "properties\n"));
3534                 (void) printf(gettext(" 10  Cache devices\n"));
3535                 (void) printf(gettext(" 11  Improved scrub performance\n"));
3536                 (void) printf(gettext(" 12  Snapshot properties\n"));
3537                 (void) printf(gettext(" 13  snapused property\n"));
3538                 (void) printf(gettext(" 14  passthrough-x aclinherit "
3539                     "support\n"));
3540                 (void) printf(gettext(" 15  Cryptographic support.\n"));
3541                 (void) printf(gettext("For more information on a particular "
3542                     "version, including supported releases, see:\n\n"));
3543                 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3544                     "version/N\n\n");
3545                 (void) printf(gettext("Where 'N' is the version number.\n"));
3546         } else if (argc == 0) {
3547                 int notfound;
3548 
3549                 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3550                 notfound = cb.cb_first;
3551 
3552                 if (!cb.cb_all && ret == 0) {
3553                         if (!cb.cb_first)
3554                                 (void) printf("\n");
3555                         cb.cb_first = B_TRUE;
3556                         cb.cb_newer = B_TRUE;
3557                         ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3558                         if (!cb.cb_first) {
3559                                 notfound = B_FALSE;
3560                                 (void) printf("\n");


3606         "destroy",
3607         "destroy_begin_sync",
3608         "inherit",
3609         "property set",
3610         "quota set",
3611         "permission update",
3612         "permission remove",
3613         "permission who remove",
3614         "promote",
3615         "receive",
3616         "rename",
3617         "reservation set",
3618         "replay_inc_sync",
3619         "replay_full_sync",
3620         "rollback",
3621         "snapshot",
3622         "filesystem version upgrade",
3623         "refquota set",
3624         "refreservation set",
3625         "pool scrub done",
3626         "crypto key create",
3627 };
3628 
3629 /*
3630  * Print out the command history for a specific pool.
3631  */
3632 static int
3633 get_history_one(zpool_handle_t *zhp, void *data)
3634 {
3635         nvlist_t *nvhis;
3636         nvlist_t **records;
3637         uint_t numrecords;
3638         char *cmdstr;
3639         char *pathstr;
3640         uint64_t dst_time;
3641         time_t tsec;
3642         struct tm t;
3643         char tbuf[30];
3644         int ret, i;
3645         uint64_t who;
3646         struct passwd *pwd;


3836                 zprop_free_list(fake_name.pl_next);
3837         else
3838                 zprop_free_list(cb.cb_proplist);
3839 
3840         return (ret);
3841 }
3842 
3843 typedef struct set_cbdata {
3844         char *cb_propname;
3845         char *cb_value;
3846         boolean_t cb_any_successful;
3847 } set_cbdata_t;
3848 
3849 int
3850 set_callback(zpool_handle_t *zhp, void *data)
3851 {
3852         int error;
3853         set_cbdata_t *cb = (set_cbdata_t *)data;
3854 
3855         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);

3856         if (!error)
3857                 cb->cb_any_successful = B_TRUE;
3858 
3859         return (error);
3860 }
3861 
3862 int
3863 zpool_do_set(int argc, char **argv)
3864 {
3865         set_cbdata_t cb = { 0 };
3866         int error;
3867 
3868         if (argc > 1 && argv[1][0] == '-') {
3869                 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3870                     argv[1][1]);
3871                 usage(B_FALSE);
3872         }
3873 
3874         if (argc < 2) {
3875                 (void) fprintf(stderr, gettext("missing property=value "


3887                 usage(B_FALSE);
3888         }
3889 
3890         cb.cb_propname = argv[1];
3891         cb.cb_value = strchr(cb.cb_propname, '=');
3892         if (cb.cb_value == NULL) {
3893                 (void) fprintf(stderr, gettext("missing value in "
3894                     "property=value argument\n"));
3895                 usage(B_FALSE);
3896         }
3897 
3898         *(cb.cb_value) = '\0';
3899         cb.cb_value++;
3900 
3901         error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3902             set_callback, &cb);
3903 
3904         return (error);
3905 }
3906 
3907 
3908 static int
3909 /* LINTED E_FUNC_ARG_UNUSED */
3910 key_callback_load(zpool_handle_t *zhp, void *data)
3911 {
3912         int ret;
3913         if (zpool_keysource_prompt(zhp)) {
3914                 char *smf_fmri = getenv("SMF_FMRI");
3915 
3916                 if (smf_fmri != NULL &&
3917                     strcmp(smf_fmri, "svc:/system/device/local") == 0) {
3918                         return (0);
3919                 }
3920         }
3921         ret = zpool_cmd_key_load(zhp);
3922         if (ret != 0 && !(ret == EEXIST || ret == ENOTSUP)) {
3923                 return (1);
3924         }
3925 
3926         return (0);
3927 }
3928 
3929 static int
3930 /* LINTED E_FUNC_ARG_UNUSED */
3931 key_callback_unload(zpool_handle_t *zhp, void *data)
3932 {
3933         int ret;
3934 
3935         ret = zpool_cmd_key_unload(zhp);
3936         if (ret != 0 && !(ret == ENOENT || ret == ENOTSUP)) {
3937                 return (1);
3938         }
3939 
3940         return (0);
3941 }
3942 
3943 
3944 static int
3945 zpool_do_key(int argc, char **argv)
3946 {
3947         int error = 1, options = 0;
3948         nvlist_t *props = NULL;
3949         char c, *propval = NULL;
3950         boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
3951         boolean_t do_all = B_FALSE;
3952         zpool_handle_t *zhp = NULL;
3953 
3954         while ((c = getopt(argc, argv, "aluco:")) != -1) {
3955                 switch (c) {
3956                 case 'a':
3957                         do_all = B_TRUE;
3958                         break;
3959 
3960                 case 'l':
3961                         load = B_TRUE;
3962                         break;
3963 
3964                 case 'u':
3965                         unload = B_TRUE;
3966                         break;
3967 
3968                 case 'c':
3969                         change = B_TRUE;
3970                         break;
3971 
3972                 case 'o':
3973                         if ((propval = strchr(optarg, '=')) == NULL) {
3974                                 (void) fprintf(stderr, gettext("missing "
3975                                     "'=' for -o option\n"));
3976                                 return (error);
3977                         }
3978 
3979                         *propval = '\0';
3980                         propval++;
3981                         if (strcmp(optarg, "keysource") != 0) {
3982                                 (void) fprintf(stderr, gettext(
3983                                     "Invalid property for key change: "
3984                                     "\"%s\"\n"),
3985                                     optarg);
3986                                 return (error);
3987                         }
3988                         if (add_prop_list(optarg, propval, &props, B_TRUE))
3989                                 return (error);
3990 
3991                         options += 2;
3992                         break;
3993 
3994                 }
3995         }
3996 
3997         if (!change && props != NULL) {
3998                 (void) fprintf(stderr, gettext("Properties are not allowed to "
3999                     "be used in this command.\n"));
4000                 goto error;
4001         }
4002 
4003         if (((load || unload) && (argc > 3)) ||
4004             (change && ((argc - options) > 3))) {
4005                         (void) fprintf(stderr,
4006                             gettext("too many arguments\n"));
4007                         usage(B_FALSE);
4008                         goto error;
4009         } else if ((load || unload) && (argc < 3)) {
4010                         (void) fprintf(stderr, gettext("missing dataset "
4011                             "argument (specify -a for all)\n"));
4012                         usage(B_FALSE);
4013                         goto error;
4014         } else if (change && ((argc - options) < 3)) {
4015                         (void) fprintf(stderr, gettext("missing dataset "
4016                             "argument\n"));
4017                         usage(B_FALSE);
4018                         goto error;
4019         }
4020 
4021         if (do_all == B_FALSE) {
4022                 zhp = zpool_open(g_zfs, argv[argc - 1]);
4023                 if (zhp == NULL)
4024                         goto error;
4025         }
4026 
4027         if (load) {
4028                 if (do_all)
4029                         error = for_each_pool(0, NULL, B_TRUE, NULL,
4030                             key_callback_load, NULL);
4031                 else
4032                         error = zpool_cmd_key_load(zhp);
4033 
4034         } else if (unload) {
4035                 if (do_all)
4036                         error = for_each_pool(0, NULL, B_TRUE, NULL,
4037                             key_callback_unload, NULL);
4038                 else
4039                         error = zpool_cmd_key_unload(zhp);
4040 
4041         } else if (change) {
4042                 if (do_all) {
4043                         (void) fprintf(stderr, gettext("cannot use '-a' with "
4044                             "change operation.\n"));
4045                         usage(B_FALSE);
4046                         goto error;
4047                 }
4048 
4049                 error = zpool_cmd_key_change(zhp, props);
4050 
4051         } else
4052                 usage(B_FALSE);
4053 
4054         if (zhp != NULL && !do_all)
4055                 zpool_close(zhp);
4056 
4057 error:
4058         nvlist_free(props);
4059         if (error != 0)
4060                 return (1);
4061         return (0);
4062 }
4063 
4064 static int
4065 find_command_idx(char *command, int *idx)
4066 {
4067         int i;
4068 
4069         for (i = 0; i < NCOMMAND; i++) {
4070                 if (command_table[i].name == NULL)
4071                         continue;
4072 
4073                 if (strcmp(command, command_table[i].name) == 0) {
4074                         *idx = i;
4075                         return (0);
4076                 }
4077         }
4078         return (1);
4079 }
4080 
4081 int
4082 main(int argc, char **argv)
4083 {