diff mbox

drm/i915: Wait for the mutex whilst the reaper runs

Message ID 1349867250-22808-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Oct. 10, 2012, 11:07 a.m. UTC
If the system is forced to start kswapd to recover pages, the system is
very starved. Fortunately, kswapd is its own process context and can
wait for the mutex.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Chris Wilson Oct. 10, 2012, 3:21 p.m. UTC | #1
On Wed, 10 Oct 2012 12:07:30 +0100, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> If the system is forced to start kswapd to recover pages, the system is
> very starved. Fortunately, kswapd is its own process context and can
> wait for the mutex.

Note this doesn't survive inspection with lockdep due to dependency upon
pfmemalloc_wait in the direct reclaim path - that is, it is possible for
__GFP_FS allocations to wait indefinitely upon kswapd (who in turn may
be waiting for the dev->struct_mutex held by the direct reclaimer). As
we don't have complete control over all allocations made whilst holding
the struct_mutex, we can't control the gfp_t to avoid the deadlock.
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ff2ea2b..7108493 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4600,8 +4600,16 @@  i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
 	int nr_to_scan = sc->nr_to_scan;
 	int cnt;
 
-	if (!mutex_trylock(&dev->struct_mutex))
-		return 0;
+	/* Force reaping when kswapd runs and the system is starved of
+	 * free pages, Otherwise only opportunistically shrink our caches,
+	 * being wary of deadlocks.
+	 */
+	if (current_is_kswapd()) {
+		mutex_lock(&dev->struct_mutex);
+	} else {
+		if (!mutex_trylock(&dev->struct_mutex))
+			return 0;
+	}
 
 	if (nr_to_scan) {
 		nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);