Le 28/09/2026 à 15:32, Pavel Begunkov a écrit :
The goal is to be able to natively use dma-buf in the read-write / IO
path. This patch adds basic building blocks serving as a glue and API
between drivers and upper layer subsystems providing the uAPI. Later
patches implement it for NVMe raw block devices and expose it to the
user space via io_uring.

There are two main objects. struct dma_buf_io_ctx and struct
dma_buf_io_map. The ctx is used during initial registration and serves
as an interface between the upper layer user like io_uring and to the
importer subsystem / driver. The map represents the actual dma map
established for the target device[s] with dma_buf_map_attachment() and
stored in a device specific format. The context is created via a new
file operation ->init_dma_buf_io_ctx.

The ctx-map separation exists to support map invalidation (see
dma_buf_io_invalidate_mappings()). A ctx can create
multiple maps during its lifetime, but there can only be no more than
one (active) map attached to it. Invalidation drops the active map
if present, and the next map will only be attempted to be created
once there is a new request that wants to use the dma-buf IO ctx.

The primary task of the dma_buf_io_map object is to count requests
using it and to wait for their completion when we want to destroy the
DMA map.

[un]mapping and any work with dma addresses is delegated to the
importer driver via an ops table stored in the ctx, see struct
dma_buf_io_ops. Only the target driver / subsystem knows about devices
it wants to use the dma-buf with, especially in case of multi-device
filesystems or stacking in the future.

Signed-off-by: Pavel Begunkov <[email protected]>
---

Hi,
a few nitpicks below, should it help


+static void dma_buf_io_kill_maps(struct dma_buf_io_ctx *ctx, bool final)
+{
+       struct dma_buf_io_map *map;
+
+       scoped_guard(mutex, &ctx->map_mutex) {

guard() is enough. This saves indentation.

+               if (final)
+                       ctx->maps_killed = true;
+
+               map = rcu_dereference_protected(ctx->map,
+                                       lockdep_is_held(&ctx->map_mutex));
+               if (!map)
+                       return;
+               rcu_assign_pointer(ctx->map, NULL);
+               percpu_ref_kill(&map->refs);
+       }
+}

...

+int dma_buf_io_ctx_create(struct file *file,
+                          struct dma_buf *dmabuf,
+                          enum dma_data_direction dir,
+                          struct dma_buf_io_ctx **out_ctx)
+{
+       struct dma_buf_io_ctx *ctx;
+       int ret;
+
+       if (!file->f_op->init_dma_buf_io_ctx)
+               return -EOPNOTSUPP;
+
+       ctx = kmalloc_obj(*ctx);

kzalloc_obj() and save the memset() below

+       if (!ctx)
+               return -ENOMEM;
+
+       memset(ctx, 0, sizeof(*ctx));
+       ctx->dir = dir;
+       ctx->dmabuf = dmabuf;
+       get_dma_buf(dmabuf);
+       mutex_init(&ctx->map_mutex);
+       mutex_init(&ctx->map_create_mutex);
+       atomic_set(&ctx->active_maps, 0);
+       atomic_set(&ctx->all_maps, 0);
+       refcount_set(&ctx->refs, 1);
+       init_waitqueue_head(&ctx->maps_wq);
+
+       ret = file->f_op->init_dma_buf_io_ctx(file, ctx);
+       if (ret) {
+               kfree(ctx);
+               dma_buf_put(dmabuf);
+               return ret;
+       }
+
+       if (WARN_ON_ONCE(!ctx->dev_ops ||
+                        !ctx->dev_ops->map ||
+                        !ctx->dev_ops->unmap ||
+                        !ctx->dev_ops->release))
+               return -EINVAL;
+
+       *out_ctx = ctx;
+       return 0;
+}
...

CJ


Reply via email to