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

Popular Posts