提交 b47b30cc 编写于 作者: C Chris Wilson

drm/i915: Avoid might_fault during pwrite whilst holding our mutex

... and so prevent a potential circular reference:

  [ INFO: possible circular locking dependency detected ]
  2.6.37-rc1-uwe1+ #4
  -------------------------------------------------------
  Xorg/1401 is trying to acquire lock:
   (&mm->mmap_sem){++++++}, at: [<c01e4ddb>] might_fault+0x4b/0xa0

  but task is already holding lock:
   (&dev->struct_mutex){+.+.+.}, at: [<f869c3ac>]
  i915_mutex_lock_interruptible+0x3c/0x60 [i915]

  which lock already depends on the new lock.

When the locking around the pwrite ioctl was simplified, I did not spot
that the phys path never took any locks and so we introduced this
potential circular reference.
Reported-by: NUwe Helm <uwe.helm@googlemail.com>
Signed-off-by: NChris Wilson <chris@chris-wilson.co.uk>
上级 16a02cf0
...@@ -4878,17 +4878,24 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, ...@@ -4878,17 +4878,24 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
void *obj_addr; void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset;
int ret; char __user *user_data = (char __user *) (uintptr_t) args->data_ptr;
char __user *user_data;
user_data = (char __user *) (uintptr_t) args->data_ptr; DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size);
obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
ret = copy_from_user(obj_addr, user_data, args->size); unsigned long unwritten;
if (ret)
/* The physical object once assigned is fixed for the lifetime
* of the obj, so we can safely drop the lock and continue
* to access vaddr.
*/
mutex_unlock(&dev->struct_mutex);
unwritten = copy_from_user(vaddr, user_data, args->size);
mutex_lock(&dev->struct_mutex);
if (unwritten)
return -EFAULT; return -EFAULT;
}
drm_agp_chipset_flush(dev); drm_agp_chipset_flush(dev);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册