aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rmap.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/rmap.h')
-rw-r--r--include/linux/rmap.h106
1 files changed, 88 insertions, 18 deletions
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index b019ae64e2ab..31b2fd75dcba 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -26,8 +26,18 @@
26 */ 26 */
27struct anon_vma { 27struct anon_vma {
28 spinlock_t lock; /* Serialize access to vma list */ 28 spinlock_t lock; /* Serialize access to vma list */
29#ifdef CONFIG_KSM 29 struct anon_vma *root; /* Root of this anon_vma tree */
30 atomic_t ksm_refcount; 30#if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
31
32 /*
33 * The external_refcount is taken by either KSM or page migration
34 * to take a reference to an anon_vma when there is no
35 * guarantee that the vma of page tables will exist for
36 * the duration of the operation. A caller that takes
37 * the reference is responsible for clearing up the
38 * anon_vma if they are the last user on release
39 */
40 atomic_t external_refcount;
31#endif 41#endif
32 /* 42 /*
33 * NOTE: the LSB of the head.next is set by 43 * NOTE: the LSB of the head.next is set by
@@ -37,29 +47,64 @@ struct anon_vma {
37 * is serialized by a system wide lock only visible to 47 * is serialized by a system wide lock only visible to
38 * mm_take_all_locks() (mm_all_locks_mutex). 48 * mm_take_all_locks() (mm_all_locks_mutex).
39 */ 49 */
40 struct list_head head; /* List of private "related" vmas */ 50 struct list_head head; /* Chain of private "related" vmas */
51};
52
53/*
54 * The copy-on-write semantics of fork mean that an anon_vma
55 * can become associated with multiple processes. Furthermore,
56 * each child process will have its own anon_vma, where new
57 * pages for that process are instantiated.
58 *
59 * This structure allows us to find the anon_vmas associated
60 * with a VMA, or the VMAs associated with an anon_vma.
61 * The "same_vma" list contains the anon_vma_chains linking
62 * all the anon_vmas associated with this VMA.
63 * The "same_anon_vma" list contains the anon_vma_chains
64 * which link all the VMAs associated with this anon_vma.
65 */
66struct anon_vma_chain {
67 struct vm_area_struct *vma;
68 struct anon_vma *anon_vma;
69 struct list_head same_vma; /* locked by mmap_sem & page_table_lock */
70 struct list_head same_anon_vma; /* locked by anon_vma->lock */
41}; 71};
42 72
43#ifdef CONFIG_MMU 73#ifdef CONFIG_MMU
44#ifdef CONFIG_KSM 74#if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
45static inline void ksm_refcount_init(struct anon_vma *anon_vma) 75static inline void anonvma_external_refcount_init(struct anon_vma *anon_vma)
46{ 76{
47 atomic_set(&anon_vma->ksm_refcount, 0); 77 atomic_set(&anon_vma->external_refcount, 0);
48} 78}
49 79
50static inline int ksm_refcount(struct anon_vma *anon_vma) 80static inline int anonvma_external_refcount(struct anon_vma *anon_vma)
51{ 81{
52 return atomic_read(&anon_vma->ksm_refcount); 82 return atomic_read(&anon_vma->external_refcount);
53} 83}
84
85static inline void get_anon_vma(struct anon_vma *anon_vma)
86{
87 atomic_inc(&anon_vma->external_refcount);
88}
89
90void drop_anon_vma(struct anon_vma *);
54#else 91#else
55static inline void ksm_refcount_init(struct anon_vma *anon_vma) 92static inline void anonvma_external_refcount_init(struct anon_vma *anon_vma)
56{ 93{
57} 94}
58 95
59static inline int ksm_refcount(struct anon_vma *anon_vma) 96static inline int anonvma_external_refcount(struct anon_vma *anon_vma)
60{ 97{
61 return 0; 98 return 0;
62} 99}
100
101static inline void get_anon_vma(struct anon_vma *anon_vma)
102{
103}
104
105static inline void drop_anon_vma(struct anon_vma *anon_vma)
106{
107}
63#endif /* CONFIG_KSM */ 108#endif /* CONFIG_KSM */
64 109
65static inline struct anon_vma *page_anon_vma(struct page *page) 110static inline struct anon_vma *page_anon_vma(struct page *page)
@@ -70,18 +115,28 @@ static inline struct anon_vma *page_anon_vma(struct page *page)
70 return page_rmapping(page); 115 return page_rmapping(page);
71} 116}
72 117
73static inline void anon_vma_lock(struct vm_area_struct *vma) 118static inline void vma_lock_anon_vma(struct vm_area_struct *vma)
74{ 119{
75 struct anon_vma *anon_vma = vma->anon_vma; 120 struct anon_vma *anon_vma = vma->anon_vma;
76 if (anon_vma) 121 if (anon_vma)
77 spin_lock(&anon_vma->lock); 122 spin_lock(&anon_vma->root->lock);
78} 123}
79 124
80static inline void anon_vma_unlock(struct vm_area_struct *vma) 125static inline void vma_unlock_anon_vma(struct vm_area_struct *vma)
81{ 126{
82 struct anon_vma *anon_vma = vma->anon_vma; 127 struct anon_vma *anon_vma = vma->anon_vma;
83 if (anon_vma) 128 if (anon_vma)
84 spin_unlock(&anon_vma->lock); 129 spin_unlock(&anon_vma->root->lock);
130}
131
132static inline void anon_vma_lock(struct anon_vma *anon_vma)
133{
134 spin_lock(&anon_vma->root->lock);
135}
136
137static inline void anon_vma_unlock(struct anon_vma *anon_vma)
138{
139 spin_unlock(&anon_vma->root->lock);
85} 140}
86 141
87/* 142/*
@@ -89,20 +144,35 @@ static inline void anon_vma_unlock(struct vm_area_struct *vma)
89 */ 144 */
90void anon_vma_init(void); /* create anon_vma_cachep */ 145void anon_vma_init(void); /* create anon_vma_cachep */
91int anon_vma_prepare(struct vm_area_struct *); 146int anon_vma_prepare(struct vm_area_struct *);
92void __anon_vma_merge(struct vm_area_struct *, struct vm_area_struct *); 147void unlink_anon_vmas(struct vm_area_struct *);
93void anon_vma_unlink(struct vm_area_struct *); 148int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
94void anon_vma_link(struct vm_area_struct *); 149int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
95void __anon_vma_link(struct vm_area_struct *); 150void __anon_vma_link(struct vm_area_struct *);
96void anon_vma_free(struct anon_vma *); 151void anon_vma_free(struct anon_vma *);
97 152
153static inline void anon_vma_merge(struct vm_area_struct *vma,
154 struct vm_area_struct *next)
155{
156 VM_BUG_ON(vma->anon_vma != next->anon_vma);
157 unlink_anon_vmas(next);
158}
159
98/* 160/*
99 * rmap interfaces called when adding or removing pte of page 161 * rmap interfaces called when adding or removing pte of page
100 */ 162 */
163void page_move_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
101void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); 164void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
165void do_page_add_anon_rmap(struct page *, struct vm_area_struct *,
166 unsigned long, int);
102void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); 167void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
103void page_add_file_rmap(struct page *); 168void page_add_file_rmap(struct page *);
104void page_remove_rmap(struct page *); 169void page_remove_rmap(struct page *);
105 170
171void hugepage_add_anon_rmap(struct page *, struct vm_area_struct *,
172 unsigned long);
173void hugepage_add_new_anon_rmap(struct page *, struct vm_area_struct *,
174 unsigned long);
175
106static inline void page_dup_rmap(struct page *page) 176static inline void page_dup_rmap(struct page *page)
107{ 177{
108 atomic_inc(&page->_mapcount); 178 atomic_inc(&page->_mapcount);
@@ -181,7 +251,7 @@ static inline int page_referenced(struct page *page, int is_locked,
181 unsigned long *vm_flags) 251 unsigned long *vm_flags)
182{ 252{
183 *vm_flags = 0; 253 *vm_flags = 0;
184 return TestClearPageReferenced(page); 254 return 0;
185} 255}
186 256
187#define try_to_unmap(page, refs) SWAP_FAIL 257#define try_to_unmap(page, refs) SWAP_FAIL