Add -p switch to "zpool get"
[zfs.git] / cmd / ztest / ztest.c
index 8655b23..93a5f1e 100644 (file)
 #include <sys/dsl_scan.h>
 #include <sys/zio_checksum.h>
 #include <sys/refcount.h>
+#include <sys/zfeature.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
 #include <sys/fs/zfs.h>
 #include <libnvpair.h>
 
-#define        ZTEST_FD_DATA 3
-#define        ZTEST_FD_RAND 4
+static int ztest_fd_data = -1;
+static int ztest_fd_rand = -1;
 
 typedef struct ztest_shared_hdr {
        uint64_t        zh_hdr_size;
@@ -330,6 +331,7 @@ ztest_func_t ztest_vdev_add_remove;
 ztest_func_t ztest_vdev_aux_add_remove;
 ztest_func_t ztest_split_pool;
 ztest_func_t ztest_reguid;
+ztest_func_t ztest_spa_upgrade;
 
 uint64_t zopt_always = 0ULL * NANOSEC;         /* all the time */
 uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
@@ -360,17 +362,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 },
-       /*
-        * The reguid test is currently broken. Disable it until
-        * we get around to fixing it.
-        */
-#if 0
        { ztest_reguid,                         1,      &zopt_sometimes },
-#endif
        { 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_rarely    },
        { ztest_vdev_LUN_growth,                1,      &zopt_rarely    },
        { ztest_vdev_add_remove,                1,
            &ztest_opts.zo_vdevtime                             },
@@ -421,6 +418,13 @@ static spa_t *ztest_spa = NULL;
 static ztest_ds_t *ztest_ds;
 
 static kmutex_t ztest_vdev_lock;
+
+/*
+ * The ztest_name_lock protects the pool and dataset namespace used by
+ * the individual tests. To modify the namespace, consumers must grab
+ * this lock as writer. Grabbing the lock as reader will ensure that the
+ * namespace does not change while the lock is held.
+ */
 static krwlock_t ztest_name_lock;
 
 static boolean_t ztest_dump_core = B_TRUE;
@@ -729,14 +733,17 @@ process_options(int argc, char **argv)
            UINT64_MAX >> 2);
 
        if (strlen(altdir) > 0) {
-               char cmd[MAXNAMELEN];
-               char realaltdir[MAXNAMELEN];
+               char *cmd;
+               char *realaltdir;
                char *bin;
                char *ztest;
                char *isa;
                int isalen;
 
-               (void) realpath(getexecname(), cmd);
+               cmd = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
+               realaltdir = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
+
+               VERIFY(NULL != realpath(getexecname(), cmd));
                if (0 != access(altdir, F_OK)) {
                        ztest_dump_core = B_FALSE;
                        fatal(B_TRUE, "invalid alternate ztest path: %s",
@@ -767,6 +774,9 @@ process_options(int argc, char **argv)
                        fatal(B_TRUE, "invalid alternate lib directory %s",
                            zo->zo_alt_libpath);
                }
+
+               umem_free(cmd, MAXPATHLEN);
+               umem_free(realaltdir, MAXPATHLEN);
        }
 }
 
@@ -783,10 +793,12 @@ ztest_random(uint64_t range)
 {
        uint64_t r;
 
+       ASSERT3S(ztest_fd_rand, >=, 0);
+
        if (range == 0)
                return (0);
 
-       if (read(ZTEST_FD_RAND, &r, sizeof (r)) != sizeof (r))
+       if (read(ztest_fd_rand, &r, sizeof (r)) != sizeof (r))
                fatal(1, "short read from /dev/urandom");
 
        return (r % range);
@@ -808,7 +820,7 @@ ztest_get_ashift(void)
 }
 
 static nvlist_t *
-make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
+make_vdev_file(char *path, char *aux, char *pool, size_t size, uint64_t ashift)
 {
        char *pathbuf;
        uint64_t vdev;
@@ -826,12 +838,13 @@ make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
                        vdev = ztest_shared->zs_vdev_aux;
                        (void) snprintf(path, MAXPATHLEN,
                            ztest_aux_template, ztest_opts.zo_dir,
-                           ztest_opts.zo_pool, aux, vdev);
+                           pool == NULL ? ztest_opts.zo_pool : pool,
+                           aux, vdev);
                } else {
                        vdev = ztest_shared->zs_vdev_next_leaf++;
                        (void) snprintf(path, MAXPATHLEN,
                            ztest_dev_template, ztest_opts.zo_dir,
-                           ztest_opts.zo_pool, vdev);
+                           pool == NULL ? ztest_opts.zo_pool : pool, vdev);
                }
        }
 
@@ -854,17 +867,18 @@ make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
 }
 
 static nvlist_t *
-make_vdev_raidz(char *path, char *aux, size_t size, uint64_t ashift, int r)
+make_vdev_raidz(char *path, char *aux, char *pool, size_t size,
+    uint64_t ashift, int r)
 {
        nvlist_t *raidz, **child;
        int c;
 
        if (r < 2)
-               return (make_vdev_file(path, aux, size, ashift));
+               return (make_vdev_file(path, aux, pool, size, ashift));
        child = umem_alloc(r * sizeof (nvlist_t *), UMEM_NOFAIL);
 
        for (c = 0; c < r; c++)
-               child[c] = make_vdev_file(path, aux, size, ashift);
+               child[c] = make_vdev_file(path, aux, pool, size, ashift);
 
        VERIFY(nvlist_alloc(&raidz, NV_UNIQUE_NAME, 0) == 0);
        VERIFY(nvlist_add_string(raidz, ZPOOL_CONFIG_TYPE,
@@ -883,19 +897,19 @@ make_vdev_raidz(char *path, char *aux, size_t size, uint64_t ashift, int r)
 }
 
 static nvlist_t *
-make_vdev_mirror(char *path, char *aux, size_t size, uint64_t ashift,
-       int r, int m)
+make_vdev_mirror(char *path, char *aux, char *pool, size_t size,
+    uint64_t ashift, int r, int m)
 {
        nvlist_t *mirror, **child;
        int c;
 
        if (m < 1)
-               return (make_vdev_raidz(path, aux, size, ashift, r));
+               return (make_vdev_raidz(path, aux, pool, size, ashift, r));
 
        child = umem_alloc(m * sizeof (nvlist_t *), UMEM_NOFAIL);
 
        for (c = 0; c < m; c++)
-               child[c] = make_vdev_raidz(path, aux, size, ashift, r);
+               child[c] = make_vdev_raidz(path, aux, pool, size, ashift, r);
 
        VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0);
        VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE,
@@ -912,8 +926,8 @@ make_vdev_mirror(char *path, char *aux, size_t size, uint64_t ashift,
 }
 
 static nvlist_t *
-make_vdev_root(char *path, char *aux, size_t size, uint64_t ashift,
-       int log, int r, int m, int t)
+make_vdev_root(char *path, char *aux, char *pool, size_t size, uint64_t ashift,
+    int log, int r, int m, int t)
 {
        nvlist_t *root, **child;
        int c;
@@ -923,7 +937,8 @@ make_vdev_root(char *path, char *aux, size_t size, uint64_t ashift,
        child = umem_alloc(t * sizeof (nvlist_t *), UMEM_NOFAIL);
 
        for (c = 0; c < t; c++) {
-               child[c] = make_vdev_mirror(path, aux, size, ashift, r, m);
+               child[c] = make_vdev_mirror(path, aux, pool, size, ashift,
+                   r, m);
                VERIFY(nvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
                    log) == 0);
        }
@@ -941,6 +956,27 @@ make_vdev_root(char *path, char *aux, size_t size, uint64_t ashift,
        return (root);
 }
 
+/*
+ * Find a random spa version. Returns back a random spa version in the
+ * range [initial_version, SPA_VERSION_FEATURES].
+ */
+static uint64_t
+ztest_random_spa_version(uint64_t initial_version)
+{
+       uint64_t version = initial_version;
+
+       if (version <= SPA_VERSION_BEFORE_FEATURES) {
+               version = version +
+                   ztest_random(SPA_VERSION_BEFORE_FEATURES - version + 1);
+       }
+
+       if (version > SPA_VERSION_BEFORE_FEATURES)
+               version = SPA_VERSION_FEATURES;
+
+       ASSERT(SPA_VERSION_IS_SUPPORTED(version));
+       return (version);
+}
+
 static int
 ztest_random_blocksize(void)
 {
@@ -1003,7 +1039,7 @@ ztest_dsl_prop_set_uint64(char *osname, zfs_prop_t prop, uint64_t value,
                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),
@@ -1037,7 +1073,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);
 }
@@ -1740,7 +1776,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);
@@ -1756,19 +1792,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 */
@@ -2267,6 +2303,7 @@ ztest_zil_remount(ztest_ds_t *zd, uint64_t id)
 {
        objset_t *os = zd->zd_os;
 
+       mutex_enter(&zd->zd_dirobj_lock);
        (void) rw_enter(&zd->zd_zilog_lock, RW_WRITER);
 
        /* zfs_sb_teardown() */
@@ -2277,6 +2314,7 @@ ztest_zil_remount(ztest_ds_t *zd, uint64_t id)
        zil_replay(os, zd, ztest_replay_vector);
 
        (void) rw_exit(&zd->zd_zilog_lock);
+       mutex_exit(&zd->zd_dirobj_lock);
 }
 
 /*
@@ -2294,7 +2332,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
        /*
         * Attempt to create using a bad file.
         */
-       nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 0, 1);
+       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));
        nvlist_free(nvroot);
@@ -2302,7 +2340,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
        /*
         * Attempt to create using a bad mirror.
         */
-       nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 2, 1);
+       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));
        nvlist_free(nvroot);
@@ -2312,7 +2350,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
         * what's in the nvroot; we should fail with EEXIST.
         */
        (void) rw_enter(&ztest_name_lock, RW_READER);
-       nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 0, 1);
+       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));
        nvlist_free(nvroot);
        VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
@@ -2322,6 +2360,78 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
        (void) rw_exit(&ztest_name_lock);
 }
 
+/* ARGSUSED */
+void
+ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
+{
+       spa_t *spa;
+       uint64_t initial_version = SPA_VERSION_INITIAL;
+       uint64_t version, newversion;
+       nvlist_t *nvroot, *props;
+       char *name;
+
+       mutex_enter(&ztest_vdev_lock);
+       name = kmem_asprintf("%s_upgrade", ztest_opts.zo_pool);
+
+       /*
+        * Clean up from previous runs.
+        */
+       (void) spa_destroy(name);
+
+       nvroot = make_vdev_root(NULL, NULL, name, ztest_opts.zo_vdev_size, 0,
+           0, ztest_opts.zo_raidz, ztest_opts.zo_mirrors, 1);
+
+       /*
+        * If we're configuring a RAIDZ device then make sure that the
+        * the initial version is capable of supporting that feature.
+        */
+       switch (ztest_opts.zo_raidz_parity) {
+       case 0:
+       case 1:
+               initial_version = SPA_VERSION_INITIAL;
+               break;
+       case 2:
+               initial_version = SPA_VERSION_RAIDZ2;
+               break;
+       case 3:
+               initial_version = SPA_VERSION_RAIDZ3;
+               break;
+       }
+
+       /*
+        * Create a pool with a spa version that can be upgraded. Pick
+        * a value between initial_version and SPA_VERSION_BEFORE_FEATURES.
+        */
+       do {
+               version = ztest_random_spa_version(initial_version);
+       } while (version > SPA_VERSION_BEFORE_FEATURES);
+
+       props = fnvlist_alloc();
+       fnvlist_add_uint64(props,
+           zpool_prop_to_name(ZPOOL_PROP_VERSION), version);
+       VERIFY3S(spa_create(name, nvroot, props, NULL, NULL), ==, 0);
+       fnvlist_free(nvroot);
+       fnvlist_free(props);
+
+       VERIFY3S(spa_open(name, &spa, FTAG), ==, 0);
+       VERIFY3U(spa_version(spa), ==, version);
+       newversion = ztest_random_spa_version(version + 1);
+
+       if (ztest_opts.zo_verbose >= 4) {
+               (void) printf("upgrading spa version from %llu to %llu\n",
+                   (u_longlong_t)version, (u_longlong_t)newversion);
+       }
+
+       spa_upgrade(spa, newversion);
+       VERIFY3U(spa_version(spa), >, version);
+       VERIFY3U(spa_version(spa), ==, fnvlist_lookup_uint64(spa->spa_config,
+           zpool_prop_to_name(ZPOOL_PROP_VERSION)));
+       spa_close(spa, FTAG);
+
+       strfree(name);
+       mutex_exit(&ztest_vdev_lock);
+}
+
 static vdev_t *
 vdev_lookup_by_path(vdev_t *vd, const char *path)
 {
@@ -2412,7 +2522,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
                /*
                 * Make 1/4 of the devices be log devices.
                 */
-               nvroot = make_vdev_root(NULL, NULL,
+               nvroot = make_vdev_root(NULL, NULL, NULL,
                    ztest_opts.zo_vdev_size, 0,
                    ztest_random(4) == 0, ztest_opts.zo_raidz,
                    zs->zs_mirrors, 1);
@@ -2471,7 +2581,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++)
@@ -2491,7 +2601,7 @@ ztest_vdev_aux_add_remove(ztest_ds_t *zd, uint64_t id)
                /*
                 * Add a new device.
                 */
-               nvlist_t *nvroot = make_vdev_root(NULL, aux,
+               nvlist_t *nvroot = make_vdev_root(NULL, aux, NULL,
                    (ztest_opts.zo_vdev_size * 5) / 4, 0, 0, 0, 0, 1);
                error = spa_vdev_add(spa, nvroot);
                if (error != 0)
@@ -2764,7 +2874,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
        /*
         * Build the nvlist describing newpath.
         */
-       root = make_vdev_root(newpath, NULL, newvd == NULL ? newsize : 0,
+       root = make_vdev_root(newpath, NULL, NULL, newvd == NULL ? newsize : 0,
            ashift, 0, 0, 0, 1);
 
        error = spa_vdev_attach(spa, oldguid, root, replacing);
@@ -3090,7 +3200,7 @@ ztest_objset_destroy_cb(const char *name, void *arg)
        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);
        }
@@ -3563,10 +3673,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.
@@ -3889,10 +3999,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);
@@ -4177,7 +4287,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);
@@ -4384,7 +4494,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);
 
                /*
@@ -4594,7 +4704,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);
@@ -4855,7 +4965,18 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
                        if (islog)
                                (void) rw_exit(&ztest_name_lock);
                } else {
+                       /*
+                        * Ideally we would like to be able to randomly
+                        * call vdev_[on|off]line without holding locks
+                        * to force unpredictable failures but the side
+                        * effects of vdev_[on|off]line prevent us from
+                        * doing so. We grab the ztest_vdev_lock here to
+                        * prevent a race between injection testing and
+                        * aux_vdev removal.
+                        */
+                       mutex_enter(&ztest_vdev_lock);
                        (void) vdev_online(spa, guid0, 0, NULL);
+                       mutex_exit(&ztest_vdev_lock);
                }
        }
 
@@ -5031,13 +5152,19 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
 {
        spa_t *spa = ztest_spa;
        uint64_t orig, load;
+       int error;
 
        orig = spa_guid(spa);
        load = spa_load_guid(spa);
-       if (spa_change_guid(spa) != 0)
+
+       (void) rw_enter(&ztest_name_lock, RW_WRITER);
+       error = spa_change_guid(spa);
+       (void) rw_exit(&ztest_name_lock);
+
+       if (error != 0)
                return;
 
-       if (ztest_opts.zo_verbose >= 3) {
+       if (ztest_opts.zo_verbose >= 4) {
                (void) printf("Changed guid old %llu -> %llu\n",
                    (u_longlong_t)orig, (u_longlong_t)spa_guid(spa));
        }
@@ -5281,11 +5408,13 @@ ztest_resume_thread(void *arg)
 
 #define GRACE  300
 
+#if 0
 static void
 ztest_deadman_alarm(int sig)
 {
        fatal(0, "failed to complete within %d seconds of deadline", GRACE);
 }
+#endif
 
 static void
 ztest_execute(int test, ztest_info_t *zi, uint64_t id)
@@ -5428,7 +5557,7 @@ ztest_dataset_open(int d)
        }
        ASSERT(error == 0 || error == EEXIST);
 
-       VERIFY3U(dmu_objset_hold(name, zd, &os), ==, 0);
+       VERIFY0(dmu_objset_hold(name, zd, &os));
        (void) rw_exit(&ztest_name_lock);
 
        ztest_zd_init(zd, ZTEST_GET_SHARED_DS(d), os);
@@ -5542,11 +5671,13 @@ ztest_run(ztest_shared_t *zs)
            (thread_func_t)ztest_resume_thread, spa, TS_RUN, NULL, 0, 0,
            PTHREAD_CREATE_JOINABLE)), !=, NULL);
 
+#if 0
        /*
         * Set a deadman alarm to abort() if we hang.
         */
        signal(SIGALRM, ztest_deadman_alarm);
        alarm((zs->zs_thread_stop - zs->zs_thread_start) / NANOSEC + GRACE);
+#endif
 
        /*
         * Verify that we can safely inquire about about any object,
@@ -5626,7 +5757,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);
 
@@ -5723,8 +5854,15 @@ ztest_freeze(void)
         */
        kernel_init(FREAD | FWRITE);
        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);
+
+       spa->spa_debug = B_TRUE;
+       ztest_spa = spa;
+       txg_wait_synced(spa_get_dsl(spa), 0);
+       ztest_reguid(NULL, 0);
+
        spa_close(spa, FTAG);
        kernel_fini();
 }
@@ -5759,10 +5897,9 @@ make_random_props(void)
 {
        nvlist_t *props;
 
-       if (ztest_random(2) == 0)
-               return (NULL);
-
        VERIFY(nvlist_alloc(&props, NV_UNIQUE_NAME, 0) == 0);
+       if (ztest_random(2) == 0)
+               return (props);
        VERIFY(nvlist_add_uint64(props, "autoreplace", 1) == 0);
 
        return (props);
@@ -5777,6 +5914,7 @@ ztest_init(ztest_shared_t *zs)
 {
        spa_t *spa;
        nvlist_t *nvroot, *props;
+       int i;
 
        mutex_init(&ztest_vdev_lock, NULL, MUTEX_DEFAULT, NULL);
        rw_init(&ztest_name_lock, NULL, RW_DEFAULT, NULL);
@@ -5790,9 +5928,16 @@ ztest_init(ztest_shared_t *zs)
        ztest_shared->zs_vdev_next_leaf = 0;
        zs->zs_splits = 0;
        zs->zs_mirrors = ztest_opts.zo_mirrors;
-       nvroot = make_vdev_root(NULL, NULL, ztest_opts.zo_vdev_size, 0,
+       nvroot = make_vdev_root(NULL, NULL, NULL, ztest_opts.zo_vdev_size, 0,
            0, ztest_opts.zo_raidz, zs->zs_mirrors, 1);
        props = make_random_props();
+       for (i = 0; i < SPA_FEATURES; i++) {
+               char *buf;
+               VERIFY3S(-1, !=, asprintf(&buf, "feature@%s",
+                   spa_feature_table[i].fi_uname));
+               VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0));
+               free(buf);
+       }
        VERIFY3U(0, ==, spa_create(ztest_opts.zo_pool, nvroot, props,
            NULL, NULL));
        nvlist_free(nvroot);
@@ -5815,38 +5960,41 @@ ztest_init(ztest_shared_t *zs)
 }
 
 static void
-setup_fds(void)
+setup_data_fd(void)
 {
-       int fd;
+       static char ztest_name_data[] = "/tmp/ztest.data.XXXXXX";
 
-       char *tmp = tempnam(NULL, NULL);
-       fd = open(tmp, O_RDWR | O_CREAT, 0700);
-       ASSERT3S(fd, >=, 0);
-       VERIFY3S(ftruncate(fd, sizeof (ztest_shared_hdr_t)), ==, 0);
-       if (fd != ZTEST_FD_DATA) {
-               VERIFY3S(dup2(fd, ZTEST_FD_DATA), ==, ZTEST_FD_DATA);
-               close(fd);
-       }
-       (void) unlink(tmp);
-       free(tmp);
+       ztest_fd_data = mkstemp(ztest_name_data);
+       ASSERT3S(ztest_fd_data, >=, 0);
+       (void) unlink(ztest_name_data);
+}
 
-       fd = open("/dev/urandom", O_RDONLY);
-       ASSERT3S(fd, >=, 0);
-       if (fd != ZTEST_FD_RAND) {
-               VERIFY3S(dup2(fd, ZTEST_FD_RAND), ==, ZTEST_FD_RAND);
-               close(fd);
-       }
+static int
+shared_data_size(ztest_shared_hdr_t *hdr)
+{
+       int size;
+
+       size = hdr->zh_hdr_size;
+       size += hdr->zh_opts_size;
+       size += hdr->zh_size;
+       size += hdr->zh_stats_size * hdr->zh_stats_count;
+       size += hdr->zh_ds_size * hdr->zh_ds_count;
+
+       return (size);
 }
 
 static void
 setup_hdr(void)
 {
+       int size;
        ztest_shared_hdr_t *hdr;
 
        hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()),
-           PROT_READ | PROT_WRITE, MAP_SHARED, ZTEST_FD_DATA, 0);
+           PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0);
        ASSERT(hdr != MAP_FAILED);
 
+       VERIFY3U(0, ==, ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t)));
+
        hdr->zh_hdr_size = sizeof (ztest_shared_hdr_t);
        hdr->zh_opts_size = sizeof (ztest_shared_opts_t);
        hdr->zh_size = sizeof (ztest_shared_t);
@@ -5855,6 +6003,9 @@ setup_hdr(void)
        hdr->zh_ds_size = sizeof (ztest_shared_ds_t);
        hdr->zh_ds_count = ztest_opts.zo_datasets;
 
+       size = shared_data_size(hdr);
+       VERIFY3U(0, ==, ftruncate(ztest_fd_data, size));
+
        (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize()));
 }
 
@@ -5866,18 +6017,14 @@ setup_data(void)
        uint8_t *buf;
 
        hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()),
-           PROT_READ, MAP_SHARED, ZTEST_FD_DATA, 0);
+           PROT_READ, MAP_SHARED, ztest_fd_data, 0);
        ASSERT(hdr != MAP_FAILED);
 
-       size = hdr->zh_hdr_size;
-       size += hdr->zh_opts_size;
-       size += hdr->zh_size;
-       size += hdr->zh_stats_size * hdr->zh_stats_count;
-       size += hdr->zh_ds_size * hdr->zh_ds_count;
+       size = shared_data_size(hdr);
 
        (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize()));
        hdr = ztest_shared_hdr = (void *)mmap(0, P2ROUNDUP(size, getpagesize()),
-           PROT_READ | PROT_WRITE, MAP_SHARED, ZTEST_FD_DATA, 0);
+           PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0);
        ASSERT(hdr != MAP_FAILED);
        buf = (uint8_t *)hdr;
 
@@ -5896,12 +6043,13 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
 {
        pid_t pid;
        int status;
-       char cmdbuf[MAXPATHLEN];
+       char *cmdbuf = NULL;
 
        pid = fork();
 
        if (cmd == NULL) {
-               (void) strlcpy(cmdbuf, getexecname(), sizeof (cmdbuf));
+               cmdbuf = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
+               (void) strlcpy(cmdbuf, getexecname(), MAXPATHLEN);
                cmd = cmdbuf;
        }
 
@@ -5910,9 +6058,15 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
 
        if (pid == 0) { /* child */
                char *emptyargv[2] = { cmd, NULL };
+               char fd_data_str[12];
 
                struct rlimit rl = { 1024, 1024 };
                (void) setrlimit(RLIMIT_NOFILE, &rl);
+
+               (void) close(ztest_fd_rand);
+               VERIFY(11 >= snprintf(fd_data_str, 12, "%d", ztest_fd_data));
+               VERIFY(0 == setenv("ZTEST_FD_DATA", fd_data_str, 1));
+
                (void) enable_extended_FILE_stdio(-1, -1);
                if (libpath != NULL)
                        VERIFY(0 == setenv("LD_LIBRARY_PATH", libpath, 1));
@@ -5921,6 +6075,11 @@ exec_child(char *cmd, char *libpath, boolean_t ignorekill, int *statusp)
                fatal(B_TRUE, "exec failed: %s", cmd);
        }
 
+       if (cmdbuf != NULL) {
+               umem_free(cmdbuf, MAXPATHLEN);
+               cmd = NULL;
+       }
+
        while (waitpid(pid, &status, 0) != pid)
                continue;
        if (statusp != NULL)
@@ -5987,39 +6146,41 @@ main(int argc, char **argv)
        char timebuf[100];
        char numbuf[6];
        spa_t *spa;
-       char cmd[MAXNAMELEN];
+       char *cmd;
        boolean_t hasalt;
        int f;
-       boolean_t ischild = (0 == lseek(ZTEST_FD_DATA, 0, SEEK_CUR));
-
-       ASSERT(ischild || errno == EBADF || errno == ESPIPE);
+       char *fd_data_str = getenv("ZTEST_FD_DATA");
 
        (void) setvbuf(stdout, NULL, _IOLBF, 0);
 
-       if (!ischild) {
+       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_fds();
+               setup_data_fd();
                setup_hdr();
                setup_data();
                bcopy(&ztest_opts, ztest_shared_opts,
                    sizeof (*ztest_shared_opts));
        } else {
+               ztest_fd_data = atoi(fd_data_str);
                setup_data();
                bcopy(ztest_shared_opts, &ztest_opts, sizeof (ztest_opts));
        }
        ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count);
 
        /* Override location of zpool.cache */
-       (void) asprintf((char **)&spa_config_path, "%s/zpool.cache",
-           ztest_opts.zo_dir);
-       
+       VERIFY(asprintf((char **)&spa_config_path, "%s/zpool.cache",
+           ztest_opts.zo_dir) != -1);
+
        ztest_ds = umem_alloc(ztest_opts.zo_datasets * sizeof (ztest_ds_t),
            UMEM_NOFAIL);
        zs = ztest_shared;
 
-       if (ischild) {
+       if (fd_data_str) {
                metaslab_gang_bang = ztest_opts.zo_metaslab_gang_bang;
                metaslab_df_alloc_threshold =
                    zs->zs_metaslab_df_alloc_threshold;
@@ -6042,7 +6203,8 @@ main(int argc, char **argv)
                    (u_longlong_t)ztest_opts.zo_time);
        }
 
-       (void) strlcpy(cmd, getexecname(), sizeof (cmd));
+       cmd = umem_alloc(MAXNAMELEN, UMEM_NOFAIL);
+       (void) strlcpy(cmd, getexecname(), MAXNAMELEN);
 
        zs->zs_do_init = B_TRUE;
        if (strlen(ztest_opts.zo_alt_ztest) != 0) {
@@ -6183,5 +6345,7 @@ main(int argc, char **argv)
                    kills, iters - kills, (100.0 * kills) / MAX(1, iters));
        }
 
+       umem_free(cmd, MAXNAMELEN);
+
        return (0);
 }