Commit aa7d7bc9 authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Mike Snitzer

dm flakey: add an "error_reads" option

dm-flakey returns error on reads if no other argument is specified.
This commit simplifies associated logic while formalizing an
"error_reads" argument and an ERROR_READS flag.

If no argument is specified, set ERROR_READS flag so that it behaves
just like before this commit.
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
parent e3675dc1
...@@ -39,6 +39,10 @@ Optional feature parameters: ...@@ -39,6 +39,10 @@ Optional feature parameters:
If no feature parameters are present, during the periods of If no feature parameters are present, during the periods of
unreliability, all I/O returns errors. unreliability, all I/O returns errors.
error_reads:
All read I/O is failed with an error signalled.
Write I/O is handled correctly.
drop_writes: drop_writes:
All write I/O is silently ignored. All write I/O is silently ignored.
Read I/O is handled correctly. Read I/O is handled correctly.
......
...@@ -37,6 +37,7 @@ struct flakey_c { ...@@ -37,6 +37,7 @@ struct flakey_c {
}; };
enum feature_flag_bits { enum feature_flag_bits {
ERROR_READS,
DROP_WRITES, DROP_WRITES,
ERROR_WRITES ERROR_WRITES
}; };
...@@ -53,7 +54,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, ...@@ -53,7 +54,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
const char *arg_name; const char *arg_name;
static const struct dm_arg _args[] = { static const struct dm_arg _args[] = {
{0, 6, "Invalid number of feature args"}, {0, 7, "Invalid number of feature args"},
{1, UINT_MAX, "Invalid corrupt bio byte"}, {1, UINT_MAX, "Invalid corrupt bio byte"},
{0, 255, "Invalid corrupt value to write into bio byte (0-255)"}, {0, 255, "Invalid corrupt value to write into bio byte (0-255)"},
{0, UINT_MAX, "Invalid corrupt bio flags mask"}, {0, UINT_MAX, "Invalid corrupt bio flags mask"},
...@@ -76,6 +77,17 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, ...@@ -76,6 +77,17 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
return -EINVAL; return -EINVAL;
} }
/*
* error_reads
*/
if (!strcasecmp(arg_name, "error_reads")) {
if (test_and_set_bit(ERROR_READS, &fc->flags)) {
ti->error = "Feature error_reads duplicated";
return -EINVAL;
}
continue;
}
/* /*
* drop_writes * drop_writes
*/ */
...@@ -171,6 +183,12 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, ...@@ -171,6 +183,12 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
return -EINVAL; return -EINVAL;
} }
if (!fc->corrupt_bio_byte && !test_bit(ERROR_READS, &fc->flags) &&
!test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags)) {
set_bit(ERROR_WRITES, &fc->flags);
set_bit(ERROR_READS, &fc->flags);
}
return 0; return 0;
} }
...@@ -346,8 +364,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio) ...@@ -346,8 +364,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
* Otherwise, flakey_end_io() will decide if the reads should be modified. * Otherwise, flakey_end_io() will decide if the reads should be modified.
*/ */
if (bio_data_dir(bio) == READ) { if (bio_data_dir(bio) == READ) {
if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags) && if (test_bit(ERROR_READS, &fc->flags))
!test_bit(ERROR_WRITES, &fc->flags))
return DM_MAPIO_KILL; return DM_MAPIO_KILL;
goto map_bio; goto map_bio;
} }
...@@ -373,11 +390,6 @@ static int flakey_map(struct dm_target *ti, struct bio *bio) ...@@ -373,11 +390,6 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
} }
goto map_bio; goto map_bio;
} }
/*
* By default, error all I/O.
*/
return DM_MAPIO_KILL;
} }
map_bio: map_bio:
...@@ -404,8 +416,8 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, ...@@ -404,8 +416,8 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
*/ */
corrupt_bio_data(bio, fc); corrupt_bio_data(bio, fc);
} }
} else if (!test_bit(DROP_WRITES, &fc->flags) && }
!test_bit(ERROR_WRITES, &fc->flags)) { if (test_bit(ERROR_READS, &fc->flags)) {
/* /*
* Error read during the down_interval if drop_writes * Error read during the down_interval if drop_writes
* and error_writes were not configured. * and error_writes were not configured.
...@@ -422,7 +434,7 @@ static void flakey_status(struct dm_target *ti, status_type_t type, ...@@ -422,7 +434,7 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
{ {
unsigned int sz = 0; unsigned int sz = 0;
struct flakey_c *fc = ti->private; struct flakey_c *fc = ti->private;
unsigned int drop_writes, error_writes; unsigned int error_reads, drop_writes, error_writes;
switch (type) { switch (type) {
case STATUSTYPE_INFO: case STATUSTYPE_INFO:
...@@ -434,10 +446,13 @@ static void flakey_status(struct dm_target *ti, status_type_t type, ...@@ -434,10 +446,13 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
(unsigned long long)fc->start, fc->up_interval, (unsigned long long)fc->start, fc->up_interval,
fc->down_interval); fc->down_interval);
error_reads = test_bit(ERROR_READS, &fc->flags);
drop_writes = test_bit(DROP_WRITES, &fc->flags); drop_writes = test_bit(DROP_WRITES, &fc->flags);
error_writes = test_bit(ERROR_WRITES, &fc->flags); error_writes = test_bit(ERROR_WRITES, &fc->flags);
DMEMIT(" %u", drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5); DMEMIT(" %u", error_reads + drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5);
if (error_reads)
DMEMIT(" error_reads");
if (drop_writes) if (drop_writes)
DMEMIT(" drop_writes"); DMEMIT(" drop_writes");
else if (error_writes) else if (error_writes)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment