* [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj
@ 2017-02-09 13:21 peter enderborg
2017-02-09 19:40 ` Michal Hocko
0 siblings, 1 reply; 3+ messages in thread
From: peter enderborg @ 2017-02-09 13:21 UTC (permalink / raw)
To: devel, Greg Kroah-Hartman, linux-kernel,
Arve Hjønnevåg, Riley Andrews, Linus Torvalds,
linux-mm
This adds subscribtion for changes in oom_score_adj, this
value is important to android systems. For task that uses
oom_score_adj they read the task list. This can be long
and need rcu locks and has a impact on the system. Let
the user track the changes based on oom_score_adj changes
and keep them in their own context so they do their actions
with minimal system impact.
Signed-off-by: Peter Enderborg <peter.enderborg@sonymobile.com>
---
fs/proc/base.c | 13 +++++++
include/linux/oom_score_notifier.h | 47 ++++++++++++++++++++++++
kernel/Makefile | 1 +
kernel/fork.c | 6 +++
kernel/oom_score_notifier.c | 75 ++++++++++++++++++++++++++++++++++++++
mm/Kconfig | 9 +++++
6 files changed, 151 insertions(+)
create mode 100644 include/linux/oom_score_notifier.h
create mode 100644 kernel/oom_score_notifier.c
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 87c9a9a..60c2d9b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -87,6 +87,7 @@
#include <linux/slab.h>
#include <linux/flex_array.h>
#include <linux/posix-timers.h>
+#include <linux/oom_score_notifier.h>
#ifdef CONFIG_HARDWALL
#include <asm/hardwall.h>
#endif
@@ -1057,6 +1058,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
static DEFINE_MUTEX(oom_adj_mutex);
struct mm_struct *mm = NULL;
struct task_struct *task;
+ int old_oom_score_adj;
int err = 0;
task = get_proc_task(file_inode(file));
@@ -1102,9 +1104,20 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
}
}
+ old_oom_score_adj = task->signal->oom_score_adj;
task->signal->oom_score_adj = oom_adj;
if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
task->signal->oom_score_adj_min = (short)oom_adj;
+
+#ifdef CONFIG_OOM_SCORE_NOTIFIER
+ err = oom_score_notify_update(task, old_oom_score_adj);
+ if (err) {
+ /* rollback and error handle. */
+ task->signal->oom_score_adj = old_oom_score_adj;
+ goto err_unlock;
+ }
+#endif
+
trace_oom_score_adj_update(task);
if (mm) {
diff --git a/include/linux/oom_score_notifier.h b/include/linux/oom_score_notifier.h
new file mode 100644
index 0000000..c5cea47
--- /dev/null
+++ b/include/linux/oom_score_notifier.h
@@ -0,0 +1,47 @@
+/*
+ * oom_score_notifier interface
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * Author: Peter Enderborg <peter.enderborg@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_OOM_SCORE_NOTIFIER_H
+#define _LINUX_OOM_SCORE_NOTIFIER_H
+
+#ifdef CONFIG_OOM_SCORE_NOTIFIER
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+enum osn_msg_type {
+ OSN_NEW,
+ OSN_FREE,
+ OSN_UPDATE
+};
+
+extern struct atomic_notifier_head oom_score_notifier;
+extern int oom_score_notifier_register(struct notifier_block *n);
+extern int oom_score_notifier_unregister(struct notifier_block *n);
+extern int oom_score_notify_free(struct task_struct *tsk);
+extern int oom_score_notify_new(struct task_struct *tsk);
+extern int oom_score_notify_update(struct task_struct *tsk, int old_score);
+
+struct oom_score_notifier_struct {
+ struct task_struct *tsk;
+ int old_score;
+};
+
+#else
+
+#define oom_score_notify_free(t) do {} while (0)
+#define oom_score_notify_new(t) false
+#define oom_score_notify_update(t, s) do {} while (0)
+
+#endif /* CONFIG_OOM_SCORE_NOTIFIER */
+
+#endif /* _LINUX_OOM_SCORE_NOTIFIER_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 12c679f..747c66c 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
+obj-$(CONFIG_OOM_SCORE_NOTIFIER) += oom_score_notifier.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
obj-$(CONFIG_ELFCORE) += elfcore.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
diff --git a/kernel/fork.c b/kernel/fork.c
index 11c5c8a..f8a1a89 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -73,6 +73,7 @@
#include <linux/signalfd.h>
#include <linux/uprobes.h>
#include <linux/aio.h>
+#include <linux/oom_score_notifier.h>
#include <linux/compiler.h>
#include <linux/sysctl.h>
#include <linux/kcov.h>
@@ -391,6 +392,7 @@ void __put_task_struct(struct task_struct *tsk)
exit_creds(tsk);
delayacct_tsk_free(tsk);
put_signal_struct(tsk->signal);
+ oom_score_notify_free(tsk);
if (!profile_handoff_task(tsk))
free_task(tsk);
@@ -1790,6 +1792,10 @@ static __latent_entropy struct task_struct *copy_process(
init_task_pid(p, PIDTYPE_PID, pid);
if (thread_group_leader(p)) {
+ retval = oom_score_notify_new(p);
+ if (retval)
+ goto bad_fork_cancel_cgroup;
+
init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));
init_task_pid(p, PIDTYPE_SID, task_session(current));
diff --git a/kernel/oom_score_notifier.c b/kernel/oom_score_notifier.c
new file mode 100644
index 0000000..6dd6d8e
--- /dev/null
+++ b/kernel/oom_score_notifier.c
@@ -0,0 +1,75 @@
+/*
+ * oom_score_notifier interface
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * Author: Peter Enderborg <peter.enderborg@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/notifier.h>
+#include <linux/oom_score_notifier.h>
+
+#ifdef CONFIG_OOM_SCORE_NOTIFIER
+ATOMIC_NOTIFIER_HEAD(oom_score_notifier);
+
+int oom_score_notifier_register(struct notifier_block *n)
+{
+ return atomic_notifier_chain_register(&oom_score_notifier, n);
+}
+EXPORT_SYMBOL_GPL(oom_score_notifier_register);
+
+int oom_score_notifier_unregister(struct notifier_block *n)
+{
+ return atomic_notifier_chain_unregister(&oom_score_notifier, n);
+}
+EXPORT_SYMBOL_GPL(oom_score_notifier_unregister);
+
+int oom_score_notify_free(struct task_struct *tsk)
+{
+ struct oom_score_notifier_struct osns;
+
+ osns.tsk = tsk;
+ return notifier_to_errno(atomic_notifier_call_chain(
+ &oom_score_notifier, OSN_FREE, &osns));
+}
+EXPORT_SYMBOL_GPL(oom_score_notify_free);
+
+int oom_score_notify_new(struct task_struct *tsk)
+{
+ struct oom_score_notifier_struct osns;
+
+ osns.tsk = tsk;
+ return notifier_to_errno(atomic_notifier_call_chain(
+ &oom_score_notifier, OSN_NEW, &osns));
+}
+EXPORT_SYMBOL_GPL(oom_score_notify_new);
+
+int oom_score_notify_update(struct task_struct *tsk, int old_score)
+{
+ struct oom_score_notifier_struct osns;
+
+ osns.tsk = tsk;
+ osns.old_score = old_score;
+ return notifier_to_errno(atomic_notifier_call_chain(&oom_score_notifier,
+ OSN_UPDATE, &osns));
+}
+EXPORT_SYMBOL_GPL(oom_score_notify_update);
+
+#else
+inline int oom_score_notifier_register(struct notifier_block *n) { return 0; };
+inline int oom_score_notifier_unregister(struct notifier_block *n)
+{
+ return 0;
+};
+inline int oom_score_notify_free(struct task_struct *tsk) { return 0; };
+inline int oom_score_notify_new(struct task_struct *tsk) { return 0; };
+inline int oom_score_notify_update(struct task_struct *tsk, int old_score)
+{
+ return 0;
+};
+
+#endif
diff --git a/mm/Kconfig b/mm/Kconfig
index 9b8fccb..fb2a5d2 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -327,6 +327,15 @@ config MMU_NOTIFIER
bool
select SRCU
+config OOM_SCORE_NOTIFIER
+ bool "OOM score notifier"
+ default n
+ help
+ This create a notifier for process oom_score_adj status.
+ It create events for new, updated or freed tasks and
+ are used to build a mirrored task list in
+ lowmemmorykiller.
+
config KSM
bool "Enable KSM for page merging"
depends on MMU
--
2.4.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj
2017-02-09 13:21 [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj peter enderborg
@ 2017-02-09 19:40 ` Michal Hocko
0 siblings, 0 replies; 3+ messages in thread
From: Michal Hocko @ 2017-02-09 19:40 UTC (permalink / raw)
To: peter enderborg
Cc: devel, Greg Kroah-Hartman, linux-kernel,
Arve Hjønnevåg, Riley Andrews, Linus Torvalds,
linux-mm
On Thu 09-02-17 14:21:49, peter enderborg wrote:
> This adds subscribtion for changes in oom_score_adj, this
> value is important to android systems.
Why? Who is user of this API?
--
Michal Hocko
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/3 staging-next] android: Collect statistics from lowmemorykiller
@ 2017-02-14 16:09 peter.enderborg
2017-02-14 16:09 ` [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj peter.enderborg
0 siblings, 1 reply; 3+ messages in thread
From: peter.enderborg @ 2017-02-14 16:09 UTC (permalink / raw)
To: devel, gregkh, linux-kernel, arve, riandrews, torvalds, linux-mm
Cc: Peter Enderborg
From: Peter Enderborg <peter.enderborg@sonymobile.com>
This collects stats for shrinker calls and how much
waste work we do within the lowmemorykiller.
Signed-off-by: Peter Enderborg <peter.enderborg@sonymobile.com>
---
drivers/staging/android/Kconfig | 11 ++++
drivers/staging/android/Makefile | 1 +
drivers/staging/android/lowmemorykiller.c | 9 ++-
drivers/staging/android/lowmemorykiller_stats.c | 85 +++++++++++++++++++++++++
drivers/staging/android/lowmemorykiller_stats.h | 29 +++++++++
5 files changed, 134 insertions(+), 1 deletion(-)
create mode 100644 drivers/staging/android/lowmemorykiller_stats.c
create mode 100644 drivers/staging/android/lowmemorykiller_stats.h
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 6c00d6f..96e86c7 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -24,6 +24,17 @@ config ANDROID_LOW_MEMORY_KILLER
scripts (/init.rc), and it defines priority values with minimum free memory size
for each priority.
+config ANDROID_LOW_MEMORY_KILLER_STATS
+ bool "Android Low Memory Killer: collect statistics"
+ depends on ANDROID_LOW_MEMORY_KILLER
+ default n
+ help
+ Create a file in /proc/lmkstats that includes
+ collected statistics about kills, scans and counts
+ and interaction with the shrinker. Its content
+ will be different depeding on lmk implementation used.
+
+
source "drivers/staging/android/ion/Kconfig"
endif # if ANDROID
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index 7ed1be7..d710eb2 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -4,3 +4,4 @@ obj-y += ion/
obj-$(CONFIG_ASHMEM) += ashmem.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
+obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER_STATS) += lowmemorykiller_stats.o
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index ec3b665..15c1b38 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -42,6 +42,7 @@
#include <linux/rcupdate.h>
#include <linux/profile.h>
#include <linux/notifier.h>
+#include "lowmemorykiller_stats.h"
static u32 lowmem_debug_level = 1;
static short lowmem_adj[6] = {
@@ -72,6 +73,7 @@ static unsigned long lowmem_deathpending_timeout;
static unsigned long lowmem_count(struct shrinker *s,
struct shrink_control *sc)
{
+ lmk_inc_stats(LMK_COUNT);
return global_node_page_state(NR_ACTIVE_ANON) +
global_node_page_state(NR_ACTIVE_FILE) +
global_node_page_state(NR_INACTIVE_ANON) +
@@ -95,6 +97,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
global_node_page_state(NR_SHMEM) -
total_swapcache_pages();
+ lmk_inc_stats(LMK_SCAN);
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
@@ -134,6 +137,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
if (task_lmk_waiting(p) &&
time_before_eq(jiffies, lowmem_deathpending_timeout)) {
task_unlock(p);
+ lmk_inc_stats(LMK_TIMEOUT);
rcu_read_unlock();
return 0;
}
@@ -179,7 +183,9 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
other_free * (long)(PAGE_SIZE / 1024));
lowmem_deathpending_timeout = jiffies + HZ;
rem += selected_tasksize;
- }
+ lmk_inc_stats(LMK_KILL);
+ } else
+ lmk_inc_stats(LMK_WASTE);
lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
sc->nr_to_scan, sc->gfp_mask, rem);
@@ -196,6 +202,7 @@ static struct shrinker lowmem_shrinker = {
static int __init lowmem_init(void)
{
register_shrinker(&lowmem_shrinker);
+ init_procfs_lmk();
return 0;
}
device_initcall(lowmem_init);
diff --git a/drivers/staging/android/lowmemorykiller_stats.c b/drivers/staging/android/lowmemorykiller_stats.c
new file mode 100644
index 0000000..673691c
--- /dev/null
+++ b/drivers/staging/android/lowmemorykiller_stats.c
@@ -0,0 +1,85 @@
+/*
+ * lowmemorykiller_stats
+ *
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * Author: Peter Enderborg <peter.enderborg@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/* This code is bookkeeping of statistical information
+ * from lowmemorykiller and provide a node in proc "/proc/lmkstats".
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include "lowmemorykiller_stats.h"
+
+struct lmk_stats {
+ atomic_long_t scans; /* counter as in shrinker scans */
+ atomic_long_t kills; /* the number of sigkills sent */
+ atomic_long_t waste; /* the numer of extensive calls that did
+ * not lead to anything
+ */
+ atomic_long_t timeout; /* counter for shrinker calls that needed
+ * to be cancelled due to pending kills
+ */
+ atomic_long_t count; /* number of shrinker count calls */
+ atomic_long_t unknown; /* internal */
+} st;
+
+void lmk_inc_stats(int key)
+{
+ switch (key) {
+ case LMK_SCAN:
+ atomic_long_inc(&st.scans);
+ break;
+ case LMK_KILL:
+ atomic_long_inc(&st.kills);
+ break;
+ case LMK_WASTE:
+ atomic_long_inc(&st.waste);
+ break;
+ case LMK_TIMEOUT:
+ atomic_long_inc(&st.timeout);
+ break;
+ case LMK_COUNT:
+ atomic_long_inc(&st.count);
+ break;
+ default:
+ atomic_long_inc(&st.unknown);
+ break;
+ }
+}
+
+static int lmk_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "kill: %ld\n", atomic_long_read(&st.kills));
+ seq_printf(m, "scan: %ld\n", atomic_long_read(&st.scans));
+ seq_printf(m, "waste: %ld\n", atomic_long_read(&st.waste));
+ seq_printf(m, "timeout: %ld\n", atomic_long_read(&st.timeout));
+ seq_printf(m, "count: %ld\n", atomic_long_read(&st.count));
+ seq_printf(m, "unknown: %ld (internal)\n",
+ atomic_long_read(&st.unknown));
+
+ return 0;
+}
+
+static int lmk_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, lmk_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations lmk_proc_fops = {
+ .open = lmk_proc_open,
+ .read = seq_read,
+ .release = single_release
+};
+
+int __init init_procfs_lmk(void)
+{
+ proc_create_data(LMK_PROCFS_NAME, 0444, NULL, &lmk_proc_fops, NULL);
+ return 0;
+}
diff --git a/drivers/staging/android/lowmemorykiller_stats.h b/drivers/staging/android/lowmemorykiller_stats.h
new file mode 100644
index 0000000..abeb6924
--- /dev/null
+++ b/drivers/staging/android/lowmemorykiller_stats.h
@@ -0,0 +1,29 @@
+/*
+ * lowmemorykiller_stats interface
+ *
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * Author: Peter Enderborg <peter.enderborg@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+enum lmk_kill_stats {
+ LMK_SCAN = 1,
+ LMK_KILL = 2,
+ LMK_WASTE = 3,
+ LMK_TIMEOUT = 4,
+ LMK_COUNT = 5
+};
+
+#define LMK_PROCFS_NAME "lmkstats"
+
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_STATS
+void lmk_inc_stats(int key);
+int __init init_procfs_lmk(void);
+#else
+static inline void lmk_inc_stats(int key) { return; };
+static inline int __init init_procfs_lmk(void) { return 0; };
+#endif
--
2.4.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj
2017-02-14 16:09 [PATCH 1/3 staging-next] android: Collect statistics from lowmemorykiller peter.enderborg
@ 2017-02-14 16:09 ` peter.enderborg
0 siblings, 0 replies; 3+ messages in thread
From: peter.enderborg @ 2017-02-14 16:09 UTC (permalink / raw)
To: devel, gregkh, linux-kernel, arve, riandrews, torvalds, linux-mm
Cc: Peter Enderborg
From: Peter Enderborg <peter.enderborg@sonymobile.com>
This adds subscribtion for changes in oom_score_adj, this
value is important to android systems. For task that uses
oom_score_adj they read the task list. This can be long
and need rcu locks and has a impact on the system. Let
the user track the changes based on oom_score_adj changes
and keep them in their own context so they do their actions
with minimal system impact.
Signed-off-by: Peter Enderborg <peter.enderborg@sonymobile.com>
---
fs/proc/base.c | 13 +++++++
include/linux/oom_score_notifier.h | 47 ++++++++++++++++++++++++
kernel/Makefile | 1 +
kernel/fork.c | 6 +++
kernel/oom_score_notifier.c | 75 ++++++++++++++++++++++++++++++++++++++
mm/Kconfig | 9 +++++
6 files changed, 151 insertions(+)
create mode 100644 include/linux/oom_score_notifier.h
create mode 100644 kernel/oom_score_notifier.c
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 87c9a9a..60c2d9b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -87,6 +87,7 @@
#include <linux/slab.h>
#include <linux/flex_array.h>
#include <linux/posix-timers.h>
+#include <linux/oom_score_notifier.h>
#ifdef CONFIG_HARDWALL
#include <asm/hardwall.h>
#endif
@@ -1057,6 +1058,7 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
static DEFINE_MUTEX(oom_adj_mutex);
struct mm_struct *mm = NULL;
struct task_struct *task;
+ int old_oom_score_adj;
int err = 0;
task = get_proc_task(file_inode(file));
@@ -1102,9 +1104,20 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
}
}
+ old_oom_score_adj = task->signal->oom_score_adj;
task->signal->oom_score_adj = oom_adj;
if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
task->signal->oom_score_adj_min = (short)oom_adj;
+
+#ifdef CONFIG_OOM_SCORE_NOTIFIER
+ err = oom_score_notify_update(task, old_oom_score_adj);
+ if (err) {
+ /* rollback and error handle. */
+ task->signal->oom_score_adj = old_oom_score_adj;
+ goto err_unlock;
+ }
+#endif
+
trace_oom_score_adj_update(task);
if (mm) {
diff --git a/include/linux/oom_score_notifier.h b/include/linux/oom_score_notifier.h
new file mode 100644
index 0000000..c5cea47
--- /dev/null
+++ b/include/linux/oom_score_notifier.h
@@ -0,0 +1,47 @@
+/*
+ * oom_score_notifier interface
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * Author: Peter Enderborg <peter.enderborg@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_OOM_SCORE_NOTIFIER_H
+#define _LINUX_OOM_SCORE_NOTIFIER_H
+
+#ifdef CONFIG_OOM_SCORE_NOTIFIER
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+enum osn_msg_type {
+ OSN_NEW,
+ OSN_FREE,
+ OSN_UPDATE
+};
+
+extern struct atomic_notifier_head oom_score_notifier;
+extern int oom_score_notifier_register(struct notifier_block *n);
+extern int oom_score_notifier_unregister(struct notifier_block *n);
+extern int oom_score_notify_free(struct task_struct *tsk);
+extern int oom_score_notify_new(struct task_struct *tsk);
+extern int oom_score_notify_update(struct task_struct *tsk, int old_score);
+
+struct oom_score_notifier_struct {
+ struct task_struct *tsk;
+ int old_score;
+};
+
+#else
+
+#define oom_score_notify_free(t) do {} while (0)
+#define oom_score_notify_new(t) false
+#define oom_score_notify_update(t, s) do {} while (0)
+
+#endif /* CONFIG_OOM_SCORE_NOTIFIER */
+
+#endif /* _LINUX_OOM_SCORE_NOTIFIER_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 12c679f..747c66c 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
+obj-$(CONFIG_OOM_SCORE_NOTIFIER) += oom_score_notifier.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
obj-$(CONFIG_ELFCORE) += elfcore.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
diff --git a/kernel/fork.c b/kernel/fork.c
index 11c5c8a..f8a1a89 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -73,6 +73,7 @@
#include <linux/signalfd.h>
#include <linux/uprobes.h>
#include <linux/aio.h>
+#include <linux/oom_score_notifier.h>
#include <linux/compiler.h>
#include <linux/sysctl.h>
#include <linux/kcov.h>
@@ -391,6 +392,7 @@ void __put_task_struct(struct task_struct *tsk)
exit_creds(tsk);
delayacct_tsk_free(tsk);
put_signal_struct(tsk->signal);
+ oom_score_notify_free(tsk);
if (!profile_handoff_task(tsk))
free_task(tsk);
@@ -1790,6 +1792,10 @@ static __latent_entropy struct task_struct *copy_process(
init_task_pid(p, PIDTYPE_PID, pid);
if (thread_group_leader(p)) {
+ retval = oom_score_notify_new(p);
+ if (retval)
+ goto bad_fork_cancel_cgroup;
+
init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));
init_task_pid(p, PIDTYPE_SID, task_session(current));
diff --git a/kernel/oom_score_notifier.c b/kernel/oom_score_notifier.c
new file mode 100644
index 0000000..6dd6d8e
--- /dev/null
+++ b/kernel/oom_score_notifier.c
@@ -0,0 +1,75 @@
+/*
+ * oom_score_notifier interface
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * Author: Peter Enderborg <peter.enderborg@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/notifier.h>
+#include <linux/oom_score_notifier.h>
+
+#ifdef CONFIG_OOM_SCORE_NOTIFIER
+ATOMIC_NOTIFIER_HEAD(oom_score_notifier);
+
+int oom_score_notifier_register(struct notifier_block *n)
+{
+ return atomic_notifier_chain_register(&oom_score_notifier, n);
+}
+EXPORT_SYMBOL_GPL(oom_score_notifier_register);
+
+int oom_score_notifier_unregister(struct notifier_block *n)
+{
+ return atomic_notifier_chain_unregister(&oom_score_notifier, n);
+}
+EXPORT_SYMBOL_GPL(oom_score_notifier_unregister);
+
+int oom_score_notify_free(struct task_struct *tsk)
+{
+ struct oom_score_notifier_struct osns;
+
+ osns.tsk = tsk;
+ return notifier_to_errno(atomic_notifier_call_chain(
+ &oom_score_notifier, OSN_FREE, &osns));
+}
+EXPORT_SYMBOL_GPL(oom_score_notify_free);
+
+int oom_score_notify_new(struct task_struct *tsk)
+{
+ struct oom_score_notifier_struct osns;
+
+ osns.tsk = tsk;
+ return notifier_to_errno(atomic_notifier_call_chain(
+ &oom_score_notifier, OSN_NEW, &osns));
+}
+EXPORT_SYMBOL_GPL(oom_score_notify_new);
+
+int oom_score_notify_update(struct task_struct *tsk, int old_score)
+{
+ struct oom_score_notifier_struct osns;
+
+ osns.tsk = tsk;
+ osns.old_score = old_score;
+ return notifier_to_errno(atomic_notifier_call_chain(&oom_score_notifier,
+ OSN_UPDATE, &osns));
+}
+EXPORT_SYMBOL_GPL(oom_score_notify_update);
+
+#else
+inline int oom_score_notifier_register(struct notifier_block *n) { return 0; };
+inline int oom_score_notifier_unregister(struct notifier_block *n)
+{
+ return 0;
+};
+inline int oom_score_notify_free(struct task_struct *tsk) { return 0; };
+inline int oom_score_notify_new(struct task_struct *tsk) { return 0; };
+inline int oom_score_notify_update(struct task_struct *tsk, int old_score)
+{
+ return 0;
+};
+
+#endif
diff --git a/mm/Kconfig b/mm/Kconfig
index 9b8fccb..fb2a5d2 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -327,6 +327,15 @@ config MMU_NOTIFIER
bool
select SRCU
+config OOM_SCORE_NOTIFIER
+ bool "OOM score notifier"
+ default n
+ help
+ This create a notifier for process oom_score_adj status.
+ It create events for new, updated or freed tasks and
+ are used to build a mirrored task list in
+ lowmemmorykiller.
+
config KSM
bool "Enable KSM for page merging"
depends on MMU
--
2.4.2
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-02-14 16:09 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-09 13:21 [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj peter enderborg
2017-02-09 19:40 ` Michal Hocko
2017-02-14 16:09 [PATCH 1/3 staging-next] android: Collect statistics from lowmemorykiller peter.enderborg
2017-02-14 16:09 ` [PATCH 2/3 staging-next] oom: Add notification for oom_score_adj peter.enderborg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox