Fix crash when dropping filesystem caches (#649871)
This commit is contained in:
parent
fbc978be69
commit
a3c890edbe
107
drm-hold-the-mutex-when-dropping-the-last-gem-reference-v2.patch
Normal file
107
drm-hold-the-mutex-when-dropping-the-last-gem-reference-v2.patch
Normal 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,
|
@ -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.)
|
||||
|
Loading…
Reference in New Issue
Block a user