From de771054887418804b06c75f546f865e5dcf975f 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 Signed-off-by: Chris Goldsworthy --- include/linux/oom.h | 11 +++++++++++ kernel/signal.c | 4 +++- mm/Kconfig | 11 +++++++++++ mm/oom_kill.c | 22 ++++++++++++++++++++++ mm/page_alloc.c | 3 +++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/include/linux/oom.h b/include/linux/oom.h index 40862dd4f223..852facb5ac39 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -122,6 +122,17 @@ extern void oom_killer_enable(void); extern struct task_struct *find_lock_task_mm(struct task_struct *p); +#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 e8f1ce7a7e47..5dd383511eed 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1407,8 +1407,10 @@ int group_send_sig_info(int sig, struct kernel_siginfo *info, 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 4a8b6d55ae4d..67c665d45adf 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -759,6 +759,17 @@ config PERCPU_STATS information includes global and per chunk statistics, which can be used to help understand percpu memory usage. + +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" help diff --git a/mm/oom_kill.c b/mm/oom_kill.c index aaa360a50dfd..e533368a9cee 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -72,6 +72,28 @@ static inline bool is_memcg_oom(struct oom_control *oc) return oc->memcg != NULL; } +/* + * 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 /** * oom_cpuset_eligible() - check task eligiblity for kill diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 81a40bc187e4..3f62feb6dad5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4680,6 +4680,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;