From 149f4538fff95a0d674f2a76ad64e53d1b2df5b4 Mon Sep 17 00:00:00 2001 From: lk_hauwei Date: Sun, 8 May 2022 16:16:52 +0800 Subject: [PATCH] Add lowmem killer debug info ohos inclusion category: feature issue: #I569HG CVE: NA -------------------------------- For lmkd to trigger in-kernel lowmem info dump Signed-off-by: lk_hauwei --- include/linux/lowmem_dbg.h | 16 +++++ mm/Kconfig | 14 +++++ mm/Makefile | 2 + mm/lmkd_dbg_trigger.c | 93 +++++++++++++++++++++++++++ mm/lowmem_dbg.c | 125 +++++++++++++++++++++++++++++++++++++ 5 files changed, 250 insertions(+) create mode 100644 include/linux/lowmem_dbg.h create mode 100644 mm/lmkd_dbg_trigger.c create mode 100644 mm/lowmem_dbg.c diff --git a/include/linux/lowmem_dbg.h b/include/linux/lowmem_dbg.h new file mode 100644 index 000000000000..be459bd18603 --- /dev/null +++ b/include/linux/lowmem_dbg.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * include/linux/lowmem_dbg.h + * + * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. + */ +#ifndef __LMK_DBG_H +#define __LMK_DBG_H + +#ifdef CONFIG_LOWMEM +void lowmem_dbg(short oom_score_adj); +#else +static inline void lowmem_dbg(short oom_score_adj) {} +#endif +#endif + diff --git a/mm/Kconfig b/mm/Kconfig index df9bf9f4ade7..f7afde1fe403 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -912,5 +912,19 @@ config ANON_VMA_NAME Assigning a name to anonymous virtual memory area might prevent that area from being merged with adjacent virtual memory areas due to the difference in their name. +# +# For lmkd to trigger in-kernel lowmem info +# +config LOWMEM + bool "Low Memory Killer" + default n + help + Enables lowmem killer parameter tuning + +config LMKD_DBG + bool "Low Memory Killer Debug" + default n + help + print processes info when lmk happen per several seconds endmenu diff --git a/mm/Makefile b/mm/Makefile index 56abb804cc19..74b2de5e868b 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -66,6 +66,8 @@ ifdef CONFIG_MMU obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o endif +obj-$(CONFIG_LMKD_DBG) += lmkd_dbg_trigger.o +obj-$(CONFIG_LOWMEM) += lowmem_dbg.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o swap_slots.o obj-$(CONFIG_FRONTSWAP) += frontswap.o obj-$(CONFIG_ZSWAP) += zswap.o diff --git a/mm/lmkd_dbg_trigger.c b/mm/lmkd_dbg_trigger.c new file mode 100644 index 000000000000..e845b14f5f02 --- /dev/null +++ b/mm/lmkd_dbg_trigger.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mm/lmkd_dbg_trigger.c + * + * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define PROC_NUMBUF 8 + +static int lmkd_oom_score_adj; +static atomic64_t lmkd_no_cma_cnt = ATOMIC64_INIT(0); + +void lmkd_inc_no_cma_cnt(void) +{ + atomic64_inc(&lmkd_no_cma_cnt); +} + +void lmkd_dec_no_cma_cnt(void) +{ + atomic64_dec(&lmkd_no_cma_cnt); +} + +static int lmkd_dbg_trigger_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "lmkd_oom_score_adj: %d\n", lmkd_oom_score_adj); + seq_printf(m, "lmkd_no_cma_cnt: %lld\n", + atomic64_read(&lmkd_no_cma_cnt)); + return 0; +} + +static int lmkd_dbg_trigger_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, lmkd_dbg_trigger_proc_show, NULL); +} + +static ssize_t lmkd_dbg_trigger_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + char buffer[PROC_NUMBUF]; + int oom_score_adj; + int err; + + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + if (copy_from_user(buffer, buf, count)) { + err = -EFAULT; + goto out; + } + + err = kstrtoint(strstrip(buffer), 0, &oom_score_adj); + if (err) + goto out; + + if (oom_score_adj < OOM_SCORE_ADJ_MIN || + oom_score_adj > OOM_SCORE_ADJ_MAX) { + err = -EINVAL; + goto out; + } + + lmkd_oom_score_adj = oom_score_adj; + lowmem_dbg(oom_score_adj); + +out: + return err < 0 ? err : count; +} + +static const struct proc_ops lmkd_dbg_trigger_proc_fops = { + .proc_open = lmkd_dbg_trigger_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = lmkd_dbg_trigger_write, +}; + +static int __init proc_lmkd_dbg_trigger_init(void) +{ + proc_create("lmkd_dbg_trigger", 0660, NULL, + &lmkd_dbg_trigger_proc_fops); + return 0; +} + +fs_initcall(proc_lmkd_dbg_trigger_init); + diff --git a/mm/lowmem_dbg.c b/mm/lowmem_dbg.c new file mode 100644 index 000000000000..fc548ce78fd2 --- /dev/null +++ b/mm/lowmem_dbg.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mm/lowmem_dbg.c + * + * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. + */ +#define pr_fmt(fmt) "lowmem:" fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LMK_PRT_TSK_RSS 10000 +#define LMK_INTERVAL 3 + +/* SERVICE_ADJ(5) * OOM_SCORE_ADJ_MAX / -OOM_DISABLE */ +#define LMK_SERVICE_ADJ 500 +/* defiine TASK STATE String */ +#define TASK_STATE_TO_CHAR_STR "RSDTtXZxKWPNn" + +static unsigned long long last_jiffs; +static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; +static void lowmem_dump(struct work_struct *work); + +static DEFINE_MUTEX(lowmem_dump_mutex); +static DECLARE_WORK(lowmem_dbg_wk, lowmem_dump); +static DECLARE_WORK(lowmem_dbg_verbose_wk, lowmem_dump); + +static int task_state_char(unsigned long state) +{ + int bit = state ? __ffs(state) + 1 : 0; + + return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?'; +} + +static void tasks_dump(bool verbose) +{ + struct task_struct *p = NULL; + struct task_struct *task = NULL; + short tsk_oom_adj = 0; + unsigned long tsk_nr_ptes = 0; + char frozen_mark = ' '; + + pr_info("[ pid ] uid tgid total_vm rss nptes swap adj s name\n"); + + rcu_read_lock(); + for_each_process(p) { + task = find_lock_task_mm(p); + if (!task) { + /* + * This is a kthread or all of p's threads have already + * detached their mm's. There's no need to report + * them; they can't be oom killed anyway. + */ + continue; + } + + tsk_oom_adj = task->signal->oom_score_adj; + if (!verbose && tsk_oom_adj && + (tsk_oom_adj <= LMK_SERVICE_ADJ) && + (get_mm_rss(task->mm) < LMK_PRT_TSK_RSS)) { + task_unlock(task); + continue; + } + + tsk_nr_ptes = mm_pgtables_bytes(task->mm); + + frozen_mark = frozen(task) ? '*' : ' '; + + pr_info("[%5d] %5d %5d %8lu %6lu %5lu %5lu %5hd %c %s%c\n", + task->pid, from_kuid(&init_user_ns, task_uid(task)), + task->tgid, task->mm->total_vm, get_mm_rss(task->mm), + tsk_nr_ptes, + get_mm_counter(task->mm, MM_SWAPENTS), + tsk_oom_adj, + task_state_char(task->state), + task->comm, + frozen_mark); /*lint !e1058*/ + task_unlock(task); + } + rcu_read_unlock(); +} + +static void lowmem_dump(struct work_struct *work) +{ + bool verbose = (work == &lowmem_dbg_verbose_wk) ? true : false; + + mutex_lock(&lowmem_dump_mutex); +#if defined(SHOW_MEM_FILTER_PAGE_COUNT) + show_mem(SHOW_MEM_FILTER_NODES | + (verbose ? 0 : SHOW_MEM_FILTER_PAGE_COUNT)); +#else + show_mem(SHOW_MEM_FILTER_NODES, NULL); +#endif + tasks_dump(verbose); + mutex_unlock(&lowmem_dump_mutex); +} + +void lowmem_dbg(short oom_score_adj) +{ + unsigned long long jiffs = get_jiffies_64(); + + if (oom_score_adj == 0) { + schedule_work(&lowmem_dbg_verbose_wk); + } else if (time_after64(jiffs, (last_jiffs + LMK_INTERVAL * HZ))) { + last_jiffs = get_jiffies_64(); + schedule_work(&lowmem_dbg_wk); + } +} + -- Gitee