diff options
Diffstat (limited to 'mm/memcontrol.c')
| -rw-r--r-- | mm/memcontrol.c | 18 | 
1 files changed, 18 insertions, 0 deletions
| diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0f1f7a7374ba..36896f3eb7f5 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -250,6 +250,14 @@ static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) | |||
| 250 | 250 | ||
| 251 | struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) | 251 | struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) | 
| 252 | { | 252 | { | 
| 253 | /* | ||
| 254 | * mm_update_next_owner() may clear mm->owner to NULL | ||
| 255 | * if it races with swapoff, page migration, etc. | ||
| 256 | * So this can be called with p == NULL. | ||
| 257 | */ | ||
| 258 | if (unlikely(!p)) | ||
| 259 | return NULL; | ||
| 260 | |||
| 253 | return container_of(task_subsys_state(p, mem_cgroup_subsys_id), | 261 | return container_of(task_subsys_state(p, mem_cgroup_subsys_id), | 
| 254 | struct mem_cgroup, css); | 262 | struct mem_cgroup, css); | 
| 255 | } | 263 | } | 
| @@ -549,6 +557,11 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, | |||
| 549 | if (likely(!memcg)) { | 557 | if (likely(!memcg)) { | 
| 550 | rcu_read_lock(); | 558 | rcu_read_lock(); | 
| 551 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | 559 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | 
| 560 | if (unlikely(!mem)) { | ||
| 561 | rcu_read_unlock(); | ||
| 562 | kmem_cache_free(page_cgroup_cache, pc); | ||
| 563 | return 0; | ||
| 564 | } | ||
| 552 | /* | 565 | /* | 
| 553 | * For every charge from the cgroup, increment reference count | 566 | * For every charge from the cgroup, increment reference count | 
| 554 | */ | 567 | */ | 
| @@ -801,11 +814,16 @@ int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask) | |||
| 801 | 814 | ||
| 802 | rcu_read_lock(); | 815 | rcu_read_lock(); | 
| 803 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | 816 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); | 
| 817 | if (unlikely(!mem)) { | ||
| 818 | rcu_read_unlock(); | ||
| 819 | return 0; | ||
| 820 | } | ||
| 804 | css_get(&mem->css); | 821 | css_get(&mem->css); | 
| 805 | rcu_read_unlock(); | 822 | rcu_read_unlock(); | 
| 806 | 823 | ||
| 807 | do { | 824 | do { | 
| 808 | progress = try_to_free_mem_cgroup_pages(mem, gfp_mask); | 825 | progress = try_to_free_mem_cgroup_pages(mem, gfp_mask); | 
| 826 | progress += res_counter_check_under_limit(&mem->res); | ||
| 809 | } while (!progress && --retry); | 827 | } while (!progress && --retry); | 
| 810 | 828 | ||
| 811 | css_put(&mem->css); | 829 | css_put(&mem->css); | 
