Print this page
@@ -78,10 +78,12 @@
static int zpool_do_history(int, char **);
static int zpool_do_get(int, char **);
static int zpool_do_set(int, char **);
+static int zpool_do_key(int, char **);
+
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
* debugging facilities.
*/
@@ -117,11 +119,12 @@
HELP_REMOVE,
HELP_SCRUB,
HELP_STATUS,
HELP_UPGRADE,
HELP_GET,
- HELP_SET
+ HELP_SET,
+ HELP_KEY
} zpool_help_t;
typedef struct zpool_command {
const char *name;
@@ -164,10 +167,12 @@
{ "upgrade", zpool_do_upgrade, HELP_UPGRADE },
{ NULL },
{ "history", zpool_do_history, HELP_HISTORY },
{ "get", zpool_do_get, HELP_GET },
{ "set", zpool_do_set, HELP_SET },
+ { NULL },
+ { "key", zpool_do_key, HELP_KEY },
};
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
zpool_command_t *current_command;
@@ -228,10 +233,13 @@
case HELP_GET:
return (gettext("\tget <\"all\" | property[,...]> "
"<pool> ...\n"));
case HELP_SET:
return (gettext("\tset <property=value> <pool> \n"));
+ case HELP_KEY:
+ return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
+ "<-a | pool>\n"));
}
abort();
/* NOTREACHED */
}
@@ -805,10 +813,11 @@
*/
int
zpool_do_destroy(int argc, char **argv)
{
boolean_t force = B_FALSE;
+ boolean_t encrypted_only = B_FALSE;
int c;
char *pool;
zpool_handle_t *zhp;
int ret;
@@ -849,11 +858,11 @@
(void) fprintf(stderr, gettext("use 'zfs destroy' to "
"destroy a dataset\n"));
return (1);
}
- if (zpool_disable_datasets(zhp, force) != 0) {
+ if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
(void) fprintf(stderr, gettext("could not destroy '%s': "
"could not unmount datasets\n"), zpool_get_name(zhp));
return (1);
}
@@ -876,10 +885,11 @@
int
zpool_do_export(int argc, char **argv)
{
boolean_t force = B_FALSE;
boolean_t hardforce = B_FALSE;
+ boolean_t encrypted_only = B_FALSE;
int c;
zpool_handle_t *zhp;
int ret;
int i;
@@ -913,11 +923,11 @@
if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
ret = 1;
continue;
}
- if (zpool_disable_datasets(zhp, force) != 0) {
+ if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
ret = 1;
zpool_close(zhp);
continue;
}
@@ -1261,10 +1271,11 @@
*/
static int
do_import(nvlist_t *config, const char *newname, const char *mntopts,
int force, nvlist_t *props, boolean_t allowfaulted)
{
+ boolean_t encrypted_only = B_FALSE;
zpool_handle_t *zhp;
char *name;
uint64_t state;
uint64_t version;
int error = 0;
@@ -1321,18 +1332,40 @@
if (newname != NULL)
name = (char *)newname;
verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
+ /*
+ * Attempt to load the crypto keys before mounting up the datasets
+ * Note that depending on the value of the keysource property
+ * this could cause us to go interactive.
+ * We don't mind if this falls though and continue to enable what
+ * datasets we can if it does.
+ *
+ * Use zpool_load_key() and tell it we are doing an import rather than
+ * zpool_cmd_key_load().
+ *
+ * We then attempt enable all datasets not just the encrypted ones.
+ */
+
+ error = zpool_load_key(zhp, B_TRUE);
+ if (error != 0 && error != ENOTSUP) {
+ libzfs_handle_t *zpool_hdl = zpool_get_handle(zhp);
+ (void) fprintf(stderr, gettext(
+ "%s.\nEncrypted datasets with keyscope=pool "
+ "will not be mounted.\n"),
+ libzfs_error_description(zpool_hdl));
+ }
+
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
- zpool_enable_datasets(zhp, mntopts, 0) != 0) {
+ zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
zpool_close(zhp);
return (1);
}
zpool_close(zhp);
- return (error);
+ return (0);
}
/*
* zpool import [-d dir] [-D]
* import [-o mntopts] [-o prop=value] ... [-R root] [-D]
@@ -2988,10 +3021,12 @@
char *msgid;
int reason;
const char *health;
uint_t c;
vdev_stat_t *vs;
+ char keystatus[MAXNAMELEN];
+ zprop_source_t srctype;
config = zpool_get_config(zhp, NULL);
reason = zpool_get_status(zhp, &msgid);
cbp->cb_count++;
@@ -3022,10 +3057,15 @@
health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
(void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
(void) printf(gettext(" state: %s\n"), health);
+ (void) zpool_get_prop(zhp, ZPOOL_PROP_KEYSTATUS, keystatus,
+ sizeof (keystatus), &srctype);
+
+ (void) printf(gettext(" key: %s\n"), keystatus);
+
switch (reason) {
case ZPOOL_STATUS_MISSING_DEV_R:
(void) printf(gettext("status: One or more devices could not "
"be opened. Sufficient replicas exist for\n\tthe pool to "
"continue functioning in a degraded state.\n"));
@@ -3495,10 +3535,11 @@
(void) printf(gettext(" 11 Improved scrub performance\n"));
(void) printf(gettext(" 12 Snapshot properties\n"));
(void) printf(gettext(" 13 snapused property\n"));
(void) printf(gettext(" 14 passthrough-x aclinherit "
"support\n"));
+ (void) printf(gettext(" 15 Cryptographic support.\n"));
(void) printf(gettext("For more information on a particular "
"version, including supported releases, see:\n\n"));
(void) printf("http://www.opensolaris.org/os/community/zfs/"
"version/N\n\n");
(void) printf(gettext("Where 'N' is the version number.\n"));
@@ -3580,10 +3621,11 @@
"snapshot",
"filesystem version upgrade",
"refquota set",
"refreservation set",
"pool scrub done",
+ "crypto key create",
};
/*
* Print out the command history for a specific pool.
*/
@@ -3809,11 +3851,10 @@
{
int error;
set_cbdata_t *cb = (set_cbdata_t *)data;
error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
-
if (!error)
cb->cb_any_successful = B_TRUE;
return (error);
}
@@ -3861,10 +3902,167 @@
set_callback, &cb);
return (error);
}
+
+static int
+/* LINTED E_FUNC_ARG_UNUSED */
+key_callback_load(zpool_handle_t *zhp, void *data)
+{
+ int ret;
+ if (zpool_keysource_prompt(zhp)) {
+ char *smf_fmri = getenv("SMF_FMRI");
+
+ if (smf_fmri != NULL &&
+ strcmp(smf_fmri, "svc:/system/device/local") == 0) {
+ return (0);
+ }
+ }
+ ret = zpool_cmd_key_load(zhp);
+ if (ret != 0 && !(ret == EEXIST || ret == ENOTSUP)) {
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+/* LINTED E_FUNC_ARG_UNUSED */
+key_callback_unload(zpool_handle_t *zhp, void *data)
+{
+ int ret;
+
+ ret = zpool_cmd_key_unload(zhp);
+ if (ret != 0 && !(ret == ENOENT || ret == ENOTSUP)) {
+ return (1);
+ }
+
+ return (0);
+}
+
+
+static int
+zpool_do_key(int argc, char **argv)
+{
+ int error = 1, options = 0;
+ nvlist_t *props = NULL;
+ char c, *propval = NULL;
+ boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
+ boolean_t do_all = B_FALSE;
+ zpool_handle_t *zhp = NULL;
+
+ while ((c = getopt(argc, argv, "aluco:")) != -1) {
+ switch (c) {
+ case 'a':
+ do_all = B_TRUE;
+ break;
+
+ case 'l':
+ load = B_TRUE;
+ break;
+
+ case 'u':
+ unload = B_TRUE;
+ break;
+
+ case 'c':
+ change = B_TRUE;
+ break;
+
+ case 'o':
+ if ((propval = strchr(optarg, '=')) == NULL) {
+ (void) fprintf(stderr, gettext("missing "
+ "'=' for -o option\n"));
+ return (error);
+ }
+
+ *propval = '\0';
+ propval++;
+ if (strcmp(optarg, "keysource") != 0) {
+ (void) fprintf(stderr, gettext(
+ "Invalid property for key change: "
+ "\"%s\"\n"),
+ optarg);
+ return (error);
+ }
+ if (add_prop_list(optarg, propval, &props, B_TRUE))
+ return (error);
+
+ options += 2;
+ break;
+
+ }
+ }
+
+ if (!change && props != NULL) {
+ (void) fprintf(stderr, gettext("Properties are not allowed to "
+ "be used in this command.\n"));
+ goto error;
+ }
+
+ if (((load || unload) && (argc > 3)) ||
+ (change && ((argc - options) > 3))) {
+ (void) fprintf(stderr,
+ gettext("too many arguments\n"));
+ usage(B_FALSE);
+ goto error;
+ } else if ((load || unload) && (argc < 3)) {
+ (void) fprintf(stderr, gettext("missing dataset "
+ "argument (specify -a for all)\n"));
+ usage(B_FALSE);
+ goto error;
+ } else if (change && ((argc - options) < 3)) {
+ (void) fprintf(stderr, gettext("missing dataset "
+ "argument\n"));
+ usage(B_FALSE);
+ goto error;
+ }
+
+ if (do_all == B_FALSE) {
+ zhp = zpool_open(g_zfs, argv[argc - 1]);
+ if (zhp == NULL)
+ goto error;
+ }
+
+ if (load) {
+ if (do_all)
+ error = for_each_pool(0, NULL, B_TRUE, NULL,
+ key_callback_load, NULL);
+ else
+ error = zpool_cmd_key_load(zhp);
+
+ } else if (unload) {
+ if (do_all)
+ error = for_each_pool(0, NULL, B_TRUE, NULL,
+ key_callback_unload, NULL);
+ else
+ error = zpool_cmd_key_unload(zhp);
+
+ } else if (change) {
+ if (do_all) {
+ (void) fprintf(stderr, gettext("cannot use '-a' with "
+ "change operation.\n"));
+ usage(B_FALSE);
+ goto error;
+ }
+
+ error = zpool_cmd_key_change(zhp, props);
+
+ } else
+ usage(B_FALSE);
+
+ if (zhp != NULL && !do_all)
+ zpool_close(zhp);
+
+error:
+ nvlist_free(props);
+ if (error != 0)
+ return (1);
+ return (0);
+}
+
static int
find_command_idx(char *command, int *idx)
{
int i;