raid5: set bio bi_vcnt 0 for discard request
authorShaohua Li <[email protected]>
Sat, 19 Oct 2013 06:50:28 +0000 (14:50 +0800)
committerNeilBrown <[email protected]>
Thu, 24 Oct 2013 01:57:36 +0000 (12:57 +1100)
SCSI layer will add new payload for discard request. If two bios are merged
to one, the second bio has bi_vcnt 1 which is set in raid5. This will confuse
SCSI and cause oops.

Suitable for backport to 3.7+

Cc: [email protected] (v3.7+)
Reported-by: Jes Sorensen <[email protected]>
Signed-off-by: Shaohua Li <[email protected]>
Signed-off-by: NeilBrown <[email protected]>
Acked-by: Martin K. Petersen <[email protected]>
drivers/md/raid5.c

index 7ff4f252ca1a42943252a9e19b975da5b2f8ce9b..302d7cd2076c61ea557caf0f77c2ba3f4f6f8b79 100644 (file)
@@ -778,6 +778,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        bi->bi_io_vec[0].bv_offset = 0;
                        bi->bi_size = STRIPE_SIZE;
+                       /*
+                        * If this is discard request, set bi_vcnt 0. We don't
+                        * want to confuse SCSI because SCSI will replace payload
+                        */
+                       if (rw & REQ_DISCARD)
+                               bi->bi_vcnt = 0;
                        if (rrdev)
                                set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
 
@@ -816,6 +822,12 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        rbi->bi_io_vec[0].bv_offset = 0;
                        rbi->bi_size = STRIPE_SIZE;
+                       /*
+                        * If this is discard request, set bi_vcnt 0. We don't
+                        * want to confuse SCSI because SCSI will replace payload
+                        */
+                       if (rw & REQ_DISCARD)
+                               rbi->bi_vcnt = 0;
                        if (conf->mddev->gendisk)
                                trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
                                                      rbi, disk_devt(conf->mddev->gendisk),