summaryrefslogtreecommitdiffstats
path: root/include/linux/bio.h
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-08-07 17:26:21 -0400
committerKent Overstreet <kmo@daterainc.com>2013-11-24 01:33:49 -0500
commit4550dd6c6b062fc5e5b647296d55da22616123c3 (patch)
tree9ca83cc0283151980b7c2f18c0e928aa34a2a0d9 /include/linux/bio.h
parent7988613b0e5b2638caf6cd493cc78e9595eba19c (diff)
block: Immutable bio vecs
This adds a mechanism by which we can advance a bio by an arbitrary number of bytes without modifying the biovec: bio->bi_iter.bi_bvec_done indicates the number of bytes completed in the current bvec. Various driver code still needs to be updated to not refer to the bvec directly before we can use this for interesting things, like efficient bio splitting. Signed-off-by: Kent Overstreet <kmo@daterainc.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Lars Ellenberg <drbd-dev@lists.linbit.com> Cc: Paul Clements <Paul.Clements@steeleye.com> Cc: drbd-user@lists.linbit.com Cc: nbd-general@lists.sourceforge.net
Diffstat (limited to 'include/linux/bio.h')
-rw-r--r--include/linux/bio.h81
1 files changed, 73 insertions, 8 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h
index c16adb5f69f8..04e592e74c92 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -64,11 +64,38 @@
64#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)])) 64#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(idx)]))
65#define __bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx) 65#define __bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_iter.bi_idx)
66 66
67#define bio_iter_iovec(bio, iter) ((bio)->bi_io_vec[(iter).bi_idx]) 67#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx])
68 68
69#define bio_page(bio) (bio_iovec((bio)).bv_page) 69#define bvec_iter_page(bvec, iter) \
70#define bio_offset(bio) (bio_iovec((bio)).bv_offset) 70 (__bvec_iter_bvec((bvec), (iter))->bv_page)
71#define bio_iovec(bio) (*__bio_iovec(bio)) 71
72#define bvec_iter_len(bvec, iter) \
73 min((iter).bi_size, \
74 __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
75
76#define bvec_iter_offset(bvec, iter) \
77 (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
78
79#define bvec_iter_bvec(bvec, iter) \
80((struct bio_vec) { \
81 .bv_page = bvec_iter_page((bvec), (iter)), \
82 .bv_len = bvec_iter_len((bvec), (iter)), \
83 .bv_offset = bvec_iter_offset((bvec), (iter)), \
84})
85
86#define bio_iter_iovec(bio, iter) \
87 bvec_iter_bvec((bio)->bi_io_vec, (iter))
88
89#define bio_iter_page(bio, iter) \
90 bvec_iter_page((bio)->bi_io_vec, (iter))
91#define bio_iter_len(bio, iter) \
92 bvec_iter_len((bio)->bi_io_vec, (iter))
93#define bio_iter_offset(bio, iter) \
94 bvec_iter_offset((bio)->bi_io_vec, (iter))
95
96#define bio_page(bio) bio_iter_page((bio), (bio)->bi_iter)
97#define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter)
98#define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter)
72 99
73#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx) 100#define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_iter.bi_idx)
74#define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9) 101#define bio_sectors(bio) ((bio)->bi_iter.bi_size >> 9)
@@ -145,16 +172,54 @@ static inline void *bio_data(struct bio *bio)
145 bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt; \ 172 bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt; \
146 i++) 173 i++)
147 174
175static inline void bvec_iter_advance(struct bio_vec *bv, struct bvec_iter *iter,
176 unsigned bytes)
177{
178 WARN_ONCE(bytes > iter->bi_size,
179 "Attempted to advance past end of bvec iter\n");
180
181 while (bytes) {
182 unsigned len = min(bytes, bvec_iter_len(bv, *iter));
183
184 bytes -= len;
185 iter->bi_size -= len;
186 iter->bi_bvec_done += len;
187
188 if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) {
189 iter->bi_bvec_done = 0;
190 iter->bi_idx++;
191 }
192 }
193}
194
195#define for_each_bvec(bvl, bio_vec, iter, start) \
196 for ((iter) = start; \
197 (bvl) = bvec_iter_bvec((bio_vec), (iter)), \
198 (iter).bi_size; \
199 bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))
200
201
202static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
203 unsigned bytes)
204{
205 iter->bi_sector += bytes >> 9;
206
207 if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK)
208 iter->bi_size -= bytes;
209 else
210 bvec_iter_advance(bio->bi_io_vec, iter, bytes);
211}
212
148#define __bio_for_each_segment(bvl, bio, iter, start) \ 213#define __bio_for_each_segment(bvl, bio, iter, start) \
149 for (iter = (start); \ 214 for (iter = (start); \
150 bvl = bio_iter_iovec((bio), (iter)), \ 215 (iter).bi_size && \
151 (iter).bi_idx < (bio)->bi_vcnt; \ 216 ((bvl = bio_iter_iovec((bio), (iter))), 1); \
152 (iter).bi_idx++) 217 bio_advance_iter((bio), &(iter), (bvl).bv_len))
153 218
154#define bio_for_each_segment(bvl, bio, iter) \ 219#define bio_for_each_segment(bvl, bio, iter) \
155 __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter) 220 __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter)
156 221
157#define bio_iter_last(bio, iter) ((iter).bi_idx == (bio)->bi_vcnt - 1) 222#define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
158 223
159/* 224/*
160 * get a reference to a bio, so it won't disappear. the intended use is 225 * get a reference to a bio, so it won't disappear. the intended use is