From: Pavel Begunkov <asml.silence@gmail.com>
To: linux-block@vger.kernel.org
Cc: asml.silence@gmail.com, 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>,
"Phil Cayton" <phil.cayton@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: [PATCH v6 04/13] block: introduce dma map backed bio type
Date: Mon, 21 Sep 2026 14:38:48 +0100 [thread overview]
Message-ID: <a3ee719abc440ca139f1a945fdaf43a45f0c6b57.1789997898.git.asml.silence@gmail.com> (raw)
In-Reply-To: <cover.1789997898.git.asml.silence@gmail.com>
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 | 45 +++++++++++++++++++++++++++++++++++++++
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, 86 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..f0ece378c2d1 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,36 @@ 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;
+
+ 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;
+
+ /*
+ * Limit by the number of segments. We don't expose the underlying
+ * mapping layout, but with a known minimum segment size, any I/O
+ * consisting of N full segments should be able to cover at least
+ * this much.
+ */
+ 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 +377,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 +420,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;
diff --git a/block/fops.c b/block/fops.c
index b182d0b30748..09fa42f8d8fa 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -362,7 +362,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
* Users don't rely on the iterator being in any particular
* state for async I/O returning -EIOCBQUEUED, hence we can
* avoid expensive iov_iter_advance(). Bypass
- * bio_iov_iter_get_pages() and set the bvec directly.
+ * bio_iov_iter_get_pages() and set the bvec/dmabuf directly.
*/
if (!bio_iov_iter_set(bio, iter)) {
ret = blkdev_iov_iter_get_pages(bio, iter, bdev);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 892ca469c570..7a794ce723b8 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -80,7 +80,8 @@ static inline bool bio_no_advance_iter(const struct bio *bio)
{
return bio_op(bio) == REQ_OP_DISCARD ||
bio_op(bio) == REQ_OP_SECURE_ERASE ||
- bio_op(bio) == REQ_OP_WRITE_ZEROES;
+ bio_op(bio) == REQ_OP_WRITE_ZEROES ||
+ op_is_dmabuf(bio->bi_opf);
}
static inline void *bio_data(struct bio *bio)
@@ -438,12 +439,12 @@ static inline void bio_wouldblock_error(struct bio *bio)
/*
* Calculate number of bvec segments that should be allocated to fit data
- * pointed by @iter. If @iter is backed by bvec it's going to be reused
- * instead of allocating a new one.
+ * pointed by @iter. If @iter is backed by a bvec or a dmabuf, the bvec array /
+ * the dma map are going to be reused, and so no extra allocation is required.
*/
static inline int bio_iov_vecs_to_alloc(struct iov_iter *iter, int max_segs)
{
- if (iov_iter_is_bvec(iter))
+ if (iov_iter_is_bvec(iter) || iov_iter_is_dmabuf_map(iter))
return 0;
return iov_iter_npages(iter, max_segs);
}
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index af878597afb8..7c7504c84e09 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -1017,6 +1017,13 @@ static inline void *blk_mq_rq_to_pdu(struct request *rq)
return rq + 1;
}
+static inline bool blk_mq_rq_is_dmabuf(struct request *rq)
+{
+ if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
+ return false;
+ return rq->bio && op_is_dmabuf(rq->bio->bi_opf);
+}
+
static inline struct blk_mq_hw_ctx *queue_hctx(struct request_queue *q, int id)
{
struct blk_mq_hw_ctx *hctx;
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 98e21b4cbf32..0cc09b975d8f 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -233,7 +233,12 @@ struct bio {
atomic_t __bi_remaining;
/* The actual vec list, preserved by bio_reset() */
- struct bio_vec *bi_io_vec;
+ union {
+ struct bio_vec *bi_io_vec;
+ /* Driver specific dma map, valid IFF REQ_DMABUF is set */
+ struct dma_buf_io_map *bi_dmabuf_map;
+ };
+
struct bvec_iter bi_iter;
union {
@@ -402,6 +407,7 @@ enum req_flag_bits {
__REQ_DRV, /* for driver use */
__REQ_FS_PRIVATE, /* for file system (submitter) use */
__REQ_ATOMIC, /* for atomic write operations */
+ __REQ_DMABUF, /* Using premmaped dma buffers */
/*
* Command specific flags, keep last:
*/
@@ -434,6 +440,7 @@ enum req_flag_bits {
#define REQ_DRV (__force blk_opf_t)(1ULL << __REQ_DRV)
#define REQ_FS_PRIVATE (__force blk_opf_t)(1ULL << __REQ_FS_PRIVATE)
#define REQ_ATOMIC (__force blk_opf_t)(1ULL << __REQ_ATOMIC)
+#define REQ_DMABUF (__force blk_opf_t)(1ULL << __REQ_DMABUF)
#define REQ_NOUNMAP (__force blk_opf_t)(1ULL << __REQ_NOUNMAP)
@@ -487,6 +494,11 @@ static inline bool op_is_discard(blk_opf_t op)
return (op & REQ_OP_MASK) == REQ_OP_DISCARD;
}
+static inline bool op_is_dmabuf(blk_opf_t op)
+{
+ return op & REQ_DMABUF;
+}
+
/*
* Check if a bio or request operation is a zone management operation.
*/
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index fc566ee1c1ff..b63914ff56e3 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -108,7 +108,8 @@ struct bvec_iter {
unsigned int bi_idx;
/*
- * Current offset in the bvec entry pointed to by `bi_idx`.
+ * Current offset in the bvec entry pointed to by `bi_idx` or into
+ * a dma-buf map.
*/
unsigned int bi_offset;
} __packed __aligned(4);
--
2.54.0
next prev parent reply other threads:[~2026-09-21 13:39 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-21 13:38 [PATCH v6 00/13] Add dmabuf read/write via io_uring Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 01/13] dma-buf: introduce initial file I/O infrastructure Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 02/13] iov_iter: add iterator type for dmabuf maps Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 03/13] block: always adjust bi_offset on bio_advance_iter Pavel Begunkov
2026-09-21 13:38 ` Pavel Begunkov [this message]
2026-09-21 13:38 ` [PATCH v6 05/13] block: add dma-buf support for raw bdev Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 06/13] nvme-pci: implement dma-buf backed requests Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 07/13] nvme-pci: rename nvme_pci_sgl_set_data to nvme_pci_dma_iter_set_sgl Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 08/13] nvme-pci: add SGL support for the dmabuf path Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 09/13] io_uring/rsrc: introduce buf registration structure Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 10/13] io_uring/rsrc: extend buffer update Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 11/13] io_uring/rsrc: add uncloneable regbuf flag Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 12/13] io_uring/rsrc: add regbuf import flags Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 13/13] io_uring/rsrc: add dmabuf backed registered buffers Pavel Begunkov
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=a3ee719abc440ca139f1a945fdaf43a45f0c6b57.1789997898.git.asml.silence@gmail.com \
--to=asml.silence@gmail.com \
--cc=agk@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=anuj20.g@samsung.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=hch@lst.de \
--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=phil.cayton@intel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®