dm flakey: add an "error_reads" option
authorMikulas Patocka <mpatocka@redhat.com>
Tue, 18 Apr 2023 19:56:41 +0000 (15:56 -0400)
committerMike Snitzer <snitzer@kernel.org>
Wed, 19 Apr 2023 15:13:43 +0000 (11:13 -0400)
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: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Documentation/admin-guide/device-mapper/dm-flakey.rst
drivers/md/dm-flakey.c

index 86138735879d023a68c115e2a970e2325d452fa1..f7104c01b0f7425f99bd035a2310169175861e55 100644 (file)
@@ -39,6 +39,10 @@ Optional feature parameters:
   If no feature parameters are present, during the periods of
   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:
        All write I/O is silently ignored.
        Read I/O is handled correctly.
index 948b6b5ee5f234bbcdfcaed71b5f99a857f9fdc0..bd80bcafbe5010df096cd7ed824e3b62a250bf99 100644 (file)
@@ -37,6 +37,7 @@ struct flakey_c {
 };
 
 enum feature_flag_bits {
+       ERROR_READS,
        DROP_WRITES,
        ERROR_WRITES
 };
@@ -53,7 +54,7 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
        const char *arg_name;
 
        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"},
                {0, 255, "Invalid corrupt value to write into bio byte (0-255)"},
                {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,
                        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
                 */
@@ -171,6 +183,12 @@ static int parse_features(struct dm_arg_set *as, struct flakey_c *fc,
                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;
 }
 
@@ -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.
                 */
                if (bio_data_dir(bio) == READ) {
-                       if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags) &&
-                           !test_bit(ERROR_WRITES, &fc->flags))
+                       if (test_bit(ERROR_READS, &fc->flags))
                                return DM_MAPIO_KILL;
                        goto map_bio;
                }
@@ -373,11 +390,6 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
                        }
                        goto map_bio;
                }
-
-               /*
-                * By default, error all I/O.
-                */
-               return DM_MAPIO_KILL;
        }
 
 map_bio:
@@ -404,8 +416,8 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
                                 */
                                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
                         * and error_writes were not configured.
@@ -422,7 +434,7 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
 {
        unsigned int sz = 0;
        struct flakey_c *fc = ti->private;
-       unsigned int drop_writes, error_writes;
+       unsigned int error_reads, drop_writes, error_writes;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -434,10 +446,13 @@ static void flakey_status(struct dm_target *ti, status_type_t type,
                       (unsigned long long)fc->start, fc->up_interval,
                       fc->down_interval);
 
+               error_reads = test_bit(ERROR_READS, &fc->flags);
                drop_writes = test_bit(DROP_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)
                        DMEMIT(" drop_writes");
                else if (error_writes)