From: Mike Snitzer Add 'corrupt_bio_byte' feature that will write 0 to the specified Nth byte of each bio (when the device is "down"). Signed-off-by: Mike Snitzer --- drivers/md/dm-flakey.c | 35 +++++++++++++++++++++++++++++++++-- drivers/md/dm-flakey.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) Index: linux-2.6.39/drivers/md/dm-flakey.c =================================================================== --- linux-2.6.39.orig/drivers/md/dm-flakey.c +++ linux-2.6.39/drivers/md/dm-flakey.c @@ -27,6 +27,7 @@ struct flakey_c { unsigned up_interval; unsigned down_interval; unsigned long flags; + unsigned corrupt_bio_byte; }; enum feature_flag_bits { @@ -41,7 +42,8 @@ static int parse_features(struct dm_arg_ const char *arg_name; static struct dm_arg _args[] = { - {0, 1, "invalid number of feature args"}, + {0, 3, "invalid number of feature args"}, + {1, UINT_MAX, "invalid corrupt bio byte value"}, }; /* No feature arguments supplied. */ @@ -56,6 +58,15 @@ static int parse_features(struct dm_arg_ arg_name = dm_shift_arg(as); argc--; + /* corrupt_bio_byte */ + if (!strnicmp(arg_name, MESG_STR("corrupt_bio_byte")) && + (argc >= 1)) { + r = dm_read_arg(_args + 1, dm_shift_arg(as), + &fc->corrupt_bio_byte, &ti->error); + argc--; + continue; + } + if (!strnicmp(arg_name, MESG_STR("drop_writes"))) { set_bit(DROP_WRITES, &fc->flags); continue; @@ -169,6 +180,16 @@ static void flakey_map_bio(struct dm_tar bio->bi_sector = flakey_map_sector(ti, bio->bi_sector); } +static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) +{ + unsigned bio_bytes = bio_cur_bytes(bio); + char *data = bio_data(bio); + + /* write 0 to the specified Nth byte of the bio */ + if (data && bio_bytes >= fc->corrupt_bio_byte) + data[fc->corrupt_bio_byte - 1] = 0; +} + static int flakey_map(struct dm_target *ti, struct bio *bio, union map_info *map_context) { @@ -181,6 +202,12 @@ static int flakey_map(struct dm_target * if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) { rw = bio_data_dir(bio); + if (fc->corrupt_bio_byte) { + /* corrupt writes but don't touch reads */ + if (rw == WRITE) + corrupt_bio_data(bio, fc); + goto map_bio; + } if (test_bit(DROP_WRITES, &fc->flags)) { /* drop writes but don't error reads */ if (rw == WRITE) { @@ -218,7 +245,10 @@ static int flakey_status(struct dm_targe fc->down_interval); drop_writes = test_bit(DROP_WRITES, &fc->flags); - DMEMIT("%u ", drop_writes); + DMEMIT("%u ", drop_writes + (fc->corrupt_bio_byte > 0) * 2); + + if (fc->corrupt_bio_byte) + DMEMIT("corrupt_bio_byte %u ", fc->corrupt_bio_byte); if (drop_writes) DMEMIT("drop_writes "); break;