The patch titled Subject: oom, oom_reaper: try to reap tasks which skip regular OOM killer path has been removed from the -mm tree. Its filename was oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path.patch This patch was dropped because it was merged into mainline or a subsystem tree ------------------------------------------------------ From: Michal Hocko <mhocko@xxxxxxxx> Subject: oom, oom_reaper: try to reap tasks which skip regular OOM killer path If either the current task is already killed or PF_EXITING or a selected task is PF_EXITING then the oom killer is suppressed and so is the oom reaper. This patch adds try_oom_reaper which checks the given task and queues it for the oom reaper if that is safe to be done meaning that the task doesn't share the mm with an alive process. This might help to release the memory pressure while the task tries to exit. [akpm@xxxxxxxxxxxxxxxxxxxx: fix nommu build] Signed-off-by: Michal Hocko <mhocko@xxxxxxxx> Cc: Raushaniya Maksudova <rmaksudova@xxxxxxxxxxxxx> Cc: Michael S. Tsirkin <mst@xxxxxxxxxx> Cc: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx> Cc: David Rientjes <rientjes@xxxxxxxxxx> Cc: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> Cc: Daniel Vetter <daniel.vetter@xxxxxxxxx> Cc: Oleg Nesterov <oleg@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- include/linux/oom.h | 8 +++ mm/memcontrol.c | 1 mm/oom_kill.c | 86 +++++++++++++++++++++++++++++++++--------- 3 files changed, 77 insertions(+), 18 deletions(-) diff -puN include/linux/oom.h~oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path include/linux/oom.h --- a/include/linux/oom.h~oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path +++ a/include/linux/oom.h @@ -72,6 +72,14 @@ static inline bool oom_task_origin(const extern void mark_oom_victim(struct task_struct *tsk); +#ifdef CONFIG_MMU +extern void try_oom_reaper(struct task_struct *tsk); +#else +static inline void try_oom_reaper(struct task_struct *tsk) +{ +} +#endif + extern unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, const nodemask_t *nodemask, unsigned long totalpages); diff -puN mm/memcontrol.c~oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path mm/memcontrol.c --- a/mm/memcontrol.c~oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path +++ a/mm/memcontrol.c @@ -1275,6 +1275,7 @@ static bool mem_cgroup_out_of_memory(str */ if (fatal_signal_pending(current) || task_will_free_mem(current)) { mark_oom_victim(current); + try_oom_reaper(current); goto unlock; } diff -puN mm/oom_kill.c~oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path mm/oom_kill.c --- a/mm/oom_kill.c~oom-oom_reaper-try-to-reap-tasks-which-skip-regular-oom-killer-path +++ a/mm/oom_kill.c @@ -412,6 +412,25 @@ bool oom_killer_disabled __read_mostly; #define K(x) ((x) << (PAGE_SHIFT-10)) +/* + * task->mm can be NULL if the task is the exited group leader. So to + * determine whether the task is using a particular mm, we examine all the + * task's threads: if one of those is using this mm then this task was also + * using it. + */ +static bool process_shares_mm(struct task_struct *p, struct mm_struct *mm) +{ + struct task_struct *t; + + for_each_thread(p, t) { + struct mm_struct *t_mm = READ_ONCE(t->mm); + if (t_mm) + return t_mm == mm; + } + return false; +} + + #ifdef CONFIG_MMU /* * OOM Reaper kernel thread which tries to reap the memory used by the OOM @@ -563,6 +582,53 @@ static void wake_oom_reaper(struct task_ wake_up(&oom_reaper_wait); } +/* Check if we can reap the given task. This has to be called with stable + * tsk->mm + */ +void try_oom_reaper(struct task_struct *tsk) +{ + struct mm_struct *mm = tsk->mm; + struct task_struct *p; + + if (!mm) + return; + + /* + * There might be other threads/processes which are either not + * dying or even not killable. + */ + if (atomic_read(&mm->mm_users) > 1) { + rcu_read_lock(); + for_each_process(p) { + bool exiting; + + if (!process_shares_mm(p, mm)) + continue; + if (same_thread_group(p, tsk)) + continue; + if (fatal_signal_pending(p)) + continue; + + /* + * If the task is exiting make sure the whole thread group + * is exiting and cannot acces mm anymore. + */ + spin_lock_irq(&p->sighand->siglock); + exiting = signal_group_exit(p->signal); + spin_unlock_irq(&p->sighand->siglock); + if (exiting) + continue; + + /* Give up */ + rcu_read_unlock(); + return; + } + rcu_read_unlock(); + } + + wake_oom_reaper(tsk); +} + static int __init oom_init(void) { oom_reaper_th = kthread_run(oom_reaper, NULL, "oom_reaper"); @@ -653,24 +719,6 @@ void oom_killer_enable(void) } /* - * task->mm can be NULL if the task is the exited group leader. So to - * determine whether the task is using a particular mm, we examine all the - * task's threads: if one of those is using this mm then this task was also - * using it. - */ -static bool process_shares_mm(struct task_struct *p, struct mm_struct *mm) -{ - struct task_struct *t; - - for_each_thread(p, t) { - struct mm_struct *t_mm = READ_ONCE(t->mm); - if (t_mm) - return t_mm == mm; - } - return false; -} - -/* * Must be called while holding a reference to p, which will be released upon * returning. */ @@ -694,6 +742,7 @@ void oom_kill_process(struct oom_control task_lock(p); if (p->mm && task_will_free_mem(p)) { mark_oom_victim(p); + try_oom_reaper(p); task_unlock(p); put_task_struct(p); return; @@ -873,6 +922,7 @@ bool out_of_memory(struct oom_control *o if (current->mm && (fatal_signal_pending(current) || task_will_free_mem(current))) { mark_oom_victim(current); + try_oom_reaper(current); return true; } _ Patches currently in -mm which might be from mhocko@xxxxxxxx are vmscan-consider-classzone_idx-in-compaction_ready.patch mm-compaction-change-compact_-constants-into-enum.patch mm-compaction-cover-all-compaction-mode-in-compact_zone.patch mm-compaction-distinguish-compact_deferred-from-compact_skipped.patch mm-compaction-distinguish-between-full-and-partial-compact_complete.patch mm-compaction-update-compaction_result-ordering.patch mm-compaction-simplify-__alloc_pages_direct_compact-feedback-interface.patch mm-compaction-abstract-compaction-feedback-to-helpers.patch mm-oom-rework-oom-detection.patch mm-throttle-on-io-only-when-there-are-too-many-dirty-and-writeback-pages.patch mm-throttle-on-io-only-when-there-are-too-many-dirty-and-writeback-pages-fix.patch mm-oom-protect-costly-allocations-some-more.patch mm-oom-protect-costly-allocations-some-more-fix.patch mm-consider-compaction-feedback-also-for-costly-allocation.patch mm-oom-compaction-prevent-from-should_compact_retry-looping-for-ever-for-costly-orders.patch mm-oom-protect-costly-allocations-some-more-for-config_compaction.patch mm-oom_reaper-hide-oom-reaped-tasks-from-oom-killer-more-carefully.patch mm-oom_reaper-do-not-mmput-synchronously-from-the-oom-reaper-context.patch mm-oom_reaper-do-not-mmput-synchronously-from-the-oom-reaper-context-fix.patch oom-consider-multi-threaded-tasks-in-task_will_free_mem.patch mm-make-mmap_sem-for-write-waits-killable-for-mm-syscalls.patch mm-make-vm_mmap-killable.patch mm-make-vm_munmap-killable.patch mm-aout-handle-vm_brk-failures.patch mm-elf-handle-vm_brk-error.patch mm-make-vm_brk-killable.patch mm-proc-make-clear_refs-killable.patch mm-fork-make-dup_mmap-wait-for-mmap_sem-for-write-killable.patch ipc-shm-make-shmem-attach-detach-wait-for-mmap_sem-killable.patch vdso-make-arch_setup_additional_pages-wait-for-mmap_sem-for-write-killable.patch coredump-make-coredump_wait-wait-for-mmap_sem-for-write-killable.patch aio-make-aio_setup_ring-killable.patch exec-make-exec-path-waiting-for-mmap_sem-killable.patch prctl-make-pr_set_thp_disable-wait-for-mmap_sem-killable.patch uprobes-wait-for-mmap_sem-for-write-killable.patch drm-i915-make-i915_gem_mmap_ioctl-wait-for-mmap_sem-killable.patch drm-radeon-make-radeon_mn_get-wait-for-mmap_sem-killable.patch drm-amdgpu-make-amdgpu_mn_get-wait-for-mmap_sem-killable.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html