aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/ttm
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2014-08-03 07:01:10 -0400
committerDave Airlie <airlied@redhat.com>2014-08-04 20:53:18 -0400
commit22e71691fd54c637800d10816bbeba9cf132d218 (patch)
tree33fe0b7ce147361bdc7b32c7c8838c14796f8ac8 /drivers/gpu/drm/ttm
parent46c2df68f03a236b30808bba361f10900c88d95e (diff)
drm/ttm: Use mutex_trylock() to avoid deadlock inside shrinker functions.
I can observe that RHEL7 environment stalls with 100% CPU usage when a certain type of memory pressure is given. While the shrinker functions are called by shrink_slab() before the OOM killer is triggered, the stall lasts for many minutes. One of reasons of this stall is that ttm_dma_pool_shrink_count()/ttm_dma_pool_shrink_scan() are called and are blocked at mutex_lock(&_manager->lock). GFP_KERNEL allocation with _manager->lock held causes someone (including kswapd) to deadlock when these functions are called due to memory pressure. This patch changes "mutex_lock();" to "if (!mutex_trylock()) return ...;" in order to avoid deadlock. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: stable <stable@kernel.org> [3.3+] Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/ttm')
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc_dma.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index d8e59f7b58b2..524cc1a2c1fa 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -1014,7 +1014,8 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
1014 if (list_empty(&_manager->pools)) 1014 if (list_empty(&_manager->pools))
1015 return SHRINK_STOP; 1015 return SHRINK_STOP;
1016 1016
1017 mutex_lock(&_manager->lock); 1017 if (!mutex_trylock(&_manager->lock))
1018 return SHRINK_STOP;
1018 if (!_manager->npools) 1019 if (!_manager->npools)
1019 goto out; 1020 goto out;
1020 pool_offset = ++start_pool % _manager->npools; 1021 pool_offset = ++start_pool % _manager->npools;
@@ -1047,7 +1048,8 @@ ttm_dma_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
1047 struct device_pools *p; 1048 struct device_pools *p;
1048 unsigned long count = 0; 1049 unsigned long count = 0;
1049 1050
1050 mutex_lock(&_manager->lock); 1051 if (!mutex_trylock(&_manager->lock))
1052 return 0;
1051 list_for_each_entry(p, &_manager->pools, pools) 1053 list_for_each_entry(p, &_manager->pools, pools)
1052 count += p->pool->npages_free; 1054 count += p->pool->npages_free;
1053 mutex_unlock(&_manager->lock); 1055 mutex_unlock(&_manager->lock);