aboutsummaryrefslogtreecommitdiffstats
path: root/mm/rmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/rmap.c')
-rw-r--r--mm/rmap.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/mm/rmap.c b/mm/rmap.c
index 68756a77ef87..27dfd3b82b0f 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -112,9 +112,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma)
112 kmem_cache_free(anon_vma_cachep, anon_vma); 112 kmem_cache_free(anon_vma_cachep, anon_vma);
113} 113}
114 114
115static inline struct anon_vma_chain *anon_vma_chain_alloc(void) 115static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp)
116{ 116{
117 return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL); 117 return kmem_cache_alloc(anon_vma_chain_cachep, gfp);
118} 118}
119 119
120static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) 120static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
@@ -159,7 +159,7 @@ int anon_vma_prepare(struct vm_area_struct *vma)
159 struct mm_struct *mm = vma->vm_mm; 159 struct mm_struct *mm = vma->vm_mm;
160 struct anon_vma *allocated; 160 struct anon_vma *allocated;
161 161
162 avc = anon_vma_chain_alloc(); 162 avc = anon_vma_chain_alloc(GFP_KERNEL);
163 if (!avc) 163 if (!avc)
164 goto out_enomem; 164 goto out_enomem;
165 165
@@ -253,9 +253,14 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
253 list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) { 253 list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
254 struct anon_vma *anon_vma; 254 struct anon_vma *anon_vma;
255 255
256 avc = anon_vma_chain_alloc(); 256 avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN);
257 if (!avc) 257 if (unlikely(!avc)) {
258 goto enomem_failure; 258 unlock_anon_vma_root(root);
259 root = NULL;
260 avc = anon_vma_chain_alloc(GFP_KERNEL);
261 if (!avc)
262 goto enomem_failure;
263 }
259 anon_vma = pavc->anon_vma; 264 anon_vma = pavc->anon_vma;
260 root = lock_anon_vma_root(root, anon_vma); 265 root = lock_anon_vma_root(root, anon_vma);
261 anon_vma_chain_link(dst, avc, anon_vma); 266 anon_vma_chain_link(dst, avc, anon_vma);
@@ -264,7 +269,6 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
264 return 0; 269 return 0;
265 270
266 enomem_failure: 271 enomem_failure:
267 unlock_anon_vma_root(root);
268 unlink_anon_vmas(dst); 272 unlink_anon_vmas(dst);
269 return -ENOMEM; 273 return -ENOMEM;
270} 274}
@@ -294,7 +298,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
294 anon_vma = anon_vma_alloc(); 298 anon_vma = anon_vma_alloc();
295 if (!anon_vma) 299 if (!anon_vma)
296 goto out_error; 300 goto out_error;
297 avc = anon_vma_chain_alloc(); 301 avc = anon_vma_chain_alloc(GFP_KERNEL);
298 if (!avc) 302 if (!avc)
299 goto out_error_free_anon_vma; 303 goto out_error_free_anon_vma;
300 304