diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index b6dfa0081a8e..8e645ee52045 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -91,6 +91,9 @@ struct scan_control { | |||
91 | /* Can pages be swapped as part of reclaim? */ | 91 | /* Can pages be swapped as part of reclaim? */ |
92 | unsigned int may_swap:1; | 92 | unsigned int may_swap:1; |
93 | 93 | ||
94 | /* Can cgroups be reclaimed below their normal consumption range? */ | ||
95 | unsigned int may_thrash:1; | ||
96 | |||
94 | unsigned int hibernation_mode:1; | 97 | unsigned int hibernation_mode:1; |
95 | 98 | ||
96 | /* One of the zones is ready for compaction */ | 99 | /* One of the zones is ready for compaction */ |
@@ -2294,6 +2297,12 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc, | |||
2294 | struct lruvec *lruvec; | 2297 | struct lruvec *lruvec; |
2295 | int swappiness; | 2298 | int swappiness; |
2296 | 2299 | ||
2300 | if (mem_cgroup_low(root, memcg)) { | ||
2301 | if (!sc->may_thrash) | ||
2302 | continue; | ||
2303 | mem_cgroup_events(memcg, MEMCG_LOW, 1); | ||
2304 | } | ||
2305 | |||
2297 | lruvec = mem_cgroup_zone_lruvec(zone, memcg); | 2306 | lruvec = mem_cgroup_zone_lruvec(zone, memcg); |
2298 | swappiness = mem_cgroup_swappiness(memcg); | 2307 | swappiness = mem_cgroup_swappiness(memcg); |
2299 | 2308 | ||
@@ -2315,8 +2324,7 @@ static bool shrink_zone(struct zone *zone, struct scan_control *sc, | |||
2315 | mem_cgroup_iter_break(root, memcg); | 2324 | mem_cgroup_iter_break(root, memcg); |
2316 | break; | 2325 | break; |
2317 | } | 2326 | } |
2318 | memcg = mem_cgroup_iter(root, memcg, &reclaim); | 2327 | } while ((memcg = mem_cgroup_iter(root, memcg, &reclaim))); |
2319 | } while (memcg); | ||
2320 | 2328 | ||
2321 | /* | 2329 | /* |
2322 | * Shrink the slab caches in the same proportion that | 2330 | * Shrink the slab caches in the same proportion that |
@@ -2519,10 +2527,11 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc) | |||
2519 | static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | 2527 | static unsigned long do_try_to_free_pages(struct zonelist *zonelist, |
2520 | struct scan_control *sc) | 2528 | struct scan_control *sc) |
2521 | { | 2529 | { |
2530 | int initial_priority = sc->priority; | ||
2522 | unsigned long total_scanned = 0; | 2531 | unsigned long total_scanned = 0; |
2523 | unsigned long writeback_threshold; | 2532 | unsigned long writeback_threshold; |
2524 | bool zones_reclaimable; | 2533 | bool zones_reclaimable; |
2525 | 2534 | retry: | |
2526 | delayacct_freepages_start(); | 2535 | delayacct_freepages_start(); |
2527 | 2536 | ||
2528 | if (global_reclaim(sc)) | 2537 | if (global_reclaim(sc)) |
@@ -2572,6 +2581,13 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
2572 | if (sc->compaction_ready) | 2581 | if (sc->compaction_ready) |
2573 | return 1; | 2582 | return 1; |
2574 | 2583 | ||
2584 | /* Untapped cgroup reserves? Don't OOM, retry. */ | ||
2585 | if (!sc->may_thrash) { | ||
2586 | sc->priority = initial_priority; | ||
2587 | sc->may_thrash = 1; | ||
2588 | goto retry; | ||
2589 | } | ||
2590 | |||
2575 | /* Any of the zones still reclaimable? Don't OOM. */ | 2591 | /* Any of the zones still reclaimable? Don't OOM. */ |
2576 | if (zones_reclaimable) | 2592 | if (zones_reclaimable) |
2577 | return 1; | 2593 | return 1; |