Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/ttm: Avoid memory allocation from shrinker functions.

Andrew Morton wrote:
> On Wed, 12 Nov 2014 13:08:55 +0900 Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> wrote:
>
> > Andrew Morton wrote:
> > > Poor ttm guys - this is a bit of a trap we set for them.
> >
> > Commit a91576d7916f6cce ("drm/ttm: Pass GFP flags in order to avoid deadlock.")
> > changed to use sc->gfp_mask rather than GFP_KERNEL.
> >
> > - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
> > - GFP_KERNEL);
> > + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
> >
> > But this bug is caused by sc->gfp_mask containing some flags which are not
> > in GFP_KERNEL, right? Then, I think
> >
> > - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
> > + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp & GFP_KERNEL);
> >
> > would hide this bug.
> >
> > But I think we should use GFP_ATOMIC (or drop __GFP_WAIT flag)
>
> Well no - ttm_page_pool_free() should stop calling kmalloc altogether.
> Just do
>
> struct page *pages_to_free[16];
>
> and rework the code to free 16 pages at a time. Easy.

Well, ttm code wants to process 512 pages at a time for performance.
Memory footprint increased by 512 * sizeof(struct page *) buffer is
only 4096 bytes. What about using static buffer like below?
----------
>From d3cb5393c9c8099d6b37e769f78c31af1541fe8c Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: Thu, 13 Nov 2014 22:21:54 +0900
Subject: [PATCH] drm/ttm: Avoid memory allocation from shrinker functions.

Commit a91576d7916f6cce ("drm/ttm: Pass GFP flags in order to avoid
deadlock.") caused BUG_ON() due to sc->gfp_mask containing flags
which are not in GFP_KERNEL.

https://bugzilla.kernel.org/show_bug.cgi?id=87891

Changing from sc->gfp_mask to (sc->gfp_mask & GFP_KERNEL) would
avoid the BUG_ON(), but avoiding memory allocation from shrinker
function is better and reliable fix.

Shrinker function is already serialized by global lock, and
clean up function is called after shrinker function is unregistered.
Thus, we can use static buffer when called from shrinker function
and clean up function.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: stable <stable@kernel.org> [2.6.35+]
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Tetsuo Handa and committed by
Dave Airlie
881fdaa5 2b0a3c40

+30 -21
+15 -11
drivers/gpu/drm/ttm/ttm_page_alloc.c
··· 297 297 * 298 298 * @pool: to free the pages from 299 299 * @free_all: If set to true will free all pages in pool 300 - * @gfp: GFP flags. 300 + * @use_static: Safe to use static buffer 301 301 **/ 302 302 static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, 303 - gfp_t gfp) 303 + bool use_static) 304 304 { 305 + static struct page *static_buf[NUM_PAGES_TO_ALLOC]; 305 306 unsigned long irq_flags; 306 307 struct page *p; 307 308 struct page **pages_to_free; ··· 312 311 if (NUM_PAGES_TO_ALLOC < nr_free) 313 312 npages_to_free = NUM_PAGES_TO_ALLOC; 314 313 315 - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); 314 + if (use_static) 315 + pages_to_free = static_buf; 316 + else 317 + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), 318 + GFP_KERNEL); 316 319 if (!pages_to_free) { 317 320 pr_err("Failed to allocate memory for pool free operation\n"); 318 321 return 0; ··· 379 374 if (freed_pages) 380 375 ttm_pages_put(pages_to_free, freed_pages); 381 376 out: 382 - kfree(pages_to_free); 377 + if (pages_to_free != static_buf) 378 + kfree(pages_to_free); 383 379 return nr_free; 384 380 } 385 381 ··· 388 382 * Callback for mm to request pool to reduce number of page held. 389 383 * 390 384 * XXX: (dchinner) Deadlock warning! 391 - * 392 - * We need to pass sc->gfp_mask to ttm_page_pool_free(). 393 385 * 394 386 * This code is crying out for a shrinker per pool.... 395 387 */ ··· 411 407 if (shrink_pages == 0) 412 408 break; 413 409 pool = &_manager->pools[(i + pool_offset)%NUM_POOLS]; 414 - shrink_pages = ttm_page_pool_free(pool, nr_free, 415 - sc->gfp_mask); 410 + /* OK to use static buffer since global mutex is held. */ 411 + shrink_pages = ttm_page_pool_free(pool, nr_free, true); 416 412 freed += nr_free - shrink_pages; 417 413 } 418 414 mutex_unlock(&lock); ··· 714 710 } 715 711 spin_unlock_irqrestore(&pool->lock, irq_flags); 716 712 if (npages) 717 - ttm_page_pool_free(pool, npages, GFP_KERNEL); 713 + ttm_page_pool_free(pool, npages, false); 718 714 } 719 715 720 716 /* ··· 853 849 pr_info("Finalizing pool allocator\n"); 854 850 ttm_pool_mm_shrink_fini(_manager); 855 851 852 + /* OK to use static buffer since global mutex is no longer used. */ 856 853 for (i = 0; i < NUM_POOLS; ++i) 857 - ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, 858 - GFP_KERNEL); 854 + ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, true); 859 855 860 856 kobject_put(&_manager->kobj); 861 857 _manager = NULL;
+15 -10
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
··· 411 411 * 412 412 * @pool: to free the pages from 413 413 * @nr_free: If set to true will free all pages in pool 414 - * @gfp: GFP flags. 414 + * @use_static: Safe to use static buffer 415 415 **/ 416 416 static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, 417 - gfp_t gfp) 417 + bool use_static) 418 418 { 419 + static struct page *static_buf[NUM_PAGES_TO_ALLOC]; 419 420 unsigned long irq_flags; 420 421 struct dma_page *dma_p, *tmp; 421 422 struct page **pages_to_free; ··· 433 432 npages_to_free, nr_free); 434 433 } 435 434 #endif 436 - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); 435 + if (use_static) 436 + pages_to_free = static_buf; 437 + else 438 + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), 439 + GFP_KERNEL); 437 440 438 441 if (!pages_to_free) { 439 442 pr_err("%s: Failed to allocate memory for pool free operation\n", ··· 507 502 if (freed_pages) 508 503 ttm_dma_pages_put(pool, &d_pages, pages_to_free, freed_pages); 509 504 out: 510 - kfree(pages_to_free); 505 + if (pages_to_free != static_buf) 506 + kfree(pages_to_free); 511 507 return nr_free; 512 508 } 513 509 ··· 537 531 if (pool->type != type) 538 532 continue; 539 533 /* Takes a spinlock.. */ 540 - ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL); 534 + /* OK to use static buffer since global mutex is held. */ 535 + ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, true); 541 536 WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); 542 537 /* This code path is called after _all_ references to the 543 538 * struct device has been dropped - so nobody should be ··· 993 986 994 987 /* shrink pool if necessary (only on !is_cached pools)*/ 995 988 if (npages) 996 - ttm_dma_page_pool_free(pool, npages, GFP_KERNEL); 989 + ttm_dma_page_pool_free(pool, npages, false); 997 990 ttm->state = tt_unpopulated; 998 991 } 999 992 EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); ··· 1002 995 * Callback for mm to request pool to reduce number of page held. 1003 996 * 1004 997 * XXX: (dchinner) Deadlock warning! 1005 - * 1006 - * We need to pass sc->gfp_mask to ttm_dma_page_pool_free(). 1007 998 * 1008 999 * I'm getting sadder as I hear more pathetical whimpers about needing per-pool 1009 1000 * shrinkers ··· 1035 1030 if (++idx < pool_offset) 1036 1031 continue; 1037 1032 nr_free = shrink_pages; 1038 - shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, 1039 - sc->gfp_mask); 1033 + /* OK to use static buffer since global mutex is held. */ 1034 + shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, true); 1040 1035 freed += nr_free - shrink_pages; 1041 1036 1042 1037 pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n",