Merge tag 'media/v4.8-6' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[deliverable/linux.git] / fs / proc / base.c
index 13a345952cc74b831f08392229e8ba9a96b0e09a..54e270262979b6f331a31b132171c0b74b92b920 100644 (file)
@@ -579,11 +579,8 @@ static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns,
        unsigned long totalpages = totalram_pages + total_swap_pages;
        unsigned long points = 0;
 
-       read_lock(&tasklist_lock);
-       if (pid_alive(task))
-               points = oom_badness(task, NULL, NULL, totalpages) *
-                                               1000 / totalpages;
-       read_unlock(&tasklist_lock);
+       points = oom_badness(task, NULL, NULL, totalpages) *
+                                       1000 / totalpages;
        seq_printf(m, "%lu\n", points);
 
        return 0;
@@ -1040,6 +1037,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 DEFINE_MUTEX(oom_adj_mutex);
+       struct mm_struct *mm = NULL;
        struct task_struct *task;
        int err = 0;
 
@@ -1069,10 +1067,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;
        if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
                task->signal->oom_score_adj_min = (short)oom_adj;
        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:
        mutex_unlock(&oom_adj_mutex);
        put_task_struct(task);
This page took 0.025684 seconds and 5 git commands to generate.