Skip to content

Commit d0de2e8

Browse files
bprotopopovbehlendorf
authored andcommitted
Add a test case for dmu_free_long_range() to ztest
Signed-off-by: Boris Protopopov <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #4754
1 parent bc77ba7 commit d0de2e8

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

cmd/ztest/ztest.c

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ ztest_func_t ztest_split_pool;
329329
ztest_func_t ztest_reguid;
330330
ztest_func_t ztest_spa_upgrade;
331331
ztest_func_t ztest_fletcher;
332+
ztest_func_t ztest_dmu_free_long_range;
332333

333334
uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */
334335
uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
@@ -375,6 +376,7 @@ ztest_info_t ztest_info[] = {
375376
ZTI_INIT(ztest_vdev_add_remove, 1, &ztest_opts.zo_vdevtime),
376377
ZTI_INIT(ztest_vdev_aux_add_remove, 1, &ztest_opts.zo_vdevtime),
377378
ZTI_INIT(ztest_fletcher, 1, &zopt_rarely),
379+
ZTI_INIT(ztest_dmu_free_long_range, 1, &zopt_always),
378380
};
379381

380382
#define ZTEST_FUNCS (sizeof (ztest_info) / sizeof (ztest_info_t))
@@ -4310,6 +4312,182 @@ ztest_dmu_write_parallel(ztest_ds_t *zd, uint64_t id)
43104312
umem_free(od, sizeof (ztest_od_t));
43114313
}
43124314

4315+
static void
4316+
ztest_write_free(ztest_ds_t *zd, ztest_od_t *od, dmu_object_info_t *doi)
4317+
{
4318+
objset_t *os = zd->zd_os;
4319+
uint64_t object = od->od_object;
4320+
uint64_t size = 1ULL << 40;
4321+
uint64_t blocksize = doi->doi_data_block_size;
4322+
uint64_t mblocksize = doi->doi_metadata_block_size;
4323+
uint64_t l1_range = (mblocksize / sizeof (blkptr_t)) *
4324+
blocksize;
4325+
void *data = umem_alloc(blocksize, UMEM_NOFAIL);
4326+
4327+
(void) memset(data, 'a' + (object + l1_range) % 5, blocksize);
4328+
4329+
while (ztest_random(10)) {
4330+
int i, nranges = 0, minoffset = 0, maxoffset = 0;
4331+
ztest_zrl_t *zrl;
4332+
struct ztest_range {
4333+
uint64_t offset;
4334+
uint64_t size;
4335+
} range[10];
4336+
/*
4337+
* Touch a few L1 ranges
4338+
*/
4339+
bzero((void *)range, sizeof (struct ztest_range)*10);
4340+
nranges = ztest_random(10);
4341+
if (nranges == 0)
4342+
nranges = 3;
4343+
4344+
for (i = 0; i < nranges; i++) {
4345+
range[i].offset = ztest_random(size/l1_range)*l1_range;
4346+
range[i].size = ztest_random(10)*l1_range;
4347+
}
4348+
4349+
(void) rw_rdlock(&zd->zd_zilog_lock);
4350+
for (i = 0; i < nranges; i++) {
4351+
if ((ztest_write(zd, object, range[i].offset, blocksize,
4352+
data)) ||
4353+
(ztest_write(zd, object, range[i].offset +
4354+
range[i].size - blocksize, blocksize, data))) {
4355+
fatal(0, "dmu_free_long_range() failed\n");
4356+
}
4357+
}
4358+
(void) rw_unlock(&zd->zd_zilog_lock);
4359+
4360+
/*
4361+
* Free all ranges in a variable number of steps
4362+
*/
4363+
for (i = 0; i < nranges; i ++) {
4364+
minoffset = MIN(minoffset, range[i].offset);
4365+
maxoffset = MAX(maxoffset, range[i].offset +
4366+
range[i].size);
4367+
}
4368+
4369+
ztest_object_lock(zd, object, RL_READER);
4370+
zrl = ztest_range_lock(zd, object, minoffset,
4371+
maxoffset-minoffset, RL_WRITER);
4372+
4373+
switch (ztest_random(4)) {
4374+
case 0:
4375+
/* Free each range separately */
4376+
for (i = 0; i < nranges; i++) {
4377+
if ((dmu_free_long_range(os, object,
4378+
range[i].offset, range[i].size))) {
4379+
fatal(0, "dmu_free_long_range() "
4380+
"failed\n");
4381+
}
4382+
}
4383+
break;
4384+
case 1:
4385+
/* Free two ranges at a time */
4386+
for (i = 0; i < ((nranges % 2) ? nranges - 1 : nranges);
4387+
i += 2) {
4388+
uint64_t start =
4389+
MIN(range[i].offset, range[i+1].offset);
4390+
uint64_t end =
4391+
MAX(range[i].offset + range[i].size,
4392+
range[i+1].offset + range[i+1].size);
4393+
if ((dmu_free_long_range(os, object, start,
4394+
end-start))) {
4395+
fatal(0, "dmu_free_long_range() "
4396+
"failed\n");
4397+
}
4398+
}
4399+
/* Free the last range for odd nranges */
4400+
if ((nranges % 2) &&
4401+
(dmu_free_long_range(os, object,
4402+
range[nranges-1].offset,
4403+
range[nranges-1].size))) {
4404+
fatal(0, "dmu_free_long_range() failed\n");
4405+
}
4406+
break;
4407+
case 2:
4408+
{
4409+
/*
4410+
* Merge the ranges in two super-ranges and
4411+
* free in two steps
4412+
*/
4413+
uint64_t start = 0, end = 0;
4414+
int inranges = ztest_random(nranges);
4415+
4416+
for (i = 0; i < inranges; i++) {
4417+
start = MIN(start, range[i].offset);
4418+
end = MAX(end, range[i].offset + range[i].size);
4419+
}
4420+
if ((inranges != 0) &&
4421+
(dmu_free_long_range(os, object, start,
4422+
end-start))) {
4423+
fatal(0, "dmu_free_long_range() failed\n");
4424+
}
4425+
4426+
for (i = inranges; i < nranges; i++) {
4427+
start = MIN(start, range[i].offset);
4428+
end = MAX(end, range[i].offset + range[i].size);
4429+
}
4430+
if ((inranges != nranges) &&
4431+
(dmu_free_long_range(os, object, start,
4432+
end-start))) {
4433+
fatal(0, "dmu_free_long_range() failed\n");
4434+
}
4435+
}
4436+
break;
4437+
case 3:
4438+
{
4439+
/* Merge in one range and free in one step */
4440+
uint64_t start = minoffset, end = maxoffset;
4441+
4442+
if ((dmu_free_long_range(os, object, start,
4443+
end-start))) {
4444+
fatal(0, "dmu_free_long_range() failed\n");
4445+
}
4446+
}
4447+
break;
4448+
case 4:
4449+
default:
4450+
/* Free the whole logical range of the object */
4451+
if ((dmu_free_long_range(os, object, 0, size))) {
4452+
fatal(0, "dmu_free_long_range() failed\n");
4453+
}
4454+
break;
4455+
}
4456+
4457+
ztest_range_unlock(zd, zrl);
4458+
ztest_object_unlock(zd, object);
4459+
}
4460+
4461+
umem_free(data, blocksize);
4462+
}
4463+
4464+
/*
4465+
* Test punching holes in an object to verify consistency of
4466+
* the dmu structures for various corner cases
4467+
*
4468+
* Force reallocation of dnode between iterations
4469+
*/
4470+
void
4471+
ztest_dmu_free_long_range(ztest_ds_t *zd, uint64_t id)
4472+
{
4473+
ztest_od_t *od = NULL;
4474+
uint64_t blocksize = ztest_random_blocksize();
4475+
dmu_object_info_t doi = {0};
4476+
4477+
od = umem_alloc(sizeof (ztest_od_t), UMEM_NOFAIL);
4478+
4479+
ztest_od_init(od, ID_PARALLEL, FTAG, 0, DMU_OT_UINT64_OTHER,
4480+
blocksize, 0);
4481+
if (ztest_object_init(zd, od, sizeof (ztest_od_t), B_FALSE) != 0)
4482+
goto out;
4483+
4484+
VERIFY3U(0, ==, dmu_object_info(zd->zd_os, od->od_object, &doi));
4485+
ztest_write_free(zd, od, &doi);
4486+
4487+
out:
4488+
umem_free(od, sizeof (ztest_od_t));
4489+
}
4490+
43134491
void
43144492
ztest_dmu_prealloc(ztest_ds_t *zd, uint64_t id)
43154493
{

0 commit comments

Comments
 (0)