]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0009-block-add-a-lower-level-bio_add_page-interface.patch
update sources to Ubuntu-4.15.0-39.42
[pve-kernel.git] / patches / kernel / 0009-block-add-a-lower-level-bio_add_page-interface.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Christoph Hellwig <hch@lst.de>
3 Date: Tue, 9 Oct 2018 17:04:39 +0100
4 Subject: [PATCH] block: add a lower-level bio_add_page interface
5
6 Buglink: https://bugs.launchpad.net/bugs/1796542
7
8 For the upcoming removal of buffer heads in XFS we need to keep track of
9 the number of outstanding writeback requests per page. For this we need
10 to know if bio_add_page merged a region with the previous bvec or not.
11 Instead of adding additional arguments this refactors bio_add_page to
12 be implemented using three lower level helpers which users like XFS can
13 use directly if they care about the merge decisions.
14
15 Signed-off-by: Christoph Hellwig <hch@lst.de>
16 Reviewed-by: Jens Axboe <axboe@kernel.dk>
17 Reviewed-by: Ming Lei <ming.lei@redhat.com>
18 Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
19 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
20 (cherry picked from commit 0aa69fd32a5f766e997ca8ab4723c5a1146efa8b)
21 Signed-off-by: Colin Ian King <colin.king@canonical.com>
22 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
23 ---
24 block/bio.c | 98 ++++++++++++++++++++++++++++++++++-------------------
25 include/linux/bio.h | 9 +++++
26 2 files changed, 73 insertions(+), 34 deletions(-)
27
28 diff --git a/block/bio.c b/block/bio.c
29 index 4b48f8eefc4c..2636d15af979 100644
30 --- a/block/bio.c
31 +++ b/block/bio.c
32 @@ -773,7 +773,7 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page
33 return 0;
34 }
35
36 - if (bio->bi_vcnt >= bio->bi_max_vecs)
37 + if (bio_full(bio))
38 return 0;
39
40 /*
41 @@ -821,6 +821,65 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page
42 EXPORT_SYMBOL(bio_add_pc_page);
43
44 /**
45 + * __bio_try_merge_page - try appending data to an existing bvec.
46 + * @bio: destination bio
47 + * @page: page to add
48 + * @len: length of the data to add
49 + * @off: offset of the data in @page
50 + *
51 + * Try to add the data at @page + @off to the last bvec of @bio. This is a
52 + * a useful optimisation for file systems with a block size smaller than the
53 + * page size.
54 + *
55 + * Return %true on success or %false on failure.
56 + */
57 +bool __bio_try_merge_page(struct bio *bio, struct page *page,
58 + unsigned int len, unsigned int off)
59 +{
60 + if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
61 + return false;
62 +
63 + if (bio->bi_vcnt > 0) {
64 + struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
65 +
66 + if (page == bv->bv_page && off == bv->bv_offset + bv->bv_len) {
67 + bv->bv_len += len;
68 + bio->bi_iter.bi_size += len;
69 + return true;
70 + }
71 + }
72 + return false;
73 +}
74 +EXPORT_SYMBOL_GPL(__bio_try_merge_page);
75 +
76 +/**
77 + * __bio_add_page - add page to a bio in a new segment
78 + * @bio: destination bio
79 + * @page: page to add
80 + * @len: length of the data to add
81 + * @off: offset of the data in @page
82 + *
83 + * Add the data at @page + @off to @bio as a new bvec. The caller must ensure
84 + * that @bio has space for another bvec.
85 + */
86 +void __bio_add_page(struct bio *bio, struct page *page,
87 + unsigned int len, unsigned int off)
88 +{
89 + struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt];
90 +
91 + WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED));
92 + WARN_ON_ONCE(bio_full(bio));
93 +
94 + bv->bv_page = page;
95 + bv->bv_offset = off;
96 + bv->bv_len = len;
97 +
98 + bio->bi_iter.bi_size += len;
99 + bio->bi_vcnt++;
100 +}
101 +EXPORT_SYMBOL_GPL(__bio_add_page);
102 +
103 +/**
104 * bio_add_page - attempt to add page to bio
105 * @bio: destination bio
106 * @page: page to add
107 @@ -833,40 +892,11 @@ EXPORT_SYMBOL(bio_add_pc_page);
108 int bio_add_page(struct bio *bio, struct page *page,
109 unsigned int len, unsigned int offset)
110 {
111 - struct bio_vec *bv;
112 -
113 - /*
114 - * cloned bio must not modify vec list
115 - */
116 - if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
117 - return 0;
118 -
119 - /*
120 - * For filesystems with a blocksize smaller than the pagesize
121 - * we will often be called with the same page as last time and
122 - * a consecutive offset. Optimize this special case.
123 - */
124 - if (bio->bi_vcnt > 0) {
125 - bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
126 -
127 - if (page == bv->bv_page &&
128 - offset == bv->bv_offset + bv->bv_len) {
129 - bv->bv_len += len;
130 - goto done;
131 - }
132 + if (!__bio_try_merge_page(bio, page, len, offset)) {
133 + if (bio_full(bio))
134 + return 0;
135 + __bio_add_page(bio, page, len, offset);
136 }
137 -
138 - if (bio->bi_vcnt >= bio->bi_max_vecs)
139 - return 0;
140 -
141 - bv = &bio->bi_io_vec[bio->bi_vcnt];
142 - bv->bv_page = page;
143 - bv->bv_len = len;
144 - bv->bv_offset = offset;
145 -
146 - bio->bi_vcnt++;
147 -done:
148 - bio->bi_iter.bi_size += len;
149 return len;
150 }
151 EXPORT_SYMBOL(bio_add_page);
152 diff --git a/include/linux/bio.h b/include/linux/bio.h
153 index a98c6ac575cf..3440870712d4 100644
154 --- a/include/linux/bio.h
155 +++ b/include/linux/bio.h
156 @@ -123,6 +123,11 @@ static inline void *bio_data(struct bio *bio)
157 return NULL;
158 }
159
160 +static inline bool bio_full(struct bio *bio)
161 +{
162 + return bio->bi_vcnt >= bio->bi_max_vecs;
163 +}
164 +
165 /*
166 * will die
167 */
168 @@ -447,6 +452,10 @@ void bio_chain(struct bio *, struct bio *);
169 extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
170 extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
171 unsigned int, unsigned int);
172 +bool __bio_try_merge_page(struct bio *bio, struct page *page,
173 + unsigned int len, unsigned int off);
174 +void __bio_add_page(struct bio *bio, struct page *page,
175 + unsigned int len, unsigned int off);
176 int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter);
177 struct rq_map_data;
178 extern struct bio *bio_map_user_iov(struct request_queue *,