drm/i915: Ratelimit request allocation under oom
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 12 Dec 2017 18:06:52 +0000 (18:06 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 13 Dec 2017 13:17:59 +0000 (13:17 +0000)
If we fail to allocate a request, we can reap the outstanding requests
and push them to the request's slab's freelist before trying again. This
forces us to ratelimit malicious clients that tie up all of the system
resources in requests, instead of causing a system-wide oom.

Testcase: igt/gem_shrink/execbuf1
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171212180652.22061-3-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_gem_request.c

index 4d5e2b7143826498db4f210d7daa40bcf0195e5b..59f023bb70157e73576d4ebd650a2aae57a9a3dd 100644 (file)
@@ -677,10 +677,21 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
         *
         * Do not use kmem_cache_zalloc() here!
         */
-       req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL);
-       if (!req) {
-               ret = -ENOMEM;
-               goto err_unreserve;
+       req = kmem_cache_alloc(dev_priv->requests,
+                              GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
+       if (unlikely(!req)) {
+               /* Ratelimit ourselves to prevent oom from malicious clients */
+               ret = i915_gem_wait_for_idle(dev_priv,
+                                            I915_WAIT_LOCKED |
+                                            I915_WAIT_INTERRUPTIBLE);
+               if (ret)
+                       goto err_unreserve;
+
+               req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL);
+               if (!req) {
+                       ret = -ENOMEM;
+                       goto err_unreserve;
+               }
        }
 
        req->timeline = i915_gem_context_lookup_timeline(ctx, engine);