* [PATCH 1/5] dma-buf-io: add tags for sharing ctx b/w files
2026-11-04 0:18 [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
@ 2026-11-04 0:18 ` Pavel Begunkov
2026-11-04 0:18 ` [PATCH 2/5] block: set dma-buf-io tag to block files Pavel Begunkov
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-11-04 0:18 UTC (permalink / raw)
To: linux-block, io-uring
Cc: Sumit Semwal, Christian König, Philipp Stanner, linux-media,
dri-devel, linaro-mm-sig, Pavel Begunkov, Jens Axboe,
Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
Nitesh Shetty, Kanchan Joshi, Anuj Gupta
Currently, it's only allowed to pass a ctx to the file it was registered
with, which is enforced on the io_uring side. Going forward we want to
support filesystems and not just block device files, and it'd be too
limiting.
Add a dma-buf-io tag to all files. We're going to save a tag of the file
passed during registration and later use to reject files which tags
don't match. A tag should be set for a file by the importer subsystem
implementing ->init_dma_buf_io_ctx on creation and should be unique for
this instance of the subsystem. For simplicity, we're going to use
pointers for which we're going to use pointers, e.g. gendisk for block
files and superblock for filesystems.
This patch adds a new field in struct file to keep a tag, but it can be
then be switched to a new f_op method.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
drivers/dma-buf/dma-buf-io.c | 3 +++
include/linux/dma-buf-io.h | 22 ++++++++++++++++++++++
include/linux/fs.h | 6 ++++++
3 files changed, 31 insertions(+)
diff --git a/drivers/dma-buf/dma-buf-io.c b/drivers/dma-buf/dma-buf-io.c
index 8440151de860..60dc58fc0c23 100644
--- a/drivers/dma-buf/dma-buf-io.c
+++ b/drivers/dma-buf/dma-buf-io.c
@@ -166,12 +166,15 @@ int dma_buf_io_ctx_create(struct file *file,
if (!file->f_op->init_dma_buf_io_ctx)
return -EOPNOTSUPP;
+ if (WARN_ON(!file->f_dma_io_tag))
+ return -EFAULT;
ctx = kzalloc_obj(*ctx);
if (!ctx)
return -ENOMEM;
ctx->dir = dir;
ctx->dmabuf = dmabuf;
+ ctx->importer_tag = file->f_dma_io_tag;
get_dma_buf(dmabuf);
ret = file->f_op->init_dma_buf_io_ctx(file, ctx);
diff --git a/include/linux/dma-buf-io.h b/include/linux/dma-buf-io.h
index d9f27650a851..299edf0baaf3 100644
--- a/include/linux/dma-buf-io.h
+++ b/include/linux/dma-buf-io.h
@@ -48,10 +48,32 @@ struct dma_buf_io_ctx {
enum dma_data_direction dir;
bool is_dead;
+ /*
+ * Tags represent an instance of the subsystem the dma-buf I/O
+ * context is bound to, the set of underlying devices and subsystem
+ * specific map / context structure representations. Remember the
+ * registration file's tag (see struct file::f_dma_io_tag) and use
+ * it to filter out files that don't share it.
+ */
+ unsigned long importer_tag;
+
void *dev_priv;
const struct dma_buf_io_ops *dev_ops;
};
+/**
+ * dma_buf_io_file_compatible - Check compatibility b/w context and file.
+ * @ctx: [in] dma-buf I/O context
+ * @file: [in] file
+ *
+ * Returns true if the context can be used to issue I/O to the given file.
+ */
+static inline bool dma_buf_io_file_compatible(const struct dma_buf_io_ctx *ctx,
+ const struct file *file)
+{
+ return file->f_dma_io_tag == ctx->importer_tag;
+}
+
int dma_buf_io_ctx_create(struct file *file,
struct dma_buf *dmabuf,
enum dma_data_direction dir,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 99caef43ff3c..a9bb63cf6f9d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1293,6 +1293,12 @@ struct file {
freeptr_t f_freeptr;
};
file_ref_t f_ref;
+
+ /*
+ * A tag representing the underlying subsystem for dma-buf I/O.
+ * See struct dma_buf_io_ctx::importer_tag.
+ */
+ unsigned long f_dma_io_tag;
/* --- cacheline 3 boundary (192 bytes) --- */
} __randomize_layout
__attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 2/5] block: set dma-buf-io tag to block files
2026-11-04 0:18 [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
2026-11-04 0:18 ` [PATCH 1/5] dma-buf-io: add tags for sharing ctx b/w files Pavel Begunkov
@ 2026-11-04 0:18 ` Pavel Begunkov
2026-11-04 0:18 ` [PATCH 3/5] io_uring: add data to dma-buf convertion helpers Pavel Begunkov
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-11-04 0:18 UTC (permalink / raw)
To: linux-block, io-uring
Cc: Sumit Semwal, Christian König, Philipp Stanner, linux-media,
dri-devel, linaro-mm-sig, Pavel Begunkov, Jens Axboe,
Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
Nitesh Shetty, Kanchan Joshi, Anuj Gupta
We need to set dma-buf-io tag to be able to share contexts between
multiple files. Use gendisk pointer as a tag, this allows sharing
b/w different partitions of the same block device.
Fixes: 839231d19393 ("block: add dma-buf support for raw bdev")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
block/fops.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/fops.c b/block/fops.c
index 60b9c9b1cefe..6f013780b76b 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -687,6 +687,7 @@ static int blkdev_open(struct inode *inode, struct file *filp)
ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
if (ret)
blkdev_put_no_open(bdev);
+ filp->f_dma_io_tag = (unsigned long)bdev->bd_disk;
return ret;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/5] io_uring: add data to dma-buf convertion helpers
2026-11-04 0:18 [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
2026-11-04 0:18 ` [PATCH 1/5] dma-buf-io: add tags for sharing ctx b/w files Pavel Begunkov
2026-11-04 0:18 ` [PATCH 2/5] block: set dma-buf-io tag to block files Pavel Begunkov
@ 2026-11-04 0:18 ` Pavel Begunkov
2026-11-04 0:19 ` [PATCH 4/5] io_uring/dma-buf: switch to tag file filtering Pavel Begunkov
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-11-04 0:18 UTC (permalink / raw)
To: linux-block, io-uring
Cc: Sumit Semwal, Christian König, Philipp Stanner, linux-media,
dri-devel, linaro-mm-sig, Pavel Begunkov, Jens Axboe,
Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
Nitesh Shetty, Kanchan Joshi, Anuj Gupta
struct io_buf_dma is stored as void * in registered buffers, and it's
casted in multiple places. It's inconvenient as void* casts can't be
type checked, so wrap all of them into helpers and keep casting
centralised. No functional changes.
Fixes: 62e4bf5b25d44 ("io_uring/rsrc: add dmabuf backed registered buffers")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
io_uring/dma-buf.c | 2 +-
io_uring/dma-buf.h | 14 ++++++++++++--
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/io_uring/dma-buf.c b/io_uring/dma-buf.c
index 132e3d0d7023..6f1d21c0f558 100644
--- a/io_uring/dma-buf.c
+++ b/io_uring/dma-buf.c
@@ -2,7 +2,7 @@
static inline void io_release_dmabuf(void *priv)
{
- struct io_buf_dma *bd = priv;
+ struct io_buf_dma *bd = io_priv_to_dmabuf(priv);
fput(bd->target_file);
dma_buf_io_ctx_release(bd->ctx);
diff --git a/io_uring/dma-buf.h b/io_uring/dma-buf.h
index 534c06b6879f..a97412ebbb3f 100644
--- a/io_uring/dma-buf.h
+++ b/io_uring/dma-buf.h
@@ -12,6 +12,16 @@ struct io_buf_dma {
struct file *target_file;
};
+static inline struct io_buf_dma *io_priv_to_dmabuf(void *data)
+{
+ return data;
+}
+
+static inline struct io_buf_dma *io_buf_to_dmabuf(struct io_mapped_ubuf *imu)
+{
+ return io_priv_to_dmabuf(imu->priv);
+}
+
int __io_register_dmabuf(struct io_ring_ctx *ctx,
struct io_uring_regbuf_desc *desc,
struct io_mapped_ubuf *imu);
@@ -39,7 +49,7 @@ static inline int io_attach_dmabuf_map(struct io_kiocb *req,
if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
return -EOPNOTSUPP;
- bd = req->buf_node->buf->priv;
+ bd = io_buf_to_dmabuf(req->buf_node->buf);
map = dma_buf_io_get_map(bd->ctx, nowait);
if (unlikely(IS_ERR(map)))
return PTR_ERR(map);
@@ -53,7 +63,7 @@ static inline int io_import_dmabuf_map(struct io_kiocb *req,
struct io_mapped_ubuf *imu,
size_t len, size_t offset)
{
- struct io_buf_dma *bd = imu->priv;
+ struct io_buf_dma *bd = io_buf_to_dmabuf(imu);
if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
return -EOPNOTSUPP;
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/5] io_uring/dma-buf: switch to tag file filtering
2026-11-04 0:18 [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
` (2 preceding siblings ...)
2026-11-04 0:18 ` [PATCH 3/5] io_uring: add data to dma-buf convertion helpers Pavel Begunkov
@ 2026-11-04 0:19 ` Pavel Begunkov
2026-11-04 0:19 ` [PATCH 5/5] io_uring/dma-buf: get rid of struct io_buf_dma Pavel Begunkov
2026-11-04 1:07 ` [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
5 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-11-04 0:19 UTC (permalink / raw)
To: linux-block, io-uring
Cc: Sumit Semwal, Christian König, Philipp Stanner, linux-media,
dri-devel, linaro-mm-sig, Pavel Begunkov, Jens Axboe,
Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
Nitesh Shetty, Kanchan Joshi, Anuj Gupta
Instead of enforcing that a dma-buf-io ctx is used only with the
registered file, allow sharing using tags.
Fixes: 62e4bf5b25d44 ("io_uring/rsrc: add dmabuf backed registered buffers")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
io_uring/dma-buf.c | 3 +--
io_uring/dma-buf.h | 6 ++----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/io_uring/dma-buf.c b/io_uring/dma-buf.c
index 6f1d21c0f558..f25749f7da22 100644
--- a/io_uring/dma-buf.c
+++ b/io_uring/dma-buf.c
@@ -4,7 +4,6 @@ static inline void io_release_dmabuf(void *priv)
{
struct io_buf_dma *bd = io_priv_to_dmabuf(priv);
- fput(bd->target_file);
dma_buf_io_ctx_release(bd->ctx);
kfree(bd);
}
@@ -52,13 +51,13 @@ int __io_register_dmabuf(struct io_ring_ctx *ctx,
if (ret)
goto err;
- bd->target_file = target_file;
imu->len = dmabuf->size;
imu->release = io_release_dmabuf;
imu->priv = bd;
imu->flags = IO_REGBUF_F_DMABUF;
imu->dir = IO_BUF_DEST | IO_BUF_SOURCE;
dma_buf_put(dmabuf);
+ fput(target_file);
return 0;
err:
kfree(bd);
diff --git a/io_uring/dma-buf.h b/io_uring/dma-buf.h
index a97412ebbb3f..9bd7c8c64397 100644
--- a/io_uring/dma-buf.h
+++ b/io_uring/dma-buf.h
@@ -9,7 +9,6 @@
struct io_buf_dma {
struct dma_buf_io_ctx *ctx;
- struct file *target_file;
};
static inline struct io_buf_dma *io_priv_to_dmabuf(void *data)
@@ -63,11 +62,10 @@ static inline int io_import_dmabuf_map(struct io_kiocb *req,
struct io_mapped_ubuf *imu,
size_t len, size_t offset)
{
- struct io_buf_dma *bd = io_buf_to_dmabuf(imu);
-
if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
return -EOPNOTSUPP;
- if (req->file != bd->target_file)
+ if (unlikely(!dma_buf_io_file_compatible(io_buf_to_dmabuf(imu)->ctx,
+ req->file)))
return -EBADF;
req->flags |= REQ_F_DMABUF;
iov_iter_dmabuf_map(iter, ddir, NULL, offset, len);
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 5/5] io_uring/dma-buf: get rid of struct io_buf_dma
2026-11-04 0:18 [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
` (3 preceding siblings ...)
2026-11-04 0:19 ` [PATCH 4/5] io_uring/dma-buf: switch to tag file filtering Pavel Begunkov
@ 2026-11-04 0:19 ` Pavel Begunkov
2026-11-04 1:07 ` [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
5 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-11-04 0:19 UTC (permalink / raw)
To: linux-block, io-uring
Cc: Sumit Semwal, Christian König, Philipp Stanner, linux-media,
dri-devel, linaro-mm-sig, Pavel Begunkov, Jens Axboe,
Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
Nitesh Shetty, Kanchan Joshi, Anuj Gupta
Now struct io_buf_dma only stores dma_buf_io_ctx, and we can use the
latter directly.
Fixes: 62e4bf5b25d44 ("io_uring/rsrc: add dmabuf backed registered buffers")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
io_uring/dma-buf.c | 16 ++++------------
io_uring/dma-buf.h | 16 ++++++----------
2 files changed, 10 insertions(+), 22 deletions(-)
diff --git a/io_uring/dma-buf.c b/io_uring/dma-buf.c
index f25749f7da22..a1fc34c0c044 100644
--- a/io_uring/dma-buf.c
+++ b/io_uring/dma-buf.c
@@ -2,17 +2,14 @@
static inline void io_release_dmabuf(void *priv)
{
- struct io_buf_dma *bd = io_priv_to_dmabuf(priv);
-
- dma_buf_io_ctx_release(bd->ctx);
- kfree(bd);
+ dma_buf_io_ctx_release(io_priv_to_dmabuf(priv));
}
int __io_register_dmabuf(struct io_ring_ctx *ctx,
struct io_uring_regbuf_desc *desc,
struct io_mapped_ubuf *imu)
{
- struct io_buf_dma *bd = NULL;
+ struct dma_buf_io_ctx *dmabuf_ctx;
struct file *target_file = NULL;
struct dma_buf *dmabuf = NULL;
int ret;
@@ -27,10 +24,6 @@ int __io_register_dmabuf(struct io_ring_ctx *ctx,
if (desc->uaddr || desc->size)
return -EINVAL;
- bd = kzalloc(sizeof(*bd), GFP_KERNEL);
- if (!bd)
- return -ENOMEM;
-
target_file = fget(desc->target_fd);
if (!target_file) {
ret = -EBADF;
@@ -47,20 +40,19 @@ int __io_register_dmabuf(struct io_ring_ctx *ctx,
goto err;
ret = dma_buf_io_ctx_create(target_file, dmabuf, DMA_BIDIRECTIONAL,
- &bd->ctx);
+ &dmabuf_ctx);
if (ret)
goto err;
imu->len = dmabuf->size;
imu->release = io_release_dmabuf;
- imu->priv = bd;
+ imu->priv = dmabuf_ctx;
imu->flags = IO_REGBUF_F_DMABUF;
imu->dir = IO_BUF_DEST | IO_BUF_SOURCE;
dma_buf_put(dmabuf);
fput(target_file);
return 0;
err:
- kfree(bd);
if (target_file)
fput(target_file);
if (dmabuf)
diff --git a/io_uring/dma-buf.h b/io_uring/dma-buf.h
index 9bd7c8c64397..c622347fbd76 100644
--- a/io_uring/dma-buf.h
+++ b/io_uring/dma-buf.h
@@ -7,16 +7,12 @@
#include "rsrc.h"
-struct io_buf_dma {
- struct dma_buf_io_ctx *ctx;
-};
-
-static inline struct io_buf_dma *io_priv_to_dmabuf(void *data)
+static inline struct dma_buf_io_ctx *io_priv_to_dmabuf(void *data)
{
return data;
}
-static inline struct io_buf_dma *io_buf_to_dmabuf(struct io_mapped_ubuf *imu)
+static inline struct dma_buf_io_ctx *io_buf_to_dmabuf(struct io_mapped_ubuf *imu)
{
return io_priv_to_dmabuf(imu->priv);
}
@@ -40,16 +36,16 @@ static inline int io_attach_dmabuf_map(struct io_kiocb *req,
unsigned issue_flags)
{
bool nowait = issue_flags & IO_URING_F_NONBLOCK;
+ struct io_mapped_ubuf *imu;
struct dma_buf_io_map *map;
- struct io_buf_dma *bd;
if (!(req->flags & REQ_F_DMABUF))
return 0;
if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
return -EOPNOTSUPP;
- bd = io_buf_to_dmabuf(req->buf_node->buf);
- map = dma_buf_io_get_map(bd->ctx, nowait);
+ imu = req->buf_node->buf;
+ map = dma_buf_io_get_map(io_buf_to_dmabuf(imu), nowait);
if (unlikely(IS_ERR(map)))
return PTR_ERR(map);
req->dmabuf_map = map;
@@ -64,7 +60,7 @@ static inline int io_import_dmabuf_map(struct io_kiocb *req,
{
if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
return -EOPNOTSUPP;
- if (unlikely(!dma_buf_io_file_compatible(io_buf_to_dmabuf(imu)->ctx,
+ if (unlikely(!dma_buf_io_file_compatible(io_buf_to_dmabuf(imu),
req->file)))
return -EBADF;
req->flags |= REQ_F_DMABUF;
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 0/5] allow dma-buf-io ctx reuse across files
2026-11-04 0:18 [PATCH 0/5] allow dma-buf-io ctx reuse across files Pavel Begunkov
` (4 preceding siblings ...)
2026-11-04 0:19 ` [PATCH 5/5] io_uring/dma-buf: get rid of struct io_buf_dma Pavel Begunkov
@ 2026-11-04 1:07 ` Pavel Begunkov
5 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-11-04 1:07 UTC (permalink / raw)
To: linux-block, io-uring
Cc: Sumit Semwal, Christian König, Philipp Stanner, linux-media,
dri-devel, linaro-mm-sig, Jens Axboe, Alexander Viro,
Christian Brauner, Jan Kara, linux-fsdevel, Nitesh Shetty,
Kanchan Joshi, Anuj Gupta
On 11/4/26 00:18, Pavel Begunkov wrote:
> Currently, dma-buf maps can only be used by the file they were
> registered with. This means that we can't open a new file, even if it
> comes from the same subsystem and point to the same block device and
> use it with an old dma-buf registration. That would be too restrictive
> for upcoming filsystem support, so lift it now and allow reusing
> contexts between files pointing to the same NVMe, even if they refer
> to different partitions.
>
> To do that, we add a tag representing for each file, save it from
> the file passed during registration and use it to reject files
> which tags don't match it. Tags are set by subsystems creating
> files, should be unique and represent the instance of the
> subsystem.
Fwiw, sashiko raised good points, I'll need to address
them in v2.
--
Pavel Begunkov
^ permalink raw reply [flat|nested] 7+ messages in thread