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 <[email protected]>
---
 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

Reply via email to