diff options
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 20 |
1 files changed, 12 insertions, 8 deletions
@@ -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 | ||
115 | static inline struct anon_vma_chain *anon_vma_chain_alloc(void) | 115 | static 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 | ||
120 | static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) | 120 | static 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 | ||