Commit 7273c2b1 authored by Oleksandr Andrushchenko's avatar Oleksandr Andrushchenko Committed by Greg Kroah-Hartman

xen/gntdev: Do not destroy context while dma-bufs are in use

[ Upstream commit fa13e665 ]

If there are exported DMA buffers which are still in use and
grant device is closed by either normal user-space close or by
a signal this leads to the grant device context to be destroyed,
thus making it not possible to correctly destroy those exported
buffers when they are returned back to gntdev and makes the module
crash:

[  339.617540] [<ffff00000854c0d8>] dmabuf_exp_ops_release+0x40/0xa8
[  339.617560] [<ffff00000867a6e8>] dma_buf_release+0x60/0x190
[  339.617577] [<ffff0000082211f0>] __fput+0x88/0x1d0
[  339.617589] [<ffff000008221394>] ____fput+0xc/0x18
[  339.617607] [<ffff0000080ed4e4>] task_work_run+0x9c/0xc0
[  339.617622] [<ffff000008089714>] do_notify_resume+0xfc/0x108

Fix this by referencing gntdev on each DMA buffer export and
unreferencing on buffer release.
Signed-off-by: default avatarOleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Reviewed-by: Boris Ostrovsky@oracle.com>
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent e9cd7f54
...@@ -80,6 +80,12 @@ struct gntdev_dmabuf_priv { ...@@ -80,6 +80,12 @@ struct gntdev_dmabuf_priv {
struct list_head imp_list; struct list_head imp_list;
/* This is the lock which protects dma_buf_xxx lists. */ /* This is the lock which protects dma_buf_xxx lists. */
struct mutex lock; struct mutex lock;
/*
* We reference this file while exporting dma-bufs, so
* the grant device context is not destroyed while there are
* external users alive.
*/
struct file *filp;
}; };
/* DMA buffer export support. */ /* DMA buffer export support. */
...@@ -311,6 +317,7 @@ static void dmabuf_exp_release(struct kref *kref) ...@@ -311,6 +317,7 @@ static void dmabuf_exp_release(struct kref *kref)
dmabuf_exp_wait_obj_signal(gntdev_dmabuf->priv, gntdev_dmabuf); dmabuf_exp_wait_obj_signal(gntdev_dmabuf->priv, gntdev_dmabuf);
list_del(&gntdev_dmabuf->next); list_del(&gntdev_dmabuf->next);
fput(gntdev_dmabuf->priv->filp);
kfree(gntdev_dmabuf); kfree(gntdev_dmabuf);
} }
...@@ -423,6 +430,7 @@ static int dmabuf_exp_from_pages(struct gntdev_dmabuf_export_args *args) ...@@ -423,6 +430,7 @@ static int dmabuf_exp_from_pages(struct gntdev_dmabuf_export_args *args)
mutex_lock(&args->dmabuf_priv->lock); mutex_lock(&args->dmabuf_priv->lock);
list_add(&gntdev_dmabuf->next, &args->dmabuf_priv->exp_list); list_add(&gntdev_dmabuf->next, &args->dmabuf_priv->exp_list);
mutex_unlock(&args->dmabuf_priv->lock); mutex_unlock(&args->dmabuf_priv->lock);
get_file(gntdev_dmabuf->priv->filp);
return 0; return 0;
fail: fail:
...@@ -834,7 +842,7 @@ long gntdev_ioctl_dmabuf_imp_release(struct gntdev_priv *priv, ...@@ -834,7 +842,7 @@ long gntdev_ioctl_dmabuf_imp_release(struct gntdev_priv *priv,
return dmabuf_imp_release(priv->dmabuf_priv, op.fd); return dmabuf_imp_release(priv->dmabuf_priv, op.fd);
} }
struct gntdev_dmabuf_priv *gntdev_dmabuf_init(void) struct gntdev_dmabuf_priv *gntdev_dmabuf_init(struct file *filp)
{ {
struct gntdev_dmabuf_priv *priv; struct gntdev_dmabuf_priv *priv;
...@@ -847,6 +855,8 @@ struct gntdev_dmabuf_priv *gntdev_dmabuf_init(void) ...@@ -847,6 +855,8 @@ struct gntdev_dmabuf_priv *gntdev_dmabuf_init(void)
INIT_LIST_HEAD(&priv->exp_wait_list); INIT_LIST_HEAD(&priv->exp_wait_list);
INIT_LIST_HEAD(&priv->imp_list); INIT_LIST_HEAD(&priv->imp_list);
priv->filp = filp;
return priv; return priv;
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
struct gntdev_dmabuf_priv; struct gntdev_dmabuf_priv;
struct gntdev_priv; struct gntdev_priv;
struct gntdev_dmabuf_priv *gntdev_dmabuf_init(void); struct gntdev_dmabuf_priv *gntdev_dmabuf_init(struct file *filp);
void gntdev_dmabuf_fini(struct gntdev_dmabuf_priv *priv); void gntdev_dmabuf_fini(struct gntdev_dmabuf_priv *priv);
......
...@@ -600,7 +600,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) ...@@ -600,7 +600,7 @@ static int gntdev_open(struct inode *inode, struct file *flip)
mutex_init(&priv->lock); mutex_init(&priv->lock);
#ifdef CONFIG_XEN_GNTDEV_DMABUF #ifdef CONFIG_XEN_GNTDEV_DMABUF
priv->dmabuf_priv = gntdev_dmabuf_init(); priv->dmabuf_priv = gntdev_dmabuf_init(flip);
if (IS_ERR(priv->dmabuf_priv)) { if (IS_ERR(priv->dmabuf_priv)) {
ret = PTR_ERR(priv->dmabuf_priv); ret = PTR_ERR(priv->dmabuf_priv);
kfree(priv); kfree(priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment