Skip to content

Commit

Permalink
vmstat: mlocked pages statistics
Browse files Browse the repository at this point in the history
Add NR_MLOCK zone page state, which provides a (conservative) count of
mlocked pages (actually, the number of mlocked pages moved off the LRU).

Reworked by lts to fit in with the modified mlock page support in the
Reclaim Scalability series.

[kosaki.motohiro@jp.fujitsu.com: fix incorrect Mlocked field of /proc/meminfo]
[lee.schermerhorn@hp.com: mlocked-pages: add event counting with statistics]
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Signed-off-by: Rik van Riel <riel@redhat.com>
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Nick Piggin authored and torvalds committed Oct 20, 2008
1 parent ba470de commit 5344b7e
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 9 deletions.
4 changes: 3 additions & 1 deletion drivers/base/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
"Node %d Active(file): %8lu kB\n"
"Node %d Inactive(file): %8lu kB\n"
#ifdef CONFIG_UNEVICTABLE_LRU
"Node %d Noreclaim: %8lu kB\n"
"Node %d Unevictable: %8lu kB\n"
"Node %d Mlocked: %8lu kB\n"
#endif
#ifdef CONFIG_HIGHMEM
"Node %d HighTotal: %8lu kB\n"
Expand Down Expand Up @@ -104,6 +105,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
nid, K(node_page_state(nid, NR_INACTIVE_FILE)),
#ifdef CONFIG_UNEVICTABLE_LRU
nid, K(node_page_state(nid, NR_UNEVICTABLE)),
nid, K(node_page_state(nid, NR_MLOCK)),
#endif
#ifdef CONFIG_HIGHMEM
nid, K(i.totalhigh),
Expand Down
2 changes: 2 additions & 0 deletions fs/proc/proc_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
"Inactive(file): %8lu kB\n"
#ifdef CONFIG_UNEVICTABLE_LRU
"Unevictable: %8lu kB\n"
"Mlocked: %8lu kB\n"
#endif
#ifdef CONFIG_HIGHMEM
"HighTotal: %8lu kB\n"
Expand Down Expand Up @@ -217,6 +218,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
K(pages[LRU_INACTIVE_FILE]),
#ifdef CONFIG_UNEVICTABLE_LRU
K(pages[LRU_UNEVICTABLE]),
K(global_page_state(NR_MLOCK)),
#endif
#ifdef CONFIG_HIGHMEM
K(i.totalhigh),
Expand Down
2 changes: 2 additions & 0 deletions include/linux/mmzone.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ enum zone_stat_item {
NR_ACTIVE_FILE, /* " " " " " */
#ifdef CONFIG_UNEVICTABLE_LRU
NR_UNEVICTABLE, /* " " " " " */
NR_MLOCK, /* mlock()ed pages found and moved off LRU */
#else
NR_UNEVICTABLE = NR_ACTIVE_FILE, /* avoid compiler errors in dead code */
NR_MLOCK = NR_ACTIVE_FILE,
#endif
NR_ANON_PAGES, /* Mapped anonymous pages */
NR_FILE_MAPPED, /* pagecache pages mapped into pagetables.
Expand Down
4 changes: 4 additions & 0 deletions include/linux/vmstat.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
UNEVICTABLE_PGCULLED, /* culled to noreclaim list */
UNEVICTABLE_PGSCANNED, /* scanned for reclaimability */
UNEVICTABLE_PGRESCUED, /* rescued from noreclaim list */
UNEVICTABLE_PGMLOCKED,
UNEVICTABLE_PGMUNLOCKED,
UNEVICTABLE_PGCLEARED, /* on COW, page truncate */
UNEVICTABLE_PGSTRANDED, /* unable to isolate on unlock */
#endif
NR_VM_EVENT_ITEMS
};
Expand Down
16 changes: 13 additions & 3 deletions mm/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ static inline int is_mlocked_vma(struct vm_area_struct *vma, struct page *page)
if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED))
return 0;

SetPageMlocked(page);
if (!TestSetPageMlocked(page)) {
inc_zone_page_state(page, NR_MLOCK);
count_vm_event(UNEVICTABLE_PGMLOCKED);
}
return 1;
}

Expand All @@ -128,12 +131,19 @@ static inline void clear_page_mlock(struct page *page)

/*
* mlock_migrate_page - called only from migrate_page_copy() to
* migrate the Mlocked page flag
* migrate the Mlocked page flag; update statistics.
*/
static inline void mlock_migrate_page(struct page *newpage, struct page *page)
{
if (TestClearPageMlocked(page))
if (TestClearPageMlocked(page)) {
unsigned long flags;

local_irq_save(flags);
__dec_zone_page_state(page, NR_MLOCK);
SetPageMlocked(newpage);
__inc_zone_page_state(newpage, NR_MLOCK);
local_irq_restore(flags);
}
}


Expand Down
41 changes: 36 additions & 5 deletions mm/mlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ void __clear_page_mlock(struct page *page)
return;
}

dec_zone_page_state(page, NR_MLOCK);
count_vm_event(UNEVICTABLE_PGCLEARED);
if (!isolate_lru_page(page)) {
putback_lru_page(page);
} else {
Expand All @@ -69,6 +71,9 @@ void __clear_page_mlock(struct page *page)
lru_add_drain_all();
if (!isolate_lru_page(page))
putback_lru_page(page);
else if (PageUnevictable(page))
count_vm_event(UNEVICTABLE_PGSTRANDED);

}
}

Expand All @@ -80,8 +85,12 @@ void mlock_vma_page(struct page *page)
{
BUG_ON(!PageLocked(page));

if (!TestSetPageMlocked(page) && !isolate_lru_page(page))
putback_lru_page(page);
if (!TestSetPageMlocked(page)) {
inc_zone_page_state(page, NR_MLOCK);
count_vm_event(UNEVICTABLE_PGMLOCKED);
if (!isolate_lru_page(page))
putback_lru_page(page);
}
}

/*
Expand All @@ -106,9 +115,31 @@ static void munlock_vma_page(struct page *page)
{
BUG_ON(!PageLocked(page));

if (TestClearPageMlocked(page) && !isolate_lru_page(page)) {
try_to_munlock(page);
putback_lru_page(page);
if (TestClearPageMlocked(page)) {
dec_zone_page_state(page, NR_MLOCK);
if (!isolate_lru_page(page)) {
int ret = try_to_munlock(page);
/*
* did try_to_unlock() succeed or punt?
*/
if (ret == SWAP_SUCCESS || ret == SWAP_AGAIN)
count_vm_event(UNEVICTABLE_PGMUNLOCKED);

putback_lru_page(page);
} else {
/*
* We lost the race. let try_to_unmap() deal
* with it. At least we get the page state and
* mlock stats right. However, page is still on
* the noreclaim list. We'll fix that up when
* the page is eventually freed or we scan the
* noreclaim list.
*/
if (PageUnevictable(page))
count_vm_event(UNEVICTABLE_PGSTRANDED);
else
count_vm_event(UNEVICTABLE_PGMUNLOCKED);
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions mm/vmstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ static const char * const vmstat_text[] = {
"nr_active_file",
#ifdef CONFIG_UNEVICTABLE_LRU
"nr_unevictable",
"nr_mlock",
#endif
"nr_anon_pages",
"nr_mapped",
Expand Down Expand Up @@ -684,6 +685,10 @@ static const char * const vmstat_text[] = {
"unevictable_pgs_culled",
"unevictable_pgs_scanned",
"unevictable_pgs_rescued",
"unevictable_pgs_mlocked",
"unevictable_pgs_munlocked",
"unevictable_pgs_cleared",
"unevictable_pgs_stranded",
#endif
#endif
};
Expand Down

0 comments on commit 5344b7e

Please sign in to comment.