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
