dm flakey: error READ bios during the down_interval
[pandora-kernel.git] / drivers / md / dm-flakey.c
index f84c080..63226d1 100644 (file)
@@ -279,10 +279,16 @@ static int flakey_map(struct dm_target *ti, struct bio *bio,
                map_context->ll = 1;
 
                /*
-                * Map reads as normal.
+                * Map reads as normal only if corrupt_bio_byte set.
                 */
-               if (bio_data_dir(bio) == READ)
-                       goto map_bio;
+               if (bio_data_dir(bio) == READ) {
+                       /* If flags were specified, only corrupt those that match. */
+                       if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
+                           all_corrupt_bio_flags_match(bio, fc))
+                               goto map_bio;
+                       else
+                               return -EIO;
+               }
 
                /*
                 * Drop writes?
@@ -321,18 +327,19 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
 
        /*
         * Corrupt successful READs while in down state.
-        * If flags were specified, only corrupt those that match.
         */
-       if (!error && bio_submitted_while_down &&
-           (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
-           all_corrupt_bio_flags_match(bio, fc))
-               corrupt_bio_data(bio, fc);
+       if (!error && bio_submitted_while_down && (bio_data_dir(bio) == READ)) {
+               if (fc->corrupt_bio_byte)
+                       corrupt_bio_data(bio, fc);
+               else
+                       return -EIO;
+       }
 
        return error;
 }
 
-static int flakey_status(struct dm_target *ti, status_type_t type,
-                        char *result, unsigned int maxlen)
+static void flakey_status(struct dm_target *ti, status_type_t type,
+                         char *result, unsigned maxlen)
 {
        unsigned sz = 0;
        struct flakey_c *fc = ti->private;
@@ -362,14 +369,22 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
 
                break;
        }
-       return 0;
 }
 
 static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
 {
        struct flakey_c *fc = ti->private;
+       struct dm_dev *dev = fc->dev;
+       int r = 0;
+
+       /*
+        * Only pass ioctls through if the device sizes match exactly.
+        */
+       if (fc->start ||
+           ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+               r = scsi_verify_blk_ioctl(NULL, cmd);
 
-       return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg);
+       return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
 }
 
 static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
@@ -396,7 +411,7 @@ static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_
 
 static struct target_type flakey_target = {
        .name   = "flakey",
-       .version = {1, 2, 0},
+       .version = {1, 2, 1},
        .module = THIS_MODULE,
        .ctr    = flakey_ctr,
        .dtr    = flakey_dtr,