During exporting dma_buf, it can fail after dma_buf is exported. In this case, exported dma_buf should be release with putting. Also dma_buf_fd can be failed to get fd, but failure cases are not handled.
Error handling routine is not quite clean, so I send this patch set as RFC.
Seung-Woo Kim (1): drm/prime: reorder drm_prime_add_buf_handle and remove prototype
YoungJun Cho (2): drm/prime: fix to put an exported dma_buf for adding handle failure drm/prime: add return check for dma_buf_fd
drivers/gpu/drm/drm_prime.c | 79 +++++++++++++++++++++++++++--------------- 1 files changed, 51 insertions(+), 28 deletions(-)
From: YoungJun Cho yj44.cho@samsung.com
When drm_prime_add_buf_handle() returns failure for an exported dma_buf, the dma_buf was already allocated and its refcount was increased, so it needs to be put.
Signed-off-by: YoungJun Cho yj44.cho@samsung.com Signed-off-by: Seung-Woo Kim sw0312.kim@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/drm_prime.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 5b7b911..afff7c8 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -235,7 +235,7 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, ret = drm_prime_add_buf_handle(&file_priv->prime, obj->export_dma_buf, handle); if (ret) - goto out; + goto fail_put_dmabuf;
*prime_fd = dma_buf_fd(buf, flags); mutex_unlock(&file_priv->prime.lock); @@ -244,6 +244,12 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, out_have_obj: get_dma_buf(dmabuf); *prime_fd = dma_buf_fd(dmabuf, flags); + goto out; + +fail_put_dmabuf: + /* clear NOT to be checked when releasing dma_buf */ + obj->export_dma_buf = NULL; + dma_buf_put(buf); out: drm_gem_object_unreference_unlocked(obj); mutex_unlock(&file_priv->prime.lock);
Signed-off-by: Seung-Woo Kim sw0312.kim@samsung.com Signed-off-by: YoungJun Cho yj44.cho@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/drm_prime.c | 32 ++++++++++++++++---------------- 1 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index afff7c8..b3bb2fb 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -62,7 +62,22 @@ struct drm_prime_member { struct dma_buf *dma_buf; uint32_t handle; }; -static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle); + +static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, + struct dma_buf *dma_buf, uint32_t handle) +{ + struct drm_prime_member *member; + + member = kmalloc(sizeof(*member), GFP_KERNEL); + if (!member) + return -ENOMEM; + + get_dma_buf(dma_buf); + member->dma_buf = dma_buf; + member->handle = handle; + list_add(&member->entry, &prime_fpriv->head); + return 0; +}
static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction dir) @@ -498,21 +513,6 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) } EXPORT_SYMBOL(drm_prime_destroy_file_private);
-static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) -{ - struct drm_prime_member *member; - - member = kmalloc(sizeof(*member), GFP_KERNEL); - if (!member) - return -ENOMEM; - - get_dma_buf(dma_buf); - member->dma_buf = dma_buf; - member->handle = handle; - list_add(&member->entry, &prime_fpriv->head); - return 0; -} - int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle) { struct drm_prime_member *member;
From: YoungJun Cho yj44.cho@samsung.com
The dma_buf_fd() can return error when it fails to prepare fd, so the dma_buf needs to be put.
Signed-off-by: YoungJun Cho yj44.cho@samsung.com Signed-off-by: Seung-Woo Kim sw0312.kim@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com --- drivers/gpu/drm/drm_prime.c | 39 ++++++++++++++++++++++++++++----------- 1 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index b3bb2fb..24c801c 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -79,6 +79,21 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, return 0; }
+static void drm_prime_remove_buf_handle_locked( + struct drm_prime_file_private *prime_fpriv, + struct dma_buf *dma_buf) +{ + struct drm_prime_member *member, *safe; + + list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { + if (member->dma_buf == dma_buf) { + dma_buf_put(dma_buf); + list_del(&member->entry); + kfree(member); + } + } +} + static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, enum dma_data_direction dir) { @@ -252,15 +267,25 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, if (ret) goto fail_put_dmabuf;
- *prime_fd = dma_buf_fd(buf, flags); + ret = dma_buf_fd(buf, flags); + if (ret < 0) + goto fail_rm_handle; + + *prime_fd = ret; mutex_unlock(&file_priv->prime.lock); return 0;
out_have_obj: get_dma_buf(dmabuf); - *prime_fd = dma_buf_fd(dmabuf, flags); + ret = dma_buf_fd(dmabuf, flags); + if (ret < 0) + dma_buf_put(dmabuf); + else + *prime_fd = ret; goto out;
+fail_rm_handle: + drm_prime_remove_buf_handle_locked(&file_priv->prime, buf); fail_put_dmabuf: /* clear NOT to be checked when releasing dma_buf */ obj->export_dma_buf = NULL; @@ -529,16 +554,8 @@ EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) { - struct drm_prime_member *member, *safe; - mutex_lock(&prime_fpriv->lock); - list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { - if (member->dma_buf == dma_buf) { - dma_buf_put(dma_buf); - list_del(&member->entry); - kfree(member); - } - } + drm_prime_remove_buf_handle_locked(prime_fpriv, dma_buf); mutex_unlock(&prime_fpriv->lock); } EXPORT_SYMBOL(drm_prime_remove_buf_handle);
dri-devel@lists.freedesktop.org