aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/node.c4
-rw-r--r--fs/proc/proc_misc.c2
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--include/linux/vmstat.h4
-rw-r--r--mm/internal.h16
-rw-r--r--mm/mlock.c41
-rw-r--r--mm/vmstat.c5
7 files changed, 65 insertions, 9 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 11a9a05cf554..fb45d88a2446 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -71,7 +71,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
71 "Node %d Active(file): %8lu kB\n" 71 "Node %d Active(file): %8lu kB\n"
72 "Node %d Inactive(file): %8lu kB\n" 72 "Node %d Inactive(file): %8lu kB\n"
73#ifdef CONFIG_UNEVICTABLE_LRU 73#ifdef CONFIG_UNEVICTABLE_LRU
74 "Node %d Noreclaim: %8lu kB\n" 74 "Node %d Unevictable: %8lu kB\n"
75 "Node %d Mlocked: %8lu kB\n"
75#endif 76#endif
76#ifdef CONFIG_HIGHMEM 77#ifdef CONFIG_HIGHMEM
77 "Node %d HighTotal: %8lu kB\n" 78 "Node %d HighTotal: %8lu kB\n"
@@ -104,6 +105,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
104 nid, K(node_page_state(nid, NR_INACTIVE_FILE)), 105 nid, K(node_page_state(nid, NR_INACTIVE_FILE)),
105#ifdef CONFIG_UNEVICTABLE_LRU 106#ifdef CONFIG_UNEVICTABLE_LRU
106 nid, K(node_page_state(nid, NR_UNEVICTABLE)), 107 nid, K(node_page_state(nid, NR_UNEVICTABLE)),
108 nid, K(node_page_state(nid, NR_MLOCK)),
107#endif 109#endif
108#ifdef CONFIG_HIGHMEM 110#ifdef CONFIG_HIGHMEM
109 nid, K(i.totalhigh), 111 nid, K(i.totalhigh),
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 6dd60eaea997..61b25f4eabe6 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -176,6 +176,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
176 "Inactive(file): %8lu kB\n" 176 "Inactive(file): %8lu kB\n"
177#ifdef CONFIG_UNEVICTABLE_LRU 177#ifdef CONFIG_UNEVICTABLE_LRU
178 "Unevictable: %8lu kB\n" 178 "Unevictable: %8lu kB\n"
179 "Mlocked: %8lu kB\n"
179#endif 180#endif
180#ifdef CONFIG_HIGHMEM 181#ifdef CONFIG_HIGHMEM
181 "HighTotal: %8lu kB\n" 182 "HighTotal: %8lu kB\n"
@@ -217,6 +218,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
217 K(pages[LRU_INACTIVE_FILE]), 218 K(pages[LRU_INACTIVE_FILE]),
218#ifdef CONFIG_UNEVICTABLE_LRU 219#ifdef CONFIG_UNEVICTABLE_LRU
219 K(pages[LRU_UNEVICTABLE]), 220 K(pages[LRU_UNEVICTABLE]),
221 K(global_page_state(NR_MLOCK)),
220#endif 222#endif
221#ifdef CONFIG_HIGHMEM 223#ifdef CONFIG_HIGHMEM
222 K(i.totalhigh), 224 K(i.totalhigh),
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index d1f60d5fe2ea..da2d053a95f1 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -88,8 +88,10 @@ enum zone_stat_item {
88 NR_ACTIVE_FILE, /* " " " " " */ 88 NR_ACTIVE_FILE, /* " " " " " */
89#ifdef CONFIG_UNEVICTABLE_LRU 89#ifdef CONFIG_UNEVICTABLE_LRU
90 NR_UNEVICTABLE, /* " " " " " */ 90 NR_UNEVICTABLE, /* " " " " " */
91 NR_MLOCK, /* mlock()ed pages found and moved off LRU */
91#else 92#else
92 NR_UNEVICTABLE = NR_ACTIVE_FILE, /* avoid compiler errors in dead code */ 93 NR_UNEVICTABLE = NR_ACTIVE_FILE, /* avoid compiler errors in dead code */
94 NR_MLOCK = NR_ACTIVE_FILE,
93#endif 95#endif
94 NR_ANON_PAGES, /* Mapped anonymous pages */ 96 NR_ANON_PAGES, /* Mapped anonymous pages */
95 NR_FILE_MAPPED, /* pagecache pages mapped into pagetables. 97 NR_FILE_MAPPED, /* pagecache pages mapped into pagetables.
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 135840cd7feb..05b805020be2 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -45,6 +45,10 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
45 UNEVICTABLE_PGCULLED, /* culled to noreclaim list */ 45 UNEVICTABLE_PGCULLED, /* culled to noreclaim list */
46 UNEVICTABLE_PGSCANNED, /* scanned for reclaimability */ 46 UNEVICTABLE_PGSCANNED, /* scanned for reclaimability */
47 UNEVICTABLE_PGRESCUED, /* rescued from noreclaim list */ 47 UNEVICTABLE_PGRESCUED, /* rescued from noreclaim list */
48 UNEVICTABLE_PGMLOCKED,
49 UNEVICTABLE_PGMUNLOCKED,
50 UNEVICTABLE_PGCLEARED, /* on COW, page truncate */
51 UNEVICTABLE_PGSTRANDED, /* unable to isolate on unlock */
48#endif 52#endif
49 NR_VM_EVENT_ITEMS 53 NR_VM_EVENT_ITEMS
50}; 54};
diff --git a/mm/internal.h b/mm/internal.h
index 48e32f790571..1cfbf2e2bc9e 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -101,7 +101,10 @@ static inline int is_mlocked_vma(struct vm_area_struct *vma, struct page *page)
101 if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) 101 if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED))
102 return 0; 102 return 0;
103 103
104 SetPageMlocked(page); 104 if (!TestSetPageMlocked(page)) {
105 inc_zone_page_state(page, NR_MLOCK);
106 count_vm_event(UNEVICTABLE_PGMLOCKED);
107 }
105 return 1; 108 return 1;
106} 109}
107 110
@@ -128,12 +131,19 @@ static inline void clear_page_mlock(struct page *page)
128 131
129/* 132/*
130 * mlock_migrate_page - called only from migrate_page_copy() to 133 * mlock_migrate_page - called only from migrate_page_copy() to
131 * migrate the Mlocked page flag 134 * migrate the Mlocked page flag; update statistics.
132 */ 135 */
133static inline void mlock_migrate_page(struct page *newpage, struct page *page) 136static inline void mlock_migrate_page(struct page *newpage, struct page *page)
134{ 137{
135 if (TestClearPageMlocked(page)) 138 if (TestClearPageMlocked(page)) {
139 unsigned long flags;
140
141 local_irq_save(flags);
142 __dec_zone_page_state(page, NR_MLOCK);
136 SetPageMlocked(newpage); 143 SetPageMlocked(newpage);
144 __inc_zone_page_state(newpage, NR_MLOCK);
145 local_irq_restore(flags);
146 }
137} 147}
138 148
139 149
diff --git a/mm/mlock.c b/mm/mlock.c
index 8b478350a2a1..bce1b22c36c2 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -60,6 +60,8 @@ void __clear_page_mlock(struct page *page)
60 return; 60 return;
61 } 61 }
62 62
63 dec_zone_page_state(page, NR_MLOCK);
64 count_vm_event(UNEVICTABLE_PGCLEARED);
63 if (!isolate_lru_page(page)) { 65 if (!isolate_lru_page(page)) {
64 putback_lru_page(page); 66 putback_lru_page(page);
65 } else { 67 } else {
@@ -69,6 +71,9 @@ void __clear_page_mlock(struct page *page)
69 lru_add_drain_all(); 71 lru_add_drain_all();
70 if (!isolate_lru_page(page)) 72 if (!isolate_lru_page(page))
71 putback_lru_page(page); 73 putback_lru_page(page);
74 else if (PageUnevictable(page))
75 count_vm_event(UNEVICTABLE_PGSTRANDED);
76
72 } 77 }
73} 78}
74 79
@@ -80,8 +85,12 @@ void mlock_vma_page(struct page *page)
80{ 85{
81 BUG_ON(!PageLocked(page)); 86 BUG_ON(!PageLocked(page));
82 87
83 if (!TestSetPageMlocked(page) && !isolate_lru_page(page)) 88 if (!TestSetPageMlocked(page)) {
84 putback_lru_page(page); 89 inc_zone_page_state(page, NR_MLOCK);
90 count_vm_event(UNEVICTABLE_PGMLOCKED);
91 if (!isolate_lru_page(page))
92 putback_lru_page(page);
93 }
85} 94}
86 95
87/* 96/*
@@ -106,9 +115,31 @@ static void munlock_vma_page(struct page *page)
106{ 115{
107 BUG_ON(!PageLocked(page)); 116 BUG_ON(!PageLocked(page));
108 117
109 if (TestClearPageMlocked(page) && !isolate_lru_page(page)) { 118 if (TestClearPageMlocked(page)) {
110 try_to_munlock(page); 119 dec_zone_page_state(page, NR_MLOCK);
111 putback_lru_page(page); 120 if (!isolate_lru_page(page)) {
121 int ret = try_to_munlock(page);
122 /*
123 * did try_to_unlock() succeed or punt?
124 */
125 if (ret == SWAP_SUCCESS || ret == SWAP_AGAIN)
126 count_vm_event(UNEVICTABLE_PGMUNLOCKED);
127
128 putback_lru_page(page);
129 } else {
130 /*
131 * We lost the race. let try_to_unmap() deal
132 * with it. At least we get the page state and
133 * mlock stats right. However, page is still on
134 * the noreclaim list. We'll fix that up when
135 * the page is eventually freed or we scan the
136 * noreclaim list.
137 */
138 if (PageUnevictable(page))
139 count_vm_event(UNEVICTABLE_PGSTRANDED);
140 else
141 count_vm_event(UNEVICTABLE_PGMUNLOCKED);
142 }
112 } 143 }
113} 144}
114 145
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 6db2f6319313..9e28abc0a0b9 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -625,6 +625,7 @@ static const char * const vmstat_text[] = {
625 "nr_active_file", 625 "nr_active_file",
626#ifdef CONFIG_UNEVICTABLE_LRU 626#ifdef CONFIG_UNEVICTABLE_LRU
627 "nr_unevictable", 627 "nr_unevictable",
628 "nr_mlock",
628#endif 629#endif
629 "nr_anon_pages", 630 "nr_anon_pages",
630 "nr_mapped", 631 "nr_mapped",
@@ -684,6 +685,10 @@ static const char * const vmstat_text[] = {
684 "unevictable_pgs_culled", 685 "unevictable_pgs_culled",
685 "unevictable_pgs_scanned", 686 "unevictable_pgs_scanned",
686 "unevictable_pgs_rescued", 687 "unevictable_pgs_rescued",
688 "unevictable_pgs_mlocked",
689 "unevictable_pgs_munlocked",
690 "unevictable_pgs_cleared",
691 "unevictable_pgs_stranded",
687#endif 692#endif
688#endif 693#endif
689}; 694};