Merge branch 'for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Jul 2016 21:34:17 +0000 (14:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Jul 2016 21:34:17 +0000 (14:34 -0700)
Pull cgroup updates from Tejun Heo:
 "Nothing too exciting.

   - updates to the pids controller so that pid limit breaches can be
     noticed and monitored from userland.

   - cleanups and non-critical bug fixes"

* 'for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  cgroup: remove duplicated include from cgroup.c
  cgroup: Use lld instead of ld when printing pids controller events_limit
  cgroup: Add pids controller event when fork fails because of pid limit
  cgroup: allow NULL return from ss->css_alloc()
  cgroup: remove unnecessary 0 check from css_from_id()
  cgroup: fix idr leak for the first cgroup root

1  2 
kernel/cgroup.c

diff --combined kernel/cgroup.c
@@@ -61,7 -61,6 +61,6 @@@
  #include <linux/cpuset.h>
  #include <linux/proc_ns.h>
  #include <linux/nsproxy.h>
- #include <linux/proc_ns.h>
  #include <net/sock.h>
  
  /*
@@@ -837,8 -836,6 +836,8 @@@ static void put_css_set_locked(struct c
  
  static void put_css_set(struct css_set *cset)
  {
 +      unsigned long flags;
 +
        /*
         * Ensure that the refcount doesn't hit zero while any readers
         * can see it. Similar to atomic_dec_and_lock(), but for an
        if (atomic_add_unless(&cset->refcount, -1, 1))
                return;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irqsave(&css_set_lock, flags);
        put_css_set_locked(cset);
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irqrestore(&css_set_lock, flags);
  }
  
  /*
@@@ -1072,11 -1069,11 +1071,11 @@@ static struct css_set *find_css_set(str
  
        /* First see if we already have a cgroup group that matches
         * the desired set */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        cset = find_existing_css_set(old_cset, cgrp, template);
        if (cset)
                get_css_set(cset);
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        if (cset)
                return cset;
         * find_existing_css_set() */
        memcpy(cset->subsys, template, sizeof(cset->subsys));
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        /* Add reference counts and links from the new css_set. */
        list_for_each_entry(link, &old_cset->cgrp_links, cgrp_link) {
                struct cgroup *c = link->cgrp;
                css_get(css);
        }
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        return cset;
  }
@@@ -1160,18 -1157,12 +1159,12 @@@ static void cgroup_exit_root_id(struct 
  {
        lockdep_assert_held(&cgroup_mutex);
  
-       if (root->hierarchy_id) {
-               idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id);
-               root->hierarchy_id = 0;
-       }
+       idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id);
  }
  
  static void cgroup_free_root(struct cgroup_root *root)
  {
        if (root) {
-               /* hierarchy ID should already have been released */
-               WARN_ON_ONCE(root->hierarchy_id);
                idr_destroy(&root->cgroup_idr);
                kfree(root);
        }
@@@ -1194,7 -1185,7 +1187,7 @@@ static void cgroup_destroy_root(struct 
         * Release all the links from cset_links to this hierarchy's
         * root cgroup
         */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) {
                list_del(&link->cset_link);
                kfree(link);
        }
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        if (!list_empty(&root->root_list)) {
                list_del(&root->root_list);
@@@ -1602,11 -1593,11 +1595,11 @@@ static int rebind_subsystems(struct cgr
                ss->root = dst_root;
                css->cgroup = dcgrp;
  
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
                hash_for_each(css_set_table, i, cset, hlist)
                        list_move_tail(&cset->e_cset_node[ss->id],
                                       &dcgrp->e_csets[ss->id]);
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
  
                /* default hierarchy doesn't enable controllers by default */
                dst_root->subsys_mask |= 1 << ssid;
@@@ -1642,10 -1633,10 +1635,10 @@@ static int cgroup_show_path(struct seq_
        if (!buf)
                return -ENOMEM;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        ns_cgroup = current_cgns_cgroup_from_root(kf_cgroot);
        len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX);
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        if (len >= PATH_MAX)
                len = -ERANGE;
@@@ -1899,7 -1890,7 +1892,7 @@@ static void cgroup_enable_task_cg_lists
  {
        struct task_struct *p, *g;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        if (use_task_css_set_links)
                goto out_unlock;
                 * entry won't be deleted though the process has exited.
                 * Do it while holding siglock so that we don't end up
                 * racing against cgroup_exit().
 +               *
 +               * Interrupts were already disabled while acquiring
 +               * the css_set_lock, so we do not need to disable it
 +               * again when acquiring the sighand->siglock here.
                 */
 -              spin_lock_irq(&p->sighand->siglock);
 +              spin_lock(&p->sighand->siglock);
                if (!(p->flags & PF_EXITING)) {
                        struct css_set *cset = task_css_set(p);
  
                        list_add_tail(&p->cg_list, &cset->tasks);
                        get_css_set(cset);
                }
 -              spin_unlock_irq(&p->sighand->siglock);
 +              spin_unlock(&p->sighand->siglock);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
  out_unlock:
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  }
  
  static void init_cgroup_housekeeping(struct cgroup *cgrp)
@@@ -2049,13 -2036,13 +2042,13 @@@ static int cgroup_setup_root(struct cgr
         * Link the root cgroup in this hierarchy into all the css_set
         * objects.
         */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        hash_for_each(css_set_table, i, cset, hlist) {
                link_css_set(&tmp_links, cset, root_cgrp);
                if (css_set_populated(cset))
                        cgroup_update_populated(root_cgrp, true);
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        BUG_ON(!list_empty(&root_cgrp->self.children));
        BUG_ON(atomic_read(&root->nr_cgrps) != 1);
@@@ -2262,11 -2249,11 +2255,11 @@@ out_mount
                struct cgroup *cgrp;
  
                mutex_lock(&cgroup_mutex);
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
  
                cgrp = cset_cgroup_from_root(ns->root_cset, root);
  
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
                mutex_unlock(&cgroup_mutex);
  
                nsdentry = kernfs_node_dentry(cgrp->kn, dentry->d_sb);
@@@ -2343,11 -2330,11 +2336,11 @@@ char *cgroup_path_ns(struct cgroup *cgr
        char *ret;
  
        mutex_lock(&cgroup_mutex);
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        ret = cgroup_path_ns_locked(cgrp, buf, buflen, ns);
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        mutex_unlock(&cgroup_mutex);
  
        return ret;
@@@ -2375,7 -2362,7 +2368,7 @@@ char *task_cgroup_path(struct task_stru
        char *path = NULL;
  
        mutex_lock(&cgroup_mutex);
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        root = idr_get_next(&cgroup_hierarchy_idr, &hierarchy_id);
  
                        path = buf;
        }
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        mutex_unlock(&cgroup_mutex);
        return path;
  }
@@@ -2563,7 -2550,7 +2556,7 @@@ static int cgroup_taskset_migrate(struc
         * the new cgroup.  There are no failure cases after here, so this
         * is the commit point.
         */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry(cset, &tset->src_csets, mg_node) {
                list_for_each_entry_safe(task, tmp_task, &cset->mg_tasks, cg_list) {
                        struct css_set *from_cset = task_css_set(task);
                        put_css_set_locked(from_cset);
                }
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        /*
         * Migration is committed, all target tasks are now on dst_csets.
@@@ -2603,13 -2590,13 +2596,13 @@@ out_cancel_attach
                }
        } while_each_subsys_mask();
  out_release_tset:
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_splice_init(&tset->dst_csets, &tset->src_csets);
        list_for_each_entry_safe(cset, tmp_cset, &tset->src_csets, mg_node) {
                list_splice_tail_init(&cset->mg_tasks, &cset->tasks);
                list_del_init(&cset->mg_node);
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        return ret;
  }
  
@@@ -2640,7 -2627,7 +2633,7 @@@ static void cgroup_migrate_finish(struc
  
        lockdep_assert_held(&cgroup_mutex);
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) {
                cset->mg_src_cgrp = NULL;
                cset->mg_dst_cgrp = NULL;
                list_del_init(&cset->mg_preload_node);
                put_css_set_locked(cset);
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  }
  
  /**
@@@ -2789,7 -2776,7 +2782,7 @@@ static int cgroup_migrate(struct task_s
         * already PF_EXITING could be freed from underneath us unless we
         * take an rcu_read_lock.
         */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        rcu_read_lock();
        task = leader;
        do {
                        break;
        } while_each_thread(leader, task);
        rcu_read_unlock();
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        return cgroup_taskset_migrate(&tset, root);
  }
@@@ -2822,7 -2809,7 +2815,7 @@@ static int cgroup_attach_task(struct cg
                return -EBUSY;
  
        /* look up all src csets */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        rcu_read_lock();
        task = leader;
        do {
                        break;
        } while_each_thread(leader, task);
        rcu_read_unlock();
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        /* prepare dst csets and commit */
        ret = cgroup_migrate_prepare_dst(&preloaded_csets);
@@@ -2865,9 -2852,9 +2858,9 @@@ static int cgroup_procs_write_permissio
                struct cgroup *cgrp;
                struct inode *inode;
  
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
                cgrp = task_cgroup_from_root(task, &cgrp_dfl_root);
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
  
                while (!cgroup_is_descendant(dst_cgrp, cgrp))
                        cgrp = cgroup_parent(cgrp);
@@@ -2968,9 -2955,9 +2961,9 @@@ int cgroup_attach_task_all(struct task_
                if (root == &cgrp_dfl_root)
                        continue;
  
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
                from_cgrp = task_cgroup_from_root(from, root);
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
  
                retval = cgroup_attach_task(from_cgrp, tsk, false);
                if (retval)
@@@ -3086,7 -3073,7 +3079,7 @@@ static int cgroup_update_dfl_csses(stru
        percpu_down_write(&cgroup_threadgroup_rwsem);
  
        /* look up all csses currently attached to @cgrp's subtree */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) {
                struct cgrp_cset_link *link;
  
                        cgroup_migrate_add_src(link->cset, dsct,
                                               &preloaded_csets);
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        /* NULL dst indicates self on default hierarchy */
        ret = cgroup_migrate_prepare_dst(&preloaded_csets);
        if (ret)
                goto out_finish;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry(src_cset, &preloaded_csets, mg_preload_node) {
                struct task_struct *task, *ntask;
  
                list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list)
                        cgroup_taskset_add(task, &tset);
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        ret = cgroup_taskset_migrate(&tset, cgrp->root);
  out_finish:
@@@ -3914,10 -3901,10 +3907,10 @@@ static int cgroup_task_count(const stru
        int count = 0;
        struct cgrp_cset_link *link;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry(link, &cgrp->cset_links, cset_link)
                count += atomic_read(&link->cset->refcount);
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        return count;
  }
  
@@@ -4255,7 -4242,7 +4248,7 @@@ void css_task_iter_start(struct cgroup_
  
        memset(it, 0, sizeof(*it));
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        it->ss = css->ss;
  
  
        css_task_iter_advance_css_set(it);
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  }
  
  /**
@@@ -4286,7 -4273,7 +4279,7 @@@ struct task_struct *css_task_iter_next(
                it->cur_task = NULL;
        }
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        if (it->task_pos) {
                it->cur_task = list_entry(it->task_pos, struct task_struct,
                css_task_iter_advance(it);
        }
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        return it->cur_task;
  }
  void css_task_iter_end(struct css_task_iter *it)
  {
        if (it->cur_cset) {
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
                list_del(&it->iters_node);
                put_css_set_locked(it->cur_cset);
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
        }
  
        if (it->cur_task)
@@@ -4344,10 -4331,10 +4337,10 @@@ int cgroup_transfer_tasks(struct cgrou
        mutex_lock(&cgroup_mutex);
  
        /* all tasks in @from are being moved, all csets are source */
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry(link, &from->cset_links, cset_link)
                cgroup_migrate_add_src(link->cset, to, &preloaded_csets);
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        ret = cgroup_migrate_prepare_dst(&preloaded_csets);
        if (ret)
@@@ -5069,7 -5056,6 +5062,7 @@@ static void init_and_link_css(struct cg
        memset(css, 0, sizeof(*css));
        css->cgroup = cgrp;
        css->ss = ss;
 +      css->id = -1;
        INIT_LIST_HEAD(&css->sibling);
        INIT_LIST_HEAD(&css->children);
        css->serial_nr = css_serial_nr_next++;
@@@ -5146,6 -5132,8 +5139,8 @@@ static struct cgroup_subsys_state *css_
        lockdep_assert_held(&cgroup_mutex);
  
        css = ss->css_alloc(parent_css);
+       if (!css)
+               css = ERR_PTR(-ENOMEM);
        if (IS_ERR(css))
                return css;
  
  
        err = cgroup_idr_alloc(&ss->css_idr, NULL, 2, 0, GFP_KERNEL);
        if (err < 0)
 -              goto err_free_percpu_ref;
 +              goto err_free_css;
        css->id = err;
  
        /* @css is ready to be brought online now, make it visible */
  
  err_list_del:
        list_del_rcu(&css->sibling);
 -      cgroup_idr_remove(&ss->css_idr, css->id);
 -err_free_percpu_ref:
 -      percpu_ref_exit(&css->refcnt);
  err_free_css:
        call_rcu(&css->rcu_head, css_free_rcu_fn);
        return ERR_PTR(err);
@@@ -5455,10 -5446,10 +5450,10 @@@ static int cgroup_destroy_locked(struc
         */
        cgrp->self.flags &= ~CSS_ONLINE;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry(link, &cgrp->cset_links, cset_link)
                link->cset->dead = true;
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
  
        /* initiate massacre of all css's */
        for_each_css(css, ssid, cgrp)
@@@ -5729,7 -5720,7 +5724,7 @@@ int proc_cgroup_show(struct seq_file *m
                goto out;
  
        mutex_lock(&cgroup_mutex);
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        for_each_root(root) {
                struct cgroup_subsys *ss;
  
        retval = 0;
  out_unlock:
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        mutex_unlock(&cgroup_mutex);
        kfree(buf);
  out:
@@@ -5927,13 -5918,13 +5922,13 @@@ void cgroup_post_fork(struct task_struc
        if (use_task_css_set_links) {
                struct css_set *cset;
  
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
                cset = task_css_set(current);
                if (list_empty(&child->cg_list)) {
                        get_css_set(cset);
                        css_set_move_task(child, NULL, cset, false);
                }
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
        }
  
        /*
@@@ -5978,9 -5969,9 +5973,9 @@@ void cgroup_exit(struct task_struct *ts
        cset = task_css_set(tsk);
  
        if (!list_empty(&tsk->cg_list)) {
 -              spin_lock_bh(&css_set_lock);
 +              spin_lock_irq(&css_set_lock);
                css_set_move_task(tsk, cset, NULL, false);
 -              spin_unlock_bh(&css_set_lock);
 +              spin_unlock_irq(&css_set_lock);
        } else {
                get_css_set(cset);
        }
@@@ -6048,9 -6039,9 +6043,9 @@@ static void cgroup_release_agent(struc
        if (!pathbuf || !agentbuf)
                goto out;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        path = cgroup_path_ns_locked(cgrp, pathbuf, PATH_MAX, &init_cgroup_ns);
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        if (!path)
                goto out;
  
@@@ -6172,7 -6163,7 +6167,7 @@@ struct cgroup_subsys_state *css_tryget_
  struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
  {
        WARN_ON_ONCE(!rcu_read_lock_held());
-       return id > 0 ? idr_find(&ss->css_idr, id) : NULL;
+       return idr_find(&ss->css_idr, id);
  }
  
  /**
@@@ -6310,12 -6301,12 +6305,12 @@@ struct cgroup_namespace *copy_cgroup_ns
                return ERR_PTR(-EPERM);
  
        mutex_lock(&cgroup_mutex);
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
  
        cset = task_css_set(current);
        get_css_set(cset);
  
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        mutex_unlock(&cgroup_mutex);
  
        new_ns = alloc_cgroup_ns();
@@@ -6439,7 -6430,7 +6434,7 @@@ static int current_css_set_cg_links_rea
        if (!name_buf)
                return -ENOMEM;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        rcu_read_lock();
        cset = rcu_dereference(current->cgroups);
        list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
                           c->root->hierarchy_id, name_buf);
        }
        rcu_read_unlock();
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        kfree(name_buf);
        return 0;
  }
@@@ -6461,7 -6452,7 +6456,7 @@@ static int cgroup_css_links_read(struc
        struct cgroup_subsys_state *css = seq_css(seq);
        struct cgrp_cset_link *link;
  
 -      spin_lock_bh(&css_set_lock);
 +      spin_lock_irq(&css_set_lock);
        list_for_each_entry(link, &css->cgroup->cset_links, cset_link) {
                struct css_set *cset = link->cset;
                struct task_struct *task;
        overflow:
                seq_puts(seq, "  ...\n");
        }
 -      spin_unlock_bh(&css_set_lock);
 +      spin_unlock_irq(&css_set_lock);
        return 0;
  }