diff options
Diffstat (limited to 'drivers/md/dm-flakey.c')
-rw-r--r-- | drivers/md/dm-flakey.c | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index dd963dc3ca08..e7c4c2a64f4b 100644 --- a/drivers/md/dm-flakey.c +++ b/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,18 @@ static int parse_features(struct dm_arg_set *as, struct dm_target *ti) arg_name = dm_shift_arg(as); argc--; + /* + * drop_writes + */ + if (!strcasecmp(arg_name, "drop_writes")) { + if (test_and_set_bit(DROP_WRITES, &fc->flags)) { + ti->error = "Feature drop_writes duplicated"; + return -EINVAL; + } + + continue; + } + ti->error = "Unrecognised flakey feature requested"; r = -EINVAL; } @@ -59,6 +77,9 @@ static int parse_features(struct dm_arg_set *as, struct dm_target *ti) /* * Construct a flakey mapping: * <dev_path> <offset> <up interval> <down interval> [<#feature args> [<arg>]*] + * + * Feature args: + * [drop_writes] */ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) { @@ -81,7 +102,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -EINVAL; } - fc = kmalloc(sizeof(*fc), GFP_KERNEL); + fc = kzalloc(sizeof(*fc), GFP_KERNEL); if (!fc) { ti->error = "Cannot allocate linear context"; return -ENOMEM; @@ -114,7 +135,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad; } - r = parse_features(&as, ti); + r = parse_features(&as, fc, ti); if (r) goto bad; @@ -162,12 +183,31 @@ static int flakey_map(struct dm_target *ti, struct bio *bio, { 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 +216,9 @@ static int flakey_map(struct dm_target *ti, struct bio *bio, 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 +226,14 @@ static int flakey_status(struct dm_target *ti, status_type_t type, 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; |