[PATCH 2/3] drm/i915: Force kswapd to reclaim our request/object slabs

Chris Wilson chris at chris-wilson.co.uk
Fri Dec 29 12:28:14 UTC 2017

The core mm fails to reclaim from RCU deferred frees under mempressure.
This is particularly noticeable for ourselves when running igt on 32b
platforms are our RCU deferred free of requests (and their callbacks)
quickly drain the available GFP_KERNEL (lowmem) and are *not* recovered,
even under oom itself. Try to remedy the lost slabs by inserting an rcu
barrier and forcibly freeing our stale objects under kswapd.

The rcu_barrier() was removed in commit bd784b7cc41a ("drm/i915: Avoid
rcu_barrier() from reclaim paths (shrinker)") due to lock inversionof
cpuhp vs rcu, at that time. However, given that the core mm still lacks
RCU reclaim, we are still running into issues where our transient
requests can cause oom.

References: bd784b7cc41a ("drm/i915: Avoid rcu_barrier() from reclaim paths (shrinker)")
References: 0eafec6d3244 ("drm/i915: Enable lockless lookup of request tracking via RCU")
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
 drivers/gpu/drm/i915/i915_drv.c          |  2 +-
 drivers/gpu/drm/i915/i915_gem.c          |  2 +-
 drivers/gpu/drm/i915/i915_gem_shrinker.c | 10 ++++++++++
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6c8da9d20c33..069c308c0383 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -805,7 +805,7 @@ static int i915_workqueues_init(struct drm_i915_private *dev_priv)
 	 * so there is no point in running more than one instance of the
 	 * workqueue at any time.  Use an ordered one.
-	dev_priv->wq = alloc_ordered_workqueue("i915", 0);
+	dev_priv->wq = alloc_ordered_workqueue("i915", WQ_MEM_RECLAIM);
 	if (dev_priv->wq == NULL)
 		goto out_err;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ba9f67c256f4..4808011264ae 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4732,7 +4732,7 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head)
 	 * detour through a worker.
 	if (llist_add(&obj->freed, &i915->mm.free_list))
-		schedule_work(&i915->mm.free_work);
+		queue_work(i915->wq, &i915->mm.free_work);
 void i915_gem_free_object(struct drm_gem_object *gem_obj)
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 9029ed04879c..2f87c27fb2ac 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -382,6 +382,16 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 	shrinker_unlock(i915, unlock);
+	/*
+	 * XXX This is mighty incongruous, for are we not doing the core mm's
+	 * job in reclaiming RCU slabs and allocations? No matter, for the
+	 * time being, this is one of the few ways we can ensure that our
+	 * requests and objects, which we marked as SLAB_RECLAIM_ACCOUNT,
+	 * do actually get reclaimed under mempressure.
+	 */
+	if (current_is_kswapd())
+		i915_gem_drain_freed_objects(i915);
 	return sc->nr_scanned ? freed : SHRINK_STOP;

More information about the Intel-gfx-trybot mailing list