@@ -329,6 +329,7 @@ ztest_func_t ztest_split_pool;
329
329
ztest_func_t ztest_reguid ;
330
330
ztest_func_t ztest_spa_upgrade ;
331
331
ztest_func_t ztest_fletcher ;
332
+ ztest_func_t ztest_dmu_free_long_range ;
332
333
333
334
uint64_t zopt_always = 0ULL * NANOSEC ; /* all the time */
334
335
uint64_t zopt_incessant = 1ULL * NANOSEC / 10 ; /* every 1/10 second */
@@ -375,6 +376,7 @@ ztest_info_t ztest_info[] = {
375
376
ZTI_INIT (ztest_vdev_add_remove , 1 , & ztest_opts .zo_vdevtime ),
376
377
ZTI_INIT (ztest_vdev_aux_add_remove , 1 , & ztest_opts .zo_vdevtime ),
377
378
ZTI_INIT (ztest_fletcher , 1 , & zopt_rarely ),
379
+ ZTI_INIT (ztest_dmu_free_long_range , 1 , & zopt_always ),
378
380
};
379
381
380
382
#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)
4310
4312
umem_free (od , sizeof (ztest_od_t ));
4311
4313
}
4312
4314
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
+
4313
4491
void
4314
4492
ztest_dmu_prealloc (ztest_ds_t * zd , uint64_t id )
4315
4493
{
0 commit comments