]> git.proxmox.com Git - mirror_zfs.git/blobdiff - cmd/ztest/ztest.c
Illumos #3949, #3950, #3952, #3953
[mirror_zfs.git] / cmd / ztest / ztest.c
index 07b81cc27ee298b700874fd4fc2bf6894acbe8e3..572af3e0bb41aab7c0151ad5e7e59769e06670d8 100644 (file)
@@ -22,6 +22,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
  */
 
 /*
 #include <sys/metaslab_impl.h>
 #include <sys/dsl_prop.h>
 #include <sys/dsl_dataset.h>
+#include <sys/dsl_destroy.h>
 #include <sys/dsl_scan.h>
 #include <sys/zio_checksum.h>
 #include <sys/refcount.h>
 #include <sys/zfeature.h>
+#include <sys/dsl_userhold.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
@@ -205,6 +208,7 @@ enum ztest_io_type {
        ZTEST_IO_WRITE_ZEROES,
        ZTEST_IO_TRUNCATE,
        ZTEST_IO_SETATTR,
+       ZTEST_IO_REWRITE,
        ZTEST_IO_TYPES
 };
 
@@ -362,12 +366,12 @@ ztest_info_t ztest_info[] = {
        { ztest_fault_inject,                   1,      &zopt_sometimes },
        { ztest_ddt_repair,                     1,      &zopt_sometimes },
        { ztest_dmu_snapshot_hold,              1,      &zopt_sometimes },
-       { ztest_reguid,                         1,      &zopt_sometimes },
+       { ztest_reguid,                         1,      &zopt_rarely    },
        { ztest_spa_rename,                     1,      &zopt_rarely    },
        { ztest_scrub,                          1,      &zopt_rarely    },
        { ztest_spa_upgrade,                    1,      &zopt_rarely    },
        { ztest_dsl_dataset_promote_busy,       1,      &zopt_rarely    },
-       { ztest_vdev_attach_detach,             1,      &zopt_rarely    },
+       { ztest_vdev_attach_detach,             1,      &zopt_sometimes },
        { ztest_vdev_LUN_growth,                1,      &zopt_rarely    },
        { ztest_vdev_add_remove,                1,
            &ztest_opts.zo_vdevtime                             },
@@ -1031,19 +1035,17 @@ ztest_dsl_prop_set_uint64(char *osname, zfs_prop_t prop, uint64_t value,
        uint64_t curval;
        int error;
 
-       error = dsl_prop_set(osname, propname,
-           (inherit ? ZPROP_SRC_NONE : ZPROP_SRC_LOCAL),
-           sizeof (value), 1, &value);
+       error = dsl_prop_set_int(osname, propname,
+           (inherit ? ZPROP_SRC_NONE : ZPROP_SRC_LOCAL), value);
 
        if (error == ENOSPC) {
                ztest_record_enospc(FTAG);
                return (error);
        }
-       ASSERT3U(error, ==, 0);
+       ASSERT0(error);
 
        setpoint = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
-       VERIFY3U(dsl_prop_get(osname, propname, sizeof (curval),
-           1, &curval, setpoint), ==, 0);
+       VERIFY0(dsl_prop_get_integer(osname, propname, &curval, setpoint));
 
        if (ztest_opts.zo_verbose >= 6) {
                VERIFY(zfs_prop_index_to_string(prop, curval, &valname) == 0);
@@ -1073,7 +1075,7 @@ ztest_spa_prop_set_uint64(zpool_prop_t prop, uint64_t value)
                ztest_record_enospc(FTAG);
                return (error);
        }
-       ASSERT3U(error, ==, 0);
+       ASSERT0(error);
 
        return (error);
 }
@@ -1776,7 +1778,7 @@ ztest_replay_setattr(ztest_ds_t *zd, lr_setattr_t *lr, boolean_t byteswap)
 
        ASSERT3U(lr->lr_size, >=, sizeof (*bbt));
        ASSERT3U(lr->lr_size, <=, db->db_size);
-       VERIFY3U(dmu_set_bonus(db, lr->lr_size, tx), ==, 0);
+       VERIFY0(dmu_set_bonus(db, lr->lr_size, tx));
        bbt = ztest_bt_bonus(db);
 
        ztest_bt_generate(bbt, os, lr->lr_foid, -1ULL, lr->lr_mode, txg, crtxg);
@@ -1792,19 +1794,19 @@ ztest_replay_setattr(ztest_ds_t *zd, lr_setattr_t *lr, boolean_t byteswap)
        return (0);
 }
 
-zil_replay_func_t *ztest_replay_vector[TX_MAX_TYPE] = {
+zil_replay_func_t ztest_replay_vector[TX_MAX_TYPE] = {
        NULL,                           /* 0 no such transaction type */
-       (zil_replay_func_t *)ztest_replay_create,       /* TX_CREATE */
+       (zil_replay_func_t)ztest_replay_create,         /* TX_CREATE */
        NULL,                                           /* TX_MKDIR */
        NULL,                                           /* TX_MKXATTR */
        NULL,                                           /* TX_SYMLINK */
-       (zil_replay_func_t *)ztest_replay_remove,       /* TX_REMOVE */
+       (zil_replay_func_t)ztest_replay_remove,         /* TX_REMOVE */
        NULL,                                           /* TX_RMDIR */
        NULL,                                           /* TX_LINK */
        NULL,                                           /* TX_RENAME */
-       (zil_replay_func_t *)ztest_replay_write,        /* TX_WRITE */
-       (zil_replay_func_t *)ztest_replay_truncate,     /* TX_TRUNCATE */
-       (zil_replay_func_t *)ztest_replay_setattr,      /* TX_SETATTR */
+       (zil_replay_func_t)ztest_replay_write,          /* TX_WRITE */
+       (zil_replay_func_t)ztest_replay_truncate,       /* TX_TRUNCATE */
+       (zil_replay_func_t)ztest_replay_setattr,        /* TX_SETATTR */
        NULL,                                           /* TX_ACL */
        NULL,                                           /* TX_CREATE_ACL */
        NULL,                                           /* TX_CREATE_ATTR */
@@ -1899,6 +1901,12 @@ ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
                    DMU_READ_NO_PREFETCH);
 
                if (error == 0) {
+                       blkptr_t *obp = dmu_buf_get_blkptr(db);
+                       if (obp) {
+                               ASSERT(BP_IS_HOLE(bp));
+                               *bp = *obp;
+                       }
+
                        zgd->zgd_db = db;
                        zgd->zgd_bp = bp;
 
@@ -2047,6 +2055,9 @@ ztest_remove(ztest_ds_t *zd, ztest_od_t *od, int count)
                        continue;
                }
 
+               /*
+                * No object was found.
+                */
                if (od->od_object == 0)
                        continue;
 
@@ -2162,6 +2173,7 @@ ztest_prealloc(ztest_ds_t *zd, uint64_t object, uint64_t offset, uint64_t size)
 static void
 ztest_io(ztest_ds_t *zd, uint64_t object, uint64_t offset)
 {
+       int err;
        ztest_block_tag_t wbt;
        dmu_object_info_t doi;
        enum ztest_io_type io_type;
@@ -2216,6 +2228,25 @@ ztest_io(ztest_ds_t *zd, uint64_t object, uint64_t offset)
                break;
        default:
                break;
+
+       case ZTEST_IO_REWRITE:
+               (void) rw_enter(&ztest_name_lock, RW_READER);
+               err = ztest_dsl_prop_set_uint64(zd->zd_name,
+                   ZFS_PROP_CHECKSUM, spa_dedup_checksum(ztest_spa),
+                   B_FALSE);
+               VERIFY(err == 0 || err == ENOSPC);
+               err = ztest_dsl_prop_set_uint64(zd->zd_name,
+                   ZFS_PROP_COMPRESSION,
+                   ztest_random_dsl_prop(ZFS_PROP_COMPRESSION),
+                   B_FALSE);
+               VERIFY(err == 0 || err == ENOSPC);
+               (void) rw_exit(&ztest_name_lock);
+
+               VERIFY0(dmu_read(zd->zd_os, object, offset, blocksize, data,
+                   DMU_READ_NO_PREFETCH));
+
+               (void) ztest_write(zd, object, offset, blocksize, data);
+               break;
        }
 
        (void) rw_exit(&zd->zd_zilog_lock);
@@ -2303,6 +2334,11 @@ ztest_zil_remount(ztest_ds_t *zd, uint64_t id)
 {
        objset_t *os = zd->zd_os;
 
+       /*
+        * We grab the zd_dirobj_lock to ensure that no other thread is
+        * updating the zil (i.e. adding in-memory log records) and the
+        * zd_zilog_lock to block any I/O.
+        */
        mutex_enter(&zd->zd_dirobj_lock);
        (void) rw_enter(&zd->zd_zilog_lock, RW_WRITER);
 
@@ -2334,7 +2370,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
         */
        nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
        VERIFY3U(ENOENT, ==,
-           spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL));
+           spa_create("ztest_bad_file", nvroot, NULL, NULL));
        nvlist_free(nvroot);
 
        /*
@@ -2342,7 +2378,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
         */
        nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 2, 1);
        VERIFY3U(ENOENT, ==,
-           spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL));
+           spa_create("ztest_bad_mirror", nvroot, NULL, NULL));
        nvlist_free(nvroot);
 
        /*
@@ -2351,7 +2387,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
         */
        (void) rw_enter(&ztest_name_lock, RW_READER);
        nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, 0, 0, 0, 1);
-       VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL));
+       VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL));
        nvlist_free(nvroot);
        VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
        VERIFY3U(EBUSY, ==, spa_destroy(zo->zo_pool));
@@ -2409,7 +2445,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);
-       VERIFY3S(spa_create(name, nvroot, props, NULL, NULL), ==, 0);
+       VERIFY3S(spa_create(name, nvroot, props, NULL), ==, 0);
        fnvlist_free(nvroot);
        fnvlist_free(props);
 
@@ -2484,8 +2520,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
        int error;
 
        mutex_enter(&ztest_vdev_lock);
-       leaves =
-               MAX(zs->zs_mirrors + zs->zs_splits, 1) * ztest_opts.zo_raidz;
+       leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) * ztest_opts.zo_raidz;
 
        spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
 
@@ -2507,7 +2542,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
                 * prevent a race between removing a slog (dmu_objset_find)
                 * and destroying a dataset. Removing the slog will
                 * grab a reference on the dataset which may cause
-                * dmu_objset_destroy() to fail with EBUSY thus
+                * dsl_destroy_head() to fail with EBUSY thus
                 * leaving the dataset in an inconsistent state.
                 */
                rw_enter(&ztest_name_lock, RW_WRITER);
@@ -2581,7 +2616,7 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
                zs->zs_vdev_aux = 0;
                for (;;) {
                        int c;
-                       (void) snprintf(path, sizeof (path), ztest_aux_template,
+                       (void) snprintf(path, MAXPATHLEN, ztest_aux_template,
                            ztest_opts.zo_dir, ztest_opts.zo_pool, aux,
                            zs->zs_vdev_aux);
                        for (c = 0; c < sav->sav_count; c++)
@@ -3196,20 +3231,24 @@ ztest_objset_destroy_cb(const char *name, void *arg)
        /*
         * Verify that the dataset contains a directory object.
         */
-       VERIFY3U(0, ==, dmu_objset_hold(name, FTAG, &os));
+       VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, 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 */
-               ASSERT3U(error, ==, 0);
+               ASSERT0(error);
                ASSERT3U(doi.doi_type, ==, DMU_OT_ZAP_OTHER);
                ASSERT3S(doi.doi_physical_blocks_512, >=, 0);
        }
-       dmu_objset_rele(os, FTAG);
+       dmu_objset_disown(os, FTAG);
 
        /*
         * Destroy the dataset.
         */
-       VERIFY3U(0, ==, dmu_objset_destroy(name, B_FALSE));
+       if (strchr(name, '@') != NULL) {
+               VERIFY0(dsl_destroy_snapshot(name, B_FALSE));
+       } else {
+               VERIFY0(dsl_destroy_head(name));
+       }
        return (0);
 }
 
@@ -3219,17 +3258,17 @@ ztest_snapshot_create(char *osname, uint64_t id)
        char snapname[MAXNAMELEN];
        int error;
 
-       (void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
-           (u_longlong_t)id);
+       (void) snprintf(snapname, sizeof (snapname), "%llu", (u_longlong_t)id);
 
-       error = dmu_objset_snapshot(osname, strchr(snapname, '@') + 1,
-           NULL, NULL, B_FALSE, B_FALSE, -1);
+       error = dmu_objset_snapshot_one(osname, snapname);
        if (error == ENOSPC) {
                ztest_record_enospc(FTAG);
                return (B_FALSE);
        }
-       if (error != 0 && error != EEXIST)
-               fatal(0, "ztest_snapshot_create(%s) = %d", snapname, error);
+       if (error != 0 && error != EEXIST) {
+               fatal(0, "ztest_snapshot_create(%s@%s) = %d", osname,
+                   snapname, error);
+       }
        return (B_TRUE);
 }
 
@@ -3242,7 +3281,7 @@ ztest_snapshot_destroy(char *osname, uint64_t id)
        (void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
            (u_longlong_t)id);
 
-       error = dmu_objset_destroy(snapname, B_FALSE);
+       error = dsl_destroy_snapshot(snapname, B_FALSE);
        if (error != 0 && error != ENOENT)
                fatal(0, "ztest_snapshot_destroy(%s) = %d", snapname, error);
        return (B_TRUE);
@@ -3270,7 +3309,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
 
        /*
         * If this dataset exists from a previous run, process its replay log
-        * half of the time.  If we don't replay it, then dmu_objset_destroy()
+        * half of the time.  If we don't replay it, then dsl_destroy_head()
         * (invoked from ztest_objset_destroy_cb()) should just throw it away.
         */
        if (ztest_random(2) == 0 &&
@@ -3292,7 +3331,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_hold(name, FTAG, &os));
+       VERIFY3U(ENOENT, ==, dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
+           FTAG, &os));
 
        /*
         * Verify that we can create a new dataset.
@@ -3306,8 +3346,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_objset_create(%s) = %d", name, error);
        }
 
-       VERIFY3U(0, ==,
-           dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
+       VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
 
        ztest_zd_init(zdtmp, NULL, os);
 
@@ -3397,21 +3436,21 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t id)
        (void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu",
            clone1name, (u_longlong_t)id);
 
-       error = dmu_objset_destroy(clone2name, B_FALSE);
+       error = dsl_destroy_head(clone2name);
        if (error && error != ENOENT)
-               fatal(0, "dmu_objset_destroy(%s) = %d", clone2name, error);
-       error = dmu_objset_destroy(snap3name, B_FALSE);
+               fatal(0, "dsl_destroy_head(%s) = %d", clone2name, error);
+       error = dsl_destroy_snapshot(snap3name, B_FALSE);
        if (error && error != ENOENT)
-               fatal(0, "dmu_objset_destroy(%s) = %d", snap3name, error);
-       error = dmu_objset_destroy(snap2name, B_FALSE);
+               fatal(0, "dsl_destroy_snapshot(%s) = %d", snap3name, error);
+       error = dsl_destroy_snapshot(snap2name, B_FALSE);
        if (error && error != ENOENT)
-               fatal(0, "dmu_objset_destroy(%s) = %d", snap2name, error);
-       error = dmu_objset_destroy(clone1name, B_FALSE);
+               fatal(0, "dsl_destroy_snapshot(%s) = %d", snap2name, error);
+       error = dsl_destroy_head(clone1name);
        if (error && error != ENOENT)
-               fatal(0, "dmu_objset_destroy(%s) = %d", clone1name, error);
-       error = dmu_objset_destroy(snap1name, B_FALSE);
+               fatal(0, "dsl_destroy_head(%s) = %d", clone1name, error);
+       error = dsl_destroy_snapshot(snap1name, B_FALSE);
        if (error && error != ENOENT)
-               fatal(0, "dmu_objset_destroy(%s) = %d", snap1name, error);
+               fatal(0, "dsl_destroy_snapshot(%s) = %d", snap1name, error);
 
        umem_free(snap1name, MAXNAMELEN);
        umem_free(clone1name, MAXNAMELEN);
@@ -3426,8 +3465,7 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t id)
 void
 ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
 {
-       objset_t *clone;
-       dsl_dataset_t *ds;
+       objset_t *os;
        char *snap1name;
        char *clone1name;
        char *snap2name;
@@ -3457,8 +3495,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
        (void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu",
            clone1name, (u_longlong_t)id);
 
-       error = dmu_objset_snapshot(osname, strchr(snap1name, '@')+1,
-           NULL, NULL, B_FALSE, B_FALSE, -1);
+       error = dmu_objset_snapshot_one(osname, strchr(snap1name, '@') + 1);
        if (error && error != EEXIST) {
                if (error == ENOSPC) {
                        ztest_record_enospc(FTAG);
@@ -3467,12 +3504,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_take_snapshot(%s) = %d", snap1name, error);
        }
 
-       error = dmu_objset_hold(snap1name, FTAG, &clone);
-       if (error)
-               fatal(0, "dmu_open_snapshot(%s) = %d", snap1name, error);
-
-       error = dmu_objset_clone(clone1name, dmu_objset_ds(clone), 0);
-       dmu_objset_rele(clone, FTAG);
+       error = dmu_objset_clone(clone1name, snap1name);
        if (error) {
                if (error == ENOSPC) {
                        ztest_record_enospc(FTAG);
@@ -3481,8 +3513,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_objset_create(%s) = %d", clone1name, error);
        }
 
-       error = dmu_objset_snapshot(clone1name, strchr(snap2name, '@')+1,
-           NULL, NULL, B_FALSE, B_FALSE, -1);
+       error = dmu_objset_snapshot_one(clone1name, strchr(snap2name, '@') + 1);
        if (error && error != EEXIST) {
                if (error == ENOSPC) {
                        ztest_record_enospc(FTAG);
@@ -3491,8 +3522,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_open_snapshot(%s) = %d", snap2name, error);
        }
 
-       error = dmu_objset_snapshot(clone1name, strchr(snap3name, '@')+1,
-           NULL, NULL, B_FALSE, B_FALSE, -1);
+       error = dmu_objset_snapshot_one(clone1name, strchr(snap3name, '@') + 1);
        if (error && error != EEXIST) {
                if (error == ENOSPC) {
                        ztest_record_enospc(FTAG);
@@ -3501,12 +3531,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
        }
 
-       error = dmu_objset_hold(snap3name, FTAG, &clone);
-       if (error)
-               fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
-
-       error = dmu_objset_clone(clone2name, dmu_objset_ds(clone), 0);
-       dmu_objset_rele(clone, FTAG);
+       error = dmu_objset_clone(clone2name, snap3name);
        if (error) {
                if (error == ENOSPC) {
                        ztest_record_enospc(FTAG);
@@ -3515,14 +3540,14 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_objset_create(%s) = %d", clone2name, error);
        }
 
-       error = dsl_dataset_own(snap2name, B_FALSE, FTAG, &ds);
+       error = dmu_objset_own(snap2name, DMU_OST_ANY, B_TRUE, FTAG, &os);
        if (error)
-               fatal(0, "dsl_dataset_own(%s) = %d", snap2name, error);
+               fatal(0, "dmu_objset_own(%s) = %d", snap2name, error);
        error = dsl_dataset_promote(clone2name, NULL);
        if (error != EBUSY)
                fatal(0, "dsl_dataset_promote(%s), %d, not EBUSY", clone2name,
                    error);
-       dsl_dataset_disown(ds, FTAG);
+       dmu_objset_disown(os, FTAG);
 
 out:
        ztest_dsl_dataset_cleanup(osname, id);
@@ -3673,10 +3698,10 @@ ztest_dmu_read_write(ztest_ds_t *zd, uint64_t id)
         */
        error = dmu_read(os, packobj, packoff, packsize, packbuf,
            DMU_READ_PREFETCH);
-       ASSERT3U(error, ==, 0);
+       ASSERT0(error);
        error = dmu_read(os, bigobj, bigoff, bigsize, bigbuf,
            DMU_READ_PREFETCH);
-       ASSERT3U(error, ==, 0);
+       ASSERT0(error);
 
        /*
         * Get a tx for the mods to both packobj and bigobj.
@@ -3690,6 +3715,9 @@ ztest_dmu_read_write(ztest_ds_t *zd, uint64_t id)
        else
                dmu_tx_hold_write(tx, bigobj, bigoff, bigsize);
 
+       /* This accounts for setting the checksum/compression. */
+       dmu_tx_hold_bonus(tx, bigobj);
+
        txg = ztest_tx_assign(tx, TXG_MIGHTWAIT, FTAG);
        if (txg == 0) {
                umem_free(packbuf, packsize);
@@ -3999,10 +4027,10 @@ ztest_dmu_read_write_zcopy(ztest_ds_t *zd, uint64_t id)
                if (i != 0 || ztest_random(2) != 0) {
                        error = dmu_read(os, packobj, packoff,
                            packsize, packbuf, DMU_READ_PREFETCH);
-                       ASSERT3U(error, ==, 0);
+                       ASSERT0(error);
                        error = dmu_read(os, bigobj, bigoff, bigsize,
                            bigbuf, DMU_READ_PREFETCH);
-                       ASSERT3U(error, ==, 0);
+                       ASSERT0(error);
                }
                compare_and_update_pbbufs(s, packbuf, bigbuf, bigsize,
                    n, chunksize, txg);
@@ -4287,7 +4315,7 @@ ztest_zap(ztest_ds_t *zd, uint64_t id)
        if (error == ENOENT)
                goto out;
 
-       ASSERT3U(error, ==, 0);
+       ASSERT0(error);
 
        tx = dmu_tx_create(os);
        dmu_tx_hold_zap(tx, object, B_TRUE, NULL);
@@ -4396,7 +4424,7 @@ ztest_zap_parallel(ztest_ds_t *zd, uint64_t id)
        }
 
        count = -1ULL;
-       VERIFY(zap_count(os, object, &count) == 0);
+       VERIFY0(zap_count(os, object, &count));
        ASSERT(count != -1ULL);
 
        /*
@@ -4494,7 +4522,7 @@ ztest_commit_callback(void *arg, int error)
        data->zcd_called = B_TRUE;
 
        if (error == ECANCELED) {
-               ASSERT3U(data->zcd_txg, ==, 0);
+               ASSERT0(data->zcd_txg);
                ASSERT(!data->zcd_added);
 
                /*
@@ -4704,7 +4732,7 @@ ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
        (void) ztest_spa_prop_set_uint64(ZPOOL_PROP_DEDUPDITTO,
            ZIO_DEDUPDITTO_MIN + ztest_random(ZIO_DEDUPDITTO_MIN));
 
-       VERIFY3U(spa_prop_get(ztest_spa, &props), ==, 0);
+       VERIFY0(spa_prop_get(ztest_spa, &props));
 
        if (ztest_opts.zo_verbose >= 6)
                dump_nvlist(props, 4);
@@ -4714,6 +4742,22 @@ ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
        (void) rw_exit(&ztest_name_lock);
 }
 
+static int
+user_release_one(const char *snapname, const char *holdname)
+{
+       nvlist_t *snaps, *holds;
+       int error;
+
+       snaps = fnvlist_alloc();
+       holds = fnvlist_alloc();
+       fnvlist_add_boolean(holds, holdname);
+       fnvlist_add_nvlist(snaps, snapname, holds);
+       fnvlist_free(holds);
+       error = dsl_dataset_user_release(snaps, NULL);
+       fnvlist_free(snaps);
+       return (error);
+}
+
 /*
  * Test snapshot hold/release and deferred destroy.
  */
@@ -4728,29 +4772,36 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
        char clonename[100];
        char tag[100];
        char osname[MAXNAMELEN];
+       nvlist_t *holds;
 
        (void) rw_enter(&ztest_name_lock, RW_READER);
 
        dmu_objset_name(os, osname);
 
-       (void) snprintf(snapname, 100, "sh1_%llu", (u_longlong_t)id);
-       (void) snprintf(fullname, 100, "%s@%s", osname, snapname);
-       (void) snprintf(clonename, 100, "%s/ch1_%llu",osname,(u_longlong_t)id);
-       (void) snprintf(tag, 100, "tag_%llu", (u_longlong_t)id);
+       (void) snprintf(snapname, sizeof (snapname), "sh1_%llu", (long long unsigned int)id);
+       (void) snprintf(fullname, sizeof (fullname), "%s@%s", osname, snapname);
+       (void) snprintf(clonename, sizeof (clonename),
+           "%s/ch1_%llu", osname, (long long unsigned int)id);
+       (void) snprintf(tag, sizeof (tag), "tag_%llu", (long long unsigned int)id);
 
        /*
         * Clean up from any previous run.
         */
-       (void) dmu_objset_destroy(clonename, B_FALSE);
-       (void) dsl_dataset_user_release(osname, snapname, tag, B_FALSE);
-       (void) dmu_objset_destroy(fullname, B_FALSE);
+       error = dsl_destroy_head(clonename);
+       if (error != ENOENT)
+               ASSERT0(error);
+       error = user_release_one(fullname, tag);
+       if (error != ESRCH && error != ENOENT)
+               ASSERT0(error);
+       error = dsl_destroy_snapshot(fullname, B_FALSE);
+       if (error != ENOENT)
+               ASSERT0(error);
 
        /*
         * Create snapshot, clone it, mark snap for deferred destroy,
         * destroy clone, verify snap was also destroyed.
         */
-       error = dmu_objset_snapshot(osname, snapname, NULL, NULL, FALSE,
-           FALSE, -1);
+       error = dmu_objset_snapshot_one(osname, snapname);
        if (error) {
                if (error == ENOSPC) {
                        ztest_record_enospc("dmu_objset_snapshot");
@@ -4759,12 +4810,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_objset_snapshot(%s) = %d", fullname, error);
        }
 
-       error = dmu_objset_hold(fullname, FTAG, &origin);
-       if (error)
-               fatal(0, "dmu_objset_hold(%s) = %d", fullname, error);
-
-       error = dmu_objset_clone(clonename, dmu_objset_ds(origin), 0);
-       dmu_objset_rele(origin, FTAG);
+       error = dmu_objset_clone(clonename, fullname);
        if (error) {
                if (error == ENOSPC) {
                        ztest_record_enospc("dmu_objset_clone");
@@ -4773,15 +4819,15 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_objset_clone(%s) = %d", clonename, error);
        }
 
-       error = dmu_objset_destroy(fullname, B_TRUE);
+       error = dsl_destroy_snapshot(fullname, B_TRUE);
        if (error) {
-               fatal(0, "dmu_objset_destroy(%s, B_TRUE) = %d",
+               fatal(0, "dsl_destroy_snapshot(%s, B_TRUE) = %d",
                    fullname, error);
        }
 
-       error = dmu_objset_destroy(clonename, B_FALSE);
+       error = dsl_destroy_head(clonename);
        if (error)
-               fatal(0, "dmu_objset_destroy(%s) = %d", clonename, error);
+               fatal(0, "dsl_destroy_head(%s) = %d", clonename, error);
 
        error = dmu_objset_hold(fullname, FTAG, &origin);
        if (error != ENOENT)
@@ -4792,8 +4838,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
         * destroy a held snapshot, mark for deferred destroy,
         * release hold, verify snapshot was destroyed.
         */
-       error = dmu_objset_snapshot(osname, snapname, NULL, NULL, FALSE,
-           FALSE, -1);
+       error = dmu_objset_snapshot_one(osname, snapname);
        if (error) {
                if (error == ENOSPC) {
                        ztest_record_enospc("dmu_objset_snapshot");
@@ -4802,28 +4847,31 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
                fatal(0, "dmu_objset_snapshot(%s) = %d", fullname, error);
        }
 
-       error = dsl_dataset_user_hold(osname, snapname, tag, B_FALSE,
-           B_TRUE, -1);
+       holds = fnvlist_alloc();
+       fnvlist_add_string(holds, fullname, tag);
+       error = dsl_dataset_user_hold(holds, 0, NULL);
+       fnvlist_free(holds);
+
        if (error)
                fatal(0, "dsl_dataset_user_hold(%s)", fullname, tag);
 
-       error = dmu_objset_destroy(fullname, B_FALSE);
+       error = dsl_destroy_snapshot(fullname, B_FALSE);
        if (error != EBUSY) {
-               fatal(0, "dmu_objset_destroy(%s, B_FALSE) = %d",
+               fatal(0, "dsl_destroy_snapshot(%s, B_FALSE) = %d",
                    fullname, error);
        }
 
-       error = dmu_objset_destroy(fullname, B_TRUE);
+       error = dsl_destroy_snapshot(fullname, B_TRUE);
        if (error) {
-               fatal(0, "dmu_objset_destroy(%s, B_TRUE) = %d",
+               fatal(0, "dsl_destroy_snapshot(%s, B_TRUE) = %d",
                    fullname, error);
        }
 
-       error = dsl_dataset_user_release(osname, snapname, tag, B_FALSE);
+       error = user_release_one(fullname, tag);
        if (error)
-               fatal(0, "dsl_dataset_user_release(%s)", fullname, tag);
+               fatal(0, "user_release_one(%s, %s) = %d", fullname, tag, error);
 
-       VERIFY(dmu_objset_hold(fullname, FTAG, &origin) == ENOENT);
+       VERIFY3U(dmu_objset_hold(fullname, FTAG, &origin), ==, ENOENT);
 
 out:
        (void) rw_exit(&ztest_name_lock);
@@ -4865,6 +4913,14 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
 
        ASSERT(leaves >= 1);
 
+       /*
+        * Grab the name lock as reader. There are some operations
+        * which don't like to have their vdevs changed while
+        * they are in progress (i.e. spa_change_guid). Those
+        * operations will have grabbed the name lock as writer.
+        */
+       (void) rw_enter(&ztest_name_lock, RW_READER);
+
        /*
         * We need SCL_STATE here because we're going to look at vd0->vdev_tsd.
         */
@@ -4894,7 +4950,14 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
                if (vd0 != NULL && vd0->vdev_top->vdev_islog)
                        islog = B_TRUE;
 
-               if (vd0 != NULL && maxfaults != 1) {
+               /*
+                * If the top-level vdev needs to be resilvered
+                * then we only allow faults on the device that is
+                * resilvering.
+                */
+               if (vd0 != NULL && maxfaults != 1 &&
+                   (!vdev_resilver_needed(vd0->vdev_top, NULL, NULL) ||
+                   vd0->vdev_resilvering)) {
                        /*
                         * Make vd0 explicitly claim to be unreadable,
                         * or unwriteable, or reach behind its back
@@ -4925,6 +4988,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
 
                if (sav->sav_count == 0) {
                        spa_config_exit(spa, SCL_STATE, FTAG);
+                       (void) rw_exit(&ztest_name_lock);
                        goto out;
                }
                vd0 = sav->sav_vdevs[ztest_random(sav->sav_count)];
@@ -4938,6 +5002,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
        }
 
        spa_config_exit(spa, SCL_STATE, FTAG);
+       (void) rw_exit(&ztest_name_lock);
 
        /*
         * If we can tolerate two or more faults, or we're dealing
@@ -4953,7 +5018,7 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
                         * prevent a race between offlining a slog and
                         * destroying a dataset. Offlining the slog will
                         * grab a reference on the dataset which may cause
-                        * dmu_objset_destroy() to fail with EBUSY thus
+                        * dsl_destroy_head() to fail with EBUSY thus
                         * leaving the dataset in an inconsistent state.
                         */
                        if (islog)
@@ -5090,8 +5155,12 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
         */
        for (i = 0; i < copies; i++) {
                uint64_t offset = i * blocksize;
-               VERIFY(dmu_buf_hold(os, object, offset, FTAG, &db,
-                   DMU_READ_NO_PREFETCH) == 0);
+               int error = dmu_buf_hold(os, object, offset, FTAG, &db,
+                   DMU_READ_NO_PREFETCH);
+               if (error != 0) {
+                       fatal(B_FALSE, "dmu_buf_hold(%p, %llu, %llu) = %u",
+                           os, (long long)object, (long long) offset, error);
+               }
                ASSERT(db->db_offset == offset);
                ASSERT(db->db_size == blocksize);
                ASSERT(ztest_pattern_match(db->db_data, db->db_size, pattern) ||
@@ -5107,8 +5176,8 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
        /*
         * Find out what block we got.
         */
-       VERIFY(dmu_buf_hold(os, object, 0, FTAG, &db,
-           DMU_READ_NO_PREFETCH) == 0);
+       VERIFY0(dmu_buf_hold(os, object, 0, FTAG, &db,
+           DMU_READ_NO_PREFETCH));
        blk = *((dmu_buf_impl_t *)db)->db_blkptr;
        dmu_buf_rele(db, FTAG);
 
@@ -5306,6 +5375,7 @@ ztest_spa_import_export(char *oldname, char *newname)
        nvlist_t *config, *newconfig;
        uint64_t pool_guid;
        spa_t *spa;
+       int error;
 
        if (ztest_opts.zo_verbose >= 4) {
                (void) printf("import/export: old = %s, new = %s\n",
@@ -5350,7 +5420,12 @@ ztest_spa_import_export(char *oldname, char *newname)
        /*
         * Import it under the new name.
         */
-       VERIFY3U(0, ==, spa_import(newname, config, NULL, 0));
+       error = spa_import(newname, config, NULL, 0);
+       if (error != 0) {
+               dump_nvlist(config, 0);
+               fatal(B_FALSE, "couldn't import pool %s as %s: error %u",
+                   oldname, newname, error);
+       }
 
        ztest_walk_pool_directory("pools after import");
 
@@ -5557,7 +5632,7 @@ ztest_dataset_open(int d)
        }
        ASSERT(error == 0 || error == EEXIST);
 
-       VERIFY3U(dmu_objset_hold(name, zd, &os), ==, 0);
+       VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, zd, &os));
        (void) rw_exit(&ztest_name_lock);
 
        ztest_zd_init(zd, ZTEST_GET_SHARED_DS(d), os);
@@ -5598,7 +5673,7 @@ ztest_dataset_close(int d)
        ztest_ds_t *zd = &ztest_ds[d];
 
        zil_close(zd->zd_zilog);
-       dmu_objset_rele(zd->zd_os, zd);
+       dmu_objset_disown(zd->zd_os, zd);
 
        ztest_zd_fini(zd);
 }
@@ -5644,13 +5719,14 @@ ztest_run(ztest_shared_t *zs)
         * Open our pool.
         */
        kernel_init(FREAD | FWRITE);
-       VERIFY(spa_open(ztest_opts.zo_pool, &spa, FTAG) == 0);
+       VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
        spa->spa_debug = B_TRUE;
        ztest_spa = spa;
 
-       VERIFY3U(0, ==, dmu_objset_hold(ztest_opts.zo_pool, FTAG, &os));
+       VERIFY0(dmu_objset_own(ztest_opts.zo_pool,
+           DMU_OST_ANY, B_TRUE, FTAG, &os));
        zs->zs_guid = dmu_objset_fsid_guid(os);
-       dmu_objset_rele(os, FTAG);
+       dmu_objset_disown(os, FTAG);
 
        spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
 
@@ -5757,7 +5833,7 @@ ztest_run(ztest_shared_t *zs)
 
        /* Verify that at least one commit cb was called in a timely fashion */
        if (zc_cb_counter >= ZTEST_COMMIT_CB_MIN_REG)
-               VERIFY3U(zc_min_txg_delay, ==, 0);
+               VERIFY0(zc_min_txg_delay);
 
        spa_close(spa, FTAG);
 
@@ -5803,6 +5879,8 @@ ztest_freeze(void)
        kernel_init(FREAD | FWRITE);
        VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG));
        VERIFY3U(0, ==, ztest_dataset_open(0));
+       spa->spa_debug = B_TRUE;
+       ztest_spa = spa;
 
        /*
         * Force the first log block to be transactionally allocated.
@@ -5938,8 +6016,7 @@ ztest_init(ztest_shared_t *zs)
                VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0));
                free(buf);
        }
-       VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props,
-           NULL, NULL));
+       VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props, NULL));
        nvlist_free(nvroot);
 
        VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG));
@@ -6153,11 +6230,12 @@ main(int argc, char **argv)
 
        (void) setvbuf(stdout, NULL, _IOLBF, 0);
 
+       dprintf_setup(&argc, argv);
+
        ztest_fd_rand = open("/dev/urandom", O_RDONLY);
        ASSERT3S(ztest_fd_rand, >=, 0);
 
        if (!fd_data_str) {
-               dprintf_setup(&argc, argv);
                process_options(argc, argv);
 
                setup_data_fd();