On Sat, Aug 01, 2026 at 04:46:19PM +0100, Pavel Begunkov wrote:
Premapped buffers don't require a generic bio_vec since these have already been dma mapped. Repurpose the bi_io_vec space to strore dmabuf maps as they are mutually exclusive.
Suggested-by: Keith Busch kbusch@kernel.org Signed-off-by: Pavel Begunkov asml.silence@gmail.com
block/bio.c | 15 +++++++++++++-- block/blk-merge.c | 37 +++++++++++++++++++++++++++++++++++++ block/fops.c | 2 +- include/linux/bio.h | 9 +++++---- include/linux/blk-mq.h | 7 +++++++ include/linux/blk_types.h | 14 +++++++++++++- include/linux/bvec.h | 3 ++- 7 files changed, 78 insertions(+), 9 deletions(-)
diff --git a/block/bio.c b/block/bio.c index 898b2f5ef8c8..1602eab05761 100644 --- a/block/bio.c +++ b/block/bio.c @@ -860,7 +860,11 @@ static int __bio_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp) bio->bi_write_hint = bio_src->bi_write_hint; bio->bi_write_stream = bio_src->bi_write_stream; bio->bi_iter = bio_src->bi_iter;
- bio->bi_io_vec = bio_src->bi_io_vec;
- if (op_is_dmabuf(bio->bi_opf))
bio->bi_dmabuf_map = bio_src->bi_dmabuf_map;- else
bio->bi_io_vec = bio_src->bi_io_vec;if (bio->bi_bdev) { if (bio->bi_bdev == bio_src->bi_bdev && @@ -1183,16 +1187,23 @@ EXPORT_SYMBOL_GPL(__bio_release_pages); bool bio_iov_iter_set(struct bio *bio, const struct iov_iter *iter) {
- if (!iov_iter_is_bvec(iter))
- if (!iov_iter_is_bvec(iter) && !iov_iter_is_dmabuf_map(iter)) return false;
WARN_ON_ONCE(bio->bi_max_vecs);
- static_assert(offsetof(struct bio, bi_io_vec) ==
offsetof(struct bio, bi_dmabuf_map));- static_assert(offsetof(struct iov_iter, bvec) ==
offsetof(struct iov_iter, dmabuf_map));- bio->bi_io_vec = (struct bio_vec *)iter->bvec; bio->bi_iter.bi_idx = 0; bio->bi_iter.bi_offset = iter->iov_offset; bio->bi_iter.bi_size = iov_iter_count(iter); bio_set_flag(bio, BIO_CLONED);
- if (iov_iter_is_dmabuf_map(iter))
return true;bio->bi_opf |= REQ_NOMERGE | REQ_DMABUF;} diff --git a/block/blk-merge.c b/block/blk-merge.c index 258a726071d1..1beedc42a85d 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -9,6 +9,7 @@ #include <linux/blk-integrity.h> #include <linux/part_stat.h> #include <linux/blk-cgroup.h> +#include <linux/dma-buf-io.h> #include <trace/events/block.h> @@ -319,6 +320,28 @@ static inline unsigned int bvec_seg_gap(struct bio_vec *bvprv, return bv->bv_offset | (bvprv->bv_offset + bvprv->bv_len); } +static inline int bio_split_io_at_dmabuf(struct bio *bio,
const struct queue_limits *lim, unsigned *segs,unsigned max_bytes, unsigned len_align_mask,unsigned start_align_mask)+{
- unsigned bytes = min(bio->bi_iter.bi_size, max_bytes);
- unsigned seg_shift = bio->bi_dmabuf_map->seg_shift;
- unsigned offset = bio->bi_iter.bi_offset & ((1U << seg_shift) - 1);
- if ((bio->bi_iter.bi_offset & start_align_mask) ||
(bio->bi_iter.bi_size & len_align_mask))return -EINVAL;- /* single contiguous range into the dma-buf */
- *segs = 1;
- bytes = min(bytes, ((unsigned)lim->max_segments << seg_shift) - offset);
I guess ->seg_shift is some sort of encoding of a max segment size?
Comments please.
linaro-mm-sig@lists.linaro.org