From aa9e75a9ff9b3ed95641d704e6d907f706c672bc Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Thu, 21 Feb 2019 12:55:10 -0800 Subject: [PATCH] mm: oom-kill: Add lmk_kill possible for ULMK While ULMK is active, prevent OOM for order <= COSTLY_ORDER pages. No special actions are taken for larger orders. Change-Id: I4ccba1b71155947569acc3d88ae2027e3b2e0620 Signed-off-by: Patrick Daly --- include/linux/oom.h | 12 ++++++++++++ kernel/signal.c | 4 +++- mm/Kconfig | 9 +++++++++ mm/oom_kill.c | 22 ++++++++++++++++++++++ mm/page_alloc.c | 3 +++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/include/linux/oom.h b/include/linux/oom.h index 9af7e197c883..1c498297e0d5 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -115,6 +115,18 @@ extern struct task_struct *find_lock_task_mm(struct task_struct *p); extern void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask); + +#ifdef CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER +extern bool should_ulmk_retry(void); +extern void ulmk_update_last_kill(void); +#else +static inline bool should_ulmk_retry(void) +{ + return false; +} +static inline void ulmk_update_last_kill(void) {} +#endif + /* sysctls */ extern int sysctl_oom_dump_tasks; extern int sysctl_oom_kill_allocating_task; diff --git a/kernel/signal.c b/kernel/signal.c index e3bb6c108942..3271bc62aabf 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1370,8 +1370,10 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, if (!ret && sig) { ret = do_send_sig_info(sig, info, p, type); - if (capable(CAP_KILL) && sig == SIGKILL) + if (capable(CAP_KILL) && sig == SIGKILL) { add_to_oom_reaper(p); + ulmk_update_last_kill(); + } } return ret; diff --git a/mm/Kconfig b/mm/Kconfig index 18b988a6b123..64f11e1be74e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -803,6 +803,15 @@ config SPECULATIVE_PAGE_FAULT allocating, it is failing its processing and a classic page fault is then tried. +config HAVE_USERSPACE_LOW_MEMORY_KILLER + bool "Have userspace low memory killer" + default n + help + The page allocator cannot directly call into a + userspace low memory killer as it can call into the OOM killer. + Therefore, add a timeout mechanism to give the userspace + low memory killer a chance to run. + config GUP_BENCHMARK bool "Enable infrastructure for get_user_pages_fast() benchmarking" default n diff --git a/mm/oom_kill.c b/mm/oom_kill.c index e56b07257898..caf8eb950680 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -66,6 +66,28 @@ int sysctl_reap_mem_on_sigkill; */ DEFINE_MUTEX(oom_lock); +/* + * If ULMK has killed a process recently, + * we are making progress. + */ + +#ifdef CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER +static atomic64_t ulmk_kill_jiffies = ATOMIC64_INIT(INITIAL_JIFFIES); + + +bool should_ulmk_retry(void) +{ + unsigned long j = atomic64_read(&ulmk_kill_jiffies); + + return time_before(jiffies, j + 2 * HZ); +} + +void ulmk_update_last_kill(void) +{ + atomic64_set(&ulmk_kill_jiffies, jiffies); +} +#endif + #ifdef CONFIG_NUMA /** * has_intersects_mems_allowed() - check task eligiblity for kill diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d2c31f60058b..a3dc699a54a3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4365,6 +4365,9 @@ retry: if (costly_order && !(gfp_mask & __GFP_RETRY_MAYFAIL)) goto nopage; + if (order <= PAGE_ALLOC_COSTLY_ORDER && should_ulmk_retry()) + goto retry; + if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags, did_some_progress > 0, &no_progress_loops)) goto retry;