Skip to content

Commit

Permalink
Replay logs before starting ztest workers
Browse files Browse the repository at this point in the history
This patch ensures that logs are replayed on all datasets prior
to starting ztest workers. This ensures that the call to
vdev_offline() a log device in ztest_fault_inject() will not fail
due to the log device being required for replay.

This patch also fixes a small issue found during testing where
spa_keystore_load_wkey() does not check that the dataset specified
is an encryption root. This check was present in libzfs, however.

Signed-off-by: Tom Caputi <tcaputi@datto.com>

TEST_ZTEST_TIMEOUT=3600
  • Loading branch information
Tom Caputi committed Oct 31, 2018
1 parent f3af06a commit 6459492
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
67 changes: 56 additions & 11 deletions cmd/ztest/ztest.c
Original file line number Diff line number Diff line change
Expand Up @@ -1304,19 +1304,18 @@ 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;
char *cp = NULL;
char ddname[ZFS_MAX_DATASET_NAME_LEN];

strcpy(ddname, name);
cp = strchr(ddname, '@');
if (cp != NULL)
*cp = '\0';

err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
if (decrypt && err == EACCES) {
char ddname[ZFS_MAX_DATASET_NAME_LEN];
while (decrypt && err == EACCES) {
dsl_crypto_params_t *dcp;
nvlist_t *crypto_args = fnvlist_alloc();
char *cp = NULL;

/* spa_keystore_load_wkey() expects a dsl dir name */
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);
Expand All @@ -1326,10 +1325,23 @@ ztest_dmu_objset_own(const char *name, dmu_objset_type_t type,
dsl_crypto_params_free(dcp, B_FALSE);
fnvlist_free(crypto_args);

if (err != 0)
return (err);
if (err != 0) {
/*
* We couldn't load a key for this dataset so try
* the parent. This loop will eventually hit the
* encryption root since ztest only makes clones
* as children of their origin datasets.
*/
cp = strchr(ddname, '/');
if (cp == NULL)
return (err);

*cp = '\0';
continue;
}

err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
break;
}

return (err);
Expand Down Expand Up @@ -6744,6 +6756,34 @@ ztest_dataset_close(int d)
ztest_zd_fini(zd);
}

/* ARGSUSED */
static int
ztest_replay_zil_cb(const char *name, void *arg)
{
objset_t *os;
ztest_ds_t *zdtmp;

VERIFY0(ztest_dmu_objset_own(name, DMU_OST_ANY, B_TRUE,
B_TRUE, FTAG, &os));

if (dmu_objset_zil(os)->zl_parse_lr_count != 0 &&
ztest_opts.zo_verbose >= 4) {
(void) printf("replaying logs for '%s' (%llu records)\n", name,
(unsigned long long)dmu_objset_zil(os)->zl_parse_lr_count);
}

zdtmp = umem_alloc(sizeof (ztest_ds_t), UMEM_NOFAIL);

ztest_zd_init(zdtmp, NULL, os);
zil_replay(os, zdtmp, ztest_replay_vector);
ztest_zd_fini(zdtmp);

umem_free(zdtmp, sizeof (ztest_ds_t));

dmu_objset_disown(os, B_TRUE, FTAG);
return (0);
}

/*
* Kick off threads to run tests on all datasets in parallel.
*/
Expand Down Expand Up @@ -6845,6 +6885,11 @@ ztest_run(ztest_shared_t *zs)
if (ztest_opts.zo_verbose >= 4)
(void) printf("starting main threads...\n");


/* Replay all logs of all datasets in the pool */
(void) dmu_objset_find(ztest_opts.zo_pool, ztest_replay_zil_cb,
NULL, DS_FIND_CHILDREN);

/*
* Kick off all the tests that run in parallel.
*/
Expand Down
9 changes: 8 additions & 1 deletion module/zfs/dsl_crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp,
dsl_crypto_key_t *dck = NULL;
dsl_wrapping_key_t *wkey = dcp->cp_wkey;
dsl_pool_t *dp = NULL;
uint64_t keyformat, salt, iters;
uint64_t rddobj, keyformat, salt, iters;

/*
* We don't validate the wrapping key's keyformat, salt, or iters
Expand Down Expand Up @@ -786,6 +786,13 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp,
goto error;
}

/* confirm that dd is the encryption root */
ret = dsl_dir_get_encryption_root_ddobj(dd, &rddobj);
if (ret != 0 || rddobj != dd->dd_object) {
ret = (SET_ERROR(EINVAL));
goto error;
}

/* initialize the wkey's ddobj */
wkey->wk_ddobj = dd->dd_object;

Expand Down

0 comments on commit 6459492

Please sign in to comment.