Re: [PATCH v5 07/16] block: introduce dma map backed bio type
Christoph Hellwig <[email protected]> Tue, 4 Aug 2026 18:24:40 +0200
| Newsgroups | gmane.linux.kernel.io-uring,gmane.linux.block,gmane.linux.kernel,gmane.linux.file-systems,gmane.linux.drivers.video-input-infrastructure,gmane.comp.video.dri.devel,gmane.comp.file-systems.btrfs,gmane.comp.file-systems.ceph.devel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> > Signed-off-by: Pavel Begunkov <[email protected]> > --- > 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)) > + bio->bi_opf |= REQ_NOMERGE | REQ_DMABUF; > return true; > } > > 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.