From: Christoph Lameter The patchset removes mlocked pages from the LRU and maintains a counter for the number of discovered mlocked pages. This is a lazy scheme for accounting for mlocked pages. The pages may only be discovered to be mlocked during reclaim. However, we attempt to detect mlocked pages at various other opportune moments. So in general the mlock counter is not far off the number of actual mlocked pages in the system. This patch: Modify try_to_unmap() so that we can distinguish failing to unmap due to a mlocked page from other causes. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton --- include/linux/rmap.h | 1 + mm/rmap.c | 21 +++++++++++++++------ mm/vmscan.c | 1 + 3 files changed, 17 insertions(+), 6 deletions(-) diff -puN include/linux/rmap.h~make-try_to_unmap-return-a-special-exit-code include/linux/rmap.h --- a/include/linux/rmap.h~make-try_to_unmap-return-a-special-exit-code +++ a/include/linux/rmap.h @@ -134,5 +134,6 @@ static inline int page_mkclean(struct pa #define SWAP_SUCCESS 0 #define SWAP_AGAIN 1 #define SWAP_FAIL 2 +#define SWAP_MLOCK 3 #endif /* _LINUX_RMAP_H */ diff -puN mm/rmap.c~make-try_to_unmap-return-a-special-exit-code mm/rmap.c --- a/mm/rmap.c~make-try_to_unmap-return-a-special-exit-code +++ a/mm/rmap.c @@ -631,10 +631,16 @@ static int try_to_unmap_one(struct page * If it's recently referenced (perhaps page_referenced * skipped over this mm) then we should reactivate it. */ - if (!migration && ((vma->vm_flags & VM_LOCKED) || - (ptep_clear_flush_young(vma, address, pte)))) { - ret = SWAP_FAIL; - goto out_unmap; + if (!migration) { + if (vma->vm_flags & VM_LOCKED) { + ret = SWAP_MLOCK; + goto out_unmap; + } + + if (ptep_clear_flush_young(vma, address, pte)) { + ret = SWAP_FAIL; + goto out_unmap; + } } /* Nuke the page table entry. */ @@ -799,7 +805,8 @@ static int try_to_unmap_anon(struct page list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { ret = try_to_unmap_one(page, vma, migration); - if (ret == SWAP_FAIL || !page_mapped(page)) + if (ret == SWAP_FAIL || ret == SWAP_MLOCK || + !page_mapped(page)) break; } spin_unlock(&anon_vma->lock); @@ -830,7 +837,8 @@ static int try_to_unmap_file(struct page spin_lock(&mapping->i_mmap_lock); vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { ret = try_to_unmap_one(page, vma, migration); - if (ret == SWAP_FAIL || !page_mapped(page)) + if (ret == SWAP_FAIL || ret == SWAP_MLOCK || + !page_mapped(page)) goto out; } @@ -913,6 +921,7 @@ out: * SWAP_SUCCESS - we succeeded in removing all mappings * SWAP_AGAIN - we missed a mapping, try again later * SWAP_FAIL - the page is unswappable + * SWAP_MLOCK - the page is under mlock() */ int try_to_unmap(struct page *page, int migration) { diff -puN mm/vmscan.c~make-try_to_unmap-return-a-special-exit-code mm/vmscan.c --- a/mm/vmscan.c~make-try_to_unmap-return-a-special-exit-code +++ a/mm/vmscan.c @@ -509,6 +509,7 @@ static unsigned long shrink_page_list(st if (page_mapped(page) && mapping) { switch (try_to_unmap(page, 0)) { case SWAP_FAIL: + case SWAP_MLOCK: goto activate_locked; case SWAP_AGAIN: goto keep_locked; _