aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index cacdf6684971..3464312bde07 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -51,11 +51,20 @@
51#define CREATE_TRACE_POINTS 51#define CREATE_TRACE_POINTS
52#include <trace/events/vmscan.h> 52#include <trace/events/vmscan.h>
53 53
54enum lumpy_mode { 54/*
55 LUMPY_MODE_NONE, 55 * lumpy_mode determines how the inactive list is shrunk
56 LUMPY_MODE_ASYNC, 56 * LUMPY_MODE_SINGLE: Reclaim only order-0 pages
57 LUMPY_MODE_SYNC, 57 * LUMPY_MODE_ASYNC: Do not block
58}; 58 * LUMPY_MODE_SYNC: Allow blocking e.g. call wait_on_page_writeback
59 * LUMPY_MODE_CONTIGRECLAIM: For high-order allocations, take a reference
60 * page from the LRU and reclaim all pages within a
61 * naturally aligned range
62 */
63typedef unsigned __bitwise__ lumpy_mode;
64#define LUMPY_MODE_SINGLE ((__force lumpy_mode)0x01u)
65#define LUMPY_MODE_ASYNC ((__force lumpy_mode)0x02u)
66#define LUMPY_MODE_SYNC ((__force lumpy_mode)0x04u)
67#define LUMPY_MODE_CONTIGRECLAIM ((__force lumpy_mode)0x08u)
59 68
60struct scan_control { 69struct scan_control {
61 /* Incremented by the number of inactive pages that were scanned */ 70 /* Incremented by the number of inactive pages that were scanned */
@@ -88,7 +97,7 @@ struct scan_control {
88 * Intend to reclaim enough continuous memory rather than reclaim 97 * Intend to reclaim enough continuous memory rather than reclaim
89 * enough amount of memory. i.e, mode for high order allocation. 98 * enough amount of memory. i.e, mode for high order allocation.
90 */ 99 */
91 enum lumpy_mode lumpy_reclaim_mode; 100 lumpy_mode lumpy_reclaim_mode;
92 101
93 /* Which cgroup do we reclaim from */ 102 /* Which cgroup do we reclaim from */
94 struct mem_cgroup *mem_cgroup; 103 struct mem_cgroup *mem_cgroup;
@@ -274,13 +283,13 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
274static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc, 283static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc,
275 bool sync) 284 bool sync)
276{ 285{
277 enum lumpy_mode mode = sync ? LUMPY_MODE_SYNC : LUMPY_MODE_ASYNC; 286 lumpy_mode syncmode = sync ? LUMPY_MODE_SYNC : LUMPY_MODE_ASYNC;
278 287
279 /* 288 /*
280 * Some reclaim have alredy been failed. No worth to try synchronous 289 * Some reclaim have alredy been failed. No worth to try synchronous
281 * lumpy reclaim. 290 * lumpy reclaim.
282 */ 291 */
283 if (sync && sc->lumpy_reclaim_mode == LUMPY_MODE_NONE) 292 if (sync && sc->lumpy_reclaim_mode & LUMPY_MODE_SINGLE)
284 return; 293 return;
285 294
286 /* 295 /*
@@ -288,17 +297,18 @@ static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc,
288 * trouble getting a small set of contiguous pages, we 297 * trouble getting a small set of contiguous pages, we
289 * will reclaim both active and inactive pages. 298 * will reclaim both active and inactive pages.
290 */ 299 */
300 sc->lumpy_reclaim_mode = LUMPY_MODE_CONTIGRECLAIM;
291 if (sc->order > PAGE_ALLOC_COSTLY_ORDER) 301 if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
292 sc->lumpy_reclaim_mode = mode; 302 sc->lumpy_reclaim_mode |= syncmode;
293 else if (sc->order && priority < DEF_PRIORITY - 2) 303 else if (sc->order && priority < DEF_PRIORITY - 2)
294 sc->lumpy_reclaim_mode = mode; 304 sc->lumpy_reclaim_mode |= syncmode;
295 else 305 else
296 sc->lumpy_reclaim_mode = LUMPY_MODE_NONE; 306 sc->lumpy_reclaim_mode = LUMPY_MODE_SINGLE | LUMPY_MODE_ASYNC;
297} 307}
298 308
299static void disable_lumpy_reclaim_mode(struct scan_control *sc) 309static void disable_lumpy_reclaim_mode(struct scan_control *sc)
300{ 310{
301 sc->lumpy_reclaim_mode = LUMPY_MODE_NONE; 311 sc->lumpy_reclaim_mode = LUMPY_MODE_SINGLE | LUMPY_MODE_ASYNC;
302} 312}
303 313
304static inline int is_page_cache_freeable(struct page *page) 314static inline int is_page_cache_freeable(struct page *page)
@@ -429,7 +439,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
429 * first attempt to free a range of pages fails. 439 * first attempt to free a range of pages fails.
430 */ 440 */
431 if (PageWriteback(page) && 441 if (PageWriteback(page) &&
432 sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC) 442 (sc->lumpy_reclaim_mode & LUMPY_MODE_SYNC))
433 wait_on_page_writeback(page); 443 wait_on_page_writeback(page);
434 444
435 if (!PageWriteback(page)) { 445 if (!PageWriteback(page)) {
@@ -622,7 +632,7 @@ static enum page_references page_check_references(struct page *page,
622 referenced_page = TestClearPageReferenced(page); 632 referenced_page = TestClearPageReferenced(page);
623 633
624 /* Lumpy reclaim - ignore references */ 634 /* Lumpy reclaim - ignore references */
625 if (sc->lumpy_reclaim_mode != LUMPY_MODE_NONE) 635 if (sc->lumpy_reclaim_mode & LUMPY_MODE_CONTIGRECLAIM)
626 return PAGEREF_RECLAIM; 636 return PAGEREF_RECLAIM;
627 637
628 /* 638 /*
@@ -739,7 +749,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
739 * for any page for which writeback has already 749 * for any page for which writeback has already
740 * started. 750 * started.
741 */ 751 */
742 if (sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC && 752 if ((sc->lumpy_reclaim_mode & LUMPY_MODE_SYNC) &&
743 may_enter_fs) 753 may_enter_fs)
744 wait_on_page_writeback(page); 754 wait_on_page_writeback(page);
745 else { 755 else {
@@ -1324,7 +1334,7 @@ static inline bool should_reclaim_stall(unsigned long nr_taken,
1324 return false; 1334 return false;
1325 1335
1326 /* Only stall on lumpy reclaim */ 1336 /* Only stall on lumpy reclaim */
1327 if (sc->lumpy_reclaim_mode == LUMPY_MODE_NONE) 1337 if (sc->lumpy_reclaim_mode & LUMPY_MODE_SINGLE)
1328 return false; 1338 return false;
1329 1339
1330 /* If we have relaimed everything on the isolated list, no stall */ 1340 /* If we have relaimed everything on the isolated list, no stall */
@@ -1375,7 +1385,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
1375 if (scanning_global_lru(sc)) { 1385 if (scanning_global_lru(sc)) {
1376 nr_taken = isolate_pages_global(nr_to_scan, 1386 nr_taken = isolate_pages_global(nr_to_scan,
1377 &page_list, &nr_scanned, sc->order, 1387 &page_list, &nr_scanned, sc->order,
1378 sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ? 1388 sc->lumpy_reclaim_mode & LUMPY_MODE_SINGLE ?
1379 ISOLATE_INACTIVE : ISOLATE_BOTH, 1389 ISOLATE_INACTIVE : ISOLATE_BOTH,
1380 zone, 0, file); 1390 zone, 0, file);
1381 zone->pages_scanned += nr_scanned; 1391 zone->pages_scanned += nr_scanned;
@@ -1388,7 +1398,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
1388 } else { 1398 } else {
1389 nr_taken = mem_cgroup_isolate_pages(nr_to_scan, 1399 nr_taken = mem_cgroup_isolate_pages(nr_to_scan,
1390 &page_list, &nr_scanned, sc->order, 1400 &page_list, &nr_scanned, sc->order,
1391 sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ? 1401 sc->lumpy_reclaim_mode & LUMPY_MODE_SINGLE ?
1392 ISOLATE_INACTIVE : ISOLATE_BOTH, 1402 ISOLATE_INACTIVE : ISOLATE_BOTH,
1393 zone, sc->mem_cgroup, 1403 zone, sc->mem_cgroup,
1394 0, file); 1404 0, file);