avoid no response when linux low memory
directly by the keyboard combination SysRq-F.
SysRq key is usually combined within PrtSc key on keyboards.
use earlyoom utils
vm.overcommit_memory=2 vm.overcommit_ratio=100
https://news.ycombinator.com/item?id=20620545
https://www.reddit.com/r/linux/comments/56r4xj/why_are_low_memory_conditions_handled_so_badly/
https://stackoverflow.com/questions/52067753/how-to-keep-executable-code-in-memory-even-under-memory-pressure-in-linux
commit 8275959d6cf4212af50b2a4c8fe35fb1d5f984be
Author: guoxing.pei <guoxing.pei@t2mobile.com>
Date: Wed Sep 11 10:27:41 2024 +0800
patch to avoid oom
diff --git a/kernel/fork.c b/kernel/fork.c
index 4d3bdef9..85c36423 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2408,6 +2408,35 @@ long _do_fork(unsigned long clone_flags,
trace = 0;
}
+ {
+ struct task_struct *tsk;
+ int runnable_task_count = 0;
+ pid_t pgid = task_pgrp(current);
+
+ int flags = current->flags;
+ current->flags |= PF_KSWAPD;
+
+ do {
+ if (runnable_task_count > 0)
+ do_sched_yield();
+
+ rcu_read_lock();
+ runnable_task_count = 0;
+ for_each_process(tsk) {
+ if (tsk->tgid == pgid &&
+ !(tsk->flags & PF_KSWAPD) &&
+ tsk->state == TASK_RUNNING)
+ runnable_task_count++;
+ }
+ rcu_read_unlock();
+
+ } while (runnable_task_count > 2);
+
+ if (!(flags & PF_KSWAPD))
+ current->flags &= ~PF_KSWAPD;
+ }
+
+
p = copy_process(clone_flags, stack_start, stack_size, parent_tidptr,
child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
add_latent_entropy();
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 68559808..67e2d61c 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -198,6 +198,36 @@ static inline int kexec_load_check(unsigned long nr_segments,
{
int result;
+ {
+ struct task_struct *tsk;
+ int runnable_task_count = 0;
+ pid_t pgid = task_pgrp(current);
+
+ int flags = current->flags;
+ current->flags |= PF_KSWAPD;
+
+ do {
+
+ if (runnable_task_count > 0)
+ do_sched_yield();
+
+
+ rcu_read_lock();
+ runnable_task_count = 0;
+ for_each_process(tsk) {
+ if (tsk->tgid == pgid &&
+ !(tsk->flags & PF_KSWAPD) &&
+ tsk->state == TASK_RUNNING)
+ runnable_task_count++;
+ }
+ rcu_read_unlock();
+
+ } while (runnable_task_count > 2);
+
+ if (!(flags & PF_KSWAPD))
+ current->flags &= ~PF_KSWAPD;
+ }
+
/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM;
{ struct task_struct *tsk; int runnable_task_count = 0; pid_t pgid = task_pgrp(current); do { if (runnable_task_count > 0) yield(); current->flags |= PF_KSWAPD; rcu_read_lock(); runnable_task_count = 0; for_each_process(tsk) { if (tsk->tgid == pgid && !(tsk->flags & PF_KSWAPD) && task_is_running(tsk)) runnable_task_count++; } rcu_read_unlock(); } while (runnable_task_count > 2); }
diff --git a/kernel/fork.c b/kernel/fork.c
index 4d3bdef952fc..0f73be84a247 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2390,6 +2390,45 @@ long _do_fork(unsigned long clone_flags,
int trace = 0;
long nr;
+ {
+ struct task_struct *p;
+ struct task_struct *ignored_task = current;
+ struct pid * pgrp = task_pgrp(current);
+
+ int runnable_task_count = 0;
+ int flags = current->flags;
+ current->flags |= PF_KSWAPD;
+
+ do {
+
+ if (runnable_task_count > 0) yield();
+
+ read_lock(&tasklist_lock);
+ runnable_task_count = 0;
+ do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
+ if ((p == ignored_task) ||
+ (p->exit_state && thread_group_empty(p)) ||
+ is_global_init(p->real_parent))
+ continue;
+
+#if 0
+ if (task_pgrp(p->real_parent) != pgrp &&
+ task_session(p->real_parent) == task_session(p))
+ continue;
+#endif
+
+ if (!(p->flags & PF_KSWAPD) &&
+ p->state == TASK_RUNNING)
+ runnable_task_count++;
+ } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
+ read_unlock(&tasklist_lock);
+
+ } while (runnable_task_count > 4);
+
+ if (!(flags & PF_KSWAPD))
+ current->flags &= ~PF_KSWAPD;
+ }
+
/*
* Determine whether and which event to report to ptracer. When
* called from kernel_thread or CLONE_UNTRACED is explicitly
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 68559808fdfa..9709ebf71c90 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -198,6 +198,45 @@ static inline int kexec_load_check(unsigned long nr_segments,
{
int result;
+ {
+ struct task_struct *p;
+ struct task_struct *ignored_task = current;
+ struct pid * pgrp = task_pgrp(current);
+
+ int runnable_task_count = 0;
+ int flags = current->flags;
+ current->flags |= PF_KSWAPD;
+
+ do {
+
+ if (runnable_task_count > 0) yield();
+
+ read_lock(&tasklist_lock);
+ runnable_task_count = 0;
+ do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
+ if ((p == ignored_task) ||
+ (p->exit_state && thread_group_empty(p)) ||
+ is_global_init(p->real_parent))
+ continue;
+
+#if 0
+ if (task_pgrp(p->real_parent) != pgrp &&
+ task_session(p->real_parent) == task_session(p))
+ continue;
+#endif
+
+ if (!(p->flags & PF_KSWAPD) &&
+ p->state == TASK_RUNNING)
+ runnable_task_count++;
+ } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
+ read_unlock(&tasklist_lock);
+
+ } while (runnable_task_count > 4);
+
+ if (!(flags & PF_KSWAPD))
+ current->flags &= ~PF_KSWAPD;
+ }
+
/* We only trust the superuser with rebooting the system. */
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM;
Comments
Post a Comment