diff options
Diffstat (limited to 'cddl/contrib/opensolaris/cmd/ztest/ztest.c')
-rw-r--r-- | cddl/contrib/opensolaris/cmd/ztest/ztest.c | 187 |
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++) { |