aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2009-06-16 18:33:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-16 22:47:45 -0400
commitfa5e084e43eb14c14942027e1e2e894aeed96097 (patch)
tree3e7ebf714858e8dd1de7042fd1ef62294a3ec20f /mm/vmscan.c
parent90afa5de6f3fa89a733861e843377302479fcf7e (diff)
vmscan: do not unconditionally treat zones that fail zone_reclaim() as full
On NUMA machines, the administrator can configure zone_reclaim_mode that is a more targetted form of direct reclaim. On machines with large NUMA distances for example, a zone_reclaim_mode defaults to 1 meaning that clean unmapped pages will be reclaimed if the zone watermarks are not being met. The problem is that zone_reclaim() failing at all means the zone gets marked full. This can cause situations where a zone is usable, but is being skipped because it has been considered full. Take a situation where a large tmpfs mount is occuping a large percentage of memory overall. The pages do not get cleaned or reclaimed by zone_reclaim(), but the zone gets marked full and the zonelist cache considers them not worth trying in the future. This patch makes zone_reclaim() return more fine-grained information about what occured when zone_reclaim() failued. The zone only gets marked full if it really is unreclaimable. If it's a case that the scan did not occur or if enough pages were not reclaimed with the limited reclaim_mode, then the zone is simply skipped. There is a side-effect to this patch. Currently, if zone_reclaim() successfully reclaimed SWAP_CLUSTER_MAX, an allocation attempt would go ahead. With this patch applied, zone watermarks are rechecked after zone_reclaim() does some work. This bug was introduced by commit 9276b1bc96a132f4068fdee00983c532f43d3a26 ("memory page_alloc zonelist caching speedup") way back in 2.6.19 when the zonelist_cache was introduced. It was not intended that zone_reclaim() aggressively consider the zone to be full when it failed as full direct reclaim can still be an option. Due to the age of the bug, it should be considered a -stable candidate. Signed-off-by: Mel Gorman <mel@csn.ul.ie> Reviewed-by: Wu Fengguang <fengguang.wu@intel.com> Reviewed-by: Rik van Riel <riel@redhat.com> Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Christoph Lameter <cl@linux-foundation.org> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 79a98d98ed33..16c82a868e2b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2492,16 +2492,16 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
2492 */ 2492 */
2493 if (zone_pagecache_reclaimable(zone) <= zone->min_unmapped_pages && 2493 if (zone_pagecache_reclaimable(zone) <= zone->min_unmapped_pages &&
2494 zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages) 2494 zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages)
2495 return 0; 2495 return ZONE_RECLAIM_FULL;
2496 2496
2497 if (zone_is_all_unreclaimable(zone)) 2497 if (zone_is_all_unreclaimable(zone))
2498 return 0; 2498 return ZONE_RECLAIM_FULL;
2499 2499
2500 /* 2500 /*
2501 * Do not scan if the allocation should not be delayed. 2501 * Do not scan if the allocation should not be delayed.
2502 */ 2502 */
2503 if (!(gfp_mask & __GFP_WAIT) || (current->flags & PF_MEMALLOC)) 2503 if (!(gfp_mask & __GFP_WAIT) || (current->flags & PF_MEMALLOC))
2504 return 0; 2504 return ZONE_RECLAIM_NOSCAN;
2505 2505
2506 /* 2506 /*
2507 * Only run zone reclaim on the local zone or on zones that do not 2507 * Only run zone reclaim on the local zone or on zones that do not
@@ -2511,10 +2511,11 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
2511 */ 2511 */
2512 node_id = zone_to_nid(zone); 2512 node_id = zone_to_nid(zone);
2513 if (node_state(node_id, N_CPU) && node_id != numa_node_id()) 2513 if (node_state(node_id, N_CPU) && node_id != numa_node_id())
2514 return 0; 2514 return ZONE_RECLAIM_NOSCAN;
2515 2515
2516 if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED)) 2516 if (zone_test_and_set_flag(zone, ZONE_RECLAIM_LOCKED))
2517 return 0; 2517 return ZONE_RECLAIM_NOSCAN;
2518
2518 ret = __zone_reclaim(zone, gfp_mask, order); 2519 ret = __zone_reclaim(zone, gfp_mask, order);
2519 zone_clear_flag(zone, ZONE_RECLAIM_LOCKED); 2520 zone_clear_flag(zone, ZONE_RECLAIM_LOCKED);
2520 2521