Replay logs before starting ztest workers

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.

Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #8084
This commit is contained in:
Tom Caputi 2018-11-07 18:40:24 -05:00 committed by Brian Behlendorf
parent ac53e50f79
commit f44ad9297d
2 changed files with 77 additions and 13 deletions

View File

@ -1304,20 +1304,19 @@ ztest_dmu_objset_own(const char *name, dmu_objset_type_t type,
boolean_t readonly, boolean_t decrypt, void *tag, objset_t **osp) boolean_t readonly, boolean_t decrypt, void *tag, objset_t **osp)
{ {
int err; 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; char *cp = NULL;
char ddname[ZFS_MAX_DATASET_NAME_LEN];
/* spa_keystore_load_wkey() expects a dsl dir name */
strcpy(ddname, name); strcpy(ddname, name);
cp = strchr(ddname, '@'); cp = strchr(ddname, '@');
if (cp != NULL) if (cp != NULL)
*cp = '\0'; *cp = '\0';
err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
while (decrypt && err == EACCES) {
dsl_crypto_params_t *dcp;
nvlist_t *crypto_args = fnvlist_alloc();
fnvlist_add_uint8_array(crypto_args, "wkeydata", fnvlist_add_uint8_array(crypto_args, "wkeydata",
(uint8_t *)ztest_wkeydata, WRAPPING_KEY_LEN); (uint8_t *)ztest_wkeydata, WRAPPING_KEY_LEN);
VERIFY0(dsl_crypto_params_create_nvlist(DCP_CMD_NONE, NULL, VERIFY0(dsl_crypto_params_create_nvlist(DCP_CMD_NONE, NULL,
@ -1326,10 +1325,26 @@ ztest_dmu_objset_own(const char *name, dmu_objset_type_t type,
dsl_crypto_params_free(dcp, B_FALSE); dsl_crypto_params_free(dcp, B_FALSE);
fnvlist_free(crypto_args); fnvlist_free(crypto_args);
if (err != 0) if (err == EINVAL) {
/*
* 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 = strrchr(ddname, '/');
if (cp == NULL)
return (err); return (err);
*cp = '\0';
err = EACCES;
continue;
} else if (err != 0) {
break;
}
err = dmu_objset_own(name, type, readonly, decrypt, tag, osp); err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
break;
} }
return (err); return (err);
@ -6744,6 +6759,39 @@ ztest_dataset_close(int d)
ztest_zd_fini(zd); 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));
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);
if (dmu_objset_zil(os)->zl_parse_lr_count != 0 &&
ztest_opts.zo_verbose >= 6) {
zilog_t *zilog = dmu_objset_zil(os);
(void) printf("%s replay %llu blocks, %llu records, seq %llu\n",
name,
(u_longlong_t)zilog->zl_parse_blk_count,
(u_longlong_t)zilog->zl_parse_lr_count,
(u_longlong_t)zilog->zl_replaying_seq);
}
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. * Kick off threads to run tests on all datasets in parallel.
*/ */
@ -6845,6 +6893,15 @@ ztest_run(ztest_shared_t *zs)
if (ztest_opts.zo_verbose >= 4) if (ztest_opts.zo_verbose >= 4)
(void) printf("starting main threads...\n"); (void) printf("starting main threads...\n");
/*
* Replay all logs of all datasets in the pool. This is primarily for
* temporary datasets which wouldn't otherwise get replayed, which
* can trigger failures when attempting to offline a SLOG in
* ztest_fault_inject().
*/
(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. * Kick off all the tests that run in parallel.
*/ */

View File

@ -758,7 +758,7 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp,
dsl_crypto_key_t *dck = NULL; dsl_crypto_key_t *dck = NULL;
dsl_wrapping_key_t *wkey = dcp->cp_wkey; dsl_wrapping_key_t *wkey = dcp->cp_wkey;
dsl_pool_t *dp = NULL; 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 * We don't validate the wrapping key's keyformat, salt, or iters
@ -775,7 +775,7 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp,
goto error; goto error;
if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ENCRYPTION)) { if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ENCRYPTION)) {
ret = (SET_ERROR(ENOTSUP)); ret = SET_ERROR(ENOTSUP);
goto error; goto error;
} }
@ -786,6 +786,13 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp,
goto error; 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 */ /* initialize the wkey's ddobj */
wkey->wk_ddobj = dd->dd_object; wkey->wk_ddobj = dd->dd_object;