Print this page


Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zpool/zpool_main.c
          +++ new/usr/src/cmd/zpool/zpool_main.c
↓ open down ↓ 72 lines elided ↑ open up ↑
  73   73  static int zpool_do_import(int, char **);
  74   74  static int zpool_do_export(int, char **);
  75   75  
  76   76  static int zpool_do_upgrade(int, char **);
  77   77  
  78   78  static int zpool_do_history(int, char **);
  79   79  
  80   80  static int zpool_do_get(int, char **);
  81   81  static int zpool_do_set(int, char **);
  82   82  
       83 +static int zpool_do_key(int, char **);
       84 +
  83   85  /*
  84   86   * These libumem hooks provide a reasonable set of defaults for the allocator's
  85   87   * debugging facilities.
  86   88   */
  87   89  
  88   90  #ifdef DEBUG
  89   91  const char *
  90   92  _umem_debug_init(void)
  91   93  {
  92   94          return ("default,verbose"); /* $UMEM_DEBUG setting */
↓ open down ↓ 19 lines elided ↑ open up ↑
 112  114          HELP_IOSTAT,
 113  115          HELP_LIST,
 114  116          HELP_OFFLINE,
 115  117          HELP_ONLINE,
 116  118          HELP_REPLACE,
 117  119          HELP_REMOVE,
 118  120          HELP_SCRUB,
 119  121          HELP_STATUS,
 120  122          HELP_UPGRADE,
 121  123          HELP_GET,
 122      -        HELP_SET
      124 +        HELP_SET,
      125 +        HELP_KEY
 123  126  } zpool_help_t;
 124  127  
 125  128  
 126  129  typedef struct zpool_command {
 127  130          const char      *name;
 128  131          int             (*func)(int, char **);
 129  132          zpool_help_t    usage;
 130  133  } zpool_command_t;
 131  134  
 132  135  /*
↓ open down ↓ 26 lines elided ↑ open up ↑
 159  162          { NULL },
 160  163          { "scrub",      zpool_do_scrub,         HELP_SCRUB              },
 161  164          { NULL },
 162  165          { "import",     zpool_do_import,        HELP_IMPORT             },
 163  166          { "export",     zpool_do_export,        HELP_EXPORT             },
 164  167          { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
 165  168          { NULL },
 166  169          { "history",    zpool_do_history,       HELP_HISTORY            },
 167  170          { "get",        zpool_do_get,           HELP_GET                },
 168  171          { "set",        zpool_do_set,           HELP_SET                },
      172 +        { NULL },
      173 +        { "key",        zpool_do_key,           HELP_KEY                },
 169  174  };
 170  175  
 171  176  #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 172  177  
 173  178  zpool_command_t *current_command;
 174  179  static char history_str[HIS_MAX_RECORD_LEN];
 175  180  
 176  181  static const char *
 177  182  get_usage(zpool_help_t idx) {
 178  183          switch (idx) {
↓ open down ↓ 44 lines elided ↑ open up ↑
 223  228                  return (gettext("\tstatus [-vx] [pool] ...\n"));
 224  229          case HELP_UPGRADE:
 225  230                  return (gettext("\tupgrade\n"
 226  231                      "\tupgrade -v\n"
 227  232                      "\tupgrade [-V version] <-a | pool ...>\n"));
 228  233          case HELP_GET:
 229  234                  return (gettext("\tget <\"all\" | property[,...]> "
 230  235                      "<pool> ...\n"));
 231  236          case HELP_SET:
 232  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"));
 233  241          }
 234  242  
 235  243          abort();
 236  244          /* NOTREACHED */
 237  245  }
 238  246  
 239  247  
 240  248  /*
 241  249   * Callback routine that will print out a pool property value.
 242  250   */
↓ open down ↓ 557 lines elided ↑ open up ↑
 800  808   * zpool destroy <pool>
 801  809   *
 802  810   *      -f      Forcefully unmount any datasets
 803  811   *
 804  812   * Destroy the given pool.  Automatically unmounts any datasets in the pool.
 805  813   */
 806  814  int
 807  815  zpool_do_destroy(int argc, char **argv)
 808  816  {
 809  817          boolean_t force = B_FALSE;
      818 +        boolean_t encrypted_only = B_FALSE;
 810  819          int c;
 811  820          char *pool;
 812  821          zpool_handle_t *zhp;
 813  822          int ret;
 814  823  
 815  824          /* check options */
 816  825          while ((c = getopt(argc, argv, "f")) != -1) {
 817  826                  switch (c) {
 818  827                  case 'f':
 819  828                          force = B_TRUE;
↓ open down ↓ 24 lines elided ↑ open up ↑
 844  853                  /*
 845  854                   * As a special case, check for use of '/' in the name, and
 846  855                   * direct the user to use 'zfs destroy' instead.
 847  856                   */
 848  857                  if (strchr(pool, '/') != NULL)
 849  858                          (void) fprintf(stderr, gettext("use 'zfs destroy' to "
 850  859                              "destroy a dataset\n"));
 851  860                  return (1);
 852  861          }
 853  862  
 854      -        if (zpool_disable_datasets(zhp, force) != 0) {
      863 +        if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
 855  864                  (void) fprintf(stderr, gettext("could not destroy '%s': "
 856  865                      "could not unmount datasets\n"), zpool_get_name(zhp));
 857  866                  return (1);
 858  867          }
 859  868  
 860  869          ret = (zpool_destroy(zhp) != 0);
 861  870  
 862  871          zpool_close(zhp);
 863  872  
 864  873          return (ret);
↓ open down ↓ 6 lines elided ↑ open up ↑
 871  880   *
 872  881   * Export the given pools.  By default, the command will attempt to cleanly
 873  882   * unmount any active datasets within the pool.  If the '-f' flag is specified,
 874  883   * then the datasets will be forcefully unmounted.
 875  884   */
 876  885  int
 877  886  zpool_do_export(int argc, char **argv)
 878  887  {
 879  888          boolean_t force = B_FALSE;
 880  889          boolean_t hardforce = B_FALSE;
      890 +        boolean_t encrypted_only = B_FALSE;
 881  891          int c;
 882  892          zpool_handle_t *zhp;
 883  893          int ret;
 884  894          int i;
 885  895  
 886  896          /* check options */
 887  897          while ((c = getopt(argc, argv, "fF")) != -1) {
 888  898                  switch (c) {
 889  899                  case 'f':
 890  900                          force = B_TRUE;
↓ open down ↓ 17 lines elided ↑ open up ↑
 908  918                  usage(B_FALSE);
 909  919          }
 910  920  
 911  921          ret = 0;
 912  922          for (i = 0; i < argc; i++) {
 913  923                  if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
 914  924                          ret = 1;
 915  925                          continue;
 916  926                  }
 917  927  
 918      -                if (zpool_disable_datasets(zhp, force) != 0) {
      928 +                if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
 919  929                          ret = 1;
 920  930                          zpool_close(zhp);
 921  931                          continue;
 922  932                  }
 923  933  
 924  934                  if (hardforce) {
 925  935                          if (zpool_export_force(zhp) != 0)
 926  936                                  ret = 1;
 927  937                  } else if (zpool_export(zhp, force) != 0) {
 928  938                          ret = 1;
↓ open down ↓ 327 lines elided ↑ open up ↑
1256 1266  
1257 1267  /*
1258 1268   * Perform the import for the given configuration.  This passes the heavy
1259 1269   * lifting off to zpool_import_props(), and then mounts the datasets contained
1260 1270   * within the pool.
1261 1271   */
1262 1272  static int
1263 1273  do_import(nvlist_t *config, const char *newname, const char *mntopts,
1264 1274      int force, nvlist_t *props, boolean_t allowfaulted)
1265 1275  {
     1276 +        boolean_t encrypted_only = B_FALSE;
1266 1277          zpool_handle_t *zhp;
1267 1278          char *name;
1268 1279          uint64_t state;
1269 1280          uint64_t version;
1270 1281          int error = 0;
1271 1282  
1272 1283          verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1273 1284              &name) == 0);
1274 1285  
1275 1286          verify(nvlist_lookup_uint64(config,
↓ open down ↓ 40 lines elided ↑ open up ↑
1316 1327  
1317 1328          if (zpool_import_props(g_zfs, config, newname, props,
1318 1329              allowfaulted) != 0)
1319 1330                  return (1);
1320 1331  
1321 1332          if (newname != NULL)
1322 1333                  name = (char *)newname;
1323 1334  
1324 1335          verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1325 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 +
1326 1359          if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1327      -            zpool_enable_datasets(zhp, mntopts, 0) != 0) {
     1360 +            zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
1328 1361                  zpool_close(zhp);
1329 1362                  return (1);
1330 1363          }
1331 1364  
1332 1365          zpool_close(zhp);
1333      -        return (error);
     1366 +        return (0);
1334 1367  }
1335 1368  
1336 1369  /*
1337 1370   * zpool import [-d dir] [-D]
1338 1371   *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1339 1372   *              [-d dir | -c cachefile] [-f] -a
1340 1373   *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1341 1374   *              [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1342 1375   *
1343 1376   *       -c     Read pool information from a cachefile instead of searching
↓ open down ↓ 1639 lines elided ↑ open up ↑
2983 3016  int
2984 3017  status_callback(zpool_handle_t *zhp, void *data)
2985 3018  {
2986 3019          status_cbdata_t *cbp = data;
2987 3020          nvlist_t *config, *nvroot;
2988 3021          char *msgid;
2989 3022          int reason;
2990 3023          const char *health;
2991 3024          uint_t c;
2992 3025          vdev_stat_t *vs;
     3026 +        char keystatus[MAXNAMELEN];
     3027 +        zprop_source_t srctype;
2993 3028  
2994 3029          config = zpool_get_config(zhp, NULL);
2995 3030          reason = zpool_get_status(zhp, &msgid);
2996 3031  
2997 3032          cbp->cb_count++;
2998 3033  
2999 3034          /*
3000 3035           * If we were given 'zpool status -x', only report those pools with
3001 3036           * problems.
3002 3037           */
↓ open down ↓ 14 lines elided ↑ open up ↑
3017 3052  
3018 3053          verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3019 3054              &nvroot) == 0);
3020 3055          verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3021 3056              (uint64_t **)&vs, &c) == 0);
3022 3057          health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3023 3058  
3024 3059          (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
3025 3060          (void) printf(gettext(" state: %s\n"), health);
3026 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 +
3027 3067          switch (reason) {
3028 3068          case ZPOOL_STATUS_MISSING_DEV_R:
3029 3069                  (void) printf(gettext("status: One or more devices could not "
3030 3070                      "be opened.  Sufficient replicas exist for\n\tthe pool to "
3031 3071                      "continue functioning in a degraded state.\n"));
3032 3072                  (void) printf(gettext("action: Attach the missing device and "
3033 3073                      "online it using 'zpool online'.\n"));
3034 3074                  break;
3035 3075  
3036 3076          case ZPOOL_STATUS_MISSING_DEV_NR:
↓ open down ↓ 453 lines elided ↑ open up ↑
3490 3530                  (void) printf(gettext(" 7   Separate intent log devices\n"));
3491 3531                  (void) printf(gettext(" 8   Delegated administration\n"));
3492 3532                  (void) printf(gettext(" 9   refquota and refreservation "
3493 3533                      "properties\n"));
3494 3534                  (void) printf(gettext(" 10  Cache devices\n"));
3495 3535                  (void) printf(gettext(" 11  Improved scrub performance\n"));
3496 3536                  (void) printf(gettext(" 12  Snapshot properties\n"));
3497 3537                  (void) printf(gettext(" 13  snapused property\n"));
3498 3538                  (void) printf(gettext(" 14  passthrough-x aclinherit "
3499 3539                      "support\n"));
     3540 +                (void) printf(gettext(" 15  Cryptographic support.\n"));
3500 3541                  (void) printf(gettext("For more information on a particular "
3501 3542                      "version, including supported releases, see:\n\n"));
3502 3543                  (void) printf("http://www.opensolaris.org/os/community/zfs/"
3503 3544                      "version/N\n\n");
3504 3545                  (void) printf(gettext("Where 'N' is the version number.\n"));
3505 3546          } else if (argc == 0) {
3506 3547                  int notfound;
3507 3548  
3508 3549                  ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3509 3550                  notfound = cb.cb_first;
↓ open down ↓ 65 lines elided ↑ open up ↑
3575 3616          "rename",
3576 3617          "reservation set",
3577 3618          "replay_inc_sync",
3578 3619          "replay_full_sync",
3579 3620          "rollback",
3580 3621          "snapshot",
3581 3622          "filesystem version upgrade",
3582 3623          "refquota set",
3583 3624          "refreservation set",
3584 3625          "pool scrub done",
     3626 +        "crypto key create",
3585 3627  };
3586 3628  
3587 3629  /*
3588 3630   * Print out the command history for a specific pool.
3589 3631   */
3590 3632  static int
3591 3633  get_history_one(zpool_handle_t *zhp, void *data)
3592 3634  {
3593 3635          nvlist_t *nvhis;
3594 3636          nvlist_t **records;
↓ open down ↓ 209 lines elided ↑ open up ↑
3804 3846          boolean_t cb_any_successful;
3805 3847  } set_cbdata_t;
3806 3848  
3807 3849  int
3808 3850  set_callback(zpool_handle_t *zhp, void *data)
3809 3851  {
3810 3852          int error;
3811 3853          set_cbdata_t *cb = (set_cbdata_t *)data;
3812 3854  
3813 3855          error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3814      -
3815 3856          if (!error)
3816 3857                  cb->cb_any_successful = B_TRUE;
3817 3858  
3818 3859          return (error);
3819 3860  }
3820 3861  
3821 3862  int
3822 3863  zpool_do_set(int argc, char **argv)
3823 3864  {
3824 3865          set_cbdata_t cb = { 0 };
↓ open down ↓ 31 lines elided ↑ open up ↑
3856 3897  
3857 3898          *(cb.cb_value) = '\0';
3858 3899          cb.cb_value++;
3859 3900  
3860 3901          error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3861 3902              set_callback, &cb);
3862 3903  
3863 3904          return (error);
3864 3905  }
3865 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 +
3866 4064  static int
3867 4065  find_command_idx(char *command, int *idx)
3868 4066  {
3869 4067          int i;
3870 4068  
3871 4069          for (i = 0; i < NCOMMAND; i++) {
3872 4070                  if (command_table[i].name == NULL)
3873 4071                          continue;
3874 4072  
3875 4073                  if (strcmp(command, command_table[i].name) == 0) {
↓ open down ↓ 84 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX