dm: backfill abnormal IO support to non-splitting IO submission
authorMike Snitzer <snitzer@redhat.com>
Mon, 26 Mar 2018 15:49:16 +0000 (11:49 -0400)
committerMike Snitzer <snitzer@redhat.com>
Tue, 3 Apr 2018 19:04:20 +0000 (15:04 -0400)
Otherwise, these abnormal IOs would be sent to the DM target
regardless of whether the target advertised support for them.

Factor out __process_abnormal_io() from __split_and_process_non_flush()
so that discards, write same, etc may be conditionally processed.

Fixes: 978e51ba3 ("dm: optimize bio-based NVMe IO submission")
Cc: stable@vger.kernel.org # 4.16
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm.c

index 353ea0ede0911c4931e78fcd06aa8b0547f7a214..038c7572fdd46e186b572c5edb3bc1266408f4fa 100644 (file)
@@ -1477,6 +1477,23 @@ static int __send_write_zeroes(struct clone_info *ci, struct dm_target *ti)
        return __send_changing_extent_only(ci, ti, get_num_write_zeroes_bios, NULL);
 }
 
+static bool __process_abnormal_io(struct clone_info *ci, struct dm_target *ti,
+                                 int *result)
+{
+       struct bio *bio = ci->bio;
+
+       if (bio_op(bio) == REQ_OP_DISCARD)
+               *result = __send_discard(ci, ti);
+       else if (bio_op(bio) == REQ_OP_WRITE_SAME)
+               *result = __send_write_same(ci, ti);
+       else if (bio_op(bio) == REQ_OP_WRITE_ZEROES)
+               *result = __send_write_zeroes(ci, ti);
+       else
+               return false;
+
+       return true;
+}
+
 /*
  * Select the correct strategy for processing a non-flush bio.
  */
@@ -1491,12 +1508,8 @@ static int __split_and_process_non_flush(struct clone_info *ci)
        if (!dm_target_is_valid(ti))
                return -EIO;
 
-       if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
-               return __send_discard(ci, ti);
-       else if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
-               return __send_write_same(ci, ti);
-       else if (unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES))
-               return __send_write_zeroes(ci, ti);
+       if (unlikely(__process_abnormal_io(ci, ti, &r)))
+               return r;
 
        if (bio_op(bio) == REQ_OP_ZONE_REPORT)
                len = ci->sector_count;
@@ -1617,9 +1630,12 @@ static blk_qc_t __process_bio(struct mapped_device *md,
                        goto out;
                }
 
-               tio = alloc_tio(&ci, ti, 0, GFP_NOIO);
                ci.bio = bio;
                ci.sector_count = bio_sectors(bio);
+               if (unlikely(__process_abnormal_io(&ci, ti, &error)))
+                       goto out;
+
+               tio = alloc_tio(&ci, ti, 0, GFP_NOIO);
                ret = __clone_and_map_simple_bio(&ci, tio, NULL);
        }
 out: