diff options
author | Mike Snitzer <snitzer@redhat.com> | 2011-08-02 07:32:05 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2011-08-02 07:32:05 -0400 |
commit | b26f5e3d7127487e934758c1fbe05d683b082cb0 (patch) | |
tree | 8b120e0e45e3a50c1c5adada0eede0870d62457d /drivers/md/dm-flakey.c | |
parent | dfd068b01f02653c6650f1c0eda443b2655d1471 (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.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 { | |||
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 | ||
30 | static int parse_features(struct dm_arg_set *as, struct dm_target *ti) | 31 | enum feature_flag_bits { |
32 | DROP_WRITES | ||
33 | }; | ||
34 | |||
35 | static 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 | */ |
63 | static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 84 | static 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 | ||
210 | map_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, | |||
176 | static int flakey_status(struct dm_target *ti, status_type_t type, | 216 | static 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; |