Skip to content

Commit 7bcd79a

Browse files
Ming Leiaxboe
authored andcommitted
block: bio: introduce helpers to get the 1st and last bvec
The bio passed to bio_will_gap() may be fast cloned from upper layer(dm, md, bcache, fs, ...), or from bio splitting in block core. Unfortunately bio_will_gap() just figures out the last bvec via 'bi_io_vec[prev->bi_vcnt - 1]' directly, and this way is obviously wrong. This patch introduces two helpers for getting the first and last bvec of one bio for fixing the issue. Cc: stable@vger.kernel.org Reported-by: Sagi Grimberg <sagig@dev.mellanox.co.il> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent e3c2ef4 commit 7bcd79a

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

include/linux/bio.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,43 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
310310
bio->bi_flags &= ~(1U << bit);
311311
}
312312

313+
static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
314+
{
315+
*bv = bio_iovec(bio);
316+
}
317+
318+
static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
319+
{
320+
struct bvec_iter iter = bio->bi_iter;
321+
int idx;
322+
323+
if (!bio_flagged(bio, BIO_CLONED)) {
324+
*bv = bio->bi_io_vec[bio->bi_vcnt - 1];
325+
return;
326+
}
327+
328+
if (unlikely(!bio_multiple_segments(bio))) {
329+
*bv = bio_iovec(bio);
330+
return;
331+
}
332+
333+
bio_advance_iter(bio, &iter, iter.bi_size);
334+
335+
if (!iter.bi_bvec_done)
336+
idx = iter.bi_idx - 1;
337+
else /* in the middle of bvec */
338+
idx = iter.bi_idx;
339+
340+
*bv = bio->bi_io_vec[idx];
341+
342+
/*
343+
* iter.bi_bvec_done records actual length of the last bvec
344+
* if this bio ends in the middle of one io vector
345+
*/
346+
if (iter.bi_bvec_done)
347+
bv->bv_len = iter.bi_bvec_done;
348+
}
349+
313350
enum bip_flags {
314351
BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
315352
BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */

0 commit comments

Comments
 (0)