]> git.proxmox.com Git - pve-kernel.git/blob - 0001-block-fix-bio_will_gap-for-first-bvec-with-offset.patch
aed9a58629517717f661adc8ba99f8dde6fde913
[pve-kernel.git] / 0001-block-fix-bio_will_gap-for-first-bvec-with-offset.patch
1 From 5a8d75a1b8c99bdc926ba69b7b7dbe4fae81a5af Mon Sep 17 00:00:00 2001
2 From: Ming Lei <ming.lei@redhat.com>
3 Date: Fri, 14 Apr 2017 13:58:29 -0600
4 Subject: [PATCH] block: fix bio_will_gap() for first bvec with offset
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Commit 729204ef49ec("block: relax check on sg gap") allows us to merge
10 bios, if both are physically contiguous. This change can merge a huge
11 number of small bios, through mkfs for example, mkfs.ntfs running time
12 can be decreased to ~1/10.
13
14 But if one rq starts with a non-aligned buffer (the 1st bvec's bv_offset
15 is non-zero) and if we allow the merge, it is quite difficult to respect
16 sg gap limit, especially the max segment size, or we risk having an
17 unaligned virtual boundary. This patch tries to avoid the issue by
18 disallowing a merge, if the req starts with an unaligned buffer.
19
20 Also add comments to explain why the merged segment can't end in
21 unaligned virt boundary.
22
23 Fixes: 729204ef49ec ("block: relax check on sg gap")
24 Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
25 Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
26 Signed-off-by: Ming Lei <ming.lei@redhat.com>
27
28 Rewrote parts of the commit message and comments.
29
30 Signed-off-by: Jens Axboe <axboe@fb.com>
31 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
32 ---
33 include/linux/blkdev.h | 32 ++++++++++++++++++++++++++++----
34 1 file changed, 28 insertions(+), 4 deletions(-)
35
36 diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
37 index 7548f332121a..01a696b0a4d3 100644
38 --- a/include/linux/blkdev.h
39 +++ b/include/linux/blkdev.h
40 @@ -1672,12 +1672,36 @@ static inline bool bios_segs_mergeable(struct request_queue *q,
41 return true;
42 }
43
44 -static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
45 - struct bio *next)
46 +static inline bool bio_will_gap(struct request_queue *q,
47 + struct request *prev_rq,
48 + struct bio *prev,
49 + struct bio *next)
50 {
51 if (bio_has_data(prev) && queue_virt_boundary(q)) {
52 struct bio_vec pb, nb;
53
54 + /*
55 + * don't merge if the 1st bio starts with non-zero
56 + * offset, otherwise it is quite difficult to respect
57 + * sg gap limit. We work hard to merge a huge number of small
58 + * single bios in case of mkfs.
59 + */
60 + if (prev_rq)
61 + bio_get_first_bvec(prev_rq->bio, &pb);
62 + else
63 + bio_get_first_bvec(prev, &pb);
64 + if (pb.bv_offset)
65 + return true;
66 +
67 + /*
68 + * We don't need to worry about the situation that the
69 + * merged segment ends in unaligned virt boundary:
70 + *
71 + * - if 'pb' ends aligned, the merged segment ends aligned
72 + * - if 'pb' ends unaligned, the next bio must include
73 + * one single bvec of 'nb', otherwise the 'nb' can't
74 + * merge with 'pb'
75 + */
76 bio_get_last_bvec(prev, &pb);
77 bio_get_first_bvec(next, &nb);
78
79 @@ -1690,12 +1714,12 @@ static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
80
81 static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
82 {
83 - return bio_will_gap(req->q, req->biotail, bio);
84 + return bio_will_gap(req->q, req, req->biotail, bio);
85 }
86
87 static inline bool req_gap_front_merge(struct request *req, struct bio *bio)
88 {
89 - return bio_will_gap(req->q, bio, req->bio);
90 + return bio_will_gap(req->q, NULL, bio, req->bio);
91 }
92
93 int kblockd_schedule_work(struct work_struct *work);
94 --
95 2.11.0
96