summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/cmd/ztest/ztest.c
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/contrib/opensolaris/cmd/ztest/ztest.c')
-rw-r--r--cddl/contrib/opensolaris/cmd/ztest/ztest.c187
1 files changed, 161 insertions, 26 deletions
diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c
index 57efe53..9c38b3f 100644
--- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c
+++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c
@@ -204,6 +204,7 @@ enum ztest_io_type {
ZTEST_IO_WRITE_ZEROES,
ZTEST_IO_TRUNCATE,
ZTEST_IO_SETATTR,
+ ZTEST_IO_REWRITE,
ZTEST_IO_TYPES
};
@@ -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 */
@@ -363,6 +365,7 @@ ztest_info_t ztest_info[] = {
{ ztest_reguid, 1, &zopt_sometimes },
{ 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_LUN_growth, 1, &zopt_rarely },
@@ -797,7 +800,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[MAXPATHLEN];
uint64_t vdev;
@@ -813,12 +816,13 @@ make_vdev_file(char *path, char *aux, size_t size, uint64_t ashift)
vdev = ztest_shared->zs_vdev_aux;
(void) snprintf(path, sizeof (pathbuf),
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, sizeof (pathbuf),
ztest_dev_template, ztest_opts.zo_dir,
- ztest_opts.zo_pool, vdev);
+ pool == NULL ? ztest_opts.zo_pool : pool, vdev);
}
}
@@ -840,17 +844,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,
@@ -869,19 +874,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,
@@ -898,8 +903,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;
@@ -909,7 +914,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);
}
@@ -927,6 +933,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)
{
@@ -1841,6 +1868,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;
@@ -1986,6 +2019,9 @@ ztest_remove(ztest_ds_t *zd, ztest_od_t *od, int count)
continue;
}
+ /*
+ * No object was found.
+ */
if (od->od_object == 0)
continue;
@@ -2101,6 +2137,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;
@@ -2153,6 +2190,25 @@ ztest_io(ztest_ds_t *zd, uint64_t object, uint64_t offset)
case ZTEST_IO_SETATTR:
(void) ztest_setattr(zd, object);
break;
+
+ case ZTEST_IO_REWRITE:
+ (void) rw_rdlock(&ztest_name_lock);
+ 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_unlock(&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_unlock(&zd->zd_zilog_lock);
@@ -2240,7 +2296,12 @@ ztest_zil_remount(ztest_ds_t *zd, uint64_t id)
{
objset_t *os = zd->zd_os;
- VERIFY(mutex_lock(&zd->zd_dirobj_lock) == 0);
+ /*
+ * 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.
+ */
+ VERIFY0(mutex_lock(&zd->zd_dirobj_lock));
(void) rw_wrlock(&zd->zd_zilog_lock);
/* zfsvfs_teardown() */
@@ -2269,7 +2330,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);
@@ -2277,7 +2338,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);
@@ -2287,7 +2348,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
* what's in the nvroot; we should fail with EEXIST.
*/
(void) rw_rdlock(&ztest_name_lock);
- 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));
@@ -2297,6 +2358,78 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
(void) rw_unlock(&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;
+
+ VERIFY0(mutex_lock(&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);
+ VERIFY0(spa_create(name, nvroot, props, NULL, NULL));
+ fnvlist_free(nvroot);
+ fnvlist_free(props);
+
+ VERIFY0(spa_open(name, &spa, FTAG));
+ 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);
+ VERIFY0(mutex_unlock(&ztest_vdev_lock));
+}
+
static vdev_t *
vdev_lookup_by_path(vdev_t *vd, const char *path)
{
@@ -2386,7 +2519,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);
@@ -2463,7 +2596,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)
@@ -2732,7 +2865,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);
@@ -4827,8 +4960,8 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
*/
for (int i = 0; i < copies; i++) {
uint64_t offset = i * blocksize;
- VERIFY(dmu_buf_hold(os, object, offset, FTAG, &db,
- DMU_READ_NO_PREFETCH) == 0);
+ VERIFY0(dmu_buf_hold(os, object, offset, FTAG, &db,
+ DMU_READ_NO_PREFETCH));
ASSERT(db->db_offset == offset);
ASSERT(db->db_size == blocksize);
ASSERT(ztest_pattern_match(db->db_data, db->db_size, pattern) ||
@@ -4844,8 +4977,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);
@@ -4900,7 +5033,7 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
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));
}
@@ -5523,6 +5656,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.
@@ -5647,7 +5782,7 @@ 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 (int i = 0; i < SPA_FEATURES; i++) {
OpenPOWER on IntegriCloud