drm/i915: Early rejection of buffer allocations larger than RAM
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 3 Sep 2018 08:33:36 +0000 (09:33 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 3 Sep 2018 11:02:04 +0000 (12:02 +0100)
We currently try to pin and allocate the whole buffer at a time. If that
object is larger than RAM, we will try to pin the whole of physical
memory, force the machine into oom, and then still fail the allocation.

If the request is obviously too large, error out early. We opt to do
this in the backend to make it easy to use alternate paths that do not
require the entire object pinned, or may easily handle proxy objects
that are larger than physical memory.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180903083337.13134-4-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_gem.c

index 625e07c..89834ce 100644 (file)
@@ -2533,13 +2533,21 @@ static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
        gfp_t noreclaim;
        int ret;
 
-       /* Assert that the object is not currently in any GPU domain. As it
+       /*
+        * Assert that the object is not currently in any GPU domain. As it
         * wasn't in the GTT, there shouldn't be any way it could have been in
         * a GPU cache
         */
        GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS);
        GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS);
 
+       /*
+        * If there's no chance of allocating enough pages for the whole
+        * object, bail early.
+        */
+       if (page_count > totalram_pages)
+               return -ENOMEM;
+
        st = kmalloc(sizeof(*st), GFP_KERNEL);
        if (st == NULL)
                return -ENOMEM;
@@ -2550,7 +2558,8 @@ rebuild_st:
                return -ENOMEM;
        }
 
-       /* Get the list of pages out of our struct file.  They'll be pinned
+       /*
+        * Get the list of pages out of our struct file.  They'll be pinned
         * at this point until we release them.
         *
         * Fail silently without starting the shrinker
@@ -2582,7 +2591,8 @@ rebuild_st:
                        i915_gem_shrink(dev_priv, 2 * page_count, NULL, *s++);
                        cond_resched();
 
-                       /* We've tried hard to allocate the memory by reaping
+                       /*
+                        * We've tried hard to allocate the memory by reaping
                         * our own buffer, now let the real VM do its job and
                         * go down in flames if truly OOM.
                         *
@@ -2594,7 +2604,8 @@ rebuild_st:
                                /* reclaim and warn, but no oom */
                                gfp = mapping_gfp_mask(mapping);
 
-                               /* Our bo are always dirty and so we require
+                               /*
+                                * Our bo are always dirty and so we require
                                 * kswapd to reclaim our pages (direct reclaim
                                 * does not effectively begin pageout of our
                                 * buffers on its own). However, direct reclaim
@@ -2638,7 +2649,8 @@ rebuild_st:
 
        ret = i915_gem_gtt_prepare_pages(obj, st);
        if (ret) {
-               /* DMA remapping failed? One possible cause is that
+               /*
+                * DMA remapping failed? One possible cause is that
                 * it could not reserve enough large entries, asking
                 * for PAGE_SIZE chunks instead may be helpful.
                 */
@@ -2672,7 +2684,8 @@ err_pages:
        sg_free_table(st);
        kfree(st);
 
-       /* shmemfs first checks if there is enough memory to allocate the page
+       /*
+        * shmemfs first checks if there is enough memory to allocate the page
         * and reports ENOSPC should there be insufficient, along with the usual
         * ENOMEM for a genuine allocation failure.
         *