[PATCH] dma-buf: fix dma_buf_export init order v2

T.J. Mercier tjmercier at google.com
Fri Dec 9 21:13:34 UTC 2022


On Fri, Dec 9, 2022 at 8:29 AM Ruhl, Michael J <michael.j.ruhl at intel.com> wrote:
>
> >-----Original Message-----
> >From: dri-devel <dri-devel-bounces at lists.freedesktop.org> On Behalf Of
> >Christian König
> >Sent: Friday, December 9, 2022 2:16 AM
> >To: quic_charante at quicinc.com; cuigaosheng1 at huawei.com;
> >sumit.semwal at linaro.org
> >Cc: linaro-mm-sig at lists.linaro.org; dri-devel at lists.freedesktop.org; linux-
> >media at vger.kernel.org
> >Subject: [PATCH] dma-buf: fix dma_buf_export init order v2
> >
> >The init order and resulting error handling in dma_buf_export
> >was pretty messy.
> >
> >Subordinate objects like the file and the sysfs kernel objects
> >were initializing and wiring itself up with the object in the
> >wrong order resulting not only in complicating and partially
> >incorrect error handling, but also in publishing only halve
> >initialized DMA-buf objects.
> >
> >Clean this up thoughtfully by allocating the file independent
> >of the DMA-buf object. Then allocate and initialize the DMA-buf
> >object itself, before publishing it through sysfs. If everything
> >works as expected the file is then connected with the DMA-buf
> >object and publish it through debugfs.
> >
> >Also adds the missing dma_resv_fini() into the error handling.
> >
> >v2: add some missing changes to dma_bug_getfile() and a missing NULL
> >    check in dma_buf_file_release()
>
> Looks good.
>
> Reviewed-by: Michael J. Ruhl <michael.j.ruhl at intel.com>
>
> Mike
>
+1

Reviewed-by: T.J. Mercier <tjmercier at google.com>

> >Signed-off-by: Christian König <christian.koenig at amd.com>
> >---
> > drivers/dma-buf/dma-buf-sysfs-stats.c |  7 +--
> > drivers/dma-buf/dma-buf-sysfs-stats.h |  4 +-
> > drivers/dma-buf/dma-buf.c             | 84 +++++++++++++--------------
> > 3 files changed, 43 insertions(+), 52 deletions(-)
> >
> >diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.c b/drivers/dma-buf/dma-
> >buf-sysfs-stats.c
> >index 2bba0babcb62..4b680e10c15a 100644
> >--- a/drivers/dma-buf/dma-buf-sysfs-stats.c
> >+++ b/drivers/dma-buf/dma-buf-sysfs-stats.c
> >@@ -168,14 +168,11 @@ void dma_buf_uninit_sysfs_statistics(void)
> >       kset_unregister(dma_buf_stats_kset);
> > }
> >
> >-int dma_buf_stats_setup(struct dma_buf *dmabuf)
> >+int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file)
> > {
> >       struct dma_buf_sysfs_entry *sysfs_entry;
> >       int ret;
> >
> >-      if (!dmabuf || !dmabuf->file)
> >-              return -EINVAL;
> >-
> >       if (!dmabuf->exp_name) {
> >               pr_err("exporter name must not be empty if stats
> >needed\n");
> >               return -EINVAL;
> >@@ -192,7 +189,7 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf)
> >
> >       /* create the directory for buffer stats */
> >       ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype,
> >NULL,
> >-                                 "%lu", file_inode(dmabuf->file)->i_ino);
> >+                                 "%lu", file_inode(file)->i_ino);
> >       if (ret)
> >               goto err_sysfs_dmabuf;
> >
> >diff --git a/drivers/dma-buf/dma-buf-sysfs-stats.h b/drivers/dma-buf/dma-
> >buf-sysfs-stats.h
> >index a49c6e2650cc..7a8a995b75ba 100644
> >--- a/drivers/dma-buf/dma-buf-sysfs-stats.h
> >+++ b/drivers/dma-buf/dma-buf-sysfs-stats.h
> >@@ -13,7 +13,7 @@
> > int dma_buf_init_sysfs_statistics(void);
> > void dma_buf_uninit_sysfs_statistics(void);
> >
> >-int dma_buf_stats_setup(struct dma_buf *dmabuf);
> >+int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file *file);
> >
> > void dma_buf_stats_teardown(struct dma_buf *dmabuf);
> > #else
> >@@ -25,7 +25,7 @@ static inline int dma_buf_init_sysfs_statistics(void)
> >
> > static inline void dma_buf_uninit_sysfs_statistics(void) {}
> >
> >-static inline int dma_buf_stats_setup(struct dma_buf *dmabuf)
> >+static inline int dma_buf_stats_setup(struct dma_buf *dmabuf, struct file
> >*file)
> > {
> >       return 0;
> > }
> >diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> >index e6f36c014c4c..eb6b59363c4f 100644
> >--- a/drivers/dma-buf/dma-buf.c
> >+++ b/drivers/dma-buf/dma-buf.c
> >@@ -95,10 +95,11 @@ static int dma_buf_file_release(struct inode *inode,
> >struct file *file)
> >               return -EINVAL;
> >
> >       dmabuf = file->private_data;
> >-
> >-      mutex_lock(&db_list.lock);
> >-      list_del(&dmabuf->list_node);
> >-      mutex_unlock(&db_list.lock);
> >+      if (dmabuf) {
> >+              mutex_lock(&db_list.lock);
> >+              list_del(&dmabuf->list_node);
> >+              mutex_unlock(&db_list.lock);
> >+      }
> >
> >       return 0;
> > }
> >@@ -523,17 +524,17 @@ static inline int is_dma_buf_file(struct file *file)
> >       return file->f_op == &dma_buf_fops;
> > }
> >
> >-static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
> >+static struct file *dma_buf_getfile(size_t size, int flags)
> > {
> >       static atomic64_t dmabuf_inode = ATOMIC64_INIT(0);
> >-      struct file *file;
> >       struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb);
> >+      struct file *file;
> >
> >       if (IS_ERR(inode))
> >               return ERR_CAST(inode);
> >
> >-      inode->i_size = dmabuf->size;
> >-      inode_set_bytes(inode, dmabuf->size);
> >+      inode->i_size = size;
> >+      inode_set_bytes(inode, size);
> >
> >       /*
> >        * The ->i_ino acquired from get_next_ino() is not unique thus
> >@@ -547,8 +548,6 @@ static struct file *dma_buf_getfile(struct dma_buf
> >*dmabuf, int flags)
> >                                flags, &dma_buf_fops);
> >       if (IS_ERR(file))
> >               goto err_alloc_file;
> >-      file->private_data = dmabuf;
> >-      file->f_path.dentry->d_fsdata = dmabuf;
> >
> >       return file;
> >
> >@@ -614,19 +613,11 @@ struct dma_buf *dma_buf_export(const struct
> >dma_buf_export_info *exp_info)
> >       size_t alloc_size = sizeof(struct dma_buf);
> >       int ret;
> >
> >-      if (!exp_info->resv)
> >-              alloc_size += sizeof(struct dma_resv);
> >-      else
> >-              /* prevent &dma_buf[1] == dma_buf->resv */
> >-              alloc_size += 1;
> >-
> >-      if (WARN_ON(!exp_info->priv
> >-                        || !exp_info->ops
> >-                        || !exp_info->ops->map_dma_buf
> >-                        || !exp_info->ops->unmap_dma_buf
> >-                        || !exp_info->ops->release)) {
> >+      if (WARN_ON(!exp_info->priv || !exp_info->ops
> >+                  || !exp_info->ops->map_dma_buf
> >+                  || !exp_info->ops->unmap_dma_buf
> >+                  || !exp_info->ops->release))
> >               return ERR_PTR(-EINVAL);
> >-      }
> >
> >       if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
> >                   (exp_info->ops->pin || exp_info->ops->unpin)))
> >@@ -638,10 +629,21 @@ struct dma_buf *dma_buf_export(const struct
> >dma_buf_export_info *exp_info)
> >       if (!try_module_get(exp_info->owner))
> >               return ERR_PTR(-ENOENT);
> >
> >+      file = dma_buf_getfile(exp_info->size, exp_info->flags);
> >+      if (IS_ERR(file)) {
> >+              ret = PTR_ERR(file);
> >+              goto err_module;
> >+      }
> >+
> >+      if (!exp_info->resv)
> >+              alloc_size += sizeof(struct dma_resv);
> >+      else
> >+              /* prevent &dma_buf[1] == dma_buf->resv */
> >+              alloc_size += 1;
> >       dmabuf = kzalloc(alloc_size, GFP_KERNEL);
> >       if (!dmabuf) {
> >               ret = -ENOMEM;
> >-              goto err_module;
> >+              goto err_file;
> >       }
> >
> >       dmabuf->priv = exp_info->priv;
> >@@ -653,44 +655,36 @@ struct dma_buf *dma_buf_export(const struct
> >dma_buf_export_info *exp_info)
> >       init_waitqueue_head(&dmabuf->poll);
> >       dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
> >       dmabuf->cb_in.active = dmabuf->cb_out.active = 0;
> >+      mutex_init(&dmabuf->lock);
> >+      INIT_LIST_HEAD(&dmabuf->attachments);
> >
> >       if (!resv) {
> >-              resv = (struct dma_resv *)&dmabuf[1];
> >-              dma_resv_init(resv);
> >+              dmabuf->resv = (struct dma_resv *)&dmabuf[1];
> >+              dma_resv_init(dmabuf->resv);
> >+      } else {
> >+              dmabuf->resv = resv;
> >       }
> >-      dmabuf->resv = resv;
> >
> >-      file = dma_buf_getfile(dmabuf, exp_info->flags);
> >-      if (IS_ERR(file)) {
> >-              ret = PTR_ERR(file);
> >+      ret = dma_buf_stats_setup(dmabuf, file);
> >+      if (ret)
> >               goto err_dmabuf;
> >-      }
> >
> >+      file->private_data = dmabuf;
> >+      file->f_path.dentry->d_fsdata = dmabuf;
> >       dmabuf->file = file;
> >
> >-      mutex_init(&dmabuf->lock);
> >-      INIT_LIST_HEAD(&dmabuf->attachments);
> >-
> >       mutex_lock(&db_list.lock);
> >       list_add(&dmabuf->list_node, &db_list.head);
> >       mutex_unlock(&db_list.lock);
> >
> >-      ret = dma_buf_stats_setup(dmabuf);
> >-      if (ret)
> >-              goto err_sysfs;
> >-
> >       return dmabuf;
> >
> >-err_sysfs:
> >-      /*
> >-       * Set file->f_path.dentry->d_fsdata to NULL so that when
> >-       * dma_buf_release() gets invoked by dentry_ops, it exits
> >-       * early before calling the release() dma_buf op.
> >-       */
> >-      file->f_path.dentry->d_fsdata = NULL;
> >-      fput(file);
> > err_dmabuf:
> >+      if (!resv)
> >+              dma_resv_fini(dmabuf->resv);
> >       kfree(dmabuf);
> >+err_file:
> >+      fput(file);
> > err_module:
> >       module_put(exp_info->owner);
> >       return ERR_PTR(ret);
> >--
> >2.34.1
>


More information about the dri-devel mailing list