summaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2013-10-16 16:46:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-10-17 00:35:53 -0400
commit4942642080ea82d99ab5b653abb9a12b7ba31f4a (patch)
tree7ec12b61f0bfdd1f1466e5233b67432828b25c33 /mm/memory.c
parentc88b05b2cd07221cdefd56f7f7422c1459eb60c9 (diff)
mm: memcg: handle non-error OOM situations more gracefully
Commit 3812c8c8f395 ("mm: memcg: do not trap chargers with full callstack on OOM") assumed that only a few places that can trigger a memcg OOM situation do not return VM_FAULT_OOM, like optional page cache readahead. But there are many more and it's impractical to annotate them all. First of all, we don't want to invoke the OOM killer when the failed allocation is gracefully handled, so defer the actual kill to the end of the fault handling as well. This simplifies the code quite a bit for added bonus. Second, since a failed allocation might not be the abrupt end of the fault, the memcg OOM handler needs to be re-entrant until the fault finishes for subsequent allocation attempts. If an allocation is attempted after the task already OOMed, allow it to bypass the limit so that it can quickly finish the fault and invoke the OOM killer. Reported-by: azurIt <azurit@pobox.sk> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/mm/memory.c b/mm/memory.c
index f7b7692c05ed..1311f26497e6 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3865,15 +3865,21 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
3865 * space. Kernel faults are handled more gracefully. 3865 * space. Kernel faults are handled more gracefully.
3866 */ 3866 */
3867 if (flags & FAULT_FLAG_USER) 3867 if (flags & FAULT_FLAG_USER)
3868 mem_cgroup_enable_oom(); 3868 mem_cgroup_oom_enable();
3869 3869
3870 ret = __handle_mm_fault(mm, vma, address, flags); 3870 ret = __handle_mm_fault(mm, vma, address, flags);
3871 3871
3872 if (flags & FAULT_FLAG_USER) 3872 if (flags & FAULT_FLAG_USER) {
3873 mem_cgroup_disable_oom(); 3873 mem_cgroup_oom_disable();
3874 3874 /*
3875 if (WARN_ON(task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))) 3875 * The task may have entered a memcg OOM situation but
3876 mem_cgroup_oom_synchronize(); 3876 * if the allocation error was handled gracefully (no
3877 * VM_FAULT_OOM), there is no need to kill anything.
3878 * Just clean up the OOM state peacefully.
3879 */
3880 if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
3881 mem_cgroup_oom_synchronize(false);
3882 }
3877 3883
3878 return ret; 3884 return ret;
3879} 3885}