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); |