aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/device-mapper/dm-flakey.txt29
-rw-r--r--drivers/md/dm-flakey.c63
2 files changed, 78 insertions, 14 deletions
diff --git a/Documentation/device-mapper/dm-flakey.txt b/Documentation/device-mapper/dm-flakey.txt
index c8efdfd19a65..1b66c868ee7e 100644
--- a/Documentation/device-mapper/dm-flakey.txt
+++ b/Documentation/device-mapper/dm-flakey.txt
@@ -1,17 +1,34 @@
1dm-flakey 1dm-flakey
2========= 2=========
3 3
4This target is the same as the linear target except that it returns I/O 4This target is the same as the linear target except that it exhibits
5errors periodically. It's been found useful in simulating failing 5unreliable behaviour periodically. It's been found useful in simulating
6devices for testing purposes. 6failing devices for testing purposes.
7 7
8Starting from the time the table is loaded, the device is available for 8Starting from the time the table is loaded, the device is available for
9<up interval> seconds, then returns errors for <down interval> seconds, 9<up interval> seconds, then exhibits unreliable behaviour for <down
10and then this cycle repeats. 10interval> seconds, and then this cycle repeats.
11 11
12Parameters: <dev path> <offset> <up interval> <down interval> 12Also, consider using this in combination with the dm-delay target too,
13which can delay reads and writes and/or send them to different
14underlying devices.
15
16Table parameters
17----------------
18 <dev path> <offset> <up interval> <down interval> \
19 [<num_features> [<feature arguments>]]
20
21Mandatory parameters:
13 <dev path>: Full pathname to the underlying block-device, or a 22 <dev path>: Full pathname to the underlying block-device, or a
14 "major:minor" device-number. 23 "major:minor" device-number.
15 <offset>: Starting sector within the device. 24 <offset>: Starting sector within the device.
16 <up interval>: Number of seconds device is available. 25 <up interval>: Number of seconds device is available.
17 <down interval>: Number of seconds device returns errors. 26 <down interval>: Number of seconds device returns errors.
27
28Optional feature parameters:
29 If no feature parameters are present, during the periods of
30 unreliability, all I/O returns errors.
31
32 drop_writes:
33 All write I/O is silently ignored.
34 Read I/O is handled correctly.
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;