@@ -47,7 +47,8 @@ enum feature_flag_bits {
47
47
};
48
48
49
49
struct per_bio_data {
50
- bool bio_submitted ;
50
+ bool bio_can_corrupt ;
51
+ struct bvec_iter saved_iter ;
51
52
};
52
53
53
54
static int parse_features (struct dm_arg_set * as , struct flakey_c * fc ,
@@ -354,7 +355,8 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio)
354
355
}
355
356
356
357
static void corrupt_bio_common (struct bio * bio , unsigned int corrupt_bio_byte ,
357
- unsigned char corrupt_bio_value )
358
+ unsigned char corrupt_bio_value ,
359
+ struct bvec_iter start )
358
360
{
359
361
struct bvec_iter iter ;
360
362
struct bio_vec bvec ;
@@ -363,7 +365,7 @@ static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte,
363
365
* Overwrite the Nth byte of the bio's data, on whichever page
364
366
* it falls.
365
367
*/
366
- bio_for_each_segment (bvec , bio , iter ) {
368
+ __bio_for_each_segment (bvec , bio , iter , start ) {
367
369
if (bio_iter_len (bio , iter ) > corrupt_bio_byte ) {
368
370
unsigned char * segment = bvec_kmap_local (& bvec );
369
371
segment [corrupt_bio_byte ] = corrupt_bio_value ;
@@ -372,36 +374,31 @@ static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte,
372
374
"(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n" ,
373
375
bio , corrupt_bio_value , corrupt_bio_byte ,
374
376
(bio_data_dir (bio ) == WRITE ) ? 'w' : 'r' , bio -> bi_opf ,
375
- (unsigned long long )bio -> bi_iter .bi_sector ,
376
- bio -> bi_iter .bi_size );
377
+ (unsigned long long )start .bi_sector ,
378
+ start .bi_size );
377
379
break ;
378
380
}
379
381
corrupt_bio_byte -= bio_iter_len (bio , iter );
380
382
}
381
383
}
382
384
383
- static void corrupt_bio_data (struct bio * bio , struct flakey_c * fc )
385
+ static void corrupt_bio_data (struct bio * bio , struct flakey_c * fc ,
386
+ struct bvec_iter start )
384
387
{
385
388
unsigned int corrupt_bio_byte = fc -> corrupt_bio_byte - 1 ;
386
389
387
- if (!bio_has_data (bio ))
388
- return ;
389
-
390
- corrupt_bio_common (bio , corrupt_bio_byte , fc -> corrupt_bio_value );
390
+ corrupt_bio_common (bio , corrupt_bio_byte , fc -> corrupt_bio_value , start );
391
391
}
392
392
393
- static void corrupt_bio_random (struct bio * bio )
393
+ static void corrupt_bio_random (struct bio * bio , struct bvec_iter start )
394
394
{
395
395
unsigned int corrupt_byte ;
396
396
unsigned char corrupt_value ;
397
397
398
- if (!bio_has_data (bio ))
399
- return ;
400
-
401
- corrupt_byte = get_random_u32 () % bio -> bi_iter .bi_size ;
398
+ corrupt_byte = get_random_u32 () % start .bi_size ;
402
399
corrupt_value = get_random_u8 ();
403
400
404
- corrupt_bio_common (bio , corrupt_byte , corrupt_value );
401
+ corrupt_bio_common (bio , corrupt_byte , corrupt_value , start );
405
402
}
406
403
407
404
static void clone_free (struct bio * clone )
@@ -496,7 +493,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
496
493
unsigned int elapsed ;
497
494
struct per_bio_data * pb = dm_per_bio_data (bio , sizeof (struct per_bio_data ));
498
495
499
- pb -> bio_submitted = false;
496
+ pb -> bio_can_corrupt = false;
500
497
501
498
if (op_is_zone_mgmt (bio_op (bio )))
502
499
goto map_bio ;
@@ -505,10 +502,11 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
505
502
elapsed = (jiffies - fc -> start_time ) / HZ ;
506
503
if (elapsed % (fc -> up_interval + fc -> down_interval ) >= fc -> up_interval ) {
507
504
bool corrupt_fixed , corrupt_random ;
508
- /*
509
- * Flag this bio as submitted while down.
510
- */
511
- pb -> bio_submitted = true;
505
+
506
+ if (bio_has_data (bio )) {
507
+ pb -> bio_can_corrupt = true;
508
+ pb -> saved_iter = bio -> bi_iter ;
509
+ }
512
510
513
511
/*
514
512
* If ERROR_READS isn't set flakey_end_io() will decide if the
@@ -531,6 +529,8 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
531
529
return DM_MAPIO_SUBMITTED ;
532
530
}
533
531
532
+ if (!pb -> bio_can_corrupt )
533
+ goto map_bio ;
534
534
/*
535
535
* Corrupt matching writes.
536
536
*/
@@ -550,9 +550,11 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
550
550
struct bio * clone = clone_bio (ti , fc , bio );
551
551
if (clone ) {
552
552
if (corrupt_fixed )
553
- corrupt_bio_data (clone , fc );
553
+ corrupt_bio_data (clone , fc ,
554
+ clone -> bi_iter );
554
555
if (corrupt_random )
555
- corrupt_bio_random (clone );
556
+ corrupt_bio_random (clone ,
557
+ clone -> bi_iter );
556
558
submit_bio (clone );
557
559
return DM_MAPIO_SUBMITTED ;
558
560
}
@@ -574,21 +576,21 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
574
576
if (op_is_zone_mgmt (bio_op (bio )))
575
577
return DM_ENDIO_DONE ;
576
578
577
- if (!* error && pb -> bio_submitted && (bio_data_dir (bio ) == READ )) {
579
+ if (!* error && pb -> bio_can_corrupt && (bio_data_dir (bio ) == READ )) {
578
580
if (fc -> corrupt_bio_byte ) {
579
581
if ((fc -> corrupt_bio_rw == READ ) &&
580
582
all_corrupt_bio_flags_match (bio , fc )) {
581
583
/*
582
584
* Corrupt successful matching READs while in down state.
583
585
*/
584
- corrupt_bio_data (bio , fc );
586
+ corrupt_bio_data (bio , fc , pb -> saved_iter );
585
587
}
586
588
}
587
589
if (fc -> random_read_corrupt ) {
588
590
u64 rnd = get_random_u64 ();
589
591
u32 rem = do_div (rnd , PROBABILITY_BASE );
590
592
if (rem < fc -> random_read_corrupt )
591
- corrupt_bio_random (bio );
593
+ corrupt_bio_random (bio , pb -> saved_iter );
592
594
}
593
595
}
594
596
0 commit comments