]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
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 8901f0c8c775ad655566b75d54d22f65179ef8a0..d4e8796b45693222f3446f8d3edd131adb81a0c5 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) {