]> git.ipfire.org Git - people/ms/linux.git/commitdiff
Merge branch 'master' into for-4.4-fixes
authorTejun Heo <tj@kernel.org>
Mon, 7 Dec 2015 15:09:03 +0000 (10:09 -0500)
committerTejun Heo <tj@kernel.org>
Mon, 7 Dec 2015 15:09:03 +0000 (10:09 -0500)
The following commit which went into mainline through networking tree

  3b13758f51de ("cgroups: Allow dynamically changing net_classid")

conflicts in net/core/netclassid_cgroup.c with the following pending
fix in cgroup/for-4.4-fixes.

  1f7dd3e5a6e4 ("cgroup: fix handling of multi-destination migration from subtree_control enabling")

The former separates out update_classid() from cgrp_attach() and
updates it to walk all fds of all tasks in the target css so that it
can be used from both migration and config change paths.  The latter
drops @css from cgrp_attach().

Resolve the conflict by making cgrp_attach() call update_classid()
with the css from the first task.  We can revive @tset walking in
cgrp_attach() but given that net_cls is v1 only where there always is
only one target css during migration, this is fine.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Nina Schiff <ninasc@fb.com>
1  2 
kernel/sched/core.c
net/core/netclassid_cgroup.c

diff --combined kernel/sched/core.c
index a9db4819e58606f11cb35768fe8f727e85425c14,7063c6a0744055c367eb82159677cfe6522b6c60..732e993b564b8179e5723bb88839329eec6df8f5
@@@ -1946,6 -1946,25 +1946,25 @@@ try_to_wake_up(struct task_struct *p, u
                goto stat;
  
  #ifdef CONFIG_SMP
+       /*
+        * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
+        * possible to, falsely, observe p->on_cpu == 0.
+        *
+        * One must be running (->on_cpu == 1) in order to remove oneself
+        * from the runqueue.
+        *
+        *  [S] ->on_cpu = 1;   [L] ->on_rq
+        *      UNLOCK rq->lock
+        *                      RMB
+        *      LOCK   rq->lock
+        *  [S] ->on_rq = 0;    [L] ->on_cpu
+        *
+        * Pairs with the full barrier implied in the UNLOCK+LOCK on rq->lock
+        * from the consecutive calls to schedule(); the first switching to our
+        * task, the second putting it to sleep.
+        */
+       smp_rmb();
        /*
         * If the owning (remote) cpu is still in the middle of schedule() with
         * this task as prev, wait until its done referencing the task.
        while (p->on_cpu)
                cpu_relax();
        /*
-        * Pairs with the smp_wmb() in finish_lock_switch().
+        * Combined with the control dependency above, we have an effective
+        * smp_load_acquire() without the need for full barriers.
+        *
+        * Pairs with the smp_store_release() in finish_lock_switch().
+        *
+        * This ensures that tasks getting woken will be fully ordered against
+        * their previous state and preserve Program Order.
         */
        smp_rmb();
  
@@@ -2039,7 -2064,6 +2064,6 @@@ out
   */
  int wake_up_process(struct task_struct *p)
  {
-       WARN_ON(task_is_stopped_or_traced(p));
        return try_to_wake_up(p, TASK_NORMAL, 0);
  }
  EXPORT_SYMBOL(wake_up_process);
@@@ -5847,13 -5871,13 +5871,13 @@@ static int init_rootdomain(struct root_
  {
        memset(rd, 0, sizeof(*rd));
  
-       if (!alloc_cpumask_var(&rd->span, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->span, GFP_KERNEL))
                goto out;
-       if (!alloc_cpumask_var(&rd->online, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->online, GFP_KERNEL))
                goto free_span;
-       if (!alloc_cpumask_var(&rd->dlo_mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->dlo_mask, GFP_KERNEL))
                goto free_online;
-       if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
                goto free_dlo_mask;
  
        init_dl_bw(&rd->dl_bw);
@@@ -8217,12 -8241,12 +8241,12 @@@ static void cpu_cgroup_fork(struct task
        sched_move_task(task);
  }
  
 -static int cpu_cgroup_can_attach(struct cgroup_subsys_state *css,
 -                               struct cgroup_taskset *tset)
 +static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
  {
        struct task_struct *task;
 +      struct cgroup_subsys_state *css;
  
 -      cgroup_taskset_for_each(task, tset) {
 +      cgroup_taskset_for_each(task, css, tset) {
  #ifdef CONFIG_RT_GROUP_SCHED
                if (!sched_rt_can_attach(css_tg(css), task))
                        return -EINVAL;
        return 0;
  }
  
 -static void cpu_cgroup_attach(struct cgroup_subsys_state *css,
 -                            struct cgroup_taskset *tset)
 +static void cpu_cgroup_attach(struct cgroup_taskset *tset)
  {
        struct task_struct *task;
 +      struct cgroup_subsys_state *css;
  
 -      cgroup_taskset_for_each(task, tset)
 +      cgroup_taskset_for_each(task, css, tset)
                sched_move_task(task);
  }
  
index 81cb3c72efe812656975a02daf6707f3e48d1f39,2e4df84c34a194ad61d818f282d1124521b9a828..d9ee8d08a3a6944ebb6e5d8dafe6fb5032aa7a52
@@@ -56,7 -56,7 +56,7 @@@ static void cgrp_css_free(struct cgroup
        kfree(css_cls_state(css));
  }
  
- static int update_classid(const void *v, struct file *file, unsigned n)
+ static int update_classid_sock(const void *v, struct file *file, unsigned n)
  {
        int err;
        struct socket *sock = sock_from_file(file, &err);
        return 0;
  }
  
- static void cgrp_attach(struct cgroup_taskset *tset)
+ static void update_classid(struct cgroup_subsys_state *css, void *v)
  {
+       struct css_task_iter it;
        struct task_struct *p;
-       struct cgroup_subsys_state *css;
-       cgroup_taskset_for_each(p, css, tset) {
-               struct cgroup_cls_state *cs = css_cls_state(css);
-               void *v = (void *)(unsigned long)cs->classid;
  
+       css_task_iter_start(css, &it);
+       while ((p = css_task_iter_next(&it))) {
                task_lock(p);
-               iterate_fd(p->files, 0, update_classid, v);
+               iterate_fd(p->files, 0, update_classid_sock, v);
                task_unlock(p);
        }
 -static void cgrp_attach(struct cgroup_subsys_state *css,
 -                      struct cgroup_taskset *tset)
+       css_task_iter_end(&it);
+ }
++static void cgrp_attach(struct cgroup_taskset *tset)
+ {
++      struct cgroup_subsys_state *css;
++
++      cgroup_taskset_first(tset, &css);
+       update_classid(css,
+                      (void *)(unsigned long)css_cls_state(css)->classid);
  }
  
  static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
  static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
                         u64 value)
  {
-       css_cls_state(css)->classid = (u32) value;
+       struct cgroup_cls_state *cs = css_cls_state(css);
+       cs->classid = (u32)value;
  
+       update_classid(css, (void *)(unsigned long)cs->classid);
        return 0;
  }