ksm: stable_node point to page and back
Add a pointer to the ksm page into struct stable_node, holding a reference to the page while the node exists. Put a pointer to the stable_node into the ksm page's ->mapping. Then we don't need get_ksm_page() while traversing the stable tree: the page to compare against is sure to be present and correct, even if it's no longer visible through any of its existing rmap_items. And we can handle the forked ksm page case more efficiently: no need to memcmp our way through the tree to find its match. Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk> Cc: Izik Eidus <ieidus@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
7b6ba2c7d3
commit
08beca44df
@@ -12,6 +12,8 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/vmstat.h>
|
||||
|
||||
struct stable_node;
|
||||
|
||||
#ifdef CONFIG_KSM
|
||||
int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end, int advice, unsigned long *vm_flags);
|
||||
@@ -34,7 +36,8 @@ static inline void ksm_exit(struct mm_struct *mm)
|
||||
/*
|
||||
* A KSM page is one of those write-protected "shared pages" or "merged pages"
|
||||
* which KSM maps into multiple mms, wherever identical anonymous page content
|
||||
* is found in VM_MERGEABLE vmas. It's a PageAnon page, with NULL anon_vma.
|
||||
* is found in VM_MERGEABLE vmas. It's a PageAnon page, pointing not to any
|
||||
* anon_vma, but to that page's node of the stable tree.
|
||||
*/
|
||||
static inline int PageKsm(struct page *page)
|
||||
{
|
||||
@@ -42,15 +45,22 @@ static inline int PageKsm(struct page *page)
|
||||
(PAGE_MAPPING_ANON | PAGE_MAPPING_KSM);
|
||||
}
|
||||
|
||||
/*
|
||||
* But we have to avoid the checking which page_add_anon_rmap() performs.
|
||||
*/
|
||||
static inline struct stable_node *page_stable_node(struct page *page)
|
||||
{
|
||||
return PageKsm(page) ? page_rmapping(page) : NULL;
|
||||
}
|
||||
|
||||
static inline void set_page_stable_node(struct page *page,
|
||||
struct stable_node *stable_node)
|
||||
{
|
||||
page->mapping = (void *)stable_node +
|
||||
(PAGE_MAPPING_ANON | PAGE_MAPPING_KSM);
|
||||
}
|
||||
|
||||
static inline void page_add_ksm_rmap(struct page *page)
|
||||
{
|
||||
if (atomic_inc_and_test(&page->_mapcount)) {
|
||||
page->mapping = (void *) (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM);
|
||||
if (atomic_inc_and_test(&page->_mapcount))
|
||||
__inc_zone_page_state(page, NR_ANON_PAGES);
|
||||
}
|
||||
}
|
||||
#else /* !CONFIG_KSM */
|
||||
|
||||
|
Reference in New Issue
Block a user