aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2016-12-13 14:54:50 -0500
committerMike Snitzer <snitzer@redhat.com>2016-12-13 15:01:31 -0500
commitef548c551e72dbbdcc6d9ed7c7b3b01083fea8e2 (patch)
tree18caf8a05714dcb02e7245eda29017aeeae2253b
parente99dda8fc4567db6e39ec25b60bbcd68182dfd7b (diff)
dm flakey: introduce "error_writes" feature
Recent dm-flakey fixes, to have reads error out during the "down" interval, made it so that the previous read behaviour is no longer available. It is useful to have reads complete like normal but have writes error out, so make it possible again with a new "error_writes" feature. Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r--drivers/md/dm-flakey.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 3643cba71351..13305a182611 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -36,7 +36,8 @@ struct flakey_c {
36}; 36};
37 37
38enum feature_flag_bits { 38enum feature_flag_bits {
39 DROP_WRITES 39 DROP_WRITES,
40 ERROR_WRITES
40}; 41};
41 42
42struct per_bio_data { 43struct per_bio_data {
@@ -76,6 +77,25 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
76 if (test_and_set_bit(DROP_WRITES, &fc->flags)) { 77 if (test_and_set_bit(DROP_WRITES, &fc->flags)) {
77 ti->error = "Feature drop_writes duplicated"; 78 ti->error = "Feature drop_writes duplicated";
78 return -EINVAL; 79 return -EINVAL;
80 } else if (test_bit(ERROR_WRITES, &fc->flags)) {
81 ti->error = "Feature drop_writes conflicts with feature error_writes";
82 return -EINVAL;
83 }
84
85 continue;
86 }
87
88 /*
89 * error_writes
90 */
91 if (!strcasecmp(arg_name, "error_writes")) {
92 if (test_and_set_bit(ERROR_WRITES, &fc->flags)) {
93 ti->error = "Feature error_writes duplicated";
94 return -EINVAL;
95
96 } else if (test_bit(DROP_WRITES, &fc->flags)) {
97 ti->error = "Feature error_writes conflicts with feature drop_writes";
98 return -EINVAL;
79 } 99 }
80 100
81 continue; 101 continue;
@@ -135,6 +155,10 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
135 if (test_bit(DROP_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) { 155 if (test_bit(DROP_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) {
136 ti->error = "drop_writes is incompatible with corrupt_bio_byte with the WRITE flag set"; 156 ti->error = "drop_writes is incompatible with corrupt_bio_byte with the WRITE flag set";
137 return -EINVAL; 157 return -EINVAL;
158
159 } else if (test_bit(ERROR_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) {
160 ti->error = "error_writes is incompatible with corrupt_bio_byte with the WRITE flag set";
161 return -EINVAL;
138 } 162 }
139 163
140 return 0; 164 return 0;
@@ -291,22 +315,27 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
291 pb->bio_submitted = true; 315 pb->bio_submitted = true;
292 316
293 /* 317 /*
294 * Error reads if neither corrupt_bio_byte or drop_writes are set. 318 * Error reads if neither corrupt_bio_byte or drop_writes or error_writes are set.
295 * Otherwise, flakey_end_io() will decide if the reads should be modified. 319 * Otherwise, flakey_end_io() will decide if the reads should be modified.
296 */ 320 */
297 if (bio_data_dir(bio) == READ) { 321 if (bio_data_dir(bio) == READ) {
298 if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags)) 322 if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags) &&
323 !test_bit(ERROR_WRITES, &fc->flags))
299 return -EIO; 324 return -EIO;
300 goto map_bio; 325 goto map_bio;
301 } 326 }
302 327
303 /* 328 /*
304 * Drop writes? 329 * Drop or error writes?
305 */ 330 */
306 if (test_bit(DROP_WRITES, &fc->flags)) { 331 if (test_bit(DROP_WRITES, &fc->flags)) {
307 bio_endio(bio); 332 bio_endio(bio);
308 return DM_MAPIO_SUBMITTED; 333 return DM_MAPIO_SUBMITTED;
309 } 334 }
335 else if (test_bit(ERROR_WRITES, &fc->flags)) {
336 bio_io_error(bio);
337 return DM_MAPIO_SUBMITTED;
338 }
310 339
311 /* 340 /*
312 * Corrupt matching writes. 341 * Corrupt matching writes.
@@ -342,10 +371,11 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
342 */ 371 */
343 corrupt_bio_data(bio, fc); 372 corrupt_bio_data(bio, fc);
344 373
345 } else if (!test_bit(DROP_WRITES, &fc->flags)) { 374 } else if (!test_bit(DROP_WRITES, &fc->flags) &&
375 !test_bit(ERROR_WRITES, &fc->flags)) {
346 /* 376 /*
347 * Error read during the down_interval if drop_writes 377 * Error read during the down_interval if drop_writes
348 * wasn't configured. 378 * and error_writes were not configured.
349 */ 379 */
350 return -EIO; 380 return -EIO;
351 } 381 }
@@ -359,7 +389,7 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
359{ 389{
360 unsigned sz = 0; 390 unsigned sz = 0;
361 struct flakey_c *fc = ti->private; 391 struct flakey_c *fc = ti->private;
362 unsigned drop_writes; 392 unsigned drop_writes, error_writes;
363 393
364 switch (type) { 394 switch (type) {
365 case STATUSTYPE_INFO: 395 case STATUSTYPE_INFO:
@@ -372,10 +402,13 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
372 fc->down_interval); 402 fc->down_interval);
373 403
374 drop_writes = test_bit(DROP_WRITES, &fc->flags); 404 drop_writes = test_bit(DROP_WRITES, &fc->flags);
375 DMEMIT("%u ", drop_writes + (fc->corrupt_bio_byte > 0) * 5); 405 error_writes = test_bit(ERROR_WRITES, &fc->flags);
406 DMEMIT("%u ", drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5);
376 407
377 if (drop_writes) 408 if (drop_writes)
378 DMEMIT("drop_writes "); 409 DMEMIT("drop_writes ");
410 else if (error_writes)
411 DMEMIT("error_writes ");
379 412
380 if (fc->corrupt_bio_byte) 413 if (fc->corrupt_bio_byte)
381 DMEMIT("corrupt_bio_byte %u %c %u %u ", 414 DMEMIT("corrupt_bio_byte %u %c %u %u ",
@@ -412,7 +445,7 @@ static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_
412 445
413static struct target_type flakey_target = { 446static struct target_type flakey_target = {
414 .name = "flakey", 447 .name = "flakey",
415 .version = {1, 3, 1}, 448 .version = {1, 4, 0},
416 .module = THIS_MODULE, 449 .module = THIS_MODULE,
417 .ctr = flakey_ctr, 450 .ctr = flakey_ctr,
418 .dtr = flakey_dtr, 451 .dtr = flakey_dtr,