Skip to content

Commit d7f0552

Browse files
gormanmtorvalds
authored andcommitted
mm, vmscan: account for skipped pages as a partial scan
Page reclaim determines whether a pgdat is unreclaimable by examining how many pages have been scanned since a page was freed and comparing that to the LRU sizes. Skipped pages are not reclaim candidates but contribute to scanned. This can prematurely mark a pgdat as unreclaimable and trigger an OOM kill. This patch accounts for skipped pages as a partial scan so that an unreclaimable pgdat will still be marked as such but by scaling the cost of a skip, it'll avoid the pgdat being marked prematurely. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Mel Gorman <[email protected]> Acked-by: Johannes Weiner <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Vlastimil Babka <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f8d1a31 commit d7f0552

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

mm/vmscan.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
14241424
LIST_HEAD(pages_skipped);
14251425

14261426
for (scan = 0; scan < nr_to_scan && nr_taken < nr_to_scan &&
1427-
!list_empty(src); scan++) {
1427+
!list_empty(src);) {
14281428
struct page *page;
14291429

14301430
page = lru_to_page(src);
@@ -1438,6 +1438,12 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
14381438
continue;
14391439
}
14401440

1441+
/*
1442+
* Account for scanned and skipped separetly to avoid the pgdat
1443+
* being prematurely marked unreclaimable by pgdat_reclaimable.
1444+
*/
1445+
scan++;
1446+
14411447
switch (__isolate_lru_page(page, mode)) {
14421448
case 0:
14431449
nr_pages = hpage_nr_pages(page);
@@ -1465,14 +1471,24 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
14651471
*/
14661472
if (!list_empty(&pages_skipped)) {
14671473
int zid;
1474+
unsigned long total_skipped = 0;
14681475

1469-
list_splice(&pages_skipped, src);
14701476
for (zid = 0; zid < MAX_NR_ZONES; zid++) {
14711477
if (!nr_skipped[zid])
14721478
continue;
14731479

14741480
__count_zid_vm_events(PGSCAN_SKIP, zid, nr_skipped[zid]);
1481+
total_skipped += nr_skipped[zid];
14751482
}
1483+
1484+
/*
1485+
* Account skipped pages as a partial scan as the pgdat may be
1486+
* close to unreclaimable. If the LRU list is empty, account
1487+
* skipped pages as a full scan.
1488+
*/
1489+
scan += list_empty(src) ? total_skipped : total_skipped >> 2;
1490+
1491+
list_splice(&pages_skipped, src);
14761492
}
14771493
*nr_scanned = scan;
14781494
trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan, scan,

0 commit comments

Comments
 (0)