drm: Prune GEM vma entries
Hook the GEM vm open/close ops into the generic drm vm open/close so that the private vma entries are created and destroy appropriately. Fixes the leak of the drm_vma_entries during the lifetime of the filp. Reported-by: Matt Mackall <mpm@selenic.com> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
73758a5d51
commit
31dfbc9392
|
@ -528,6 +528,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
|
||||||
struct drm_gem_object *obj = vma->vm_private_data;
|
struct drm_gem_object *obj = vma->vm_private_data;
|
||||||
|
|
||||||
drm_gem_object_reference(obj);
|
drm_gem_object_reference(obj);
|
||||||
|
|
||||||
|
mutex_lock(&obj->dev->struct_mutex);
|
||||||
|
drm_vm_open_locked(vma);
|
||||||
|
mutex_unlock(&obj->dev->struct_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_gem_vm_open);
|
EXPORT_SYMBOL(drm_gem_vm_open);
|
||||||
|
|
||||||
|
@ -535,7 +539,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct drm_gem_object *obj = vma->vm_private_data;
|
struct drm_gem_object *obj = vma->vm_private_data;
|
||||||
|
|
||||||
drm_gem_object_unreference_unlocked(obj);
|
mutex_lock(&obj->dev->struct_mutex);
|
||||||
|
drm_vm_close_locked(vma);
|
||||||
|
drm_gem_object_unreference(obj);
|
||||||
|
mutex_unlock(&obj->dev->struct_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_gem_vm_close);
|
EXPORT_SYMBOL(drm_gem_vm_close);
|
||||||
|
|
||||||
|
|
|
@ -433,6 +433,25 @@ static void drm_vm_open(struct vm_area_struct *vma)
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drm_vm_close_locked(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
struct drm_file *priv = vma->vm_file->private_data;
|
||||||
|
struct drm_device *dev = priv->minor->dev;
|
||||||
|
struct drm_vma_entry *pt, *temp;
|
||||||
|
|
||||||
|
DRM_DEBUG("0x%08lx,0x%08lx\n",
|
||||||
|
vma->vm_start, vma->vm_end - vma->vm_start);
|
||||||
|
atomic_dec(&dev->vma_count);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
|
||||||
|
if (pt->vma == vma) {
|
||||||
|
list_del(&pt->head);
|
||||||
|
kfree(pt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \c close method for all virtual memory types.
|
* \c close method for all virtual memory types.
|
||||||
*
|
*
|
||||||
|
@ -445,20 +464,9 @@ static void drm_vm_close(struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct drm_file *priv = vma->vm_file->private_data;
|
struct drm_file *priv = vma->vm_file->private_data;
|
||||||
struct drm_device *dev = priv->minor->dev;
|
struct drm_device *dev = priv->minor->dev;
|
||||||
struct drm_vma_entry *pt, *temp;
|
|
||||||
|
|
||||||
DRM_DEBUG("0x%08lx,0x%08lx\n",
|
|
||||||
vma->vm_start, vma->vm_end - vma->vm_start);
|
|
||||||
atomic_dec(&dev->vma_count);
|
|
||||||
|
|
||||||
mutex_lock(&dev->struct_mutex);
|
mutex_lock(&dev->struct_mutex);
|
||||||
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
|
drm_vm_close_locked(vma);
|
||||||
if (pt->vma == vma) {
|
|
||||||
list_del(&pt->head);
|
|
||||||
kfree(pt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1175,6 +1175,7 @@ extern int drm_release(struct inode *inode, struct file *filp);
|
||||||
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
|
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||||
extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
|
extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
|
||||||
extern void drm_vm_open_locked(struct vm_area_struct *vma);
|
extern void drm_vm_open_locked(struct vm_area_struct *vma);
|
||||||
|
extern void drm_vm_close_locked(struct vm_area_struct *vma);
|
||||||
extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
|
extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
|
||||||
extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
|
extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
|
||||||
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
|
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
|
||||||
|
|
Loading…
Reference in New Issue