|
@@ -1040,6 +1040,7 @@ static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
|
|
static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
|
|
static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
|
|
{
|
|
{
|
|
static DEFINE_MUTEX(oom_adj_mutex);
|
|
static DEFINE_MUTEX(oom_adj_mutex);
|
|
|
|
+ struct mm_struct *mm = NULL;
|
|
struct task_struct *task;
|
|
struct task_struct *task;
|
|
int err = 0;
|
|
int err = 0;
|
|
|
|
|
|
@@ -1069,10 +1070,55 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Make sure we will check other processes sharing the mm if this is
|
|
|
|
+ * not vfrok which wants its own oom_score_adj.
|
|
|
|
+ * pin the mm so it doesn't go away and get reused after task_unlock
|
|
|
|
+ */
|
|
|
|
+ if (!task->vfork_done) {
|
|
|
|
+ struct task_struct *p = find_lock_task_mm(task);
|
|
|
|
+
|
|
|
|
+ if (p) {
|
|
|
|
+ if (atomic_read(&p->mm->mm_users) > 1) {
|
|
|
|
+ mm = p->mm;
|
|
|
|
+ atomic_inc(&mm->mm_count);
|
|
|
|
+ }
|
|
|
|
+ task_unlock(p);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
task->signal->oom_score_adj = oom_adj;
|
|
task->signal->oom_score_adj = oom_adj;
|
|
if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
|
|
if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
|
|
task->signal->oom_score_adj_min = (short)oom_adj;
|
|
task->signal->oom_score_adj_min = (short)oom_adj;
|
|
trace_oom_score_adj_update(task);
|
|
trace_oom_score_adj_update(task);
|
|
|
|
+
|
|
|
|
+ if (mm) {
|
|
|
|
+ struct task_struct *p;
|
|
|
|
+
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+ for_each_process(p) {
|
|
|
|
+ if (same_thread_group(task, p))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ /* do not touch kernel threads or the global init */
|
|
|
|
+ if (p->flags & PF_KTHREAD || is_global_init(p))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ task_lock(p);
|
|
|
|
+ if (!p->vfork_done && process_shares_mm(p, mm)) {
|
|
|
|
+ pr_info("updating oom_score_adj for %d (%s) from %d to %d because it shares mm with %d (%s). Report if this is unexpected.\n",
|
|
|
|
+ task_pid_nr(p), p->comm,
|
|
|
|
+ p->signal->oom_score_adj, oom_adj,
|
|
|
|
+ task_pid_nr(task), task->comm);
|
|
|
|
+ p->signal->oom_score_adj = oom_adj;
|
|
|
|
+ if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
|
|
|
|
+ p->signal->oom_score_adj_min = (short)oom_adj;
|
|
|
|
+ }
|
|
|
|
+ task_unlock(p);
|
|
|
|
+ }
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+ mmdrop(mm);
|
|
|
|
+ }
|
|
err_unlock:
|
|
err_unlock:
|
|
mutex_unlock(&oom_adj_mutex);
|
|
mutex_unlock(&oom_adj_mutex);
|
|
put_task_struct(task);
|
|
put_task_struct(task);
|