Merge tag 'trace-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux-2.6-microblaze.git] / mm / oom_kill.c
index c729a4c..831340e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched/task.h>
 #include <linux/sched/debug.h>
 #include <linux/swap.h>
+#include <linux/syscalls.h>
 #include <linux/timex.h>
 #include <linux/jiffies.h>
 #include <linux/cpuset.h>
@@ -1141,3 +1142,72 @@ void pagefault_out_of_memory(void)
        out_of_memory(&oc);
        mutex_unlock(&oom_lock);
 }
+
+SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags)
+{
+#ifdef CONFIG_MMU
+       struct mm_struct *mm = NULL;
+       struct task_struct *task;
+       struct task_struct *p;
+       unsigned int f_flags;
+       bool reap = true;
+       struct pid *pid;
+       long ret = 0;
+
+       if (flags)
+               return -EINVAL;
+
+       pid = pidfd_get_pid(pidfd, &f_flags);
+       if (IS_ERR(pid))
+               return PTR_ERR(pid);
+
+       task = get_pid_task(pid, PIDTYPE_TGID);
+       if (!task) {
+               ret = -ESRCH;
+               goto put_pid;
+       }
+
+       /*
+        * Make sure to choose a thread which still has a reference to mm
+        * during the group exit
+        */
+       p = find_lock_task_mm(task);
+       if (!p) {
+               ret = -ESRCH;
+               goto put_task;
+       }
+
+       mm = p->mm;
+       mmgrab(mm);
+
+       /* If the work has been done already, just exit with success */
+       if (test_bit(MMF_OOM_SKIP, &mm->flags))
+               reap = false;
+       else if (!task_will_free_mem(p)) {
+               reap = false;
+               ret = -EINVAL;
+       }
+       task_unlock(p);
+
+       if (!reap)
+               goto drop_mm;
+
+       if (mmap_read_lock_killable(mm)) {
+               ret = -EINTR;
+               goto drop_mm;
+       }
+       if (!__oom_reap_task_mm(mm))
+               ret = -EAGAIN;
+       mmap_read_unlock(mm);
+
+drop_mm:
+       mmdrop(mm);
+put_task:
+       put_task_struct(task);
+put_pid:
+       put_pid(pid);
+       return ret;
+#else
+       return -ENOSYS;
+#endif /* CONFIG_MMU */
+}