mm: vmscan: do not OOM if aborting reclaim to start compaction
authorMel Gorman <[email protected]>
Fri, 13 Jan 2012 01:19:33 +0000 (17:19 -0800)
committerLinus Torvalds <[email protected]>
Fri, 13 Jan 2012 04:13:09 +0000 (20:13 -0800)
During direct reclaim it is possible that reclaim will be aborted so that
compaction can be attempted to satisfy a high-order allocation.  If this
decision is made before any pages are reclaimed, it is possible that 0 is
returned to the page allocator potentially triggering an OOM.  This has
not been observed but it is a possibility so this patch addresses it.

Signed-off-by: Mel Gorman <[email protected]>
Reviewed-by: Rik van Riel <[email protected]>
Cc: Andrea Arcangeli <[email protected]>
Cc: Minchan Kim <[email protected]>
Cc: Dave Jones <[email protected]>
Cc: Jan Kara <[email protected]>
Cc: Andy Isaacson <[email protected]>
Cc: Nai Xia <[email protected]>
Cc: Johannes Weiner <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
mm/vmscan.c

index 866ab27c52a5d0ac809efe48c15205fd45e37ec4..cb68c53db4ecc19359a77192632e149db890265f 100644 (file)
@@ -2263,6 +2263,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
        struct zoneref *z;
        struct zone *zone;
        unsigned long writeback_threshold;
+       bool should_abort_reclaim;
 
        get_mems_allowed();
        delayacct_freepages_start();
@@ -2274,7 +2275,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                sc->nr_scanned = 0;
                if (!priority)
                        disable_swap_token(sc->target_mem_cgroup);
-               if (shrink_zones(priority, zonelist, sc))
+               should_abort_reclaim = shrink_zones(priority, zonelist, sc);
+               if (should_abort_reclaim)
                        break;
 
                /*
@@ -2342,6 +2344,10 @@ out:
        if (oom_killer_disabled)
                return 0;
 
+       /* Aborting reclaim to try compaction? don't OOM, then */
+       if (should_abort_reclaim)
+               return 1;
+
        /* top priority shrink_zones still had more to do? don't OOM, then */
        if (global_reclaim(sc) && !all_unreclaimable(zonelist, sc))
                return 1;