summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/availdevs/availdevs.c2
-rw-r--r--usr/src/cmd/mdb/common/modules/zfs/zfs.c46
-rw-r--r--usr/src/cmd/mdb/intel/amd64/libzpool/Makefile3
-rw-r--r--usr/src/cmd/mdb/intel/amd64/zfs/Makefile1
-rw-r--r--usr/src/cmd/mdb/intel/ia32/libzpool/Makefile3
-rw-r--r--usr/src/cmd/mdb/sparc/v7/libzpool/Makefile3
-rw-r--r--usr/src/cmd/mdb/sparc/v9/libzpool/Makefile3
-rw-r--r--usr/src/cmd/mdb/sparc/v9/zfs/Makefile1
-rw-r--r--usr/src/cmd/truss/codes.c6
-rw-r--r--usr/src/cmd/zdb/Makefile.com3
-rw-r--r--usr/src/cmd/zdb/zdb.c74
-rw-r--r--usr/src/cmd/zdb/zdb_il.c11
-rw-r--r--usr/src/cmd/zfs/zfs_main.c297
-rw-r--r--usr/src/cmd/zinject/translate.c8
-rw-r--r--usr/src/cmd/zinject/zinject.c32
-rw-r--r--usr/src/cmd/zoneadm/Makefile2
-rw-r--r--usr/src/cmd/zpool/zpool_main.c168
-rw-r--r--usr/src/cmd/zstreamdump/zstreamdump.c138
-rw-r--r--usr/src/cmd/ztest/ztest.c172
19 files changed, 850 insertions, 123 deletions
diff --git a/usr/src/cmd/availdevs/availdevs.c b/usr/src/cmd/availdevs/availdevs.c
index 6c39f394d1..ed0e2b2eed 100644
--- a/usr/src/cmd/availdevs/availdevs.c
+++ b/usr/src/cmd/availdevs/availdevs.c
@@ -169,7 +169,7 @@ add_pool_to_xml(nvlist_t *config, void *data)
(xmlChar *)zjni_pool_state_to_str(state));
(void) xmlSetProp(pool, (xmlChar *)ATTR_POOL_STATUS, (xmlChar *)
- zjni_pool_status_to_str(zpool_import_status(config, &c)));
+ zjni_pool_status_to_str(zpool_import_status(config, &c, NULL)));
return (0);
}
diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
index 271ce782ba..89b3a4873e 100644
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
@@ -27,6 +27,17 @@
/* Portions Copyright 2010 Robert Milkowski */
+/*
+ * ZFS_MDB lets dmu.h know that we don't have dmu_ot, and we will define our
+ * own macros to access the target's dmu_ot. Therefore it must be defined
+ * before including any ZFS headers. Note that we don't define
+ * DMU_OT_IS_ENCRYPTED_IMPL() or DMU_OT_BYTESWAP_IMPL(), therefore using them
+ * will result in a compilation error. If they are needed in the future, we
+ * can implement them similarly to mdb_dmu_ot_is_encrypted_impl().
+ */
+#define ZFS_MDB
+#define DMU_OT_IS_ENCRYPTED_IMPL(ot) mdb_dmu_ot_is_encrypted_impl(ot)
+
#include <mdb/mdb_ctf.h>
#include <sys/zfs_context.h>
#include <sys/mdb_modapi.h>
@@ -567,6 +578,30 @@ dva(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
+typedef struct mdb_dmu_object_type_info {
+ boolean_t ot_encrypt;
+} mdb_dmu_object_type_info_t;
+
+static boolean_t
+mdb_dmu_ot_is_encrypted_impl(dmu_object_type_t ot)
+{
+ mdb_dmu_object_type_info_t mdoti;
+ GElf_Sym sym;
+ size_t sz = mdb_ctf_sizeof_by_name("dmu_object_type_info_t");
+
+ if (mdb_lookup_by_obj(ZFS_OBJ_NAME, "dmu_ot", &sym)) {
+ mdb_warn("failed to find " ZFS_OBJ_NAME "`dmu_ot");
+ return (B_FALSE);
+ }
+
+ if (mdb_ctf_vread(&mdoti, "dmu_object_type_info_t",
+ "mdb_dmu_object_type_info_t", sym.st_value + sz * ot, 0) != 0) {
+ return (B_FALSE);
+ }
+
+ return (mdoti.ot_encrypt);
+}
+
/* ARGSUSED */
static int
blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
@@ -2839,13 +2874,6 @@ zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
dmu_object_type_t t;
zfs_blkstat_t *tzb;
uint64_t ditto;
- dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES + 10];
- /* +10 in case it grew */
-
- if (mdb_readvar(&dmu_ot, "dmu_ot") == -1) {
- mdb_warn("failed to read 'dmu_ot'");
- return (DCMD_ERR);
- }
if (mdb_getopts(argc, argv,
'v', MDB_OPT_SETBITS, TRUE, &verbose,
@@ -2894,8 +2922,8 @@ zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
strcpy(typename, "other");
else if (t == DMU_OT_TOTAL)
strcpy(typename, "Total");
- else if (mdb_readstr(typename, sizeof (typename),
- (uintptr_t)dmu_ot[t].ot_name) == -1) {
+ else if (enum_lookup("enum dmu_object_type",
+ t, "DMU_OT_", sizeof (typename), typename) == -1) {
mdb_warn("failed to read type name");
return (DCMD_ERR);
}
diff --git a/usr/src/cmd/mdb/intel/amd64/libzpool/Makefile b/usr/src/cmd/mdb/intel/amd64/libzpool/Makefile
index b0ebe4c7c8..b5bbd8467b 100644
--- a/usr/src/cmd/mdb/intel/amd64/libzpool/Makefile
+++ b/usr/src/cmd/mdb/intel/amd64/libzpool/Makefile
@@ -42,7 +42,8 @@ GENUNIX_DIR = ../../../common/modules/genunix
CPPFLAGS.first = -I$(SRC)/lib/libfakekernel/common -D_FAKE_KERNEL
CPPFLAGS += -I../../../../../lib/libzpool/common \
- -I../../../../../uts/common/fs/zfs
+ -I../../../../../uts/common/fs/zfs \
+ -I../../../../../common/zfs
CSTD= $(CSTD_GNU99)
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/mdb/intel/amd64/zfs/Makefile b/usr/src/cmd/mdb/intel/amd64/zfs/Makefile
index 8224d7593d..4ffa954410 100644
--- a/usr/src/cmd/mdb/intel/amd64/zfs/Makefile
+++ b/usr/src/cmd/mdb/intel/amd64/zfs/Makefile
@@ -39,6 +39,7 @@ include ../../../common/modules/zfs/Makefile.zfs
CPPFLAGS += -I../../../../../uts/common/fs/zfs
CPPFLAGS += -I../../../../../uts/common/fs/zfs/lua
+CPPFLAGS += -I../../../../../common/zfs
CSTD= $(CSTD_GNU99)
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/mdb/intel/ia32/libzpool/Makefile b/usr/src/cmd/mdb/intel/ia32/libzpool/Makefile
index 0ed9a6d470..c19d9c56a5 100644
--- a/usr/src/cmd/mdb/intel/ia32/libzpool/Makefile
+++ b/usr/src/cmd/mdb/intel/ia32/libzpool/Makefile
@@ -43,7 +43,8 @@ GENUNIX_DIR = ../../../common/modules/genunix
CPPFLAGS.first = -I$(SRC)/lib/libfakekernel/common -D_FAKE_KERNEL
CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs \
- -I../../../../../uts/common/fs/zfs/lua
+ -I../../../../../uts/common/fs/zfs/lua \
+ -I../../../../../common/zfs
CSTD= $(CSTD_GNU99)
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/mdb/sparc/v7/libzpool/Makefile b/usr/src/cmd/mdb/sparc/v7/libzpool/Makefile
index f8f2b3fae3..5b24c538e4 100644
--- a/usr/src/cmd/mdb/sparc/v7/libzpool/Makefile
+++ b/usr/src/cmd/mdb/sparc/v7/libzpool/Makefile
@@ -41,7 +41,8 @@ GENUNIX_DIR = ../../../common/modules/genunix
CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs \
- -I../../../../../uts/common/fs/zfs/lua
+ -I../../../../../uts/common/fs/zfs/lua \
+ -I../../../../../common/zfs
CSTD= $(CSTD_GNU99)
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/mdb/sparc/v9/libzpool/Makefile b/usr/src/cmd/mdb/sparc/v9/libzpool/Makefile
index 6b50bacc96..f512dc4c10 100644
--- a/usr/src/cmd/mdb/sparc/v9/libzpool/Makefile
+++ b/usr/src/cmd/mdb/sparc/v9/libzpool/Makefile
@@ -42,7 +42,8 @@ GENUNIX_DIR = ../../../common/modules/genunix
CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs \
- -I../../../../../uts/common/fs/zfs/lua
+ -I../../../../../uts/common/fs/zfs/lua \
+ -I../../../../../common/zfs
CSTD= $(CSTD_GNU99)
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/mdb/sparc/v9/zfs/Makefile b/usr/src/cmd/mdb/sparc/v9/zfs/Makefile
index 116cc938d8..e2407effa9 100644
--- a/usr/src/cmd/mdb/sparc/v9/zfs/Makefile
+++ b/usr/src/cmd/mdb/sparc/v9/zfs/Makefile
@@ -39,6 +39,7 @@ include ../../../common/modules/zfs/Makefile.zfs
CPPFLAGS += -I../../../../../uts/common/fs/zfs
CPPFLAGS += -I../../../../../uts/common/fs/zfs/lua
+CPPFLAGS += -I../../../../../common/zfs
CSTD= $(CSTD_GNU99)
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index ac49896686..888e6c9caf 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -1294,6 +1294,12 @@ const struct ioc {
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_POOL_SYNC, "ZFS_IOC_POOL_SYNC",
"zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_LOAD_KEY, "ZFS_IOC_LOAD_KEY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_UNLOAD_KEY, "ZFS_IOC_UNLOAD_KEY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_CHANGE_KEY, "ZFS_IOC_CHANGE_KEY",
+ "zfs_cmd_t" },
/* kssl ioctls */
{ (uint_t)KSSL_ADD_ENTRY, "KSSL_ADD_ENTRY",
diff --git a/usr/src/cmd/zdb/Makefile.com b/usr/src/cmd/zdb/Makefile.com
index be85c6dbb5..1834e9b2f8 100644
--- a/usr/src/cmd/zdb/Makefile.com
+++ b/usr/src/cmd/zdb/Makefile.com
@@ -65,6 +65,9 @@ LINTFLAGS64 += -xerroff=E_NAME_DEF_NOT_USED2
LINTFLAGS += -erroff=E_STATIC_UNUSED
LINTFLAGS64 += -erroff=E_STATIC_UNUSED
+LINTFLAGS += -erroff=E_BAD_PTR_CAST_ALIGN
+LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN
+
.KEEP_STATE:
all: $(PROG)
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index 16c8c60df1..26ed6dacf8 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -65,6 +65,7 @@
#include <sys/abd.h>
#include <sys/blkptr.h>
#include <sys/dsl_scan.h>
+#include <sys/dsl_crypt.h>
#include <zfs_comutil.h>
#include <libcmdutils.h>
#undef verify
@@ -1388,7 +1389,7 @@ static void
snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
{
const dva_t *dva = bp->blk_dva;
- int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
+ unsigned int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
if (dump_opt['b'] >= 6) {
snprintf_blkptr(blkbuf, buflen, bp);
@@ -1406,7 +1407,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
}
blkbuf[0] = '\0';
- for (int i = 0; i < ndvas; i++)
+ for (unsigned int i = 0; i < ndvas; i++)
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), "%llu:%llx:%llx ",
(u_longlong_t)DVA_GET_VDEV(&dva[i]),
@@ -1871,14 +1872,14 @@ open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
uint64_t version = 0;
VERIFY3P(sa_os, ==, NULL);
- err = dmu_objset_own(path, type, B_TRUE, tag, osp);
+ err = dmu_objset_own(path, type, B_TRUE, B_FALSE, tag, osp);
if (err != 0) {
(void) fprintf(stderr, "failed to own dataset '%s': %s\n", path,
strerror(err));
return (err);
}
- if (dmu_objset_type(*osp) == DMU_OST_ZFS) {
+ if (dmu_objset_type(*osp) == DMU_OST_ZFS && !(*osp)->os_encrypted) {
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
8, 1, &version);
if (version >= ZPL_VERSION_SA) {
@@ -1890,7 +1891,7 @@ open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
if (err != 0) {
(void) fprintf(stderr, "sa_setup failed: %s\n",
strerror(err));
- dmu_objset_disown(*osp, tag);
+ dmu_objset_disown(*osp, B_FALSE, tag);
*osp = NULL;
}
}
@@ -1905,7 +1906,7 @@ close_objset(objset_t *os, void *tag)
VERIFY3P(os, ==, sa_os);
if (os->os_sa != NULL)
sa_tear_down(os);
- dmu_objset_disown(os, tag);
+ dmu_objset_disown(os, B_FALSE, tag);
sa_attr_table = NULL;
sa_os = NULL;
}
@@ -2061,6 +2062,7 @@ dump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size)
{
}
+
static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
dump_none, /* unallocated */
dump_zap, /* object directory */
@@ -2126,6 +2128,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
dmu_buf_t *db = NULL;
dmu_object_info_t doi;
dnode_t *dn;
+ boolean_t dnode_held = B_FALSE;
void *bonus = NULL;
size_t bsize = 0;
char iblk[32], dblk[32], lsize[32], asize[32], fill[32], dnsize[32];
@@ -2149,16 +2152,33 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
if (object == 0) {
dn = DMU_META_DNODE(os);
+ dmu_object_info_from_dnode(dn, &doi);
} else {
- error = dmu_bonus_hold(os, object, FTAG, &db);
+ /*
+ * Encrypted datasets will have sensitive bonus buffers
+ * encrypted. Therefore we cannot hold the bonus buffer and
+ * must hold the dnode itself instead.
+ */
+ error = dmu_object_info(os, object, &doi);
if (error)
- fatal("dmu_bonus_hold(%llu) failed, errno %u",
- object, error);
- bonus = db->db_data;
- bsize = db->db_size;
- dn = DB_DNODE((dmu_buf_impl_t *)db);
+ fatal("dmu_object_info() failed, errno %u", error);
+
+ if (os->os_encrypted &&
+ DMU_OT_IS_ENCRYPTED(doi.doi_bonus_type)) {
+ error = dnode_hold(os, object, FTAG, &dn);
+ if (error)
+ fatal("dnode_hold() failed, errno %u", error);
+ dnode_held = B_TRUE;
+ } else {
+ error = dmu_bonus_hold(os, object, FTAG, &db);
+ if (error)
+ fatal("dmu_bonus_hold(%llu) failed, errno %u",
+ object, error);
+ bonus = db->db_data;
+ bsize = db->db_size;
+ dn = DB_DNODE((dmu_buf_impl_t *)db);
+ }
}
- dmu_object_info_from_dnode(dn, &doi);
if (dnode_slots_used != NULL)
*dnode_slots_used = doi.doi_dnodesize / DNODE_MIN_SIZE;
@@ -2207,9 +2227,20 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
(void) printf("\tdnode maxblkid: %llu\n",
(longlong_t)dn->dn_phys->dn_maxblkid);
- object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os, object,
- bonus, bsize);
- object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0);
+ if (!dnode_held) {
+ object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os,
+ object, bonus, bsize);
+ } else {
+ (void) printf("\t\t(bonus encrypted)\n");
+ }
+
+ if (!os->os_encrypted || !DMU_OT_IS_ENCRYPTED(doi.doi_type)) {
+ object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object,
+ NULL, 0);
+ } else {
+ (void) printf("\t\t(object encrypted)\n");
+ }
+
*print_header = 1;
}
@@ -2253,6 +2284,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
if (db != NULL)
dmu_buf_rele(db, FTAG);
+ if (dnode_held)
+ dnode_rele(dn, FTAG);
}
static void
@@ -2631,7 +2664,7 @@ dump_path(char *ds, char *path)
if (err != 0) {
(void) fprintf(stderr, "can't lookup root znode: %s\n",
strerror(err));
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_FALSE, FTAG);
return (EINVAL);
}
@@ -3729,7 +3762,8 @@ dump_block_stats(spa_t *spa)
zdb_cb_t zcb;
zdb_blkstats_t *zb, *tzb;
uint64_t norm_alloc, norm_space, total_alloc, total_found;
- int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA | TRAVERSE_HARD;
+ int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
+ TRAVERSE_NO_DECRYPT | TRAVERSE_HARD;
boolean_t leaks = B_FALSE;
int err;
@@ -4106,8 +4140,8 @@ dump_simulated_ddt(spa_t *spa)
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
- (void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA,
- zdb_ddt_add_cb, &t);
+ (void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
+ TRAVERSE_NO_DECRYPT, zdb_ddt_add_cb, &t);
spa_config_exit(spa, SCL_CONFIG, FTAG);
diff --git a/usr/src/cmd/zdb/zdb_il.c b/usr/src/cmd/zdb/zdb_il.c
index 9daf9a7000..7439cdbae9 100644
--- a/usr/src/cmd/zdb/zdb_il.c
+++ b/usr/src/cmd/zdb/zdb_il.c
@@ -325,8 +325,13 @@ print_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t claim_txg)
(u_longlong_t)lr->lrc_txg,
(u_longlong_t)lr->lrc_seq);
- if (txtype && verbose >= 3)
- zil_rec_info[txtype].zri_print(zilog, txtype, lr);
+ if (txtype && verbose >= 3) {
+ if (!zilog->zl_os->os_encrypted) {
+ zil_rec_info[txtype].zri_print(zilog, txtype, lr);
+ } else {
+ (void) printf("%s(encrypted)\n", tab_prefix);
+ }
+ }
zil_rec_info[txtype].zri_count++;
zil_rec_info[0].zri_count++;
@@ -418,7 +423,7 @@ dump_intent_log(zilog_t *zilog)
if (verbose >= 2) {
(void) printf("\n");
(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
- zh->zh_claim_txg);
+ zh->zh_claim_txg, B_FALSE);
print_log_stats(verbose);
}
}
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index 283f3ff044..6265d4ad4e 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -111,6 +111,9 @@ static int zfs_do_diff(int argc, char **argv);
static int zfs_do_bookmark(int argc, char **argv);
static int zfs_do_remap(int argc, char **argv);
static int zfs_do_channel_program(int argc, char **argv);
+static int zfs_do_load_key(int argc, char **argv);
+static int zfs_do_unload_key(int argc, char **argv);
+static int zfs_do_change_key(int argc, char **argv);
/*
* Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
@@ -160,6 +163,9 @@ typedef enum {
HELP_REMAP,
HELP_BOOKMARK,
HELP_CHANNEL_PROGRAM,
+ HELP_LOAD_KEY,
+ HELP_UNLOAD_KEY,
+ HELP_CHANGE_KEY,
} zfs_help_t;
typedef struct zfs_command {
@@ -215,6 +221,9 @@ static zfs_command_t command_table[] = {
{ "release", zfs_do_release, HELP_RELEASE },
{ "diff", zfs_do_diff, HELP_DIFF },
{ "remap", zfs_do_remap, HELP_REMAP },
+ { "load-key", zfs_do_load_key, HELP_LOAD_KEY },
+ { "unload-key", zfs_do_unload_key, HELP_UNLOAD_KEY },
+ { "change-key", zfs_do_change_key, HELP_CHANGE_KEY },
};
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
@@ -256,7 +265,7 @@ get_usage(zfs_help_t idx)
"[filesystem|volume|snapshot] ...\n"));
case HELP_MOUNT:
return (gettext("\tmount\n"
- "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
+ "\tmount [-lvO] [-o opts] <-a | filesystem>\n"));
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
@@ -273,16 +282,16 @@ get_usage(zfs_help_t idx)
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
- return (gettext("\tsend [-DnPpRvLec] [-[iI] snapshot] "
+ return (gettext("\tsend [-DnPpRvLecr] [-[iI] snapshot] "
"<snapshot>\n"
- "\tsend [-Le] [-i snapshot|bookmark] "
+ "\tsend [-Lecr] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"
"\tsend [-nvPe] -t <receive_resume_token>\n"));
case HELP_SET:
return (gettext("\tset <property=value> ... "
"<filesystem|volume|snapshot> ...\n"));
case HELP_SHARE:
- return (gettext("\tshare <-a | filesystem>\n"));
+ return (gettext("\tshare [-l] <-a | filesystem>\n"));
case HELP_SNAPSHOT:
return (gettext("\tsnapshot [-r] [-o property=value] ... "
"<filesystem|volume>@<snap> ...\n"));
@@ -339,6 +348,17 @@ get_usage(zfs_help_t idx)
return (gettext("\tprogram [-jn] [-t <instruction limit>] "
"[-m <memory limit (b)>] <pool> <program file> "
"[lua args...]\n"));
+ case HELP_LOAD_KEY:
+ return (gettext("\tload-key [-rn] [-L <keylocation>] "
+ "<-a | filesystem|volume>\n"));
+ case HELP_UNLOAD_KEY:
+ return (gettext("\tunload-key [-r] "
+ "<-a | filesystem|volume>\n"));
+ case HELP_CHANGE_KEY:
+ return (gettext("\tchange-key [-l] [-o keyformat=<value>]\n"
+ "\t [-o keylocation=<value>] [-o pbkfd2iters=<value>]\n"
+ "\t <filesystem|volume>\n"
+ "\tchange-key -i [-l] <filesystem|volume>\n"));
}
abort();
@@ -872,7 +892,7 @@ zfs_do_create(int argc, char **argv)
(void) snprintf(msg, sizeof (msg),
gettext("cannot create '%s'"), argv[0]);
if (props && (real_props = zfs_valid_proplist(g_zfs, type,
- props, 0, NULL, zpool_handle, msg)) == NULL) {
+ props, 0, NULL, zpool_handle, B_TRUE, msg)) == NULL) {
zpool_close(zpool_handle);
goto error;
}
@@ -3745,11 +3765,12 @@ zfs_do_send(int argc, char **argv)
{"embed", no_argument, NULL, 'e'},
{"resume", required_argument, NULL, 't'},
{"compressed", no_argument, NULL, 'c'},
+ {"raw", no_argument, NULL, 'w'},
{0, 0, 0, 0}
};
/* check options */
- while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:c", long_options,
+ while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:cw", long_options,
NULL)) != -1) {
switch (c) {
case 'i':
@@ -3797,6 +3818,12 @@ zfs_do_send(int argc, char **argv)
case 'c':
flags.compress = B_TRUE;
break;
+ case 'w':
+ flags.raw = B_TRUE;
+ flags.compress = B_TRUE;
+ flags.embed_data = B_TRUE;
+ flags.largeblock = B_TRUE;
+ break;
case ':':
/*
* If a parameter was not passed, optopt contains the
@@ -3904,6 +3931,8 @@ zfs_do_send(int argc, char **argv)
lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
if (flags.compress)
lzc_flags |= LZC_SEND_FLAG_COMPRESS;
+ if (flags.raw)
+ lzc_flags |= LZC_SEND_FLAG_RAW;
if (fromname != NULL &&
(fromname[0] == '#' || fromname[0] == '@')) {
@@ -4140,6 +4169,8 @@ zfs_do_receive(int argc, char **argv)
#define ZFS_DELEG_PERM_DIFF "diff"
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
#define ZFS_DELEG_PERM_REMAP "remap"
+#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
+#define ZFS_DELEG_PERM_CHANGE_KEY "change-key"
#define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
@@ -4161,6 +4192,8 @@ static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
{ ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
{ ZFS_DELEG_PERM_REMAP, ZFS_DELEG_NOTE_REMAP },
+ { ZFS_DELEG_PERM_LOAD_KEY, ZFS_DELEG_NOTE_LOAD_KEY },
+ { ZFS_DELEG_PERM_CHANGE_KEY, ZFS_DELEG_NOTE_CHANGE_KEY },
{ ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
{ ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
@@ -4728,6 +4761,12 @@ deleg_perm_comment(zfs_deleg_note_t note)
case ZFS_DELEG_NOTE_SNAPSHOT:
str = gettext("");
break;
+ case ZFS_DELEG_NOTE_LOAD_KEY:
+ str = gettext("Allows loading or unloading an encryption key");
+ break;
+ case ZFS_DELEG_NOTE_CHANGE_KEY:
+ str = gettext("Allows changing or adding an encryption key");
+ break;
/*
* case ZFS_DELEG_NOTE_VSCAN:
* str = gettext("");
@@ -5963,6 +6002,22 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
}
/*
+ * If this filesystem is encrypted and does not have
+ * a loaded key, we can not mount it.
+ */
+ if ((flags & MS_CRYPT) == 0 &&
+ zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF &&
+ zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) ==
+ ZFS_KEYSTATUS_UNAVAILABLE) {
+ if (!explicit)
+ return (0);
+
+ (void) fprintf(stderr, gettext("cannot %s '%s': "
+ "encryption key not loaded\n"), cmdname, zfs_get_name(zhp));
+ return (1);
+ }
+
+ /*
* If this filesystem is inconsistent and has a receive resume
* token, we can not mount it.
*/
@@ -6008,7 +6063,7 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
}
if (!zfs_is_mounted(zhp, NULL) &&
- zfs_mount(zhp, NULL, 0) != 0)
+ zfs_mount(zhp, NULL, flags) != 0)
return (1);
if (protocol == NULL) {
@@ -6135,7 +6190,7 @@ share_mount(int op, int argc, char **argv)
int flags = 0;
/* check options */
- while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:O" : "a"))
+ while ((c = getopt(argc, argv, op == OP_MOUNT ? ":alvo:O" : "al"))
!= -1) {
switch (c) {
case 'a':
@@ -6144,6 +6199,9 @@ share_mount(int op, int argc, char **argv)
case 'v':
verbose = B_TRUE;
break;
+ case 'l':
+ flags |= MS_CRYPT;
+ break;
case 'o':
if (*optarg == '\0') {
(void) fprintf(stderr, gettext("empty mount "
@@ -7289,6 +7347,229 @@ usage:
return (-1);
}
+typedef struct loadkey_cbdata {
+ boolean_t cb_loadkey;
+ boolean_t cb_recursive;
+ boolean_t cb_noop;
+ char *cb_keylocation;
+ uint64_t cb_numfailed;
+ uint64_t cb_numattempted;
+} loadkey_cbdata_t;
+
+static int
+load_key_callback(zfs_handle_t *zhp, void *data)
+{
+ int ret;
+ boolean_t is_encroot;
+ loadkey_cbdata_t *cb = data;
+ uint64_t keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS);
+
+ /*
+ * If we are working recursively, we want to skip loading / unloading
+ * keys for non-encryption roots and datasets whose keys are already
+ * in the desired end-state.
+ */
+ if (cb->cb_recursive) {
+ ret = zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL);
+ if (ret != 0)
+ return (ret);
+ if (!is_encroot)
+ return (0);
+
+ if ((cb->cb_loadkey && keystatus == ZFS_KEYSTATUS_AVAILABLE) ||
+ (!cb->cb_loadkey && keystatus == ZFS_KEYSTATUS_UNAVAILABLE))
+ return (0);
+ }
+
+ cb->cb_numattempted++;
+
+ if (cb->cb_loadkey)
+ ret = zfs_crypto_load_key(zhp, cb->cb_noop, cb->cb_keylocation);
+ else
+ ret = zfs_crypto_unload_key(zhp);
+
+ if (ret != 0) {
+ cb->cb_numfailed++;
+ return (ret);
+ }
+
+ return (0);
+}
+
+static int
+load_unload_keys(int argc, char **argv, boolean_t loadkey)
+{
+ int c, ret = 0, flags = 0;
+ boolean_t do_all = B_FALSE;
+ loadkey_cbdata_t cb = { 0 };
+
+ cb.cb_loadkey = loadkey;
+
+ while ((c = getopt(argc, argv, "anrL:")) != -1) {
+ /* noop and alternate keylocations only apply to zfs load-key */
+ if (loadkey) {
+ switch (c) {
+ case 'n':
+ cb.cb_noop = B_TRUE;
+ continue;
+ case 'L':
+ cb.cb_keylocation = optarg;
+ continue;
+ default:
+ break;
+ }
+ }
+
+ switch (c) {
+ case 'a':
+ do_all = B_TRUE;
+ cb.cb_recursive = B_TRUE;
+ break;
+ case 'r':
+ flags |= ZFS_ITER_RECURSE;
+ cb.cb_recursive = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("invalid option '%c'\n"), optopt);
+ usage(B_FALSE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!do_all && argc == 0) {
+ (void) fprintf(stderr,
+ gettext("Missing dataset argument or -a option\n"));
+ usage(B_FALSE);
+ }
+
+ if (do_all && argc != 0) {
+ (void) fprintf(stderr,
+ gettext("Cannot specify dataset with -a option\n"));
+ usage(B_FALSE);
+ }
+
+ if (cb.cb_recursive && cb.cb_keylocation != NULL &&
+ strcmp(cb.cb_keylocation, "prompt") != 0) {
+ (void) fprintf(stderr, gettext("alternate keylocation may only "
+ "be 'prompt' with -r or -a\n"));
+ usage(B_FALSE);
+ }
+
+ ret = zfs_for_each(argc, argv, flags,
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL, 0,
+ load_key_callback, &cb);
+
+ if (cb.cb_noop || (cb.cb_recursive && cb.cb_numattempted != 0)) {
+ (void) printf(gettext("%llu / %llu key(s) successfully %s\n"),
+ (u_longlong_t)(cb.cb_numattempted - cb.cb_numfailed),
+ (u_longlong_t)cb.cb_numattempted,
+ loadkey ? (cb.cb_noop ? "verified" : "loaded") :
+ "unloaded");
+ }
+
+ if (cb.cb_numfailed != 0)
+ ret = -1;
+
+ return (ret);
+}
+
+static int
+zfs_do_load_key(int argc, char **argv)
+{
+ return (load_unload_keys(argc, argv, B_TRUE));
+}
+
+
+static int
+zfs_do_unload_key(int argc, char **argv)
+{
+ return (load_unload_keys(argc, argv, B_FALSE));
+}
+
+static int
+zfs_do_change_key(int argc, char **argv)
+{
+ int c, ret;
+ uint64_t keystatus;
+ boolean_t loadkey = B_FALSE, inheritkey = B_FALSE;
+ zfs_handle_t *zhp = NULL;
+ nvlist_t *props = fnvlist_alloc();
+
+ while ((c = getopt(argc, argv, "lio:")) != -1) {
+ switch (c) {
+ case 'l':
+ loadkey = B_TRUE;
+ break;
+ case 'i':
+ inheritkey = B_TRUE;
+ break;
+ case 'o':
+ if (parseprop(props, optarg) != 0) {
+ nvlist_free(props);
+ return (1);
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("invalid option '%c'\n"), optopt);
+ usage(B_FALSE);
+ }
+ }
+
+ if (inheritkey && !nvlist_empty(props)) {
+ (void) fprintf(stderr,
+ gettext("Properties not allowed for inheriting\n"));
+ usage(B_FALSE);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ (void) fprintf(stderr, gettext("Missing dataset argument\n"));
+ usage(B_FALSE);
+ }
+
+ if (argc > 1) {
+ (void) fprintf(stderr, gettext("Too many arguments\n"));
+ usage(B_FALSE);
+ }
+
+ zhp = zfs_open(g_zfs, argv[argc - 1],
+ ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
+ if (zhp == NULL)
+ usage(B_FALSE);
+
+ if (loadkey) {
+ keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS);
+ if (keystatus != ZFS_KEYSTATUS_AVAILABLE) {
+ ret = zfs_crypto_load_key(zhp, B_FALSE, NULL);
+ if (ret != 0) {
+ nvlist_free(props);
+ zfs_close(zhp);
+ return (-1);
+ }
+ }
+
+ /* refresh the properties so the new keystatus is visible */
+ zfs_refresh_properties(zhp);
+ }
+
+ ret = zfs_crypto_rewrap(zhp, props, inheritkey);
+ if (ret != 0) {
+ nvlist_free(props);
+ zfs_close(zhp);
+ return (-1);
+ }
+
+ nvlist_free(props);
+ zfs_close(zhp);
+ return (0);
+}
+
int
main(int argc, char **argv)
{
diff --git a/usr/src/cmd/zinject/translate.c b/usr/src/cmd/zinject/translate.c
index 53a38e1ea8..090f2448b0 100644
--- a/usr/src/cmd/zinject/translate.c
+++ b/usr/src/cmd/zinject/translate.c
@@ -175,7 +175,7 @@ object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
*/
sync();
- err = dmu_objset_own(dataset, DMU_OST_ZFS, B_TRUE, FTAG, &os);
+ err = dmu_objset_own(dataset, DMU_OST_ZFS, B_TRUE, B_FALSE, FTAG, &os);
if (err != 0) {
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
dataset, strerror(err));
@@ -185,7 +185,7 @@ object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
record->zi_objset = dmu_objset_id(os);
record->zi_object = statbuf->st_ino;
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_FALSE, FTAG);
return (0);
}
@@ -261,7 +261,7 @@ calculate_range(const char *dataset, err_type_t type, int level, char *range,
* size.
*/
if ((err = dmu_objset_own(dataset, DMU_OST_ANY,
- B_TRUE, FTAG, &os)) != 0) {
+ B_TRUE, B_FALSE, FTAG, &os)) != 0) {
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
dataset, strerror(err));
goto out;
@@ -323,7 +323,7 @@ out:
dnode_rele(dn, FTAG);
}
if (os)
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_FALSE, FTAG);
return (ret);
}
diff --git a/usr/src/cmd/zinject/zinject.c b/usr/src/cmd/zinject/zinject.c
index 1c0b3199bd..fc836f11e5 100644
--- a/usr/src/cmd/zinject/zinject.c
+++ b/usr/src/cmd/zinject/zinject.c
@@ -112,9 +112,9 @@
* specified.
*
* The '-e' option takes a string describing the errno to simulate. This must
- * be either 'io' or 'checksum'. In most cases this will result in the same
- * behavior, but RAID-Z will produce a different set of ereports for this
- * situation.
+ * be one of 'io', 'checksum', or 'decrypt'. In most cases this will result
+ * in the same behavior, but RAID-Z will produce a different set of ereports
+ * for this situation.
*
* The '-a', '-u', and '-m' flags toggle internal flush behavior. If '-a' is
* specified, then the ARC cache is flushed appropriately. If '-u' is
@@ -296,8 +296,9 @@ usage(void)
"\t\tinterperted depending on the '-t' option.\n"
"\n"
"\t\t-q\tQuiet mode. Only print out the handler number added.\n"
- "\t\t-e\tInject a specific error. Must be either 'io' or\n"
- "\t\t\t'checksum', or 'decompress'. Default is 'io'.\n"
+ "\t\t-e\tInject a specific error. Must be one of 'io', "
+ "'checksum',\n"
+ "\t\t\t'decompress', or decrypt. Default is 'io'.\n"
"\t\t-C\tInject the given error only into specific DVAs. The\n"
"\t\t\tDVAs should be specified as a list of 0-indexed DVAs\n"
"\t\t\tseparated by commas (ex. '0,2').\n"
@@ -817,6 +818,8 @@ main(int argc, char **argv)
error = EIO;
} else if (strcasecmp(optarg, "checksum") == 0) {
error = ECKSUM;
+ } else if (strcasecmp(optarg, "decrypt") == 0) {
+ error = EACCES;
} else if (strcasecmp(optarg, "nxio") == 0) {
error = ENXIO;
} else if (strcasecmp(optarg, "dtl") == 0) {
@@ -1144,14 +1147,29 @@ main(int argc, char **argv)
(void) fprintf(stderr, "the '-C' option may "
"not be used with logical data errors "
"'decrypt' and 'decompress'\n");
+ record.zi_dvas = dvas;
+ }
+ }
+
+ record.zi_cmd = ZINJECT_DATA_FAULT;
+
+ if (error == EACCES) {
+ if (type != TYPE_DATA) {
+ (void) fprintf(stderr, "decryption errors "
+ "may only be injected for 'data' types\n");
libzfs_fini(g_zfs);
return (1);
}
- record.zi_dvas = dvas;
+ record.zi_cmd = ZINJECT_DECRYPT_FAULT;
+ /*
+ * Internally, ZFS actually uses ECKSUM for decryption
+ * errors since EACCES is used to indicate the key was
+ * not found.
+ */
+ error = ECKSUM;
}
- record.zi_cmd = ZINJECT_DATA_FAULT;
if (translate_record(type, argv[0], range, level, &record, pool,
dataset) != 0)
return (1);
diff --git a/usr/src/cmd/zoneadm/Makefile b/usr/src/cmd/zoneadm/Makefile
index 2b01078aec..23584bbb5b 100644
--- a/usr/src/cmd/zoneadm/Makefile
+++ b/usr/src/cmd/zoneadm/Makefile
@@ -38,6 +38,8 @@ POFILES= $(OBJS:%.o=%.po)
LDLIBS += -lzonecfg -lsocket -lgen -lpool -lzfs -luuid -lnvpair -lbrand -ldladm -lsecdb
+INCS += -I../../common/zfs
+
CERRWARN += -_gcc=-Wno-uninitialized
.KEEP_STATE:
diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c
index 86d924fba9..dc77a21341 100644
--- a/usr/src/cmd/zpool/zpool_main.c
+++ b/usr/src/cmd/zpool/zpool_main.c
@@ -247,11 +247,13 @@ get_usage(zpool_help_t idx)
return (gettext("\thistory [-il] [<pool>] ...\n"));
case HELP_IMPORT:
return (gettext("\timport [-d dir] [-D]\n"
+ "\timport [-d dir | -c cachefile] [-F [-n]] [-l] "
+ "<pool | id>\n"
"\timport [-o mntopts] [-o property=value] ... \n"
- "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
+ "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
"[-R root] [-F [-n]] -a\n"
"\timport [-o mntopts] [-o property=value] ... \n"
- "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
+ "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
"[-R root] [-F [-n]] [-t]\n"
"\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
case HELP_IOSTAT:
@@ -292,7 +294,7 @@ get_usage(zpool_help_t idx)
case HELP_SET:
return (gettext("\tset <property=value> <pool> \n"));
case HELP_SPLIT:
- return (gettext("\tsplit [-gLnP] [-R altroot] [-o mntopts]\n"
+ return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n"
"\t [-o property=value] <pool> <newpool> "
"[<device> ...]\n"));
case HELP_REGUID:
@@ -1955,6 +1957,7 @@ show_import(nvlist_t *config)
char *hostname = "unknown";
nvlist_t *nvroot, *nvinfo;
int reason;
+ zpool_errata_t errata;
const char *health;
uint_t vsc;
char *comment;
@@ -1973,7 +1976,7 @@ show_import(nvlist_t *config)
(uint64_t **)&vs, &vsc) == 0);
health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
- reason = zpool_import_status(config, &msgid);
+ reason = zpool_import_status(config, &msgid, &errata);
(void) printf(gettext(" pool: %s\n"), name);
(void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
@@ -2072,6 +2075,11 @@ show_import(nvlist_t *config)
"resilvered.\n"));
break;
+ case ZPOOL_STATUS_ERRATA:
+ (void) printf(gettext(" status: Errata #%d detected.\n"),
+ errata);
+ break;
+
default:
/*
* No other status can be seen when importing pools.
@@ -2093,6 +2101,55 @@ show_import(nvlist_t *config)
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier and\n\tthe '-f' flag.\n"));
+ } else if (reason == ZPOOL_STATUS_ERRATA) {
+ switch (errata) {
+ case ZPOOL_ERRATA_NONE:
+ break;
+
+ case ZPOOL_ERRATA_ZOL_2094_SCRUB:
+ (void) printf(gettext(" action: The pool can "
+ "be imported using its name or numeric "
+ "identifier,\n\thowever there is a compat"
+ "ibility issue which should be corrected"
+ "\n\tby running 'zpool scrub'\n"));
+ break;
+
+ case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
+ (void) printf(gettext(" action: The pool can"
+ "not be imported with this version of ZFS "
+ "due to\n\tan active asynchronous destroy. "
+ "Revert to an earlier version\n\tand "
+ "allow the destroy to complete before "
+ "updating.\n"));
+ break;
+
+ case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
+ (void) printf(gettext(" action: Existing "
+ "encrypted datasets contain an on-disk "
+ "incompatibility, which\n\tneeds to be "
+ "corrected. Backup these datasets to new "
+ "encrypted datasets\n\tand destroy the "
+ "old ones.\n"));
+ break;
+ case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
+ (void) printf(gettext(" action: Any existing "
+ "encrypted datasets contain an on-disk "
+ "incompatibility which\n\tmay cause "
+ "on-disk corruption with 'zfs recv' and "
+ "which needs to be\n\tcorrected. Enable "
+ "the bookmark_v2 feature and backup "
+ "these datasets to new encrypted "
+ "datasets and\n\tdestroy the old ones. "
+ "If this pool does not contain any "
+ "encrypted datasets, simply enable\n\t"
+ "the bookmark_v2 feature.\n"));
+ break;
+ default:
+ /*
+ * All errata must contain an action message.
+ */
+ assert(0);
+ }
} else {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
@@ -2235,6 +2292,7 @@ static int
do_import(nvlist_t *config, const char *newname, const char *mntopts,
nvlist_t *props, int flags)
{
+ int ret = 0;
zpool_handle_t *zhp;
char *name;
uint64_t version;
@@ -2315,6 +2373,16 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
return (1);
+ /*
+ * Loading keys is best effort. We don't want to return immediately
+ * if it fails but we do want to give the error to the caller.
+ */
+ if (flags & ZFS_IMPORT_LOAD_KEYS) {
+ ret = zfs_crypto_attempt_load_keys(g_zfs, name);
+ if (ret != 0)
+ ret = 1;
+ }
+
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
!(flags & ZFS_IMPORT_ONLY) &&
zpool_enable_datasets(zhp, mntopts, 0) != 0) {
@@ -2323,7 +2391,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
}
zpool_close(zhp);
- return (0);
+ return (ret);
}
/*
@@ -2401,9 +2469,9 @@ zpool_do_checkpoint(int argc, char **argv)
/*
* zpool import [-d dir] [-D]
- * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
+ * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
* [-d dir | -c cachefile] [-f] -a
- * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
+ * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
* [-d dir | -c cachefile] [-f] [-n] [-F] [-t]
* <pool | id> [newpool]
*
@@ -2443,6 +2511,7 @@ zpool_do_checkpoint(int argc, char **argv)
* -a Import all pools found.
*
* -o Set property=value and/or temporary mount options (without '=').
+ * -l Load encryption keys while importing.
*
* --rewind-to-checkpoint
* Import the pool and revert back to the checkpoint.
@@ -2487,7 +2556,7 @@ zpool_do_import(int argc, char **argv)
};
/* check options */
- while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:tT:VX",
+ while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX",
long_options, NULL)) != -1) {
switch (c) {
case 'a':
@@ -2518,6 +2587,9 @@ zpool_do_import(int argc, char **argv)
case 'F':
do_rewind = B_TRUE;
break;
+ case 'l':
+ flags |= ZFS_IMPORT_LOAD_KEYS;
+ break;
case 'm':
flags |= ZFS_IMPORT_MISSING_LOG;
break;
@@ -2591,6 +2663,17 @@ zpool_do_import(int argc, char **argv)
usage(B_FALSE);
}
+ if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
+ (void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
+ usage(B_FALSE);
+ }
+
+ if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) {
+ (void) fprintf(stderr, gettext("-l is only meaningful during "
+ "an import\n"));
+ usage(B_FALSE);
+ }
+
if ((dryrun || xtreme_rewind) && !do_rewind) {
(void) fprintf(stderr,
gettext("-n or -X only meaningful with -F\n"));
@@ -4034,6 +4117,7 @@ zpool_do_detach(int argc, char **argv)
* -o Set property=value, or set mount options.
* -P Display full path for vdev name.
* -R Mount the split-off pool under an alternate root.
+ * -l Load encryption keys while importing.
*
* Splits the named pool and gives it the new pool name. Devices to be split
* off may be listed, provided that no more than one device is specified
@@ -4051,6 +4135,7 @@ zpool_do_split(int argc, char **argv)
char *mntopts = NULL;
splitflags_t flags;
int c, ret = 0;
+ boolean_t loadkeys = B_FALSE;
zpool_handle_t *zhp;
nvlist_t *config, *props = NULL;
@@ -4059,7 +4144,7 @@ zpool_do_split(int argc, char **argv)
flags.name_flags = 0;
/* check options */
- while ((c = getopt(argc, argv, ":gLR:no:P")) != -1) {
+ while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) {
switch (c) {
case 'g':
flags.name_flags |= VDEV_NAME_GUID;
@@ -4076,6 +4161,9 @@ zpool_do_split(int argc, char **argv)
usage(B_FALSE);
}
break;
+ case 'l':
+ loadkeys = B_TRUE;
+ break;
case 'n':
flags.dryrun = B_TRUE;
break;
@@ -4114,6 +4202,12 @@ zpool_do_split(int argc, char **argv)
usage(B_FALSE);
}
+ if (!flags.import && loadkeys) {
+ (void) fprintf(stderr, gettext("loading keys is only "
+ "valid when importing the pool\n"));
+ usage(B_FALSE);
+ }
+
argc -= optind;
argv += optind;
@@ -4159,6 +4253,13 @@ zpool_do_split(int argc, char **argv)
*/
if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
return (1);
+
+ if (loadkeys) {
+ ret = zfs_crypto_attempt_load_keys(g_zfs, newpool);
+ if (ret != 0)
+ ret = 1;
+ }
+
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
zpool_enable_datasets(zhp, mntopts, 0) != 0) {
ret = 1;
@@ -5203,12 +5304,13 @@ status_callback(zpool_handle_t *zhp, void *data)
nvlist_t *config, *nvroot;
char *msgid;
int reason;
+ zpool_errata_t errata;
const char *health;
uint_t c;
vdev_stat_t *vs;
config = zpool_get_config(zhp, NULL);
- reason = zpool_get_status(zhp, &msgid);
+ reason = zpool_get_status(zhp, &msgid, &errata);
cbp->cb_count++;
@@ -5434,6 +5536,52 @@ status_callback(zpool_handle_t *zhp, void *data)
"'zpool clear'.\n"));
break;
+ case ZPOOL_STATUS_ERRATA:
+ (void) printf(gettext("status: Errata #%d detected.\n"),
+ errata);
+
+ switch (errata) {
+ case ZPOOL_ERRATA_NONE:
+ break;
+
+ case ZPOOL_ERRATA_ZOL_2094_SCRUB:
+ (void) printf(gettext("action: To correct the issue "
+ "run 'zpool scrub'.\n"));
+ break;
+
+ case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
+ (void) printf(gettext("\tExisting encrypted datasets "
+ "contain an on-disk incompatibility\n\twhich "
+ "needs to be corrected.\n"));
+ (void) printf(gettext("action: To correct the issue "
+ "backup existing encrypted datasets to new\n\t"
+ "encrypted datasets and destroy the old ones. "
+ "'zfs mount -o ro' can\n\tbe used to temporarily "
+ "mount existing encrypted datasets readonly.\n"));
+ break;
+
+ case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
+ (void) printf(gettext("\tExisting encrypted datasets "
+ "contain an on-disk incompatibility\n\twhich "
+ "needs to be corrected.\n"));
+ (void) printf(gettext("action: To correct the issue "
+ "enable the bookmark_v2 feature and "
+ "backup\n\tany existing encrypted datasets to "
+ "new encrypted datasets and\n\tdestroy the old "
+ "ones. If this pool does not contain any\n\t"
+ "encrypted datasets, simply enable the "
+ "bookmark_v2 feature\n"));
+ break;
+
+ default:
+ /*
+ * All errata which allow the pool to be imported
+ * must contain an action message.
+ */
+ assert(0);
+ }
+ break;
+
default:
/*
* The remaining errors can't actually be generated, yet.
diff --git a/usr/src/cmd/zstreamdump/zstreamdump.c b/usr/src/cmd/zstreamdump/zstreamdump.c
index 987f4fdf12..3f14c08179 100644
--- a/usr/src/cmd/zstreamdump/zstreamdump.c
+++ b/usr/src/cmd/zstreamdump/zstreamdump.c
@@ -196,12 +196,33 @@ print_block(char *buf, int length)
}
}
+/*
+ * Print an array of bytes to stdout as hexidecimal characters. str must
+ * have buf_len * 2 + 1 bytes of space.
+ */
+static void
+sprintf_bytes(char *str, uint8_t *buf, uint_t buf_len)
+{
+ int i, n;
+
+ for (i = 0; i < buf_len; i++) {
+ n = sprintf(str, "%02x", buf[i] & 0xff);
+ str += n;
+ }
+
+ str[0] = '\0';
+}
+
int
main(int argc, char *argv[])
{
char *buf = safe_malloc(SPA_MAXBLOCKSIZE);
uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };
+ char salt[ZIO_DATA_SALT_LEN * 2 + 1];
+ char iv[ZIO_DATA_IV_LEN * 2 + 1];
+ char mac[ZIO_DATA_MAC_LEN * 2 + 1];
uint64_t total_records = 0;
+ uint64_t payload_size;
dmu_replay_record_t thedrr;
dmu_replay_record_t *drr = &thedrr;
struct drr_begin *drrb = &thedrr.drr_u.drr_begin;
@@ -213,6 +234,7 @@ main(int argc, char *argv[])
struct drr_free *drrf = &thedrr.drr_u.drr_free;
struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
+ struct drr_object_range *drror = &thedrr.drr_u.drr_object_range;
struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;
char c;
boolean_t verbose = B_FALSE;
@@ -412,26 +434,37 @@ main(int argc, char *argv[])
drro->drr_blksz = BSWAP_32(drro->drr_blksz);
drro->drr_bonuslen =
BSWAP_32(drro->drr_bonuslen);
+ drro->drr_raw_bonuslen =
+ BSWAP_32(drro->drr_raw_bonuslen);
drro->drr_toguid = BSWAP_64(drro->drr_toguid);
}
+
+ payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
+
if (verbose) {
(void) printf("OBJECT object = %" PRIu64
- " type = %u bonustype = %u blksz = %u"
- " bonuslen = %u dn_slots = %u\n",
- drro->drr_object,
+ "type = %u bonustype = %u blksz = %u "
+ "bonuslen = %u "
+ "raw_bonuslen = %u flags = %u maxblkid "
+ "= %llu "
+ "indblkshift = %u nlevels = %u "
+ "nblkptr = %u\n",
+ (u_longlong_t)drro->drr_object,
drro->drr_type,
drro->drr_bonustype,
drro->drr_blksz,
drro->drr_bonuslen,
- drro->drr_dn_slots);
+ drro->drr_raw_bonuslen,
+ drro->drr_flags,
+ (u_longlong_t)drro->drr_maxblkid,
+ drro->drr_indblkshift,
+ drro->drr_nlevels,
+ drro->drr_nblkptr);
}
if (drro->drr_bonuslen > 0) {
- (void) ssread(buf,
- P2ROUNDUP(drro->drr_bonuslen, 8), &zc);
- if (dump) {
- print_block(buf,
- P2ROUNDUP(drro->drr_bonuslen, 8));
- }
+ (void) ssread(buf, payload_size, &zc);
+ if (dump)
+ print_block(buf, payload_size);
}
break;
@@ -465,28 +498,40 @@ main(int argc, char *argv[])
BSWAP_64(drrw->drr_compressed_size);
}
- uint64_t payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
+ payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
/*
* If this is verbose and/or dump output,
* print info on the modified block
*/
if (verbose) {
+ sprintf_bytes(salt, drrw->drr_salt,
+ ZIO_DATA_SALT_LEN);
+ sprintf_bytes(iv, drrw->drr_iv,
+ ZIO_DATA_IV_LEN);
+ sprintf_bytes(mac, drrw->drr_mac,
+ ZIO_DATA_MAC_LEN);
+
(void) printf("WRITE object = %llu type = %u "
"checksum type = %u compression type = %u\n"
- " offset = %llu logical_size = %llu "
+ " flags = %u offset = %llu "
+ "logical_size = %llu "
"compressed_size = %llu "
- "payload_size = %llu "
- "props = %llx\n",
+ "payload_size = %llu props = %llx "
+ "salt = %s iv = %s mac = %s\n",
(u_longlong_t)drrw->drr_object,
drrw->drr_type,
drrw->drr_checksumtype,
drrw->drr_compressiontype,
+ drrw->drr_flags,
(u_longlong_t)drrw->drr_offset,
(u_longlong_t)drrw->drr_logical_size,
(u_longlong_t)drrw->drr_compressed_size,
(u_longlong_t)payload_size,
- (u_longlong_t)drrw->drr_key.ddk_prop);
+ (u_longlong_t)drrw->drr_key.ddk_prop,
+ salt,
+ iv,
+ mac);
}
/*
@@ -557,15 +602,40 @@ main(int argc, char *argv[])
if (do_byteswap) {
drrs->drr_object = BSWAP_64(drrs->drr_object);
drrs->drr_length = BSWAP_64(drrs->drr_length);
+ drrs->drr_compressed_size =
+ BSWAP_64(drrs->drr_compressed_size);
+ drrs->drr_type = BSWAP_32(drrs->drr_type);
}
+
+ payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);
+
if (verbose) {
+ sprintf_bytes(salt, drrs->drr_salt,
+ ZIO_DATA_SALT_LEN);
+ sprintf_bytes(iv, drrs->drr_iv,
+ ZIO_DATA_IV_LEN);
+ sprintf_bytes(mac, drrs->drr_mac,
+ ZIO_DATA_MAC_LEN);
+
(void) printf("SPILL block for object = %llu "
- "length = %llu\n", drrs->drr_object,
- drrs->drr_length);
+ "length = %llu flags = %u "
+ "compression type = %u "
+ "compressed_size = %llu "
+ "payload_size = %llu "
+ "salt = %s iv = %s mac = %s\n",
+ (u_longlong_t)drrs->drr_object,
+ (u_longlong_t)drrs->drr_length,
+ drrs->drr_flags,
+ drrs->drr_compressiontype,
+ (u_longlong_t)drrs->drr_compressed_size,
+ (u_longlong_t)payload_size,
+ salt,
+ iv,
+ mac);
}
- (void) ssread(buf, drrs->drr_length, &zc);
+ (void) ssread(buf, payload_size, &zc);
if (dump) {
- print_block(buf, drrs->drr_length);
+ print_block(buf, payload_size);
}
break;
case DRR_WRITE_EMBEDDED:
@@ -600,6 +670,36 @@ main(int argc, char *argv[])
(void) ssread(buf,
P2ROUNDUP(drrwe->drr_psize, 8), &zc);
break;
+ case DRR_OBJECT_RANGE:
+ if (do_byteswap) {
+ drror->drr_firstobj =
+ BSWAP_64(drror->drr_firstobj);
+ drror->drr_numslots =
+ BSWAP_64(drror->drr_numslots);
+ drror->drr_toguid = BSWAP_64(drror->drr_toguid);
+ }
+ if (verbose) {
+ sprintf_bytes(salt, drror->drr_salt,
+ ZIO_DATA_SALT_LEN);
+ sprintf_bytes(iv, drror->drr_iv,
+ ZIO_DATA_IV_LEN);
+ sprintf_bytes(mac, drror->drr_mac,
+ ZIO_DATA_MAC_LEN);
+
+ (void) printf("OBJECT_RANGE firstobj = %llu "
+ "numslots = %llu flags = %u "
+ "salt = %s iv = %s mac = %s\n",
+ (u_longlong_t)drror->drr_firstobj,
+ (u_longlong_t)drror->drr_numslots,
+ drror->drr_flags,
+ salt,
+ iv,
+ mac);
+ }
+ break;
+ case DRR_NUMTYPES:
+ /* should never be reached */
+ exit(1);
}
if (drr->drr_type != DRR_BEGIN && very_verbose) {
(void) printf(" checksum = %llx/%llx/%llx/%llx\n",
diff --git a/usr/src/cmd/ztest/ztest.c b/usr/src/cmd/ztest/ztest.c
index c0054cddbe..39cdf261b9 100644
--- a/usr/src/cmd/ztest/ztest.c
+++ b/usr/src/cmd/ztest/ztest.c
@@ -212,6 +212,7 @@ extern unsigned long zfs_reconstruct_indirect_damage_fraction;
static ztest_shared_opts_t *ztest_shared_opts;
static ztest_shared_opts_t ztest_opts;
+static char *ztest_wkeydata = "abcdefghijklmnopqrstuvwxyz012345";
typedef struct ztest_shared_ds {
uint64_t zd_seq;
@@ -1213,6 +1214,42 @@ ztest_spa_prop_set_uint64(zpool_prop_t prop, uint64_t value)
return (error);
}
+static int
+ztest_dmu_objset_own(const char *name, dmu_objset_type_t type,
+ boolean_t readonly, boolean_t decrypt, void *tag, objset_t **osp)
+{
+ int err;
+
+ err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
+ if (decrypt && err == EACCES) {
+ char ddname[ZFS_MAX_DATASET_NAME_LEN];
+ dsl_crypto_params_t *dcp;
+ nvlist_t *crypto_args = fnvlist_alloc();
+ char *cp = NULL;
+
+ /* spa_keystore_load_wkey() expects a dsl dir name */
+ (void) strcpy(ddname, name);
+ cp = strchr(ddname, '@');
+ if (cp != NULL)
+ *cp = '\0';
+
+ fnvlist_add_uint8_array(crypto_args, "wkeydata",
+ (uint8_t *)ztest_wkeydata, WRAPPING_KEY_LEN);
+ VERIFY0(dsl_crypto_params_create_nvlist(DCP_CMD_NONE, NULL,
+ crypto_args, &dcp));
+ err = spa_keystore_load_wkey(ddname, dcp, B_FALSE);
+ dsl_crypto_params_free(dcp, B_FALSE);
+ fnvlist_free(crypto_args);
+
+ if (err != 0)
+ return (err);
+
+ err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
+ }
+
+ return (err);
+}
+
static void
ztest_rll_init(rll_t *rll)
{
@@ -1856,7 +1893,7 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap)
dmu_write(os, lr->lr_foid, offset, length, data, tx);
} else {
bcopy(data, abuf->b_data, length);
- dmu_assign_arcbuf(db, offset, abuf, tx);
+ dmu_assign_arcbuf_by_dbuf(db, offset, abuf, tx);
}
(void) ztest_log_write(zd, tx, lr);
@@ -2563,7 +2600,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
*/
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1);
VERIFY3U(ENOENT, ==,
- spa_create("ztest_bad_file", nvroot, NULL, NULL));
+ spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL));
nvlist_free(nvroot);
/*
@@ -2571,7 +2608,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
*/
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 2, 1);
VERIFY3U(ENOENT, ==,
- spa_create("ztest_bad_mirror", nvroot, NULL, NULL));
+ spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL));
nvlist_free(nvroot);
/*
@@ -2580,7 +2617,8 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
*/
rw_enter(&ztest_name_lock, RW_READER);
nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1);
- VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL));
+ VERIFY3U(EEXIST, ==,
+ spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL));
nvlist_free(nvroot);
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
VERIFY3U(EBUSY, ==, spa_destroy(zo->zo_pool));
@@ -2691,7 +2729,7 @@ ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
props = fnvlist_alloc();
fnvlist_add_uint64(props,
zpool_prop_to_name(ZPOOL_PROP_VERSION), version);
- VERIFY0(spa_create(name, nvroot, props, NULL));
+ VERIFY0(spa_create(name, nvroot, props, NULL, NULL));
fnvlist_free(nvroot);
fnvlist_free(props);
@@ -3713,11 +3751,65 @@ ztest_objset_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
static int
ztest_dataset_create(char *dsname)
{
- uint64_t zilset = ztest_random(100);
- int err = dmu_objset_create(dsname, DMU_OST_OTHER, 0,
+ int err;
+ uint64_t rand;
+ dsl_crypto_params_t *dcp = NULL;
+
+ /*
+ * 50% of the time, we create encrypted datasets
+ * using a random cipher suite and a hard-coded
+ * wrapping key.
+ */
+#ifdef WITHCRYPTO
+ /*
+ * Until the crypto framework is compiled in userland, the ztest using
+ * crypto will not work.
+ */
+ rand = ztest_random(2);
+#else
+ rand = 0;
+#endif
+ if (rand != 0) {
+ nvlist_t *crypto_args = fnvlist_alloc();
+ nvlist_t *props = fnvlist_alloc();
+
+ /* slight bias towards the default cipher suite */
+ rand = ztest_random(ZIO_CRYPT_FUNCTIONS);
+ if (rand < ZIO_CRYPT_AES_128_CCM)
+ rand = ZIO_CRYPT_ON;
+
+ fnvlist_add_uint64(props,
+ zfs_prop_to_name(ZFS_PROP_ENCRYPTION), rand);
+ fnvlist_add_uint8_array(crypto_args, "wkeydata",
+ (uint8_t *)ztest_wkeydata, WRAPPING_KEY_LEN);
+
+ /*
+ * These parameters aren't really used by the kernel. They
+ * are simply stored so that userspace knows how to load
+ * the wrapping key.
+ */
+ fnvlist_add_uint64(props,
+ zfs_prop_to_name(ZFS_PROP_KEYFORMAT), ZFS_KEYFORMAT_RAW);
+ fnvlist_add_string(props,
+ zfs_prop_to_name(ZFS_PROP_KEYLOCATION), "prompt");
+ fnvlist_add_uint64(props,
+ zfs_prop_to_name(ZFS_PROP_PBKDF2_SALT), 0ULL);
+ fnvlist_add_uint64(props,
+ zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS), 0ULL);
+
+ VERIFY0(dsl_crypto_params_create_nvlist(DCP_CMD_NONE, props,
+ crypto_args, &dcp));
+
+ fnvlist_free(crypto_args);
+ fnvlist_free(props);
+ }
+
+ err = dmu_objset_create(dsname, DMU_OST_OTHER, 0, dcp,
ztest_objset_create_cb, NULL);
+ dsl_crypto_params_free(dcp, !!err);
- if (err || zilset < 80)
+ rand = ztest_random(100);
+ if (err || rand < 80)
return (err);
if (ztest_opts.zo_verbose >= 6)
@@ -3737,7 +3829,8 @@ ztest_objset_destroy_cb(const char *name, void *arg)
/*
* Verify that the dataset contains a directory object.
*/
- VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_TRUE, FTAG, &os));
+ VERIFY0(ztest_dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
+ B_TRUE, FTAG, &os));
error = dmu_object_info(os, ZTEST_DIROBJ, &doi);
if (error != ENOENT) {
/* We could have crashed in the middle of destroying it */
@@ -3745,7 +3838,7 @@ ztest_objset_destroy_cb(const char *name, void *arg)
ASSERT3U(doi.doi_type, ==, DMU_OT_ZAP_OTHER);
ASSERT3S(doi.doi_physical_blocks_512, >=, 0);
}
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_TRUE, FTAG);
/*
* Destroy the dataset.
@@ -3818,11 +3911,12 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
* (invoked from ztest_objset_destroy_cb()) should just throw it away.
*/
if (ztest_random(2) == 0 &&
- dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os) == 0) {
+ ztest_dmu_objset_own(name, DMU_OST_OTHER, B_FALSE,
+ B_TRUE, FTAG, &os) == 0) {
ztest_zd_init(&zdtmp, NULL, os);
zil_replay(os, &zdtmp, ztest_replay_vector);
ztest_zd_fini(&zdtmp);
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_TRUE, FTAG);
}
/*
@@ -3836,8 +3930,8 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
/*
* Verify that the destroyed dataset is no longer in the namespace.
*/
- VERIFY3U(ENOENT, ==, dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
- FTAG, &os));
+ VERIFY3U(ENOENT, ==, ztest_dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
+ B_TRUE, FTAG, &os));
/*
* Verify that we can create a new dataset.
@@ -3852,7 +3946,8 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
fatal(0, "dmu_objset_create(%s) = %d", name, error);
}
- VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
+ VERIFY0(ztest_dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, B_TRUE,
+ FTAG, &os));
ztest_zd_init(&zdtmp, NULL, os);
@@ -3876,7 +3971,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
* Verify that we cannot create an existing dataset.
*/
VERIFY3U(EEXIST, ==,
- dmu_objset_create(name, DMU_OST_OTHER, 0, NULL, NULL));
+ dmu_objset_create(name, DMU_OST_OTHER, 0, NULL, NULL, NULL));
/*
* Verify that we can hold an objset that is also owned.
@@ -3887,11 +3982,11 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
/*
* Verify that we cannot own an objset that is already owned.
*/
- VERIFY3U(EBUSY, ==,
- dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os2));
+ VERIFY3U(EBUSY, ==, ztest_dmu_objset_own(name, DMU_OST_OTHER,
+ B_FALSE, B_TRUE, FTAG, &os2));
zil_close(zilog);
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_TRUE, FTAG);
ztest_zd_fini(&zdtmp);
rw_exit(&ztest_name_lock);
@@ -4025,19 +4120,20 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
fatal(0, "dmu_objset_create(%s) = %d", clone2name, error);
}
- error = dmu_objset_own(snap2name, DMU_OST_ANY, B_TRUE, FTAG, &os);
+ error = ztest_dmu_objset_own(snap2name, DMU_OST_ANY, B_TRUE, B_TRUE,
+ FTAG, &os);
if (error)
fatal(0, "dmu_objset_own(%s) = %d", snap2name, error);
error = dsl_dataset_promote(clone2name, NULL);
if (error == ENOSPC) {
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_TRUE, FTAG);
ztest_record_enospc(FTAG);
goto out;
}
if (error != EBUSY)
fatal(0, "dsl_dataset_promote(%s), %d, not EBUSY", clone2name,
error);
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_TRUE, FTAG);
out:
ztest_dsl_dataset_cleanup(osname, id);
@@ -4403,7 +4499,7 @@ ztest_dmu_read_write_zcopy(ztest_ds_t *zd, uint64_t id)
* bigobj, at the tail of the nth chunk
*
* The chunk size is set equal to bigobj block size so that
- * dmu_assign_arcbuf() can be tested for object updates.
+ * dmu_assign_arcbuf_by_dbuf() can be tested for object updates.
*/
/*
@@ -4463,7 +4559,7 @@ ztest_dmu_read_write_zcopy(ztest_ds_t *zd, uint64_t id)
/*
* In iteration 5 (i == 5) use arcbufs
* that don't match bigobj blksz to test
- * dmu_assign_arcbuf() when it can't directly
+ * dmu_assign_arcbuf_by_dbuf() when it can't directly
* assign an arcbuf to a dbuf.
*/
for (j = 0; j < s; j++) {
@@ -4508,8 +4604,8 @@ ztest_dmu_read_write_zcopy(ztest_ds_t *zd, uint64_t id)
/*
* 50% of the time don't read objects in the 1st iteration to
- * test dmu_assign_arcbuf() for the case when there're no
- * existing dbufs for the specified offsets.
+ * test dmu_assign_arcbuf_by_dbuf() for the case when there are
+ * no existing dbufs for the specified offsets.
*/
if (i != 0 || ztest_random(2) != 0) {
error = dmu_read(os, packobj, packoff,
@@ -4554,12 +4650,12 @@ ztest_dmu_read_write_zcopy(ztest_ds_t *zd, uint64_t id)
FTAG, &dbt, DMU_READ_NO_PREFETCH) == 0);
}
if (i != 5 || chunksize < (SPA_MINBLOCKSIZE * 2)) {
- dmu_assign_arcbuf(bonus_db, off,
+ dmu_assign_arcbuf_by_dbuf(bonus_db, off,
bigbuf_arcbufs[j], tx);
} else {
- dmu_assign_arcbuf(bonus_db, off,
+ dmu_assign_arcbuf_by_dbuf(bonus_db, off,
bigbuf_arcbufs[2 * j], tx);
- dmu_assign_arcbuf(bonus_db,
+ dmu_assign_arcbuf_by_dbuf(bonus_db,
off + chunksize / 2,
bigbuf_arcbufs[2 * j + 1], tx);
}
@@ -6273,7 +6369,8 @@ ztest_dataset_open(int d)
}
ASSERT(error == 0 || error == EEXIST);
- VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, zd, &os));
+ VERIFY0(ztest_dmu_objset_own(name, DMU_OST_OTHER, B_FALSE,
+ B_TRUE, zd, &os));
rw_exit(&ztest_name_lock);
ztest_zd_init(zd, ZTEST_GET_SHARED_DS(d), os);
@@ -6314,7 +6411,7 @@ ztest_dataset_close(int d)
ztest_ds_t *zd = &ztest_ds[d];
zil_close(zd->zd_zilog);
- dmu_objset_disown(zd->zd_os, zd);
+ dmu_objset_disown(zd->zd_os, B_TRUE, zd);
ztest_zd_fini(zd);
}
@@ -6364,13 +6461,13 @@ ztest_run(ztest_shared_t *zs)
ztest_spa = spa;
dmu_objset_stats_t dds;
- VERIFY0(dmu_objset_own(ztest_opts.zo_pool,
- DMU_OST_ANY, B_TRUE, FTAG, &os));
+ VERIFY0(ztest_dmu_objset_own(ztest_opts.zo_pool,
+ DMU_OST_ANY, B_TRUE, B_TRUE, FTAG, &os));
dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
dmu_objset_fast_stat(os, &dds);
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
zs->zs_guid = dds.dds_guid;
- dmu_objset_disown(os, FTAG);
+ dmu_objset_disown(os, B_TRUE, FTAG);
spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
@@ -6584,10 +6681,9 @@ ztest_freeze(void)
VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG));
ASSERT(spa_freeze_txg(spa) == UINT64_MAX);
VERIFY3U(0, ==, ztest_dataset_open(0));
- ztest_dataset_close(0);
-
ztest_spa = spa;
txg_wait_synced(spa_get_dsl(spa), 0);
+ ztest_dataset_close(0);
ztest_reguid(NULL, 0);
spa_close(spa, FTAG);
@@ -6715,7 +6811,8 @@ ztest_init(ztest_shared_t *zs)
spa_feature_table[i].fi_uname);
VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0));
}
- VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props, NULL));
+ VERIFY3U(0, ==,
+ spa_create(ztest_opts.zo_pool, nvroot, props, NULL, NULL));
nvlist_free(nvroot);
nvlist_free(props);
@@ -6748,7 +6845,6 @@ setup_data_fd(void)
(void) unlink(ztest_name_data);
}
-
static int
shared_data_size(ztest_shared_hdr_t *hdr)
{