aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-flakey.c
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2011-08-02 07:32:05 -0400
committerAlasdair G Kergon <agk@redhat.com>2011-08-02 07:32:05 -0400
commitb26f5e3d7127487e934758c1fbe05d683b082cb0 (patch)
tree8b120e0e45e3a50c1c5adada0eede0870d62457d /drivers/md/dm-flakey.c
parentdfd068b01f02653c6650f1c0eda443b2655d1471 (diff)
dm flakey: add drop_writes
Add 'drop_writes' option to drop writes silently while the device is 'down'. Reads are not touched. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-flakey.c')
-rw-r--r--drivers/md/dm-flakey.c63
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 {
25 sector_t start; 25 sector_t start;
26 unsigned up_interval; 26 unsigned up_interval;
27 unsigned down_interval; 27 unsigned down_interval;
28 unsigned long flags;
28}; 29};
29 30
30static int parse_features(struct dm_arg_set *as, struct dm_target *ti) 31enum feature_flag_bits {
32 DROP_WRITES
33};
34
35static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
36 struct dm_target *ti)
31{ 37{
32 int r; 38 int r;
33 unsigned argc; 39 unsigned argc;
34 const char *arg_name; 40 const char *arg_name;
35 41
36 static struct dm_arg _args[] = { 42 static struct dm_arg _args[] = {
37 {0, 0, "Invalid number of feature args"}, 43 {0, 1, "Invalid number of feature args"},
38 }; 44 };
39 45
40 /* No feature arguments supplied. */ 46 /* No feature arguments supplied. */
@@ -49,6 +55,18 @@ static int parse_features(struct dm_arg_set *as, struct dm_target *ti)
49 arg_name = dm_shift_arg(as); 55 arg_name = dm_shift_arg(as);
50 argc--; 56 argc--;
51 57
58 /*
59 * drop_writes
60 */
61 if (!strcasecmp(arg_name, "drop_writes")) {
62 if (test_and_set_bit(DROP_WRITES, &fc->flags)) {
63 ti->error = "Feature drop_writes duplicated";
64 return -EINVAL;
65 }
66
67 continue;
68 }
69
52 ti->error = "Unrecognised flakey feature requested"; 70 ti->error = "Unrecognised flakey feature requested";
53 r = -EINVAL; 71 r = -EINVAL;
54 } 72 }
@@ -59,6 +77,9 @@ static int parse_features(struct dm_arg_set *as, struct dm_target *ti)
59/* 77/*
60 * Construct a flakey mapping: 78 * Construct a flakey mapping:
61 * <dev_path> <offset> <up interval> <down interval> [<#feature args> [<arg>]*] 79 * <dev_path> <offset> <up interval> <down interval> [<#feature args> [<arg>]*]
80 *
81 * Feature args:
82 * [drop_writes]
62 */ 83 */
63static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) 84static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
64{ 85{
@@ -81,7 +102,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
81 return -EINVAL; 102 return -EINVAL;
82 } 103 }
83 104
84 fc = kmalloc(sizeof(*fc), GFP_KERNEL); 105 fc = kzalloc(sizeof(*fc), GFP_KERNEL);
85 if (!fc) { 106 if (!fc) {
86 ti->error = "Cannot allocate linear context"; 107 ti->error = "Cannot allocate linear context";
87 return -ENOMEM; 108 return -ENOMEM;
@@ -114,7 +135,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
114 goto bad; 135 goto bad;
115 } 136 }
116 137
117 r = parse_features(&as, ti); 138 r = parse_features(&as, fc, ti);
118 if (r) 139 if (r)
119 goto bad; 140 goto bad;
120 141
@@ -162,12 +183,31 @@ static int flakey_map(struct dm_target *ti, struct bio *bio,
162{ 183{
163 struct flakey_c *fc = ti->private; 184 struct flakey_c *fc = ti->private;
164 unsigned elapsed; 185 unsigned elapsed;
186 unsigned rw;
165 187
166 /* Are we alive ? */ 188 /* Are we alive ? */
167 elapsed = (jiffies - fc->start_time) / HZ; 189 elapsed = (jiffies - fc->start_time) / HZ;
168 if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) 190 if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval) {
191 rw = bio_data_dir(bio);
192
193 /*
194 * Drop writes. Map reads as normal.
195 */
196 if (test_bit(DROP_WRITES, &fc->flags)) {
197 if (rw == WRITE) {
198 bio_endio(bio, 0);
199 return DM_MAPIO_SUBMITTED;
200 }
201 goto map_bio;
202 }
203
204 /*
205 * Default setting errors all I/O.
206 */
169 return -EIO; 207 return -EIO;
208 }
170 209
210map_bio:
171 flakey_map_bio(ti, bio); 211 flakey_map_bio(ti, bio);
172 212
173 return DM_MAPIO_REMAPPED; 213 return DM_MAPIO_REMAPPED;
@@ -176,7 +216,9 @@ static int flakey_map(struct dm_target *ti, struct bio *bio,
176static int flakey_status(struct dm_target *ti, status_type_t type, 216static int flakey_status(struct dm_target *ti, status_type_t type,
177 char *result, unsigned int maxlen) 217 char *result, unsigned int maxlen)
178{ 218{
219 unsigned sz = 0;
179 struct flakey_c *fc = ti->private; 220 struct flakey_c *fc = ti->private;
221 unsigned drop_writes;
180 222
181 switch (type) { 223 switch (type) {
182 case STATUSTYPE_INFO: 224 case STATUSTYPE_INFO:
@@ -184,9 +226,14 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
184 break; 226 break;
185 227
186 case STATUSTYPE_TABLE: 228 case STATUSTYPE_TABLE:
187 snprintf(result, maxlen, "%s %llu %u %u", fc->dev->name, 229 DMEMIT("%s %llu %u %u ", fc->dev->name,
188 (unsigned long long)fc->start, fc->up_interval, 230 (unsigned long long)fc->start, fc->up_interval,
189 fc->down_interval); 231 fc->down_interval);
232
233 drop_writes = test_bit(DROP_WRITES, &fc->flags);
234 DMEMIT("%u ", drop_writes);
235 if (drop_writes)
236 DMEMIT("drop_writes ");
190 break; 237 break;
191 } 238 }
192 return 0; 239 return 0;