* [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O
@ 2026-10-22 14:44 Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 1/5] io_uring/rsrc: pass import flags to io_import_reg_buf() Anuj Gupta
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Anuj Gupta @ 2026-10-22 14:44 UTC (permalink / raw)
To: axboe, asml.silence, kbusch, hch, sagi, James.Bottomley, mkp,
bernd, joannelkoong, miklos
Cc: io-uring, linux-nvme, linux-block, linux-scsi, fuse-devel,
joshi.k, anuj20.g
This series adds support for dma-buf registered buffers in NVMe
uring_cmd passthrough.
It depends on this fix:
https://lore.kernel.org/io-uring/20261022132027.2293931-1-anuj1072538@gmail.com/
Patches 1-2 add import flags to the fixed buffer import helpers, so
uring_cmd users have to opt in to dma-buf. Patch 3 adds the io_uring
side, patch 4 lets the block layer map dma-buf iterators for
passthrough, and patch 5 enables it for the NVMe namespace character
device.
Tested with this liburing test:
https://github.com/anuj7781/liburing/tree/rw-dmabuf-pt
Changes since v1:
- split into io_uring, block and nvme patches (Christoph)
- pass import flags to io_import_reg_buf() and
io_uring_cmd_import_fixed(), and make callers opt in to dma-buf
(Christoph, Pavel)
- add io_uring_cmd_hw_done(), so nvme no longer handles the dma-buf
map (Pavel)
- warn if task_work is queued with a dma-buf map attached (Pavel)
- make the -EREMOTEIO conversion explicit and comment it (Christoph)
- refuse dma-bufs larger than 4GiB on the character device
v1: https://lore.kernel.org/linux-nvme/20261016103453.1129150-1-anuj1072538@gmail.com/
Anuj Gupta (5):
io_uring/rsrc: pass import flags to io_import_reg_buf()
io_uring/uring_cmd: add import flags to io_uring_cmd_import_fixed()
io_uring/uring_cmd: support dma-buf registered buffers
block: map dma-buf iterators in blk_rq_map_user_iov()
nvme: support dma-buf registered buffers for passthrough
block/blk-map.c | 15 ++++++++++++++-
drivers/nvme/host/core.c | 16 ++++++++++++++++
drivers/nvme/host/ioctl.c | 5 +++--
drivers/scsi/scsi_bsg.c | 2 +-
fs/fuse/dev_uring.c | 2 +-
include/linux/io_uring/cmd.h | 14 ++++++++++++--
io_uring/net.c | 6 +++---
io_uring/rsrc.c | 6 +++---
io_uring/rsrc.h | 13 +++----------
io_uring/rw.c | 5 +++--
io_uring/uring_cmd.c | 31 +++++++++++++++++++++++++++++--
11 files changed, 88 insertions(+), 27 deletions(-)
base-commit: fd13f31ac62abac4df2166bb0a6fbff53b288e0c
prerequisite-patch-id: 6ad52e1ffc603df71c6855926838f2df402c3ed1
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/5] io_uring/rsrc: pass import flags to io_import_reg_buf()
2026-10-22 14:44 [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O Anuj Gupta
@ 2026-10-22 14:44 ` Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 2/5] io_uring/uring_cmd: add import flags to io_uring_cmd_import_fixed() Anuj Gupta
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Anuj Gupta @ 2026-10-22 14:44 UTC (permalink / raw)
To: axboe, asml.silence, kbusch, hch, sagi, James.Bottomley, mkp,
bernd, joannelkoong, miklos
Cc: io-uring, linux-nvme, linux-block, linux-scsi, fuse-devel,
joshi.k, anuj20.g
From: Anuj Gupta <anuj20.g@samsung.com>
Give io_import_reg_buf() the import flags argument and drop the
__io_import_reg_buf() variant, which only existed to pass them.
No functional change.
Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
io_uring/net.c | 6 +++---
io_uring/rsrc.c | 6 +++---
io_uring/rsrc.h | 13 +++----------
io_uring/rw.c | 5 +++--
io_uring/uring_cmd.c | 2 +-
5 files changed, 13 insertions(+), 19 deletions(-)
diff --git a/io_uring/net.c b/io_uring/net.c
index 050ed274170a..63089744d43e 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -644,7 +644,7 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags)
if (req->flags & REQ_F_IMPORT_BUFFER) {
ret = io_import_reg_buf(req, &kmsg->msg.msg_iter,
(u64)(uintptr_t)sr->buf, sr->len,
- ITER_SOURCE, issue_flags);
+ ITER_SOURCE, issue_flags, 0);
if (unlikely(ret))
return ret;
req->flags &= ~REQ_F_IMPORT_BUFFER;
@@ -1216,7 +1216,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
if (req->flags & REQ_F_IMPORT_BUFFER) {
ret = io_import_reg_buf(req, &kmsg->msg.msg_iter,
(u64)(uintptr_t)sr->buf, sr->len,
- ITER_DEST, issue_flags);
+ ITER_DEST, issue_flags, 0);
if (unlikely(ret)) {
kmsg->msg.msg_inq = -1;
sel.buf_list = NULL;
@@ -1509,7 +1509,7 @@ static int io_send_zc_import(struct io_kiocb *req,
if (!(sr->flags & IORING_SEND_VECTORIZED)) {
ret = io_import_reg_buf(notif, &kmsg->msg.msg_iter,
(u64)(uintptr_t)sr->buf, sr->len,
- ITER_SOURCE, issue_flags);
+ ITER_SOURCE, issue_flags, 0);
} else {
unsigned uvec_segs = kmsg->msg.msg_iter.nr_segs;
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index d64228b0e19e..1abfbb86dae8 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -1365,9 +1365,9 @@ inline struct io_rsrc_node *io_find_buf_node(struct io_kiocb *req,
return NULL;
}
-int __io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
- u64 buf_addr, size_t len, int ddir,
- unsigned issue_flags, unsigned import_flags)
+int io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
+ u64 buf_addr, size_t len, int ddir,
+ unsigned issue_flags, unsigned import_flags)
{
struct io_rsrc_node *node;
diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h
index 418d236152ff..6226c7862d4e 100644
--- a/io_uring/rsrc.h
+++ b/io_uring/rsrc.h
@@ -66,21 +66,14 @@ int io_rsrc_data_alloc(struct io_rsrc_data *data, unsigned nr);
struct io_rsrc_node *io_find_buf_node(struct io_kiocb *req,
unsigned issue_flags);
-int __io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
- u64 buf_addr, size_t len, int ddir,
- unsigned issue_flags, unsigned import_flags);
+int io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
+ u64 buf_addr, size_t len, int ddir,
+ unsigned issue_flags, unsigned import_flags);
int __io_import_reg_vec(int ddir, struct iov_iter *iter,
struct io_kiocb *req, struct iou_vec *vec,
unsigned nr_iovs, unsigned issue_flags,
unsigned import_flags);
-static inline int io_import_reg_buf(struct io_kiocb *req, struct iov_iter *iter,
- u64 buf_addr, size_t len, int ddir,
- unsigned issue_flags)
-{
- return __io_import_reg_buf(req, iter, buf_addr, len, ddir, issue_flags, 0);
-}
-
static inline int io_import_reg_vec(int ddir, struct iov_iter *iter,
struct io_kiocb *req, struct iou_vec *vec,
unsigned nr_iovs, unsigned issue_flags)
diff --git a/io_uring/rw.c b/io_uring/rw.c
index d33b925a848e..71782a23e16b 100644
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@ -360,8 +360,9 @@ static int io_init_rw_fixed(struct io_kiocb *req, unsigned int issue_flags,
int ret;
if (!io->bytes_done) {
- ret = __io_import_reg_buf(req, &io->iter, rw->addr, rw->len, ddir,
- issue_flags, IO_REGBUF_IMPORT_ALLOW_DMABUF);
+ ret = io_import_reg_buf(req, &io->iter, rw->addr, rw->len, ddir,
+ issue_flags,
+ IO_REGBUF_IMPORT_ALLOW_DMABUF);
if (ret)
return ret;
iov_iter_save_state(&io->iter, &io->iter_state);
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index 73b606899833..45c9c845f5d0 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -279,7 +279,7 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
if (WARN_ON_ONCE(!(ioucmd->flags & IORING_URING_CMD_FIXED)))
return -EINVAL;
- return io_import_reg_buf(req, iter, ubuf, len, rw, issue_flags);
+ return io_import_reg_buf(req, iter, ubuf, len, rw, issue_flags, 0);
}
EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/5] io_uring/uring_cmd: add import flags to io_uring_cmd_import_fixed()
2026-10-22 14:44 [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 1/5] io_uring/rsrc: pass import flags to io_import_reg_buf() Anuj Gupta
@ 2026-10-22 14:44 ` Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 3/5] io_uring/uring_cmd: support dma-buf registered buffers Anuj Gupta
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Anuj Gupta @ 2026-10-22 14:44 UTC (permalink / raw)
To: axboe, asml.silence, kbusch, hch, sagi, James.Bottomley, mkp,
bernd, joannelkoong, miklos
Cc: io-uring, linux-nvme, linux-block, linux-scsi, fuse-devel,
joshi.k, anuj20.g
From: Anuj Gupta <anuj20.g@samsung.com>
Add an import flags argument to io_uring_cmd_import_fixed(), so callers
can opt in to buffer types they support. No flags are defined yet, and
all callers pass 0.
No functional change.
Suggested-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
drivers/nvme/host/ioctl.c | 2 +-
drivers/scsi/scsi_bsg.c | 2 +-
fs/fuse/dev_uring.c | 2 +-
include/linux/io_uring/cmd.h | 5 +++--
io_uring/uring_cmd.c | 5 ++++-
5 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 3aa5d2f2dfbb..612d3009dd29 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -533,7 +533,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
ddir, &iter, issue_flags);
else
ret = io_uring_cmd_import_fixed(d.addr, d.data_len,
- ddir, &iter, ioucmd, issue_flags);
+ ddir, &iter, ioucmd, issue_flags, 0);
if (ret < 0)
return ret;
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index 5eec248a77a6..e53b417c27b9 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -87,7 +87,7 @@ static int scsi_bsg_map_user_buffer(struct request *req,
if (ioucmd->flags & IORING_URING_CMD_FIXED) {
ret = io_uring_cmd_import_fixed(buf_addr, buf_len,
is_write ? WRITE : READ,
- &iter, ioucmd, issue_flags);
+ &iter, ioucmd, issue_flags, 0);
if (ret < 0)
return ret;
ret = blk_rq_map_user_iov(req->q, req, NULL, &iter, gfp_mask);
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index c6dd420c4034..5cc206abccc0 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -727,7 +727,7 @@ static int fuse_uring_import_payload(struct fuse_ring_ent *ent, int dir,
if (bufpool_registered(ent->queue))
err = io_uring_cmd_import_fixed((u64)(uintptr_t)base, len, dir,
- iter, ent->cmd, issue_flags);
+ iter, ent->cmd, issue_flags, 0);
else
err = import_ubuf(dir, base, len, iter);
diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h
index e18d4af62e1a..23fb66a1e2c1 100644
--- a/include/linux/io_uring/cmd.h
+++ b/include/linux/io_uring/cmd.h
@@ -64,7 +64,8 @@ static inline void io_uring_cmd_set_res32(struct io_uring_cmd *cmd, s32 ret, u64
int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
struct iov_iter *iter,
struct io_uring_cmd *ioucmd,
- unsigned int issue_flags);
+ unsigned int issue_flags,
+ unsigned int import_flags);
int io_uring_cmd_import_fixed_vec(struct io_uring_cmd *ioucmd,
const struct iovec __user *uvec,
size_t uvec_segs,
@@ -124,7 +125,7 @@ int io_buffer_unregister(struct io_uring_cmd *cmd, unsigned int index,
static inline int
io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
struct iov_iter *iter, struct io_uring_cmd *ioucmd,
- unsigned int issue_flags)
+ unsigned int issue_flags, unsigned int import_flags)
{
return -EOPNOTSUPP;
}
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index 45c9c845f5d0..c2bc9dd242ec 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -272,12 +272,15 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
struct iov_iter *iter,
struct io_uring_cmd *ioucmd,
- unsigned int issue_flags)
+ unsigned int issue_flags,
+ unsigned int import_flags)
{
struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
if (WARN_ON_ONCE(!(ioucmd->flags & IORING_URING_CMD_FIXED)))
return -EINVAL;
+ if (WARN_ON_ONCE(import_flags))
+ return -EINVAL;
return io_import_reg_buf(req, iter, ubuf, len, rw, issue_flags, 0);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/5] io_uring/uring_cmd: support dma-buf registered buffers
2026-10-22 14:44 [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 1/5] io_uring/rsrc: pass import flags to io_import_reg_buf() Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 2/5] io_uring/uring_cmd: add import flags to io_uring_cmd_import_fixed() Anuj Gupta
@ 2026-10-22 14:44 ` Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 4/5] block: map dma-buf iterators in blk_rq_map_user_iov() Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 5/5] nvme: support dma-buf registered buffers for passthrough Anuj Gupta
4 siblings, 0 replies; 6+ messages in thread
From: Anuj Gupta @ 2026-10-22 14:44 UTC (permalink / raw)
To: axboe, asml.silence, kbusch, hch, sagi, James.Bottomley, mkp,
bernd, joannelkoong, miklos
Cc: io-uring, linux-nvme, linux-block, linux-scsi, fuse-devel,
joshi.k, anuj20.g
From: Anuj Gupta <anuj20.g@samsung.com>
Let callers of io_uring_cmd_import_fixed() opt in to dma-buf registered
buffers with IO_URING_CMD_IMPORT_DMABUF, and attach the current map on
import.
The map has to be dropped at hardware completion rather than from
task_work. Add io_uring_cmd_hw_done() for drivers to call from end_io,
which drops the map and queues task_work, and warn if task_work is
queued with a map still attached.
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
include/linux/io_uring/cmd.h | 9 +++++++++
io_uring/uring_cmd.c | 28 ++++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h
index 23fb66a1e2c1..d4e17c2f59fd 100644
--- a/include/linux/io_uring/cmd.h
+++ b/include/linux/io_uring/cmd.h
@@ -12,6 +12,9 @@
/* io_uring_cmd is being issued again */
#define IORING_URING_CMD_REISSUE (1U << 31)
+/* io_uring_cmd_import_fixed() flags */
+#define IO_URING_CMD_IMPORT_DMABUF (1U << 0)
+
struct io_uring_cmd {
struct file *file;
const struct io_uring_sqe *sqe;
@@ -86,6 +89,8 @@ void __io_uring_cmd_done(struct io_uring_cmd *, unsigned issue_flags);
void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
io_req_tw_func_t task_work_cb,
unsigned flags);
+void io_uring_cmd_hw_done(struct io_uring_cmd *ioucmd,
+ io_req_tw_func_t task_work_cb);
/*
* Note: the caller should never hard code @issue_flags and only use the
@@ -145,6 +150,10 @@ static inline void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
io_req_tw_func_t task_work_cb, unsigned flags)
{
}
+static inline void io_uring_cmd_hw_done(struct io_uring_cmd *ioucmd,
+ io_req_tw_func_t task_work_cb)
+{
+}
static inline void io_uring_cmd_mark_cancelable(struct io_uring_cmd *cmd,
unsigned int issue_flags)
{
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index c2bc9dd242ec..c89f154190b1 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -10,6 +10,7 @@
#include "io_uring.h"
#include "alloc_cache.h"
+#include "dma-buf.h"
#include "rsrc.h"
#include "kbuf.h"
#include "uring_cmd.h"
@@ -28,6 +29,7 @@ static void io_req_uring_cleanup(struct io_kiocb *req, unsigned int issue_flags)
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
struct io_async_cmd *ac = req->async_data;
+ io_detach_dmabuf_map(req);
if (issue_flags & IO_URING_F_UNLOCKED)
return;
@@ -132,12 +134,26 @@ void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
if (WARN_ON_ONCE(req->flags & REQ_F_APOLL_MULTISHOT))
return;
+ /* the dma-buf map must be dropped first, see io_uring_cmd_hw_done() */
+ WARN_ON_ONCE(req->dmabuf_map);
req->io_task_work.func = task_work_cb;
__io_req_task_work_add(req, flags);
}
EXPORT_SYMBOL_GPL(__io_uring_cmd_do_in_task);
+/*
+ * Queue completion in task context after dropping references that must be
+ * released at hardware completion rather than from task_work.
+ */
+void io_uring_cmd_hw_done(struct io_uring_cmd *ioucmd,
+ io_req_tw_func_t task_work_cb)
+{
+ io_detach_dmabuf_map(cmd_to_io_kiocb(ioucmd));
+ __io_uring_cmd_do_in_task(ioucmd, task_work_cb, IOU_F_TWQ_LAZY_WAKE);
+}
+EXPORT_SYMBOL_GPL(io_uring_cmd_hw_done);
+
/*
* Called by consumers of io_uring_cmd, if they originally returned
* -EIOCBQUEUED upon receiving the command.
@@ -257,6 +273,7 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
ret = file->f_op->uring_cmd(ioucmd, issue_flags);
if (ret == -EAGAIN) {
+ io_detach_dmabuf_map(req);
ioucmd->flags |= IORING_URING_CMD_REISSUE;
return ret;
}
@@ -276,13 +293,20 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
unsigned int import_flags)
{
struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
+ unsigned int flags = 0;
+ int ret;
if (WARN_ON_ONCE(!(ioucmd->flags & IORING_URING_CMD_FIXED)))
return -EINVAL;
- if (WARN_ON_ONCE(import_flags))
+ if (WARN_ON_ONCE(import_flags & ~IO_URING_CMD_IMPORT_DMABUF))
return -EINVAL;
+ if (import_flags & IO_URING_CMD_IMPORT_DMABUF)
+ flags |= IO_REGBUF_IMPORT_ALLOW_DMABUF;
- return io_import_reg_buf(req, iter, ubuf, len, rw, issue_flags, 0);
+ ret = io_import_reg_buf(req, iter, ubuf, len, rw, issue_flags, flags);
+ if (ret)
+ return ret;
+ return io_attach_dmabuf_map(req, iter, issue_flags);
}
EXPORT_SYMBOL_GPL(io_uring_cmd_import_fixed);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 4/5] block: map dma-buf iterators in blk_rq_map_user_iov()
2026-10-22 14:44 [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O Anuj Gupta
` (2 preceding siblings ...)
2026-10-22 14:44 ` [PATCH v2 3/5] io_uring/uring_cmd: support dma-buf registered buffers Anuj Gupta
@ 2026-10-22 14:44 ` Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 5/5] nvme: support dma-buf registered buffers for passthrough Anuj Gupta
4 siblings, 0 replies; 6+ messages in thread
From: Anuj Gupta @ 2026-10-22 14:44 UTC (permalink / raw)
To: axboe, asml.silence, kbusch, hch, sagi, James.Bottomley, mkp,
bernd, joannelkoong, miklos
Cc: io-uring, linux-nvme, linux-block, linux-scsi, fuse-devel,
joshi.k, anuj20.g
From: Anuj Gupta <anuj20.g@samsung.com>
A dma-buf iterator can't fall back to a bounce copy, so map it directly
with blk_rq_map_user_bvec(), which already handles it through
bio_iov_iter_set(). Fail with -EINVAL where a copy would otherwise be
needed, and update the blk_rq_map_user_bvec() comment to match.
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
block/blk-map.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/block/blk-map.c b/block/blk-map.c
index 9cb9605d1f62..d1e096fdb03d 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -459,7 +459,7 @@ int blk_rq_append_bio(struct request *rq, struct bio *bio)
}
EXPORT_SYMBOL(blk_rq_append_bio);
-/* Prepare bio for passthrough IO given ITER_BVEC iter */
+/* Prepare a bio for passthrough I/O from a directly mapped iterator. */
static int blk_rq_map_user_bvec(struct request *rq, const struct iov_iter *iter)
{
unsigned int max_bytes = rq->q->limits.max_hw_sectors << SECTOR_SHIFT;
@@ -506,6 +506,19 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
struct iov_iter i;
int ret = -EINVAL;
+ if (iov_iter_is_dmabuf_map(iter)) {
+ if (map_data || (iov_iter_alignment(iter) & align))
+ return -EINVAL;
+ ret = blk_rq_map_user_bvec(rq, iter);
+ /*
+ * -EREMOTEIO asks the caller to fall back to a bounce copy,
+ * which a dma-buf can't do.
+ */
+ if (ret == -EREMOTEIO)
+ ret = -EINVAL;
+ return ret;
+ }
+
if (map_data)
copy = true;
else if (iov_iter_alignment(iter) & align)
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 5/5] nvme: support dma-buf registered buffers for passthrough
2026-10-22 14:44 [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O Anuj Gupta
` (3 preceding siblings ...)
2026-10-22 14:44 ` [PATCH v2 4/5] block: map dma-buf iterators in blk_rq_map_user_iov() Anuj Gupta
@ 2026-10-22 14:44 ` Anuj Gupta
4 siblings, 0 replies; 6+ messages in thread
From: Anuj Gupta @ 2026-10-22 14:44 UTC (permalink / raw)
To: axboe, asml.silence, kbusch, hch, sagi, James.Bottomley, mkp,
bernd, joannelkoong, miklos
Cc: io-uring, linux-nvme, linux-block, linux-scsi, fuse-devel,
joshi.k, anuj20.g
From: Anuj Gupta <anuj20.g@samsung.com>
Allow registering a dma-buf against an NVMe namespace character device
and using it as the data buffer of fixed uring_cmd passthrough I/O.
Complete through io_uring_cmd_hw_done(), so the dma-buf map is released
at hardware completion.
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
drivers/nvme/host/core.c | 16 ++++++++++++++++
drivers/nvme/host/ioctl.c | 5 +++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index d81462e864a4..6157ff839929 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -8,6 +8,7 @@
#include <linux/blkdev.h>
#include <linux/blk-mq.h>
#include <linux/blk-integrity.h>
+#include <linux/dma-buf-io.h>
#include <linux/compat.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -3982,6 +3983,20 @@ static int nvme_ns_chr_release(struct inode *inode, struct file *file)
return 0;
}
+static int nvme_ns_chr_init_dma_buf_io_ctx(struct file *file,
+ struct dma_buf_io_ctx *ctx)
+{
+ struct nvme_ns *ns =
+ container_of(file_inode(file)->i_cdev, struct nvme_ns, cdev);
+ struct nvme_ctrl *ctrl = ns->ctrl;
+
+ if (ctx->dmabuf->size > UINT_MAX)
+ return -EINVAL;
+ if (!ctrl->ops->init_dma_buf_io_ctx)
+ return -EINVAL;
+ return ctrl->ops->init_dma_buf_io_ctx(ctrl, ctx);
+}
+
static const struct file_operations nvme_ns_chr_fops = {
.owner = THIS_MODULE,
.open = nvme_ns_chr_open,
@@ -3990,6 +4005,7 @@ static const struct file_operations nvme_ns_chr_fops = {
.compat_ioctl = compat_ptr_ioctl,
.uring_cmd = nvme_ns_chr_uring_cmd,
.uring_cmd_iopoll = nvme_ns_chr_uring_cmd_iopoll,
+ .init_dma_buf_io_ctx = nvme_ns_chr_init_dma_buf_io_ctx,
};
static void nvme_add_ns_cdev(struct nvme_ns *ns)
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 612d3009dd29..645446acc10a 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -472,7 +472,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
blk_rq_unmap_user(pdu->bio);
__io_uring_cmd_done(ioucmd, 0);
} else {
- io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
+ io_uring_cmd_hw_done(ioucmd, nvme_uring_task_cb);
}
return RQ_END_IO_FREE;
}
@@ -533,7 +533,8 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
ddir, &iter, issue_flags);
else
ret = io_uring_cmd_import_fixed(d.addr, d.data_len,
- ddir, &iter, ioucmd, issue_flags, 0);
+ ddir, &iter, ioucmd, issue_flags,
+ IO_URING_CMD_IMPORT_DMABUF);
if (ret < 0)
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-22 14:46 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22 14:44 [PATCH v2 0/5] dma-buf backed NVMe passthrough I/O Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 1/5] io_uring/rsrc: pass import flags to io_import_reg_buf() Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 2/5] io_uring/uring_cmd: add import flags to io_uring_cmd_import_fixed() Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 3/5] io_uring/uring_cmd: support dma-buf registered buffers Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 4/5] block: map dma-buf iterators in blk_rq_map_user_iov() Anuj Gupta
2026-10-22 14:44 ` [PATCH v2 5/5] nvme: support dma-buf registered buffers for passthrough Anuj Gupta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox