|
@@ -173,7 +173,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp);
|
|
|
static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
|
|
|
bool is_add);
|
|
|
static void cgroup_pidlist_destroy_all(struct cgroup *cgrp);
|
|
|
-static void cgroup_enable_task_cg_lists(void);
|
|
|
|
|
|
/**
|
|
|
* cgroup_css - obtain a cgroup's css for the specified subsystem
|
|
@@ -370,14 +369,6 @@ static unsigned long css_set_hash(struct cgroup_subsys_state *css[])
|
|
|
return key;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * We don't maintain the lists running through each css_set to its task
|
|
|
- * until after the first call to css_task_iter_start(). This reduces the
|
|
|
- * fork()/exit() overhead for people who have cgroups compiled into their
|
|
|
- * kernel but not actually in use.
|
|
|
- */
|
|
|
-static bool use_task_css_set_links __read_mostly;
|
|
|
-
|
|
|
static void __put_css_set(struct css_set *cset, int taskexit)
|
|
|
{
|
|
|
struct cgrp_cset_link *link, *tmp_link;
|
|
@@ -1307,6 +1298,54 @@ static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * To reduce the fork() overhead for systems that are not actually using
|
|
|
+ * their cgroups capability, we don't maintain the lists running through
|
|
|
+ * each css_set to its tasks until we see the list actually used - in other
|
|
|
+ * words after the first mount.
|
|
|
+ */
|
|
|
+static bool use_task_css_set_links __read_mostly;
|
|
|
+
|
|
|
+static void cgroup_enable_task_cg_lists(void)
|
|
|
+{
|
|
|
+ struct task_struct *p, *g;
|
|
|
+
|
|
|
+ write_lock(&css_set_lock);
|
|
|
+
|
|
|
+ if (use_task_css_set_links)
|
|
|
+ goto out_unlock;
|
|
|
+
|
|
|
+ use_task_css_set_links = true;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We need tasklist_lock because RCU is not safe against
|
|
|
+ * while_each_thread(). Besides, a forking task that has passed
|
|
|
+ * cgroup_post_fork() without seeing use_task_css_set_links = 1
|
|
|
+ * is not guaranteed to have its child immediately visible in the
|
|
|
+ * tasklist if we walk through it with RCU.
|
|
|
+ */
|
|
|
+ read_lock(&tasklist_lock);
|
|
|
+ do_each_thread(g, p) {
|
|
|
+ task_lock(p);
|
|
|
+
|
|
|
+ WARN_ON_ONCE(!list_empty(&p->cg_list) ||
|
|
|
+ task_css_set(p) != &init_css_set);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We should check if the process is exiting, otherwise
|
|
|
+ * it will race with cgroup_exit() in that the list
|
|
|
+ * entry won't be deleted though the process has exited.
|
|
|
+ */
|
|
|
+ if (!(p->flags & PF_EXITING))
|
|
|
+ list_add(&p->cg_list, &task_css_set(p)->tasks);
|
|
|
+
|
|
|
+ task_unlock(p);
|
|
|
+ } while_each_thread(g, p);
|
|
|
+ read_unlock(&tasklist_lock);
|
|
|
+out_unlock:
|
|
|
+ write_unlock(&css_set_lock);
|
|
|
+}
|
|
|
+
|
|
|
static void init_cgroup_housekeeping(struct cgroup *cgrp)
|
|
|
{
|
|
|
atomic_set(&cgrp->refcnt, 1);
|
|
@@ -2364,52 +2403,6 @@ int cgroup_task_count(const struct cgroup *cgrp)
|
|
|
return count;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * To reduce the fork() overhead for systems that are not actually using
|
|
|
- * their cgroups capability, we don't maintain the lists running through
|
|
|
- * each css_set to its tasks until we see the list actually used - in other
|
|
|
- * words after the first mount.
|
|
|
- */
|
|
|
-static void cgroup_enable_task_cg_lists(void)
|
|
|
-{
|
|
|
- struct task_struct *p, *g;
|
|
|
-
|
|
|
- write_lock(&css_set_lock);
|
|
|
-
|
|
|
- if (use_task_css_set_links)
|
|
|
- goto out_unlock;
|
|
|
-
|
|
|
- use_task_css_set_links = true;
|
|
|
-
|
|
|
- /*
|
|
|
- * We need tasklist_lock because RCU is not safe against
|
|
|
- * while_each_thread(). Besides, a forking task that has passed
|
|
|
- * cgroup_post_fork() without seeing use_task_css_set_links = 1
|
|
|
- * is not guaranteed to have its child immediately visible in the
|
|
|
- * tasklist if we walk through it with RCU.
|
|
|
- */
|
|
|
- read_lock(&tasklist_lock);
|
|
|
- do_each_thread(g, p) {
|
|
|
- task_lock(p);
|
|
|
-
|
|
|
- WARN_ON_ONCE(!list_empty(&p->cg_list) ||
|
|
|
- task_css_set(p) != &init_css_set);
|
|
|
-
|
|
|
- /*
|
|
|
- * We should check if the process is exiting, otherwise
|
|
|
- * it will race with cgroup_exit() in that the list
|
|
|
- * entry won't be deleted though the process has exited.
|
|
|
- */
|
|
|
- if (!(p->flags & PF_EXITING))
|
|
|
- list_add(&p->cg_list, &task_css_set(p)->tasks);
|
|
|
-
|
|
|
- task_unlock(p);
|
|
|
- } while_each_thread(g, p);
|
|
|
- read_unlock(&tasklist_lock);
|
|
|
-out_unlock:
|
|
|
- write_unlock(&css_set_lock);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* css_next_child - find the next child of a given css
|
|
|
* @pos_css: the current position (%NULL to initiate traversal)
|