Continue unloading shmem_sg_alloc_table by placing reading folios and shrink call into a new helper. Make the code a bit more reader-friendly by removing moving over structure elements and replacing it with a sequence of instructions.
Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: Krzysztof Karas <[email protected]> --- v6: * switched to passing gfp by pointer, because in v5 the mask was local to the helper, so GEM_BUG_ON(gfp & __GFP_DMA32 && ...) checked a mask that was never used for the allocation; * dropped useless folio = NULL initialiser; * ran final checks with Claude Opus and added a tag. drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 103 ++++++++++++---------- 1 file changed, 56 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 3915633e52fd..0fa34a4ae466 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -79,6 +79,56 @@ static int validate_set_page_count(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; + + 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; + + /* Retry once after shrinking and gfp modification. */ + cond_resched(); + folio = shmem_read_folio_gfp(mapping, folio_index, *gfp); + } + + 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, @@ -120,57 +170,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; 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
