diff options
| -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 | ||
