浏览代码

drm/i915: Fix unsafe vma iteration in i915_drop_caches

When unbinding, there is a possibility that we drop the active reference
on the object, thereby freeing it. If that happens, we may destroy the
vm link as well as the object and vma. So iterate carefully.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Chris Wilson 11 年之前
父节点
当前提交
4ad72b7fad
共有 1 个文件被更改,包括 11 次插入6 次删除
  1. 11 6
      drivers/gpu/drm/i915/i915_debugfs.c

+ 11 - 6
drivers/gpu/drm/i915/i915_debugfs.c

@@ -3812,8 +3812,6 @@ i915_drop_caches_set(void *data, u64 val)
 	struct drm_device *dev = data;
 	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj, *next;
 	struct drm_i915_gem_object *obj, *next;
-	struct i915_address_space *vm;
-	struct i915_vma *vma, *x;
 	int ret;
 	int ret;
 
 
 	DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
 	DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
@@ -3834,16 +3832,23 @@ i915_drop_caches_set(void *data, u64 val)
 		i915_gem_retire_requests(dev);
 		i915_gem_retire_requests(dev);
 
 
 	if (val & DROP_BOUND) {
 	if (val & DROP_BOUND) {
-		list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
-			list_for_each_entry_safe(vma, x, &vm->inactive_list,
-						 mm_list) {
+		list_for_each_entry_safe(obj, next, &dev_priv->mm.bound_list,
+					 global_list) {
+			struct i915_vma *vma, *v;
+
+			ret = 0;
+			drm_gem_object_reference(&obj->base);
+			list_for_each_entry_safe(vma, v, &obj->vma_list, vma_link) {
 				if (vma->pin_count)
 				if (vma->pin_count)
 					continue;
 					continue;
 
 
 				ret = i915_vma_unbind(vma);
 				ret = i915_vma_unbind(vma);
 				if (ret)
 				if (ret)
-					goto unlock;
+					break;
 			}
 			}
+			drm_gem_object_unreference(&obj->base);
+			if (ret)
+				goto unlock;
 		}
 		}
 	}
 	}