aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rmap.h
diff options
context:
space:
mode:
authorRik van Riel <riel@redhat.com>2010-08-09 20:18:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:44:55 -0400
commit76545066c8521f3e32c849744744842b4df25b79 (patch)
tree978b6b003f63e1e22618586b7d9c2dd8ef363614 /include/linux/rmap.h
parent012f18004da33ba672e3c60838cc4898126174d3 (diff)
mm: extend KSM refcounts to the anon_vma root
KSM reference counts can cause an anon_vma to exist after the processe it belongs to have already exited. Because the anon_vma lock now lives in the root anon_vma, we need to ensure that the root anon_vma stays around until after all the "child" anon_vmas have been freed. The obvious way to do this is to have a "child" anon_vma take a reference to the root in anon_vma_fork. When the anon_vma is freed at munmap or process exit, we drop the refcount in anon_vma_unlink and possibly free the root anon_vma. The KSM anon_vma reference count function also needs to be modified to deal with the possibility of freeing 2 levels of anon_vma. The easiest way to do this is to break out the KSM magic and make it generic. When compiling without CONFIG_KSM, this code is compiled out. Signed-off-by: Rik van Riel <riel@redhat.com> Tested-by: Larry Woodman <lwoodman@redhat.com> Acked-by: Larry Woodman <lwoodman@redhat.com> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Tested-by: Dave Young <hidave.darkstar@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/rmap.h')
-rw-r--r--include/linux/rmap.h15
1 files changed, 15 insertions, 0 deletions
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index af43cb9a0506..dc9b3c0bf5d4 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -81,6 +81,13 @@ static inline int anonvma_external_refcount(struct anon_vma *anon_vma)
81{ 81{
82 return atomic_read(&anon_vma->external_refcount); 82 return atomic_read(&anon_vma->external_refcount);
83} 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 *);
84#else 91#else
85static inline void anonvma_external_refcount_init(struct anon_vma *anon_vma) 92static inline void anonvma_external_refcount_init(struct anon_vma *anon_vma)
86{ 93{
@@ -90,6 +97,14 @@ static inline int anonvma_external_refcount(struct anon_vma *anon_vma)
90{ 97{
91 return 0; 98 return 0;
92} 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}
93#endif /* CONFIG_KSM */ 108#endif /* CONFIG_KSM */
94 109
95static inline struct anon_vma *page_anon_vma(struct page *page) 110static inline struct anon_vma *page_anon_vma(struct page *page)