mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
mlock: mlocked pages are unevictable
Make sure that mlocked pages also live on the unevictable LRU, so kswapd will not scan them over and over again. This is achieved through various strategies: 1) add yet another page flag--PG_mlocked--to indicate that the page is locked for efficient testing in vmscan and, optionally, fault path. This allows early culling of unevictable pages, preventing them from getting to page_referenced()/try_to_unmap(). Also allows separate accounting of mlock'd pages, as Nick's original patch did. Note: Nick's original mlock patch used a PG_mlocked flag. I had removed this in favor of the PG_unevictable flag + an mlock_count [new page struct member]. I restored the PG_mlocked flag to eliminate the new count field. 2) add the mlock/unevictable infrastructure to mm/mlock.c, with internal APIs in mm/internal.h. This is a rework of Nick's original patch to these files, taking into account that mlocked pages are now kept on unevictable LRU list. 3) update vmscan.c:page_evictable() to check PageMlocked() and, if vma passed in, the vm_flags. Note that the vma will only be passed in for new pages in the fault path; and then only if the "cull unevictable pages in fault path" patch is included. 4) add try_to_unlock() to rmap.c to walk a page's rmap and ClearPageMlocked() if no other vmas have it mlocked. Reuses as much of try_to_unmap() as possible. This effectively replaces the use of one of the lru list links as an mlock count. If this mechanism let's pages in mlocked vmas leak through w/o PG_mlocked set [I don't know that it does], we should catch them later in try_to_unmap(). One hopes this will be rare, as it will be relatively expensive. Original mm/internal.h, mm/rmap.c and mm/mlock.c changes: Signed-off-by: Nick Piggin <[email protected]> splitlru: introduce __get_user_pages(): New munlock processing need to GUP_FLAGS_IGNORE_VMA_PERMISSIONS. because current get_user_pages() can't grab PROT_NONE pages theresore it cause PROT_NONE pages can't munlock. [[email protected]: fix this for pagemap-pass-mm-into-pagewalkers.patch] [[email protected]: untangle patch interdependencies] [[email protected]: fix things after out-of-order merging] [[email protected]: fix page-flags mess] [[email protected]: fix munlock page table walk - now requires 'mm'] [[email protected]: build fix] [[email protected]: fix truncate race and sevaral comments] [[email protected]: splitlru: introduce __get_user_pages()] Signed-off-by: KOSAKI Motohiro <[email protected]> Signed-off-by: Rik van Riel <[email protected]> Signed-off-by: Lee Schermerhorn <[email protected]> Cc: Nick Piggin <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Matt Mackall <[email protected]> Signed-off-by: Hugh Dickins <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
89e004ea55
commit
b291f00039
13 changed files with 817 additions and 91 deletions
36
mm/vmscan.c
36
mm/vmscan.c
|
|
@ -582,11 +582,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
|
|||
|
||||
sc->nr_scanned++;
|
||||
|
||||
if (unlikely(!page_evictable(page, NULL))) {
|
||||
unlock_page(page);
|
||||
putback_lru_page(page);
|
||||
continue;
|
||||
}
|
||||
if (unlikely(!page_evictable(page, NULL)))
|
||||
goto cull_mlocked;
|
||||
|
||||
if (!sc->may_swap && page_mapped(page))
|
||||
goto keep_locked;
|
||||
|
|
@ -624,9 +621,19 @@ static unsigned long shrink_page_list(struct list_head *page_list,
|
|||
* Anonymous process memory has backing store?
|
||||
* Try to allocate it some swap space here.
|
||||
*/
|
||||
if (PageAnon(page) && !PageSwapCache(page))
|
||||
if (PageAnon(page) && !PageSwapCache(page)) {
|
||||
switch (try_to_munlock(page)) {
|
||||
case SWAP_FAIL: /* shouldn't happen */
|
||||
case SWAP_AGAIN:
|
||||
goto keep_locked;
|
||||
case SWAP_MLOCK:
|
||||
goto cull_mlocked;
|
||||
case SWAP_SUCCESS:
|
||||
; /* fall thru'; add to swap cache */
|
||||
}
|
||||
if (!add_to_swap(page, GFP_ATOMIC))
|
||||
goto activate_locked;
|
||||
}
|
||||
#endif /* CONFIG_SWAP */
|
||||
|
||||
mapping = page_mapping(page);
|
||||
|
|
@ -641,6 +648,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
|
|||
goto activate_locked;
|
||||
case SWAP_AGAIN:
|
||||
goto keep_locked;
|
||||
case SWAP_MLOCK:
|
||||
goto cull_mlocked;
|
||||
case SWAP_SUCCESS:
|
||||
; /* try to free the page below */
|
||||
}
|
||||
|
|
@ -731,6 +740,11 @@ free_it:
|
|||
}
|
||||
continue;
|
||||
|
||||
cull_mlocked:
|
||||
unlock_page(page);
|
||||
putback_lru_page(page);
|
||||
continue;
|
||||
|
||||
activate_locked:
|
||||
/* Not a candidate for swapping, so reclaim swap space. */
|
||||
if (PageSwapCache(page) && vm_swap_full())
|
||||
|
|
@ -742,7 +756,7 @@ keep_locked:
|
|||
unlock_page(page);
|
||||
keep:
|
||||
list_add(&page->lru, &ret_pages);
|
||||
VM_BUG_ON(PageLRU(page));
|
||||
VM_BUG_ON(PageLRU(page) || PageUnevictable(page));
|
||||
}
|
||||
list_splice(&ret_pages, page_list);
|
||||
if (pagevec_count(&freed_pvec))
|
||||
|
|
@ -2329,12 +2343,13 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
|
|||
* @vma: the VMA in which the page is or will be mapped, may be NULL
|
||||
*
|
||||
* Test whether page is evictable--i.e., should be placed on active/inactive
|
||||
* lists vs unevictable list.
|
||||
* lists vs unevictable list. The vma argument is !NULL when called from the
|
||||
* fault path to determine how to instantate a new page.
|
||||
*
|
||||
* Reasons page might not be evictable:
|
||||
* (1) page's mapping marked unevictable
|
||||
* (2) page is part of an mlocked VMA
|
||||
*
|
||||
* TODO - later patches
|
||||
*/
|
||||
int page_evictable(struct page *page, struct vm_area_struct *vma)
|
||||
{
|
||||
|
|
@ -2342,7 +2357,8 @@ int page_evictable(struct page *page, struct vm_area_struct *vma)
|
|||
if (mapping_unevictable(page_mapping(page)))
|
||||
return 0;
|
||||
|
||||
/* TODO: test page [!]evictable conditions */
|
||||
if (PageMlocked(page) || (vma && is_mlocked_vma(vma, page)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue