Skip to content

Commit 13e7907

Browse files
bmarzinsMikulas Patocka
authored andcommitted
dm-flakey: make corrupting read bios work
dm-flakey corrupts the read bios in the endio function. However, the corrupt_bio_* functions checked bio_has_data() to see if there was data to corrupt. Since this was the endio function, there was no data left to complete, so bio_has_data() was always false. Fix this by saving a copy of the bio's bi_iter in flakey_map(), and using this to initialize the iter for corrupting the read bios. This patch also skips cloning the bio for write bios with no data. Reported-by: Kent Overstreet <kent.overstreet@linux.dev> Fixes: a399879 ("dm flakey: add corrupt_bio_byte feature") Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
1 parent 4319f0a commit 13e7907

File tree

1 file changed

+28
-26
lines changed

1 file changed

+28
-26
lines changed

drivers/md/dm-flakey.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ enum feature_flag_bits {
4747
};
4848

4949
struct per_bio_data {
50-
bool bio_submitted;
50+
bool bio_can_corrupt;
51+
struct bvec_iter saved_iter;
5152
};
5253

5354
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)
354355
}
355356

356357
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)
358360
{
359361
struct bvec_iter iter;
360362
struct bio_vec bvec;
@@ -363,7 +365,7 @@ static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte,
363365
* Overwrite the Nth byte of the bio's data, on whichever page
364366
* it falls.
365367
*/
366-
bio_for_each_segment(bvec, bio, iter) {
368+
__bio_for_each_segment(bvec, bio, iter, start) {
367369
if (bio_iter_len(bio, iter) > corrupt_bio_byte) {
368370
unsigned char *segment = bvec_kmap_local(&bvec);
369371
segment[corrupt_bio_byte] = corrupt_bio_value;
@@ -372,36 +374,31 @@ static void corrupt_bio_common(struct bio *bio, unsigned int corrupt_bio_byte,
372374
"(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n",
373375
bio, corrupt_bio_value, corrupt_bio_byte,
374376
(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);
377379
break;
378380
}
379381
corrupt_bio_byte -= bio_iter_len(bio, iter);
380382
}
381383
}
382384

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)
384387
{
385388
unsigned int corrupt_bio_byte = fc->corrupt_bio_byte - 1;
386389

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);
391391
}
392392

393-
static void corrupt_bio_random(struct bio *bio)
393+
static void corrupt_bio_random(struct bio *bio, struct bvec_iter start)
394394
{
395395
unsigned int corrupt_byte;
396396
unsigned char corrupt_value;
397397

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;
402399
corrupt_value = get_random_u8();
403400

404-
corrupt_bio_common(bio, corrupt_byte, corrupt_value);
401+
corrupt_bio_common(bio, corrupt_byte, corrupt_value, start);
405402
}
406403

407404
static void clone_free(struct bio *clone)
@@ -496,7 +493,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
496493
unsigned int elapsed;
497494
struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
498495

499-
pb->bio_submitted = false;
496+
pb->bio_can_corrupt = false;
500497

501498
if (op_is_zone_mgmt(bio_op(bio)))
502499
goto map_bio;
@@ -505,10 +502,11 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
505502
elapsed = (jiffies - fc->start_time) / HZ;
506503
if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) {
507504
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+
}
512510

513511
/*
514512
* 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)
531529
return DM_MAPIO_SUBMITTED;
532530
}
533531

532+
if (!pb->bio_can_corrupt)
533+
goto map_bio;
534534
/*
535535
* Corrupt matching writes.
536536
*/
@@ -550,9 +550,11 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
550550
struct bio *clone = clone_bio(ti, fc, bio);
551551
if (clone) {
552552
if (corrupt_fixed)
553-
corrupt_bio_data(clone, fc);
553+
corrupt_bio_data(clone, fc,
554+
clone->bi_iter);
554555
if (corrupt_random)
555-
corrupt_bio_random(clone);
556+
corrupt_bio_random(clone,
557+
clone->bi_iter);
556558
submit_bio(clone);
557559
return DM_MAPIO_SUBMITTED;
558560
}
@@ -574,21 +576,21 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
574576
if (op_is_zone_mgmt(bio_op(bio)))
575577
return DM_ENDIO_DONE;
576578

577-
if (!*error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
579+
if (!*error && pb->bio_can_corrupt && (bio_data_dir(bio) == READ)) {
578580
if (fc->corrupt_bio_byte) {
579581
if ((fc->corrupt_bio_rw == READ) &&
580582
all_corrupt_bio_flags_match(bio, fc)) {
581583
/*
582584
* Corrupt successful matching READs while in down state.
583585
*/
584-
corrupt_bio_data(bio, fc);
586+
corrupt_bio_data(bio, fc, pb->saved_iter);
585587
}
586588
}
587589
if (fc->random_read_corrupt) {
588590
u64 rnd = get_random_u64();
589591
u32 rem = do_div(rnd, PROBABILITY_BASE);
590592
if (rem < fc->random_read_corrupt)
591-
corrupt_bio_random(bio);
593+
corrupt_bio_random(bio, pb->saved_iter);
592594
}
593595
}
594596

0 commit comments

Comments
 (0)