aboutsummaryrefslogtreecommitdiffstats
path: root/mm/internal.h
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2008-10-18 23:26:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 11:52:30 -0400
commitb291f000393f5a0b679012b39d79fbc85c018233 (patch)
tree28eb785d4d157d3396e4377294e6054635a4bd90 /mm/internal.h
parent89e004ea55abe201b29e2d6e35124101f1288ef7 (diff)
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 <npiggin@suse.de> 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. [akpm@linux-foundation.org: fix this for pagemap-pass-mm-into-pagewalkers.patch] [akpm@linux-foundation.org: untangle patch interdependencies] [akpm@linux-foundation.org: fix things after out-of-order merging] [hugh@veritas.com: fix page-flags mess] [lee.schermerhorn@hp.com: fix munlock page table walk - now requires 'mm'] [kosaki.motohiro@jp.fujitsu.com: build fix] [kosaki.motohiro@jp.fujitsu.com: fix truncate race and sevaral comments] [kosaki.motohiro@jp.fujitsu.com: splitlru: introduce __get_user_pages()] Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Rik van Riel <riel@redhat.com> Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: Nick Piggin <npiggin@suse.de> Cc: Dave Hansen <dave@linux.vnet.ibm.com> Cc: Matt Mackall <mpm@selenic.com> Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/internal.h')
-rw-r--r--mm/internal.h71
1 files changed, 71 insertions, 0 deletions
diff --git a/mm/internal.h b/mm/internal.h
index 3db17b2a1ac6..4ebf0bef9a39 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -61,6 +61,10 @@ static inline unsigned long page_order(struct page *page)
61 return page_private(page); 61 return page_private(page);
62} 62}
63 63
64extern int mlock_vma_pages_range(struct vm_area_struct *vma,
65 unsigned long start, unsigned long end);
66extern void munlock_vma_pages_all(struct vm_area_struct *vma);
67
64#ifdef CONFIG_UNEVICTABLE_LRU 68#ifdef CONFIG_UNEVICTABLE_LRU
65/* 69/*
66 * unevictable_migrate_page() called only from migrate_page_copy() to 70 * unevictable_migrate_page() called only from migrate_page_copy() to
@@ -79,6 +83,65 @@ static inline void unevictable_migrate_page(struct page *new, struct page *old)
79} 83}
80#endif 84#endif
81 85
86#ifdef CONFIG_UNEVICTABLE_LRU
87/*
88 * Called only in fault path via page_evictable() for a new page
89 * to determine if it's being mapped into a LOCKED vma.
90 * If so, mark page as mlocked.
91 */
92static inline int is_mlocked_vma(struct vm_area_struct *vma, struct page *page)
93{
94 VM_BUG_ON(PageLRU(page));
95
96 if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED))
97 return 0;
98
99 SetPageMlocked(page);
100 return 1;
101}
102
103/*
104 * must be called with vma's mmap_sem held for read, and page locked.
105 */
106extern void mlock_vma_page(struct page *page);
107
108/*
109 * Clear the page's PageMlocked(). This can be useful in a situation where
110 * we want to unconditionally remove a page from the pagecache -- e.g.,
111 * on truncation or freeing.
112 *
113 * It is legal to call this function for any page, mlocked or not.
114 * If called for a page that is still mapped by mlocked vmas, all we do
115 * is revert to lazy LRU behaviour -- semantics are not broken.
116 */
117extern void __clear_page_mlock(struct page *page);
118static inline void clear_page_mlock(struct page *page)
119{
120 if (unlikely(TestClearPageMlocked(page)))
121 __clear_page_mlock(page);
122}
123
124/*
125 * mlock_migrate_page - called only from migrate_page_copy() to
126 * migrate the Mlocked page flag
127 */
128static inline void mlock_migrate_page(struct page *newpage, struct page *page)
129{
130 if (TestClearPageMlocked(page))
131 SetPageMlocked(newpage);
132}
133
134
135#else /* CONFIG_UNEVICTABLE_LRU */
136static inline int is_mlocked_vma(struct vm_area_struct *v, struct page *p)
137{
138 return 0;
139}
140static inline void clear_page_mlock(struct page *page) { }
141static inline void mlock_vma_page(struct page *page) { }
142static inline void mlock_migrate_page(struct page *new, struct page *old) { }
143
144#endif /* CONFIG_UNEVICTABLE_LRU */
82 145
83/* 146/*
84 * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node, 147 * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node,
@@ -148,4 +211,12 @@ static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
148} 211}
149#endif /* CONFIG_SPARSEMEM */ 212#endif /* CONFIG_SPARSEMEM */
150 213
214#define GUP_FLAGS_WRITE 0x1
215#define GUP_FLAGS_FORCE 0x2
216#define GUP_FLAGS_IGNORE_VMA_PERMISSIONS 0x4
217
218int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
219 unsigned long start, int len, int flags,
220 struct page **pages, struct vm_area_struct **vmas);
221
151#endif 222#endif