Messages in this thread Patch in this message |  | | | Date | Sun, 27 Nov 2005 15:21:08 -0800 | | From | Andrew Morton <> | | Subject | Re: 2.6.14 kswapd eating too much CPU |
| |
Marcelo Tosatti <marcelo.tosatti@cyclades.com> wrote: > > It does seem to scan SLABs intensively: >
It might be worth trying the below. Mainly for the debugging check.
From: Andrea Arcangeli <andrea@suse.de>
Greg Edwards found some deadlock in the icache shrinker.
I believe the major bug is that the VM is currently potentially setting nr = LONG_MAX before shrinking the icache (and the icache shrinker never returns -1, which means the api doesn't currently require shrinkers to return -1 when they're finished).
The below is the most obviously safe way I could address this problem (still untested).
This is not necessairly the way we want to fix it in mainline, but it at least shows what I believe to be the major cuplrit in the code (i.e. nr growing insane ;).
Signed-off-by: Andrea Arcangeli <andrea@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> --- mm/vmscan.c | 18 +++++++++++++++--- 1 files changed, 15 insertions(+), 3 deletions(-) diff -puN mm/vmscan.c~shrinker-nr-=-long_max-means-deadlock-for-icache mm/vmscan.c --- devel/mm/vmscan.c~shrinker-nr-=-long_max-means-deadlock-for-icache 2005-11-19 02:53:18.000000000 -0800 +++ devel-akpm/mm/vmscan.c 2005-11-19 03:00:25.000000000 -0800 @@ -201,13 +201,25 @@ static int shrink_slab(unsigned long sca list_for_each_entry(shrinker, &shrinker_list, list) { unsigned long long delta; unsigned long total_scan; + unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask); delta = (4 * scanned) / shrinker->seeks; - delta *= (*shrinker->shrinker)(0, gfp_mask); + delta *= max_pass; do_div(delta, lru_pages + 1); shrinker->nr += delta; - if (shrinker->nr < 0) - shrinker->nr = LONG_MAX; /* It wrapped! */ + if (shrinker->nr < 0) { + printk(KERN_ERR "%s: nr=%ld\n", + __FUNCTION__, shrinker->nr); + shrinker->nr = max_pass; + } + + /* + * Avoid risking looping forever due to too large nr value: + * never try to free more than twice the estimate number of + * freeable entries. + */ + if (shrinker->nr > max_pass * 2) + shrinker->nr = max_pass * 2; total_scan = shrinker->nr; shrinker->nr = 0; _ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|  |