Continue unloading shmem_sg_alloc_table by placing reading
folios and shrink call into a new helper.
Make the loop a bit more reader-friendly by removing iteration
over a structure and replacing it with a do-while loop.

Signed-off-by: Krzysztof Karas <[email protected]>
---
v3:
 * Split refactoring and put it after the fix in shmem folio
  counting suggested by Andi.
 * Use do-while loop suggested by Robin. 

 drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 102 ++++++++++++----------
 1 file changed, 55 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c 
b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 4a61b012fb6f..7c8de8fe0a22 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -78,6 +78,55 @@ static int validate_size(size_t size, unsigned int 
page_count,
        return 0;
 }
 
+static struct folio *shmem_shrink_get_folio(struct address_space *mapping,
+                                           unsigned long folio_index,
+                                           gfp_t gfp, unsigned int page_count,
+                                           struct drm_i915_private *i915)
+{
+       struct folio *folio = NULL;
+       unsigned int retries = 2;
+
+       do {
+               cond_resched();
+               folio = shmem_read_folio_gfp(mapping, folio_index, gfp);
+               if (IS_ERR(folio)) {
+                       i915_gem_shrink(NULL, i915, 2 * page_count, NULL,
+                                       I915_SHRINK_BOUND | 
I915_SHRINK_UNBOUND);
+
+                       /*
+                        * 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.
+                        *
+                        * However, since graphics tend to be disposable,
+                        * defer the oom here by reporting the ENOMEM back
+                        * to userspace.
+                        *
+                        * Reclaim and warn, but no oom.
+                        */
+                       gfp = mapping_gfp_mask(mapping);
+
+                       /*
+                        * 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
+                        * only waits for kswapd when under allocation
+                        * congestion. So as a result __GFP_RECLAIM is
+                        * unreliable and fails to actually reclaim our
+                        * dirty pages -- unless you try over and over
+                        * again with !__GFP_NORETRY. However, we still
+                        * want to fail this allocation rather than
+                        * trigger the out-of-memory killer and for
+                        * this we want __GFP_RETRY_MAYFAIL.
+                        */
+                       gfp |= __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
+               }
+       } while (IS_ERR(folio) && --retries);
+
+       return folio;
+}
+
 int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st,
                         size_t size, struct intel_memory_region *mr,
                         struct address_space *mapping,
@@ -117,57 +166,16 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, 
struct sg_table *st,
        for (i = 0; i < page_count; i++) {
                unsigned long folio_page_index = 0;
                unsigned long nr_pages;
-               const unsigned int shrink[] = {
-                       I915_SHRINK_BOUND | I915_SHRINK_UNBOUND,
-                       0,
-               }, *s = shrink;
                gfp_t gfp = noreclaim;
 
                /* Grab the next folio if we exhausted the current one. */
                if (!i || i > folio_end) {
-                       do {
-                               cond_resched();
-                               folio = shmem_read_folio_gfp(mapping, i, gfp);
-                               if (!IS_ERR(folio))
-                                       break;
-
-                               if (!*s) {
-                                       ret = PTR_ERR(folio);
-                                       goto err_sg;
-                               }
-
-                               i915_gem_shrink(NULL, i915, 2 * page_count, 
NULL, *s++);
-
-                               /*
-                               * 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.
-                               *
-                               * However, since graphics tend to be disposable,
-                               * defer the oom here by reporting the ENOMEM 
back
-                               * to userspace.
-                               */
-                               if (!*s) {
-                                       /* reclaim and warn, but no oom */
-                                       gfp = mapping_gfp_mask(mapping);
-
-                                       /*
-                                        * 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
-                                        * only waits for kswapd when under 
allocation
-                                        * congestion. So as a result 
__GFP_RECLAIM is
-                                        * unreliable and fails to actually 
reclaim our
-                                        * dirty pages -- unless you try over 
and over
-                                        * again with !__GFP_NORETRY. However, 
we still
-                                        * want to fail this allocation rather 
than
-                                        * trigger the out-of-memory killer and 
for
-                                        * this we want __GFP_RETRY_MAYFAIL.
-                                        */
-                                       gfp |= __GFP_RETRY_MAYFAIL | 
__GFP_NOWARN;
-                               }
-                       } while (1);
+                       folio = shmem_shrink_get_folio(mapping, i, gfp,
+                                                      page_count, i915);
+                       if (IS_ERR(folio)) {
+                               ret = PTR_ERR(folio);
+                               goto err_sg;
+                       }
 
                        folio_start = folio_pgoff(folio);
                        folio_end = folio_start + folio_nr_pages(folio) - 1;
-- 
2.34.1

Reply via email to