Fix crash when dropping filesystem caches (#649871)

This commit is contained in:
Chuck Ebbert 2011-02-24 14:12:44 -05:00
parent fbc978be69
commit a3c890edbe
2 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,107 @@
From 39b4d07aa3583ceefe73622841303a0a3e942ca1 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Thu, 30 Sep 2010 09:10:26 +0100
Subject: drm: Hold the mutex when dropping the last GEM reference (v2)
From: Chris Wilson <chris@chris-wilson.co.uk>
commit 39b4d07aa3583ceefe73622841303a0a3e942ca1 upstream.
In order to be fully threadsafe we need to check that the drm_gem_object
refcount is still 0 after acquiring the mutex in order to call the free
function. Otherwise, we may encounter scenarios like:
Thread A: Thread B:
drm_gem_close
unreference_unlocked
kref_put mutex_lock
... i915_gem_evict
... kref_get -> BUG
... i915_gem_unbind
... kref_put
... i915_gem_object_free
... mutex_unlock
mutex_lock
i915_gem_object_free -> BUG
i915_gem_object_unbind
kfree
mutex_unlock
Note that no driver is currently using the free_unlocked vfunc and it is
scheduled for removal, hasten that process.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=30454
Reported-and-Tested-by: Magnus Kessler <Magnus.Kessler@gmx.net>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/gpu/drm/drm_gem.c | 22 ----------------------
include/drm/drmP.h | 10 ++++++----
2 files changed, 6 insertions(+), 26 deletions(-)
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -451,28 +451,6 @@ drm_gem_object_free(struct kref *kref)
}
EXPORT_SYMBOL(drm_gem_object_free);
-/**
- * Called after the last reference to the object has been lost.
- * Must be called without holding struct_mutex
- *
- * Frees the object
- */
-void
-drm_gem_object_free_unlocked(struct kref *kref)
-{
- struct drm_gem_object *obj = (struct drm_gem_object *) kref;
- struct drm_device *dev = obj->dev;
-
- if (dev->driver->gem_free_object_unlocked != NULL)
- dev->driver->gem_free_object_unlocked(obj);
- else if (dev->driver->gem_free_object != NULL) {
- mutex_lock(&dev->struct_mutex);
- dev->driver->gem_free_object(obj);
- mutex_unlock(&dev->struct_mutex);
- }
-}
-EXPORT_SYMBOL(drm_gem_object_free_unlocked);
-
static void drm_gem_object_ref_bug(struct kref *list_kref)
{
BUG();
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -802,7 +802,6 @@ struct drm_driver {
*/
int (*gem_init_object) (struct drm_gem_object *obj);
void (*gem_free_object) (struct drm_gem_object *obj);
- void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
/* vga arb irq handler */
void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1430,7 +1429,6 @@ int drm_gem_init(struct drm_device *dev)
void drm_gem_destroy(struct drm_device *dev);
void drm_gem_object_release(struct drm_gem_object *obj);
void drm_gem_object_free(struct kref *kref);
-void drm_gem_object_free_unlocked(struct kref *kref);
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
size_t size);
int drm_gem_object_init(struct drm_device *dev,
@@ -1456,8 +1454,12 @@ drm_gem_object_unreference(struct drm_ge
static inline void
drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
{
- if (obj != NULL)
- kref_put(&obj->refcount, drm_gem_object_free_unlocked);
+ if (obj != NULL) {
+ struct drm_device *dev = obj->dev;
+ mutex_lock(&dev->struct_mutex);
+ kref_put(&obj->refcount, drm_gem_object_free);
+ mutex_unlock(&dev->struct_mutex);
+ }
}
int drm_gem_handle_create(struct drm_file *file_priv,

View File

@ -890,6 +890,9 @@ Patch13950: sunrpc-kernel-panic-when-mount-nfsv4.patch
# rhbz#650151
Patch13951: bridge-fix-mglist-corruption-that-leads-to-memory-corruption.patch
# rhbz#649871
Patch13952: drm-hold-the-mutex-when-dropping-the-last-gem-reference-v2.patch
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@ -1692,6 +1695,9 @@ ApplyPatch sunrpc-kernel-panic-when-mount-nfsv4.patch
# rhbz#650151
ApplyPatch bridge-fix-mglist-corruption-that-leads-to-memory-corruption.patch
# rhbz#649871
ApplyPatch drm-hold-the-mutex-when-dropping-the-last-gem-reference-v2.patch
# END OF PATCH APPLICATIONS
%endif
@ -2312,6 +2318,9 @@ fi
%kernel_variant_files %{with_pae_debug} PAEdebug
%changelog
* Thu Feb 24 2011 Chuck Ebbert <cebbert@redhat.com>
- Fix crash when dropping filesystem caches (#649871)
* Mon Feb 14 2011 Kyle McMartin <kmcmartin@redhat.com> 2.6.34.8-68
- Backport commits from longterm-2.6.35.y to 'fix' Intel Sandy Bridge
chipsets. (Requested by Intel folks.)