]> granicus.if.org Git - zfs/commitdiff
Replay logs before starting ztest workers
authorTom Caputi <tcaputi@datto.com>
Wed, 7 Nov 2018 23:40:24 +0000 (18:40 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 7 Nov 2018 23:40:24 +0000 (15:40 -0800)
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

cmd/ztest/ztest.c
module/zfs/dsl_crypt.c

index 1ad87bb30cdf45d26dd9d1af59eeb5cf21cce723..36647c4ff9d00cd8b16df97be4e94c7785db5de4 100644 (file)
@@ -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);
@@ -1326,10 +1325,26 @@ 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 == 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);
+
+                       *cp = '\0';
+                       err = EACCES;
+                       continue;
+               } else if (err != 0) {
+                       break;
+               }
 
                err = dmu_objset_own(name, type, readonly, decrypt, tag, osp);
+               break;
        }
 
        return (err);
@@ -6744,6 +6759,39 @@ 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));
+
+       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.
  */
@@ -6845,6 +6893,15 @@ 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. 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.
         */
index d2545c6fa41b5b6f90bbc5fb1749d5d1d1f9aa8e..da2a126f2ebc4e05c6dfb608f8df88e72851aace 100644 (file)
@@ -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
@@ -775,7 +775,7 @@ spa_keystore_load_wkey(const char *dsname, dsl_crypto_params_t *dcp,
                goto error;
 
        if (!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_ENCRYPTION)) {
-               ret = (SET_ERROR(ENOTSUP));
+               ret = SET_ERROR(ENOTSUP);
                goto error;
        }
 
@@ -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;