From: Mike Snitzer Add 'drop_writes' option to drop writes silently while the device is 'down'. Reads are not touched. Signed-off-by: Mike Snitzer Signed-off-by: Alasdair G Kergon --- drivers/md/dm-flakey.c | 47 +++++++++++++++++++++++++++++++++++++++-------- Documentation/device-mapper/dm-flakey.txt | 30 +++++++++++++--- drivers/md/dm-flakey.c | 53 +++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 14 deletions(-) Index: linux/Documentation/device-mapper/dm-flakey.txt =================================================================== --- linux.orig/Documentation/device-mapper/dm-flakey.txt +++ linux/Documentation/device-mapper/dm-flakey.txt @@ -1,17 +1,35 @@ dm-flakey ========= -This target is the same as the linear target except that it returns I/O -errors periodically. It's been found useful in simulating failing -devices for testing purposes. +This target is the same as the linear target except that it exhibits +unreliable behaviour periodically. It's been found useful in simulating +failing devices for testing purposes. Starting from the time the table is loaded, the device is available for - seconds, then returns errors for seconds, -and then this cycle repeats. + seconds, then exhibits unreliable behaviour for seconds, and then this cycle repeats. -Parameters: +Also, consider using this in combination with the dm-delay target too, +which can delay reads and writes and/or send them to different +underlying devices. + +Table parameters +---------------- + \ + [ []] + +Mandatory parameters: : Full pathname to the underlying block-device, or a "major:minor" device-number. : Starting sector within the device. : Number of seconds device is available. : Number of seconds device returns errors. + +Optional feature parameters: + If no feature parameters are present, during the periods of + unreliability, all I/O returns errors. + + drop_writes: + All write I/O is silently ignored. + Read I/O is handled correctly. + Index: linux/drivers/md/dm-flakey.c =================================================================== --- linux.orig/drivers/md/dm-flakey.c +++ linux/drivers/md/dm-flakey.c @@ -25,16 +25,22 @@ struct flakey_c { sector_t start; unsigned up_interval; unsigned down_interval; + unsigned long flags; }; -static int parse_features(struct dm_arg_set *as, struct dm_target *ti) +enum feature_flag_bits { + DROP_WRITES +}; + +static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, + struct dm_target *ti) { int r; unsigned argc; const char *arg_name; static struct dm_arg _args[] = { - {0, 0, "invalid number of feature args"}, + {0, 1, "invalid number of feature args"}, }; /* No feature arguments supplied. */ @@ -49,6 +55,11 @@ static int parse_features(struct dm_arg_ arg_name = dm_shift_arg(as); argc--; + if (!strcasecmp(arg_name, "drop_writes")) { + set_bit(DROP_WRITES, &fc->flags); + continue; + } + ti->error = "Unrecognised flakey feature request"; r = -EINVAL; } @@ -81,7 +92,7 @@ static int flakey_ctr(struct dm_target * return -EINVAL; } - fc = kmalloc(sizeof(*fc), GFP_KERNEL); + fc = kzalloc(sizeof(*fc), GFP_KERNEL); if (!fc) { ti->error = "dm-flakey: Cannot allocate linear context"; return -ENOMEM; @@ -114,7 +125,7 @@ static int flakey_ctr(struct dm_target * goto bad; } - r = parse_features(&as, ti); + r = parse_features(&as, fc, ti); if (r) goto bad; @@ -162,12 +173,31 @@ static int flakey_map(struct dm_target * { struct flakey_c *fc = ti->private; unsigned elapsed; + unsigned rw; /* Are we alive ? */ elapsed = (jiffies - fc->start_time) / HZ; - if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) + if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) { + rw = bio_data_dir(bio); + + /* + * Drop writes. Map reads as normal. + */ + if (test_bit(DROP_WRITES, &fc->flags)) { + if (rw == WRITE) { + bio_endio(bio, 0); + return DM_MAPIO_SUBMITTED; + } + goto map_bio; + } + + /* + * Default setting errors all I/O. + */ return -EIO; + } +map_bio: flakey_map_bio(ti, bio); return DM_MAPIO_REMAPPED; @@ -176,7 +206,9 @@ static int flakey_map(struct dm_target * static int flakey_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { + unsigned sz = 0; struct flakey_c *fc = ti->private; + unsigned drop_writes; switch (type) { case STATUSTYPE_INFO: @@ -184,9 +216,14 @@ static int flakey_status(struct dm_targe break; case STATUSTYPE_TABLE: - snprintf(result, maxlen, "%s %llu %u %u", fc->dev->name, - (unsigned long long)fc->start, fc->up_interval, - fc->down_interval); + DMEMIT("%s %llu %u %u ", fc->dev->name, + (unsigned long long)fc->start, fc->up_interval, + fc->down_interval); + + drop_writes = test_bit(DROP_WRITES, &fc->flags); + DMEMIT("%u ", drop_writes); + if (drop_writes) + DMEMIT("drop_writes "); break; } return 0;