aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorLee Schermerhorn <lee.schermerhorn@hp.com>2008-04-28 05:13:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:24 -0400
commit52cd3b074050dd664380b5e8cfc85d4a6ed8ad48 (patch)
treefcfcf55c0e81376ea34919fab26e29bedd7f3b88 /include/linux
parenta6020ed759404372e8be2b276e85e51735472cc9 (diff)
mempolicy: rework mempolicy Reference Counting [yet again]
After further discussion with Christoph Lameter, it has become clear that my earlier attempts to clean up the mempolicy reference counting were a bit of overkill in some areas, resulting in superflous ref/unref in what are usually fast paths. In other areas, further inspection reveals that I botched the unref for interleave policies. A separate patch, suitable for upstream/stable trees, fixes up the known errors in the previous attempt to fix reference counting. This patch reworks the memory policy referencing counting and, one hopes, simplifies the code. Maybe I'll get it right this time. See the update to the numa_memory_policy.txt document for a discussion of memory policy reference counting that motivates this patch. Summary: Lookup of mempolicy, based on (vma, address) need only add a reference for shared policy, and we need only unref the policy when finished for shared policies. So, this patch backs out all of the unneeded extra reference counting added by my previous attempt. It then unrefs only shared policies when we're finished with them, using the mpol_cond_put() [conditional put] helper function introduced by this patch. Note that shmem_swapin() calls read_swap_cache_async() with a dummy vma containing just the policy. read_swap_cache_async() can call alloc_page_vma() multiple times, so we can't let alloc_page_vma() unref the shared policy in this case. To avoid this, we make a copy of any non-null shared policy and remove the MPOL_F_SHARED flag from the copy. This copy occurs before reading a page [or multiple pages] from swap, so the overhead should not be an issue here. I introduced a new static inline function "mpol_cond_copy()" to copy the shared policy to an on-stack policy and remove the flags that would require a conditional free. The current implementation of mpol_cond_copy() assumes that the struct mempolicy contains no pointers to dynamically allocated structures that must be duplicated or reference counted during copy. Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: Christoph Lameter <clameter@sgi.com> Cc: David Rientjes <rientjes@google.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/mempolicy.h35
1 files changed, 35 insertions, 0 deletions
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 017def89e568..172b9c6acb91 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -112,6 +112,31 @@ static inline void mpol_put(struct mempolicy *pol)
112 __mpol_put(pol); 112 __mpol_put(pol);
113} 113}
114 114
115/*
116 * Does mempolicy pol need explicit unref after use?
117 * Currently only needed for shared policies.
118 */
119static inline int mpol_needs_cond_ref(struct mempolicy *pol)
120{
121 return (pol && (pol->flags & MPOL_F_SHARED));
122}
123
124static inline void mpol_cond_put(struct mempolicy *pol)
125{
126 if (mpol_needs_cond_ref(pol))
127 __mpol_put(pol);
128}
129
130extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
131 struct mempolicy *frompol);
132static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol,
133 struct mempolicy *frompol)
134{
135 if (!frompol)
136 return frompol;
137 return __mpol_cond_copy(tompol, frompol);
138}
139
115extern struct mempolicy *__mpol_dup(struct mempolicy *pol); 140extern struct mempolicy *__mpol_dup(struct mempolicy *pol);
116static inline struct mempolicy *mpol_dup(struct mempolicy *pol) 141static inline struct mempolicy *mpol_dup(struct mempolicy *pol)
117{ 142{
@@ -201,6 +226,16 @@ static inline void mpol_put(struct mempolicy *p)
201{ 226{
202} 227}
203 228
229static inline void mpol_cond_put(struct mempolicy *pol)
230{
231}
232
233static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to,
234 struct mempolicy *from)
235{
236 return from;
237}
238
204static inline void mpol_get(struct mempolicy *pol) 239static inline void mpol_get(struct mempolicy *pol)
205{ 240{
206} 241}