Skip to content

Commit f7ad2a6

Browse files
shligittorvalds
authored andcommitted
mm: move MADV_FREE pages into LRU_INACTIVE_FILE list
madv()'s MADV_FREE indicate pages are 'lazyfree'. They are still anonymous pages, but they can be freed without pageout. To distinguish these from normal anonymous pages, we clear their SwapBacked flag. MADV_FREE pages could be freed without pageout, so they pretty much like used once file pages. For such pages, we'd like to reclaim them once there is memory pressure. Also it might be unfair reclaiming MADV_FREE pages always before used once file pages and we definitively want to reclaim the pages before other anonymous and file pages. To speed up MADV_FREE pages reclaim, we put the pages into LRU_INACTIVE_FILE list. The rationale is LRU_INACTIVE_FILE list is tiny nowadays and should be full of used once file pages. Reclaiming MADV_FREE pages will not have much interfere of anonymous and active file pages. And the inactive file pages and MADV_FREE pages will be reclaimed according to their age, so we don't reclaim too many MADV_FREE pages too. Putting the MADV_FREE pages into LRU_INACTIVE_FILE_LIST also means we can reclaim the pages without swap support. This idea is suggested by Johannes. This patch doesn't move MADV_FREE pages to LRU_INACTIVE_FILE list yet to avoid bisect failure, next patch will do it. The patch is based on Minchan's original patch. [[email protected]: coding-style fixes] Link: http://lkml.kernel.org/r/2f87063c1e9354677b7618c647abde77b07561e5.1487965799.git.shli@fb.com Signed-off-by: Shaohua Li <[email protected]> Suggested-by: Johannes Weiner <[email protected]> Acked-by: Johannes Weiner <[email protected]> Acked-by: Minchan Kim <[email protected]> Acked-by: Michal Hocko <[email protected]> Acked-by: Hillf Danton <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Mel Gorman <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d44d363 commit f7ad2a6

File tree

6 files changed

+31
-28
lines changed

6 files changed

+31
-28
lines changed

include/linux/swap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ extern void lru_add_drain_cpu(int cpu);
279279
extern void lru_add_drain_all(void);
280280
extern void rotate_reclaimable_page(struct page *page);
281281
extern void deactivate_file_page(struct page *page);
282-
extern void deactivate_page(struct page *page);
282+
extern void mark_page_lazyfree(struct page *page);
283283
extern void swap_setup(void);
284284

285285
extern void add_page_to_unevictable_list(struct page *page);

include/linux/vm_event_item.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
2525
FOR_ALL_ZONES(PGALLOC),
2626
FOR_ALL_ZONES(ALLOCSTALL),
2727
FOR_ALL_ZONES(PGSCAN_SKIP),
28-
PGFREE, PGACTIVATE, PGDEACTIVATE,
28+
PGFREE, PGACTIVATE, PGDEACTIVATE, PGLAZYFREE,
2929
PGFAULT, PGMAJFAULT,
3030
PGLAZYFREED,
3131
PGREFILL,

mm/huge_memory.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,9 +1564,6 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
15641564
ClearPageDirty(page);
15651565
unlock_page(page);
15661566

1567-
if (PageActive(page))
1568-
deactivate_page(page);
1569-
15701567
if (pmd_young(orig_pmd) || pmd_dirty(orig_pmd)) {
15711568
pmdp_invalidate(vma, addr, pmd);
15721569
orig_pmd = pmd_mkold(orig_pmd);

mm/madvise.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,6 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
411411
ptent = pte_mkold(ptent);
412412
ptent = pte_mkclean(ptent);
413413
set_pte_at(mm, addr, pte, ptent);
414-
if (PageActive(page))
415-
deactivate_page(page);
416414
tlb_remove_tlb_entry(tlb, pte, addr);
417415
}
418416
}

mm/swap.c

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int page_cluster;
4646
static DEFINE_PER_CPU(struct pagevec, lru_add_pvec);
4747
static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs);
4848
static DEFINE_PER_CPU(struct pagevec, lru_deactivate_file_pvecs);
49-
static DEFINE_PER_CPU(struct pagevec, lru_deactivate_pvecs);
49+
static DEFINE_PER_CPU(struct pagevec, lru_lazyfree_pvecs);
5050
#ifdef CONFIG_SMP
5151
static DEFINE_PER_CPU(struct pagevec, activate_page_pvecs);
5252
#endif
@@ -571,20 +571,27 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec,
571571
}
572572

573573

574-
static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec,
574+
static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec,
575575
void *arg)
576576
{
577-
if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) {
578-
int file = page_is_file_cache(page);
579-
int lru = page_lru_base_type(page);
577+
if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) &&
578+
!PageUnevictable(page)) {
579+
bool active = PageActive(page);
580580

581-
del_page_from_lru_list(page, lruvec, lru + LRU_ACTIVE);
581+
del_page_from_lru_list(page, lruvec,
582+
LRU_INACTIVE_ANON + active);
582583
ClearPageActive(page);
583584
ClearPageReferenced(page);
584-
add_page_to_lru_list(page, lruvec, lru);
585+
/*
586+
* lazyfree pages are clean anonymous pages. They have
587+
* SwapBacked flag cleared to distinguish normal anonymous
588+
* pages
589+
*/
590+
ClearPageSwapBacked(page);
591+
add_page_to_lru_list(page, lruvec, LRU_INACTIVE_FILE);
585592

586-
__count_vm_event(PGDEACTIVATE);
587-
update_page_reclaim_stat(lruvec, file, 0);
593+
__count_vm_events(PGLAZYFREE, hpage_nr_pages(page));
594+
update_page_reclaim_stat(lruvec, 1, 0);
588595
}
589596
}
590597

@@ -614,9 +621,9 @@ void lru_add_drain_cpu(int cpu)
614621
if (pagevec_count(pvec))
615622
pagevec_lru_move_fn(pvec, lru_deactivate_file_fn, NULL);
616623

617-
pvec = &per_cpu(lru_deactivate_pvecs, cpu);
624+
pvec = &per_cpu(lru_lazyfree_pvecs, cpu);
618625
if (pagevec_count(pvec))
619-
pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL);
626+
pagevec_lru_move_fn(pvec, lru_lazyfree_fn, NULL);
620627

621628
activate_page_drain(cpu);
622629
}
@@ -648,22 +655,22 @@ void deactivate_file_page(struct page *page)
648655
}
649656

650657
/**
651-
* deactivate_page - deactivate a page
658+
* mark_page_lazyfree - make an anon page lazyfree
652659
* @page: page to deactivate
653660
*
654-
* deactivate_page() moves @page to the inactive list if @page was on the active
655-
* list and was not an unevictable page. This is done to accelerate the reclaim
656-
* of @page.
661+
* mark_page_lazyfree() moves @page to the inactive file list.
662+
* This is done to accelerate the reclaim of @page.
657663
*/
658-
void deactivate_page(struct page *page)
664+
void mark_page_lazyfree(struct page *page)
659665
{
660-
if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) {
661-
struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs);
666+
if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) &&
667+
!PageUnevictable(page)) {
668+
struct pagevec *pvec = &get_cpu_var(lru_lazyfree_pvecs);
662669

663670
get_page(page);
664671
if (!pagevec_add(pvec, page) || PageCompound(page))
665-
pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL);
666-
put_cpu_var(lru_deactivate_pvecs);
672+
pagevec_lru_move_fn(pvec, lru_lazyfree_fn, NULL);
673+
put_cpu_var(lru_lazyfree_pvecs);
667674
}
668675
}
669676

@@ -703,7 +710,7 @@ void lru_add_drain_all(void)
703710
if (pagevec_count(&per_cpu(lru_add_pvec, cpu)) ||
704711
pagevec_count(&per_cpu(lru_rotate_pvecs, cpu)) ||
705712
pagevec_count(&per_cpu(lru_deactivate_file_pvecs, cpu)) ||
706-
pagevec_count(&per_cpu(lru_deactivate_pvecs, cpu)) ||
713+
pagevec_count(&per_cpu(lru_lazyfree_pvecs, cpu)) ||
707714
need_activate_page_drain(cpu)) {
708715
INIT_WORK(work, lru_add_drain_per_cpu);
709716
queue_work_on(cpu, mm_percpu_wq, work);

mm/vmstat.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,7 @@ const char * const vmstat_text[] = {
991991
"pgfree",
992992
"pgactivate",
993993
"pgdeactivate",
994+
"pglazyfree",
994995

995996
"pgfault",
996997
"pgmajfault",

0 commit comments

Comments
 (0)