md/raid1: fix write behind issues introduced by bio_clone_bioset_partial
authorShaohua Li <shli@fb.com>
Tue, 21 Feb 2017 22:27:57 +0000 (14:27 -0800)
committerShaohua Li <shli@fb.com>
Thu, 23 Feb 2017 19:59:44 +0000 (11:59 -0800)
There are two issues, introduced by commit 8e58e32(md/raid1: use
bio_clone_bioset_partial() in case of write behind):
- bio_clone_bioset_partial() uses bytes instead of sectors as parameters
- in writebehind mode, we return bio if all !writemostly disk bios finish,
  which could happen before writemostly disk bios run. So all
  writemostly disk bios should have their bvec. Here we just make sure
  all bios are cloned instead of fast cloned.

Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/raid1.c

index 8901f0c..d4e8796 100644 (file)
@@ -1472,8 +1472,8 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio)
                            !waitqueue_active(&bitmap->behind_wait)) {
                                mbio = bio_clone_bioset_partial(bio, GFP_NOIO,
                                                                mddev->bio_set,
-                                                               offset,
-                                                               max_sectors);
+                                                               offset << 9,
+                                                               max_sectors << 9);
                                alloc_behind_pages(mbio, r1_bio);
                        }
 
@@ -1485,8 +1485,15 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio)
                }
 
                if (!mbio) {
-                       mbio = bio_clone_fast(bio, GFP_NOIO, mddev->bio_set);
-                       bio_trim(mbio, offset, max_sectors);
+                       if (r1_bio->behind_bvecs)
+                               mbio = bio_clone_bioset_partial(bio, GFP_NOIO,
+                                                               mddev->bio_set,
+                                                               offset << 9,
+                                                               max_sectors << 9);
+                       else {
+                               mbio = bio_clone_fast(bio, GFP_NOIO, mddev->bio_set);
+                               bio_trim(mbio, offset, max_sectors);
+                       }
                }
 
                if (r1_bio->behind_bvecs) {