Message ID | 1379932951-9089-1-git-send-email-inki.dae@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Please, ignore this patch. This patch has still some problems. I will post it later. Thanks, Inki Dae > -----Original Message----- > From: Inki Dae [mailto:inki.dae@samsung.com] > Sent: Monday, September 23, 2013 7:43 PM > To: airlied@linux.ie; dri-devel@lists.freedesktop.org > Cc: Inki Dae; Kyungmin Park > Subject: [PATCH] drm/exynos: fix deadlock issue at mmap > > This patch fixes the deadlock issue when another process requested > mmap system call. > > This issue can incur the deadlock if another process sharing the same > file called mmap system call between ->f_op pointer chaning and restoring. > > So this patch calls down_write(&mm->mmap_sem) before do_mmap_pgoff > call and then up_write(&mm->mmap_sem) after do_mmap_pg_off call > so that when another process called mmap system call, the process > can wait for up_write() call until the ->f_op pointer is restored. > > Signed-off-by: Inki Dae <inki.dae@samsung.com> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> > --- > drivers/gpu/drm/exynos/exynos_drm_gem.c | 20 ++++++++++++++++++-- > 1 file changed, 18 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c > b/drivers/gpu/drm/exynos/exynos_drm_gem.c > index 49f9cd2..779c2d7 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c > @@ -13,6 +13,7 @@ > #include <drm/drm_vma_manager.h> > > #include <linux/shmem_fs.h> > +#include <linux/security.h> > #include <drm/exynos_drm.h> > > #include "exynos_drm_drv.h" > @@ -420,6 +421,7 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, > void *data, > { > struct drm_exynos_gem_mmap *args = data; > struct drm_gem_object *obj; > + struct mm_struct *mm = current->mm; > unsigned long addr; > > if (!(dev->driver->driver_features & DRIVER_GEM)) { > @@ -433,6 +435,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, > void *data, > return -EINVAL; > } > > + down_write(&mm->mmap_sem); > + > /* > * We have to use gem object and its fops for specific mmaper, > * but vm_mmap() can deliver only filp. So we have to change > @@ -457,8 +461,17 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, > void *data, > */ > file_priv->filp->private_data = obj; > > - addr = vm_mmap(file_priv->filp, 0, args->size, > - PROT_READ | PROT_WRITE, MAP_SHARED, 0); > + addr = security_mmap_file(file_priv->filp, PROT_READ | PROT_WRITE, > + MAP_SHARED); > + if (!addr) { > + unsigned long populate; > + > + addr = do_mmap_pgoff(file_priv->filp, 0, args->size, > + PROT_READ | PROT_WRITE, > + MAP_SHARED, 0, &populate); > + if (populate) > + mm_populate(addr, populate); > + } > > drm_gem_object_unreference(obj); > > @@ -469,10 +482,13 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, > void *data, > file_priv->filp->private_data = file_priv; > } > mutex_unlock(&dev->struct_mutex); > + up_write(&mm->mmap_sem); > + > return (int)addr; > } > > mutex_unlock(&dev->struct_mutex); > + up_write(&mm->mmap_sem); > > args->mapped = addr; > > -- > 1.7.9.5
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 49f9cd2..779c2d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -13,6 +13,7 @@ #include <drm/drm_vma_manager.h> #include <linux/shmem_fs.h> +#include <linux/security.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h" @@ -420,6 +421,7 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, { struct drm_exynos_gem_mmap *args = data; struct drm_gem_object *obj; + struct mm_struct *mm = current->mm; unsigned long addr; if (!(dev->driver->driver_features & DRIVER_GEM)) { @@ -433,6 +435,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, return -EINVAL; } + down_write(&mm->mmap_sem); + /* * We have to use gem object and its fops for specific mmaper, * but vm_mmap() can deliver only filp. So we have to change @@ -457,8 +461,17 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, */ file_priv->filp->private_data = obj; - addr = vm_mmap(file_priv->filp, 0, args->size, - PROT_READ | PROT_WRITE, MAP_SHARED, 0); + addr = security_mmap_file(file_priv->filp, PROT_READ | PROT_WRITE, + MAP_SHARED); + if (!addr) { + unsigned long populate; + + addr = do_mmap_pgoff(file_priv->filp, 0, args->size, + PROT_READ | PROT_WRITE, + MAP_SHARED, 0, &populate); + if (populate) + mm_populate(addr, populate); + } drm_gem_object_unreference(obj); @@ -469,10 +482,13 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, file_priv->filp->private_data = file_priv; } mutex_unlock(&dev->struct_mutex); + up_write(&mm->mmap_sem); + return (int)addr; } mutex_unlock(&dev->struct_mutex); + up_write(&mm->mmap_sem); args->mapped = addr;