From: Christoph Hellwig <hch@lst.de>
To: Pavel Begunkov <asml.silence@gmail.com>
Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
linaro-mm-sig@lists.linaro.org, linux-nvme@lists.infradead.org,
linux-fsdevel@vger.kernel.org, io-uring@vger.kernel.org,
"Christoph Hellwig" <hch@lst.de>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>,
"Keith Busch" <kbusch@kernel.org>,
"Sagi Grimberg" <sagi@grimberg.me>,
"Alexander Viro" <viro@zeniv.linux.org.uk>,
"Christian Brauner" <brauner@kernel.org>,
"Jan Kara" <jack@suse.cz>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Jens Axboe" <axboe@kernel.dk>,
"Nitesh Shetty" <nj.shetty@samsung.com>,
"Kanchan Joshi" <joshi.k@samsung.com>,
"Anuj Gupta" <anuj20.g@samsung.com>,
"Tushar Gohad" <tushar.gohad@intel.com>,
"William Power" <william.power@intel.com>,
"Matthew Brost" <matthew.brost@intel.com>,
"Alasdair Kergon" <agk@redhat.com>,
"Mike Snitzer" <snitzer@kernel.org>,
"Mikulas Patocka" <mpatocka@redhat.com>,
"Benjamin Marzinski" <bmarzins@redhat.com>,
dm-devel@lists.linux.dev
Subject: Re: [PATCH v11 04/13] block: introduce dma map backed bio type
Date: Wed, 14 Oct 2026 15:15:54 +0200 [thread overview]
Message-ID: <20261014131554.GA16467@lst.de> (raw)
In-Reply-To: <39b964cf7510f42755188563da63d3d5acaf2aa9.1791975048.git.asml.silence@gmail.com>
On Wed, Oct 14, 2026 at 12:02:02PM +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 store dmabuf
> maps as they are mutually exclusive.
>
> The bio splitting differs from the normal path because it's already
> pre-mapped and for the block layer it's just an offset into the dma-buf.
> The actual segmentation is only available to the importer driver and not
> the block layer, however, it doesn't contain alignment gaps and we don't
> have to check it. For the same reason we can't precisely split by the
> number of segments, but we use ->min_seg_shift stored in the map to
> calculate the minimum number of bytes a request consisting of
> lim->max_segments full segments can cover and split by that. It's
> stricter and can add extra splitting. E.g. for a {4K, 4G} segmentation,
> the min segment size is 4K, and we'll split it into bios of
> (4K * lim->max_segments) bytes each, but it should be good enough for
> now to cover the most popular use cases.
>
> Suggested-by: Keith Busch <kbusch@kernel.org>
> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
> ---
> block/bio.c | 15 +++++++++--
> block/blk-merge.c | 52 +++++++++++++++++++++++++++++++++++++++
> block/blk-mq.c | 6 +++++
> 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 ++-
> 8 files changed, 99 insertions(+), 9 deletions(-)
>
> diff --git a/block/bio.c b/block/bio.c
> index b48091c7663f..1e0d9714c541 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -881,7 +881,11 @@ static int __bio_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp)
> bio->bi_write_stream = bio_src->bi_write_stream;
> bio->bi_bvec_gap_bit = bio_src->bi_bvec_gap_bit;
> 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 &&
> @@ -1204,16 +1208,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..501ddc01c449 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,41 @@ 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->min_seg_shift;
> + unsigned offset = bio->bi_iter.bi_offset & ((1U << seg_shift) - 1);
> + u64 max_segs_bytes;
> +
> + /*
> + * dma-buf maps don't expose the underlying segmentation, but they're
> + * guaranteed to not have alignment gaps, we only need to check the
> + * start and length alignment.
> + */
> + if ((bio->bi_iter.bi_offset & start_align_mask) ||
> + (bio->bi_iter.bi_size & len_align_mask))
> + return -EINVAL;
> +
> + /* Presented as a single contiguous range into the dma-buf */
> + *segs = 1;
> +
> + /*
> + * Limit by the number of segments by using the minimal segment size.
> + * Any I/O consisting of N full segments should be able to cover at
> + * least N multiplied by the segment size. It's stricter than walking
> + * the segments and might cause extra splitting.
> + */
> + max_segs_bytes = (u64)lim->max_segments << seg_shift;
> + bytes = min_t(u64, bytes, max_segs_bytes - offset);
> + if (bytes != bio->bi_iter.bi_size)
> + return bytes;
> + return 0;
> +}
> +
> /**
> * bio_split_io_at - check if and where to split a bio
> * @bio: [in] bio to be split
> @@ -346,6 +382,19 @@ int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
> len_align_mask |= (bc->bc_key->crypto_cfg.data_unit_size - 1);
> }
>
> + if (op_is_dmabuf(bio->bi_opf)) {
> + int ret;
> +
> + ret = bio_split_io_at_dmabuf(bio, lim, &nsegs, max_bytes,
> + len_align_mask, start_align_mask);
> + if (ret < 0)
> + return ret;
> + if (!ret)
> + goto out;
> + bytes = ret;
> + goto split;
> + }
> +
> bio_for_each_bvec(bv, bio, iter) {
> if (bv.bv_offset & start_align_mask ||
> bv.bv_len & len_align_mask)
> @@ -376,6 +425,7 @@ int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
> bvprvp = &bvprv;
> }
>
> +out:
> *segs = nsegs;
> bio->bi_bvec_gap_bit = ffs(gaps);
> return 0;
> @@ -493,6 +543,8 @@ unsigned int blk_recalc_rq_segments(struct request *rq)
>
> if (!rq->bio)
> return 0;
> + if (op_is_dmabuf(rq->bio->bi_opf))
> + return 1;
>
> switch (bio_op(rq->bio)) {
> case REQ_OP_DISCARD:
> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index e929f94b25c7..1b7f8cbbda8b 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -3150,6 +3150,12 @@ void blk_mq_submit_bio(struct bio *bio)
> goto queue_exit;
> }
>
> + if (unlikely(op_is_dmabuf(bio->bi_opf) &&
> + bdev_has_integrity_csum(bio->bi_bdev))) {
> + bio_endio_status(bio, BLK_STS_NOTSUPP);
Wrong indentation, conditions are never indented the same level as
the following code block, even with the weirdest preferences.
/me note the patch from Anuj on the list actually got this right..
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
next prev parent reply other threads:[~2026-10-14 13:16 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-14 11:01 [PATCH v11 00/13] Add dmabuf read/write via io_uring Pavel Begunkov
2026-10-14 11:01 ` [PATCH v11 01/13] dma-buf: introduce initial file I/O infrastructure Pavel Begunkov
2026-10-14 11:13 ` sashiko-bot
2026-10-14 12:30 ` Christian König
2026-10-14 13:06 ` Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 02/13] iov_iter: add iterator type for dmabuf maps Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 03/13] block: always adjust bi_offset on bio_advance_iter Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 04/13] block: introduce dma map backed bio type Pavel Begunkov
2026-10-14 11:21 ` sashiko-bot
2026-10-14 13:03 ` Pavel Begunkov
2026-10-14 13:15 ` Christoph Hellwig [this message]
2026-10-14 16:43 ` Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 05/13] block: add dma-buf support for raw bdev Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 06/13] nvme-pci: rename nvme_pci_sgl_set_data to nvme_pci_dma_iter_set_sgl Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 07/13] nvme-pci: implement dma-buf backed requests Pavel Begunkov
2026-10-14 11:26 ` sashiko-bot
2026-10-14 13:16 ` Christoph Hellwig
2026-10-14 11:02 ` [PATCH v11 08/13] nvme-pci: add SGL support for the dmabuf path Pavel Begunkov
2026-10-14 11:23 ` sashiko-bot
2026-10-14 13:16 ` Christoph Hellwig
2026-10-14 11:02 ` [PATCH v11 09/13] io_uring/rsrc: introduce buf registration structure Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 10/13] io_uring/rsrc: extend buffer update Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 11/13] io_uring/rsrc: add uncloneable regbuf flag Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 12/13] io_uring/rsrc: add regbuf import flags Pavel Begunkov
2026-10-14 11:02 ` [PATCH v11 13/13] io_uring/rsrc: add dmabuf backed registered buffers Pavel Begunkov
2026-10-14 11:18 ` sashiko-bot
2026-10-14 13:40 ` Jens Axboe
2026-10-14 13:43 ` [PATCH v11 00/13] Add dmabuf read/write via io_uring Jens Axboe
2026-10-14 14:37 ` Anuj gupta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261014131554.GA16467@lst.de \
--to=hch@lst.de \
--cc=agk@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=anuj20.g@samsung.com \
--cc=asml.silence@gmail.com \
--cc=axboe@kernel.dk \
--cc=bmarzins@redhat.com \
--cc=brauner@kernel.org \
--cc=christian.koenig@amd.com \
--cc=dm-devel@lists.linux.dev \
--cc=dri-devel@lists.freedesktop.org \
--cc=io-uring@vger.kernel.org \
--cc=jack@suse.cz \
--cc=joshi.k@samsung.com \
--cc=kbusch@kernel.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=matthew.brost@intel.com \
--cc=mpatocka@redhat.com \
--cc=nj.shetty@samsung.com \
--cc=sagi@grimberg.me \
--cc=snitzer@kernel.org \
--cc=sumit.semwal@linaro.org \
--cc=tushar.gohad@intel.com \
--cc=viro@zeniv.linux.org.uk \
--cc=william.power@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.