drm/i915: Fix race in __i915_vma_remove_closed
authorKarol Herbst <kherbst@redhat.com>
Wed, 20 Apr 2022 09:57:20 +0000 (11:57 +0200)
committerTvrtko Ursulin <tvrtko.ursulin@intel.com>
Wed, 4 May 2022 15:22:13 +0000 (16:22 +0100)
i915_vma_reopen checked if the vma is closed before without taking the
lock. So multiple threads could attempt removing the vma.

Instead the lock needs to be taken before actually checking.

v2: move struct declaration

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v5.3+
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5732
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Fixes: 155ab8836caa ("drm/i915: Move object close under its own lock")
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220420095720.3331609-1-kherbst@redhat.com
drivers/gpu/drm/i915/i915_vma.c

index 3b6482f43d6a9c9f7765d0687decf00879fcfcad..79c286f85413bd0db78bf9c465fa919f810a47ed 100644 (file)
@@ -1610,17 +1610,17 @@ void i915_vma_close(struct i915_vma *vma)
 
 static void __i915_vma_remove_closed(struct i915_vma *vma)
 {
-       struct intel_gt *gt = vma->vm->gt;
-
-       spin_lock_irq(&gt->closed_lock);
        list_del_init(&vma->closed_link);
-       spin_unlock_irq(&gt->closed_lock);
 }
 
 void i915_vma_reopen(struct i915_vma *vma)
 {
+       struct intel_gt *gt = vma->vm->gt;
+
+       spin_lock_irq(&gt->closed_lock);
        if (i915_vma_is_closed(vma))
                __i915_vma_remove_closed(vma);
+       spin_unlock_irq(&gt->closed_lock);
 }
 
 static void force_unbind(struct i915_vma *vma)
@@ -1636,6 +1636,7 @@ static void force_unbind(struct i915_vma *vma)
 static void release_references(struct i915_vma *vma, bool vm_ddestroy)
 {
        struct drm_i915_gem_object *obj = vma->obj;
+       struct intel_gt *gt = vma->vm->gt;
 
        GEM_BUG_ON(i915_vma_is_active(vma));
 
@@ -1646,7 +1647,9 @@ static void release_references(struct i915_vma *vma, bool vm_ddestroy)
 
        spin_unlock(&obj->vma.lock);
 
+       spin_lock_irq(&gt->closed_lock);
        __i915_vma_remove_closed(vma);
+       spin_unlock_irq(&gt->closed_lock);
 
        if (vm_ddestroy)
                i915_vm_resv_put(vma->vm);