Loading kernel/cgroup.c +48 −55 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) Loading Loading
kernel/cgroup.c +48 −55 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) Loading