]> git.proxmox.com Git - pve-kernel.git/blame - 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
CommitLineData
dbb1ed6d
TL
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Christoph Hellwig <hch@lst.de>
3Date: Tue, 9 Oct 2018 17:04:39 +0100
4Subject: [PATCH] block: add a lower-level bio_add_page interface
5
6Buglink: https://bugs.launchpad.net/bugs/1796542
7
8For the upcoming removal of buffer heads in XFS we need to keep track of
9the number of outstanding writeback requests per page. For this we need
10to know if bio_add_page merged a region with the previous bvec or not.
11Instead of adding additional arguments this refactors bio_add_page to
12be implemented using three lower level helpers which users like XFS can
13use directly if they care about the merge decisions.
14
15Signed-off-by: Christoph Hellwig <hch@lst.de>
16Reviewed-by: Jens Axboe <axboe@kernel.dk>
17Reviewed-by: Ming Lei <ming.lei@redhat.com>
18Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
19Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
20(cherry picked from commit 0aa69fd32a5f766e997ca8ab4723c5a1146efa8b)
21Signed-off-by: Colin Ian King <colin.king@canonical.com>
22Signed-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
28diff --git a/block/bio.c b/block/bio.c
29index 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);
152diff --git a/include/linux/bio.h b/include/linux/bio.h
153index 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 *,