cgroup: cleanups after kernfs conversion
Subsystems (6)
Tejun Heo
maintainerPATCH 1/1 cgroup: cleanups after kernfs conversion
Hello,
This patchset does a number of cleanups which are possible now that cgroup is converted to kernfs. This patchset contains the following eight patches.
0001-cgroup-warn-if-xattr-is-specified-with-sane_behavior.patch 0002-cgroup-relocate-cgroup_rm_cftypes.patch 0003-cgroup-remove-cftype_set.patch 0004-cgroup-simplify-dynamic-cftype-addition-and-removal.patch 0005-cgroup-make-cgroup-hold-onto-its-kernfs_node.patch 0006-cgroup-remove-cgroup-name.patch 0007-cgroup-rename-cgroupfs_root-number_of_cgroups-to-nr_.patch 0008-cgroup-remove-cgroupfs_root-refcnt.patch
This patchset is on top of
linus#master 54c0a4b46150 ("Merge branch 'akpm' (incoming from Andrew)")
+ [1] [PATCHSET cgroup/for-3.14-fixes] cgroup: four misc fixes
+ [2] [PATCH] arm, pm, vmpressure: add missing slab.h includes
+ [3] [PATCHSET v2 cgroup/for-3.15] cgroup: drop module support and cgroup_root_mutex
+ git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git review-kernfs-cgroup-prep
+ [4] [PATCHSET cgroup/for-3.15] cgroup: convert to kernfs
and also available in the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-post-kernfs-conversion
block/blk-cgroup.h | 12 - fs/kernfs/dir.c | 1 include/linux/cgroup.h | 91 ++++------ kernel/cgroup.c | 417 +++++++++++++++++-------------------------------- kernel/cpuset.c | 27 +-- kernel/sched/debug.c | 3 mm/memcontrol.c | 63 +------ 7 files changed, 228 insertions(+), 386 deletions(-)
Thanks.
--
tejun
[L] http://lkml.kernel.org/g/<1389982317-22225-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
[1] http://lkml.kernel.org/g/<1390923125-4369-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
[2] http://lkml.kernel.org/g/<20140128221922.GC16060-9pTldWuhBndy/[email protected]>
[3] http://lkml.kernel.org/g/<1390952641-15950-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
[4] http://lkml.kernel.org/g/<1390953285-16360-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Tejun Heo
maintainerPATCH 1/8 cgroup: warn if "xattr" is specified with "sane_behavior"
Mount option "xattr" is no longer necessary as it's enabled by default on kernfs. Warn if "xattr" is specified with "sane_behavior" so that the option can be removed in the future.
--- include/linux/cgroup.h | 2 ++ kernel/cgroup.c | 3 +++ 2 files changed, 5 insertions(+)
include/linux/cgroup.h +2 -0
@@ -262,6 +262,8 @@ enum {* - "release_agent" and "notify_on_release" are removed. * Replacement notification mechanism will be implemented. * +* - "xattr" mount option is deprecated. kernfs always enables it. +* * - cpuset: tasks will be kept in empty cpusets when hotplug happens * and take masks of ancestors with non-empty cpus/mems, instead of * being moved to an ancestor.
kernel/cgroup.c +3 -0
@@ -1265,6 +1265,9 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)pr_err ("cgroup: sane_behavior: clone_children is not allowed\n" );return -EINVAL ; } + +if (opts->flags &CGRP_ROOT_XATTR ) +pr_warning ("cgroup: sane_behavior: xattr is always available, flag unnecessary\n" ); }/*
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 2/8 cgroup: relocate cgroup_rm_cftypes()
In reply to Tejun Heocftype handling is about to be revamped. Relocate cgroup_rm_cftypes() above cgroup_add_cftypes() in preparation. This is pure relocation.
--- kernel/cgroup.c | 70 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 35 deletions(-)
kernel/cgroup.c +35 -35
@@ -2400,6 +2400,41 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) }/** +* cgroup_rm_cftypes - remove an array of cftypes from a subsystem +* @cfts: zero-length name terminated array of cftypes +* +* Unregister @cfts. Files described by @cfts are removed from all +* existing cgroups and all future cgroups won't have them either. This +* function can be called anytime whether @cfts' subsys is attached or not. +* +* Returns 0 on successful unregistration, -ENOENT if @cfts is not +* registered. +*/ +int cgroup_rm_cftypes (struct cftype *cfts) +{ +struct cftype *found =NULL ; +struct cftype_set *set; + +if (!cfts || !cfts[0 ].ss) +return -ENOENT ; + +cgroup_cfts_prepare (); + +list_for_each_entry (set, &cfts[0 ].ss->cftsets, node) { +if (set->cfts == cfts) { +list_del (&set->node); +kfree (set); + found = cfts; +break ; + } + } + +cgroup_cfts_commit (found, false); +cgroup_exit_cftypes (cfts); +return found ?0 : -ENOENT ; +} + +/** * cgroup_add_cftypes - add an array of cftypes to a subsystem * @ss: target cgroup subsystem * @cfts: zero-length name terminated array of cftypes
@@ -2437,41 +2472,6 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)EXPORT_SYMBOL_GPL (cgroup_add_cftypes);/** -* cgroup_rm_cftypes - remove an array of cftypes from a subsystem -* @cfts: zero-length name terminated array of cftypes -* -* Unregister @cfts. Files described by @cfts are removed from all -* existing cgroups and all future cgroups won't have them either. This -* function can be called anytime whether @cfts' subsys is attached or not. -* -* Returns 0 on successful unregistration, -ENOENT if @cfts is not -* registered. -*/ -int cgroup_rm_cftypes (struct cftype *cfts) -{ -struct cftype *found =NULL ; -struct cftype_set *set; - -if (!cfts || !cfts[0 ].ss) -return -ENOENT ; - -cgroup_cfts_prepare (); - -list_for_each_entry (set, &cfts[0 ].ss->cftsets, node) { -if (set->cfts == cfts) { -list_del (&set->node); -kfree (set); - found = cfts; -break ; - } - } - -cgroup_cfts_commit (found, false); -cgroup_exit_cftypes (cfts); -return found ?0 : -ENOENT ; -} - -/** * cgroup_task_count - count the number of tasks in a cgroup. * @cgrp: the cgroup in question *
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 3/8 cgroup: remove cftype_set
In reply to Tejun Heocftype_set was added primarily to allow registering the same cftype array more than once for different subsystems. Nobody uses or needs such thing and it's already broken because each cftype has ->ss pointer which is initialized during registration.
Let's add list_head ->node to cftype and use the first cftype entry in the array to link them instead of allocating separate cftype_set. While at it, trigger WARN if cft seems previously initialized during registration.
This simplifies cftype handling a bit.
--- include/linux/cgroup.h | 26 +++++++++----------------- kernel/cgroup.c | 41 +++++++++++++---------------------------- 2 files changed, 22 insertions(+), 45 deletions(-)
include/linux/cgroup.h +9 -17
@@ -410,12 +410,11 @@ struct cftype {unsigned int flags;/* -* The subsys this file belongs to. Initialized automatically -* during registration. NULL for cgroup core files. +* Fields used for internal bookkeeping. Initialized automatically +* during registration. */ -struct cgroup_subsys *ss; - -/* kernfs_ops to use, initialized automatically during registration */ +struct cgroup_subsys *ss;/* NULL for cgroup core files */ +struct list_head node;/* anchored at ss->cfts */ struct kernfs_ops *kf_ops;/*
@@ -470,16 +469,6 @@ struct cftype { };/* -* cftype_sets describe cftypes belonging to a subsystem and are chained at -* cgroup_subsys->cftsets. Each cftset points to an array of cftypes -* terminated by zero length name. -*/ -struct cftype_set { -struct list_head node;/* chained at subsys->cftsets */ -struct cftype *cfts; -}; - -/* * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This * function can be called as long as @cgrp is accessible. */
@@ -595,8 +584,11 @@ struct cgroup_subsys {/* link to parent, protected by cgroup_lock() */ struct cgroupfs_root *root; -/* list of cftype_sets */ -struct list_head cftsets; +/* +* List of cftypes. Each entry is the first entry of an array +* terminated by zero length name. +*/ +struct list_head cfts;/* base cftypes, automatically registered with subsys itself */ struct cftype *base_cftypes;
kernel/cgroup.c +13 -28
97 lines not on this page · raw message
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 4/8 cgroup: simplify dynamic cftype addition and removal
In reply to Tejun HeoDynamic cftype addition and removal using cgroup_add/rm_cftypes() respectively has been quite hairy due to vfs i_mutex. As i_mutex nests outside cgroup_mutex, cgroup_mutex has to be released and regrabbed on each iteration through the hierarchy complicating the process. Now that i_mutex is no longer in play, it can be simplified.
* Just holding cgroup_tree_mutex is enough. No need to meddle with cgroup_mutex.
* No reason to play the unlock - relock - check serial_nr dancing. Everything can be atomically while holding cgroup_tree_mutex.
* cgroup_cfts_prepare() is replaced with direct locking of cgroup_tree_mutex.
* cgroup_cfts_commit() no longer fiddles with locking. It just applies the cftypes change to the existing cgroups in the hierarchy. Renamed to cgroup_cfts_apply().
--- kernel/cgroup.c | 87 +++++++++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 55 deletions(-)
kernel/cgroup.c +32 -55
@@ -2287,46 +2287,19 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],return 0 ; } -static void cgroup_cfts_prepare (void ) - __acquires(&cgroup_mutex) -{ -/* -* Thanks to the entanglement with vfs inode locking, we can't walk -* the existing cgroups under cgroup_mutex and create files. -* Instead, we use css_for_each_descendant_pre() and drop RCU read -* lock before calling cgroup_addrm_files(). -*/ -mutex_lock (&cgroup_tree_mutex); -mutex_lock (&cgroup_mutex); -} - -static int cgroup_cfts_commit (struct cftype *cfts,bool is_add) - __releases(&cgroup_mutex) +static int cgroup_apply_cftypes (struct cftype *cfts,bool is_add) {LIST_HEAD (pending);struct cgroup_subsys *ss = cfts[0 ].ss;struct cgroup *root = &ss->root->top_cgroup; -struct cgroup *prev =NULL ;struct cgroup_subsys_state *css; -u64 update_before;int ret =0 ; -mutex_unlock (&cgroup_mutex); +lockdep_assert_held (&cgroup_tree_mutex); -/* %NULL @cfts indicates abort and don't bother if @ss isn't attached */ -if (!cfts || ss->root == &cgroup_dummy_root) { -mutex_unlock (&cgroup_tree_mutex); +/* don't bother if @ss isn't attached */ +if (ss->root == &cgroup_dummy_root)return 0 ; - } - -cgroup_get_root (ss->root); - -/* -* All cgroups which are created after we drop cgroup_mutex will -* have the updated set of files, so we only need to update the -* cgroups created before the current @cgroup_serial_nr_next. -*/ - update_before = cgroup_serial_nr_next;/* add/rm files for all cgroups created before */ css_for_each_descendant_pre (css,cgroup_css (root, ss)) {
@@ -2335,22 +2308,13 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)if (cgroup_is_dead (cgrp))continue ; -cgroup_get (cgrp); -if (prev) -cgroup_put (prev); - prev = cgrp; - -if (cgrp->serial_nr < update_before && !cgroup_is_dead (cgrp)) { - ret =cgroup_addrm_files (cgrp, cfts, is_add); -if (is_add) -kernfs_activate (cgrp->kn); - } + ret =cgroup_addrm_files (cgrp, cfts, is_add);if (ret)break ; } -mutex_unlock (&cgroup_tree_mutex); -cgroup_put (prev); -cgroup_put_root (ss->root); + +if (is_add && !ret) +kernfs_activate (root->kn);return ret; }
@@ -2401,6 +2365,19 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)return 0 ; } +static int cgroup_rm_cftypes_locked (struct cftype *cfts) +{ +lockdep_assert_held (&cgroup_tree_mutex); + +if (!cfts || !cfts[0 ].ss) +return -ENOENT ; + +list_del (&cfts->node); +cgroup_apply_cftypes (cfts, false); +cgroup_exit_cftypes (cfts); +return 0 ; +} +/** * cgroup_rm_cftypes - remove an array of cftypes from a subsystem * @cfts: zero-length name terminated array of cftypes
@@ -2414,15 +2391,12 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)*/ int cgroup_rm_cftypes (struct cftype *cfts) { -if (!cfts || !cfts[0 ].ss) -return -ENOENT ; - -cgroup_cfts_prepare (); -list_del (&cfts->node); -cgroup_cfts_commit (cfts, false); +int ret; -cgroup_exit_cftypes (cfts); -return 0 ; +mutex_lock (&cgroup_tree_mutex); + ret =cgroup_rm_cftypes_locked (cfts); +mutex_unlock (&cgroup_tree_mutex); +return ret; }/**
@@ -2447,11 +2421,14 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)if (ret)return ret; -cgroup_cfts_prepare (); +mutex_lock (&cgroup_tree_mutex); +list_add_tail (&cfts->node, &ss->cfts); - ret =cgroup_cfts_commit (cfts, true); + ret =cgroup_apply_cftypes (cfts, true);if (ret) -cgroup_rm_cftypes (cfts); +cgroup_rm_cftypes_locked (cfts); + +mutex_unlock (&cgroup_tree_mutex);return ret; }EXPORT_SYMBOL_GPL (cgroup_add_cftypes);
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 5/8 cgroup: make cgroup hold onto its kernfs_node
In reply to Tejun Heocgroup currently releases its kernfs_node when it gets removed. While not buggy, this makes cgroup->kn access rules complicated than necessary and leads to things like get/put protection around kernfs_remove() in cgroup_destroy_locked(). In addition, we want to use kernfs_name/path() and friends but also want to be able to determine a cgroup's name between removal and release.
This patch makes cgroup hold onto its kernfs_node until freed so that cgroup->kn is always accessible.
--- kernel/cgroup.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
kernel/cgroup.c +9 -7
@@ -957,6 +957,8 @@ static void cgroup_free_fn(struct work_struct *work)cgroup_pidlist_destroy_all (cgrp); +kernfs_put (cgrp->kn); +kfree (rcu_dereference_raw (cgrp->name));kfree (cgrp); }
@@ -3768,6 +3770,12 @@ static long cgroup_create(struct cgroup *parent, const char *name_str, } cgrp->kn = kn; +/* +* This extra ref will be put in cgroup_free_fn() and guarantees +* that @cgrp->kn is always accessible. +*/ +kernfs_get (kn); + cgrp->serial_nr = cgroup_serial_nr_next++;/* allocation complete, commit to creation */
@@ -3948,7 +3956,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) {struct cgroup *child;struct cgroup_subsys_state *css; -struct kernfs_node *kn;bool empty;int ssid;
@@ -4026,13 +4033,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)* cgrp->kn->priv backpointer, which should be cleared after all * files under it have been removed. */ - kn = cgrp->kn; -kernfs_get (kn); - -kernfs_remove (cgrp->kn); - +kernfs_remove (cgrp->kn);/* @cgrp has an extra ref on its kn */ RCU_INIT_POINTER (cgrp->kn->priv,NULL ); -kernfs_put (kn);mutex_lock (&cgroup_mutex);
Signature · 1 line
1.8.5.3
A message that is not in the archive (sent off-list or not yet received): 1390953585-16554-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
PATCH 5/8 cgroup: make cgroup hold onto its kernfs_node
cgroup currently releases its kernfs_node when it gets removed. While not buggy, this makes cgroup->kn access rules complicated than necessary and leads to things like get/put protection around kernfs_remove() in cgroup_destroy_locked(). In addition, we want to use kernfs_name/path() and friends but also want to be able to determine a cgroup's name between removal and release.
This patch makes cgroup hold onto its kernfs_node until freed so that cgroup->kn is always accessible.
--- kernel/cgroup.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
kernel/cgroup.c +9 -7
@@ -957,6 +957,8 @@ static void cgroup_free_fn(struct work_struct *work)cgroup_pidlist_destroy_all (cgrp); +kernfs_put (cgrp->kn); +kfree (rcu_dereference_raw (cgrp->name));kfree (cgrp); }
@@ -3768,6 +3770,12 @@ static long cgroup_create(struct cgroup *parent, const char *name_str, } cgrp->kn = kn; +/* +* This extra ref will be put in cgroup_free_fn() and guarantees +* that @cgrp->kn is always accessible. +*/ +kernfs_get (kn); + cgrp->serial_nr = cgroup_serial_nr_next++;/* allocation complete, commit to creation */
@@ -3948,7 +3956,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) {struct cgroup *child;struct cgroup_subsys_state *css; -struct kernfs_node *kn;bool empty;int ssid;
@@ -4026,13 +4033,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)* cgrp->kn->priv backpointer, which should be cleared after all * files under it have been removed. */ - kn = cgrp->kn; -kernfs_get (kn); - -kernfs_remove (cgrp->kn); - +kernfs_remove (cgrp->kn);/* @cgrp has an extra ref on its kn */ RCU_INIT_POINTER (cgrp->kn->priv,NULL ); -kernfs_put (kn);mutex_lock (&cgroup_mutex);
Signature · 1 line
1.8.5.3
PATCH 8/8 cgroup: remove cgroupfs_root->refcnt
In reply to a message not in the archiveCurrently, cgroupfs_root and its ->top_cgroup are separated reference counted and the latter's is ignored. There's no reason to do this separately. This patch removes cgroupfs_root->refcnt and destroys cgroupfs_root when the top_cgroup is released.
* cgroup_put() updated to ignore cgroup_is_dead() test for top cgroups. cgroup_free_fn() updated to handle root destruction when releasing a top cgroup.
* As root destruction is now bounced through cgroup destruction, it is asynchronous. Update cgroup_mount() so that it waits for pending release which is currently implemented using msleep(). Converting this to proper wait_queue isn't hard but likely unnecessary.
--- include/linux/cgroup.h | 4 +-- kernel/cgroup.c | 86 ++++++++++++++++++++++---------------------------- 2 files changed, 39 insertions(+), 51 deletions(-)
include/linux/cgroup.h +1 -3
@@ -280,12 +280,10 @@ struct cgroupfs_root {/* The bitmask of subsystems attached to this hierarchy */ unsigned long subsys_mask; -atomic_t refcnt; -/* Unique id for this hierarchy. */ int hierarchy_id; -/* The root cgroup for this hierarchy */ +/* The root cgroup. Root is destroyed on its release. */ struct cgroup top_cgroup;/* Number of cgroups in the hierarchy, used only for /proc/cgroups */
kernel/cgroup.c +38 -48
156 lines not on this page · raw message
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 6/8 cgroup: remove cgroup->name
In reply to Tejun Heocgroup->name handling became quite complicated over time involving dedicated struct cgroup_name for RCU protection. Now that cgroup is on kernfs, we can drop all of it and simply use kernfs_name/path() and friends. Replace cgroup->name and all related code with kernfs name/path constructs.
* Reimplement cgroup_name() and cgroup_path() as thin wrappers on top of kernfs counterparts, which involves semantic changes. pr_cont_cgroup_name() and pr_cont_cgroup_path() added.
* cgroup->name handling dropped from cgroup_rename().
* All users of cgroup_name/path() updated to the new semantics. Users which were formatting the string just to printk them are converted to use pr_cont_cgroup_name/path() instead, which simplifies things quite a bit. As cgroup_name() no longer requires RCU read lock around it, RCU lockings which were protecting only cgroup_name() are removed.
--- block/blk-cgroup.h | 12 ++-- fs/kernfs/dir.c | 1 + include/linux/cgroup.h | 55 +++++++++--------- kernel/cgroup.c | 148 ++++++++++++------------------------------------- kernel/cpuset.c | 27 +++++---- kernel/sched/debug.c | 3 +- mm/memcontrol.c | 63 ++++++--------------- 7 files changed, 102 insertions(+), 207 deletions(-)
block/blk-cgroup.h +8 -4
@@ -241,12 +241,16 @@ static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd)*/ static inline int blkg_path (struct blkcg_gq *blkg,char *buf,int buflen) { -int ret; +char *p; - ret =cgroup_path (blkg->blkcg->css.cgroup, buf, buflen); -if (ret) + p =cgroup_path (blkg->blkcg->css.cgroup, buf, buflen); +if (!p) {strncpy (buf,"<unavailable>" , buflen); -return ret; +return -ENAMETOOLONG ; + } + +memmove (buf, p, buf + buflen - p); +return 0 ; }/**
fs/kernfs/dir.c +1 -0
@@ -112,6 +112,7 @@ char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)spin_unlock_irqrestore (&kernfs_rename_lock, flags);return p; } +EXPORT_SYMBOL_GPL (kernfs_path);/** * pr_cont_kernfs_name - pr_cont name of a kernfs_node
include/linux/cgroup.h +28 -27
84 lines not on this page · raw message
kernel/cgroup.c +34 -114
307 lines not on this page · raw message
kernel/cpuset.c +13 -14
@@ -2088,10 +2088,9 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs) parent =parent_cs (parent);if (cgroup_transfer_tasks (parent->css.cgroup, cs->css.cgroup)) { -rcu_read_lock (); -printk (KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n" , -cgroup_name (cs->css.cgroup)); -rcu_read_unlock (); +printk (KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset " ); +pr_cont_cgroup_name (cs->css.cgroup); +pr_cont ("\n" ); } }
@@ -2619,19 +2618,17 @@ void cpuset_print_task_mems_allowed(struct task_struct *tsk)/* Statically allocated to prevent using excess stack. */ static char cpuset_nodelist[CPUSET_NODELIST_LEN ];static DEFINE_SPINLOCK (cpuset_buffer_lock); -struct cgroup *cgrp =task_cs (tsk)->css.cgroup; -rcu_read_lock ();spin_lock (&cpuset_buffer_lock);nodelist_scnprintf (cpuset_nodelist,CPUSET_NODELIST_LEN , tsk->mems_allowed); -printk (KERN_INFO "%s cpuset=%s mems_allowed=%s\n" , - tsk->comm,cgroup_name (cgrp), cpuset_nodelist); +printk (KERN_INFO "%s cpuset=" , tsk->comm); +pr_cont_cgroup_name (cgrp); +pr_cont (" mems_allowed=%s\n" , cpuset_nodelist);spin_unlock (&cpuset_buffer_lock); -rcu_read_unlock (); }/*
@@ -2681,12 +2678,12 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v) {struct pid *pid;struct task_struct *tsk; -char *buf; +char *buf, *p;struct cgroup_subsys_state *css;int retval; retval = -ENOMEM ; - buf =kmalloc (PAGE_SIZE ,GFP_KERNEL ); + buf =kmalloc (PATH_MAX ,GFP_KERNEL );if (!buf) goto out;
@@ -2696,14 +2693,16 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v)if (!tsk) goto out_free; + retval = -ENAMETOOLONG ;rcu_read_lock (); css =task_css (tsk, cpuset_cgrp_id); - retval =cgroup_path (css->cgroup, buf,PAGE_SIZE ); + p =cgroup_path (css->cgroup, buf,PATH_MAX );rcu_read_unlock (); -if (retval <0 ) +if (!p) goto out_put_task; -seq_puts (m, buf); +seq_puts (m, p);seq_putc (m,'\n' ); + retval =0 ; out_put_task:put_task_struct (tsk); out_free:
kernel/sched/debug.c +1 -2
@@ -111,8 +111,7 @@ static char *task_group_path(struct task_group *tg)if (autogroup_path (tg, group_path,PATH_MAX ))return group_path; -cgroup_path (tg->css.cgroup, group_path,PATH_MAX ); - return group_path; + return cgroup_path(tg->css.cgroup, group_path, PATH_MAX); }#endif
mm/memcontrol.c +17 -46
101 lines not on this page · raw message
Signature · 1 line
1.8.5.3
Re: [PATCH 6/8] cgroup: remove cgroup->name
Quoted 19 lines · Tejun Heo
cgroup->namehandling became quite complicated over time involving dedicated structcgroup_namefor RCU protection. Now that cgroup is on kernfs, we can drop all of it and simply use kernfs_name/path() and friends. Replacecgroup->nameand all related code with kernfs name/path constructs.* Reimplement
cgroup_name()andcgroup_path()as thin wrappers on top of kernfs counterparts, which involves semantic changes.pr_cont_cgroup_name()andpr_cont_cgroup_path()added.*
cgroup->namehandling dropped fromcgroup_rename().* All users of cgroup_name/path() updated to the new semantics. Users which were formatting the string just to printk them are converted to use pr_cont_cgroup_name/path() instead, which simplifies things quite a bit. As
cgroup_name()no longer requires RCU read lock around it, RCU lockings which were protecting onlycgroup_name()are removed.
Quoted 7 lines
Signed-off-by Tejun Heo <[email protected]>Cc Li Zefan <[email protected]>Cc Ingo Molnar <[email protected]>Cc Johannes Weiner <[email protected]>Cc Michal Hocko <[email protected]>Cc Balbir Singh <[email protected]>Cc KAMEZAWA Hiroyuki <[email protected]>
Re: [PATCH 6/8] cgroup: remove cgroup->name
In reply to Tejun HeoQuoted 19 lines · Tejun Heo
cgroup->namehandling became quite complicated over time involving dedicated structcgroup_namefor RCU protection. Now that cgroup is on kernfs, we can drop all of it and simply use kernfs_name/path() and friends. Replacecgroup->nameand all related code with kernfs name/path constructs.* Reimplement
cgroup_name()andcgroup_path()as thin wrappers on top of kernfs counterparts, which involves semantic changes.pr_cont_cgroup_name()andpr_cont_cgroup_path()added.*
cgroup->namehandling dropped fromcgroup_rename().* All users of cgroup_name/path() updated to the new semantics. Users which were formatting the string just to printk them are converted to use pr_cont_cgroup_name/path() instead, which simplifies things quite a bit. As
cgroup_name()no longer requires RCU read lock around it, RCU lockings which were protecting onlycgroup_name()are removed.
Quoted 8 lines
Signed-off-by Tejun Heo <[email protected]>Cc Li Zefan <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Johannes Weiner <[email protected]>Cc Michal Hocko <[email protected]>Cc Balbir Singh <[email protected]>Cc KAMEZAWA Hiroyuki <[email protected]>
Nice. I hated the way how we retrieved the name previously.
Btw. after this change we should drop part of the comment above oom_info_lock:
mm/memcontrol.c +1 -2
@@ -1684,8 +1684,7 @@ static void move_unlock_mem_cgroup(struct mem_cgroup *memcg,void mem_cgroup_print_oom_info (struct mem_cgroup *memcg,struct task_struct *p) {/* -* protects memcg_name and makes sure that parallel ooms do not -* interleave +* Makes sure that parallel ooms do not interleave */ static DEFINE_SPINLOCK (oom_info_lock);struct cgroup *task_cgrp;
Signature · 2 lines
Michal Hocko SUSE Labs
Tejun Heo
maintainerRe: [PATCH 6/8] cgroup: remove cgroup->name
Quoted 2 lines · Michal Hocko
Btw. after this change we should drop part of the comment above
oom_info_lock:
Updated the comment to
/* oom_info_lock ensures that parallel ooms do not interleave */
Thanks!
Signature · 1 line
tejun
A message that is not in the archive (sent off-list or not yet received): 1390953585-16554-7-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Michal Hocko
Acked-byRe: [PATCH 6/8] cgroup: remove cgroup->name
Quoted 19 lines · Tejun Heo
cgroup->namehandling became quite complicated over time involving dedicated structcgroup_namefor RCU protection. Now that cgroup is on kernfs, we can drop all of it and simply use kernfs_name/path() and friends. Replacecgroup->nameand all related code with kernfs name/path constructs.* Reimplement
cgroup_name()andcgroup_path()as thin wrappers on top of kernfs counterparts, which involves semantic changes.pr_cont_cgroup_name()andpr_cont_cgroup_path()added.*
cgroup->namehandling dropped fromcgroup_rename().* All users of cgroup_name/path() updated to the new semantics. Users which were formatting the string just to printk them are converted to use pr_cont_cgroup_name/path() instead, which simplifies things quite a bit. As
cgroup_name()no longer requires RCU read lock around it, RCU lockings which were protecting onlycgroup_name()are removed.
Quoted 8 lines
Signed-off-by Tejun Heo <[email protected]>Cc Li Zefan <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Johannes Weiner <[email protected]>Cc Michal Hocko <[email protected]>Cc Balbir Singh <[email protected]>Cc KAMEZAWA Hiroyuki <[email protected]>
Nice. I hated the way how we retrieved the name previously.
Btw. after this change we should drop part of the comment above oom_info_lock:
mm/memcontrol.c +1 -2
@@ -1684,8 +1684,7 @@ static void move_unlock_mem_cgroup(struct mem_cgroup *memcg,void mem_cgroup_print_oom_info (struct mem_cgroup *memcg,struct task_struct *p) {/* -* protects memcg_name and makes sure that parallel ooms do not -* interleave +* Makes sure that parallel ooms do not interleave */ static DEFINE_SPINLOCK (oom_info_lock);struct cgroup *task_cgrp;
Signature · 2 lines
Michal Hocko SUSE Labs
PATCH v2 6/8 cgroup: remove cgroup->name
In reply to a message not in the archiveFrom 77d1305150b68913a314757065211188a1aed0c7 Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Wed, 29 Jan 2014 11:02:33 -0500
cgroup->name handling became quite complicated over time involving dedicated struct cgroup_name for RCU protection. Now that cgroup is on kernfs, we can drop all of it and simply use kernfs_name/path() and friends. Replace cgroup->name and all related code with kernfs name/path constructs.
* Reimplement cgroup_name() and cgroup_path() as thin wrappers on top of kernfs counterparts, which involves semantic changes. pr_cont_cgroup_name() and pr_cont_cgroup_path() added.
* cgroup->name handling dropped from cgroup_rename().
* All users of cgroup_name/path() updated to the new semantics. Users which were formatting the string just to printk them are converted to use pr_cont_cgroup_name/path() instead, which simplifies things quite a bit. As cgroup_name() no longer requires RCU read lock around it, RCU lockings which were protecting only cgroup_name() are removed.
v2: Comment above oom_info_lock updated as suggested by Michal.
--- block/blk-cgroup.h | 12 ++-- fs/kernfs/dir.c | 1 + include/linux/cgroup.h | 55 +++++++++--------- kernel/cgroup.c | 148 ++++++++++++------------------------------------- kernel/cpuset.c | 27 +++++---- kernel/sched/debug.c | 3 +- mm/memcontrol.c | 68 ++++++----------------- 7 files changed, 103 insertions(+), 211 deletions(-)
block/blk-cgroup.h +8 -4
@@ -241,12 +241,16 @@ static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd)*/ static inline int blkg_path (struct blkcg_gq *blkg,char *buf,int buflen) { -int ret; +char *p; - ret =cgroup_path (blkg->blkcg->css.cgroup, buf, buflen); -if (ret) + p =cgroup_path (blkg->blkcg->css.cgroup, buf, buflen); +if (!p) {strncpy (buf,"<unavailable>" , buflen); -return ret; +return -ENAMETOOLONG ; + } + +memmove (buf, p, buf + buflen - p); +return 0 ; }/**
fs/kernfs/dir.c +1 -0
@@ -112,6 +112,7 @@ char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)spin_unlock_irqrestore (&kernfs_rename_lock, flags);return p; } +EXPORT_SYMBOL_GPL (kernfs_path);/** * pr_cont_kernfs_name - pr_cont name of a kernfs_node
include/linux/cgroup.h +28 -27
84 lines not on this page · raw message
kernel/cgroup.c +34 -114
307 lines not on this page · raw message
kernel/cpuset.c +13 -14
@@ -2088,10 +2088,9 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs) parent =parent_cs (parent);if (cgroup_transfer_tasks (parent->css.cgroup, cs->css.cgroup)) { -rcu_read_lock (); -printk (KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n" , -cgroup_name (cs->css.cgroup)); -rcu_read_unlock (); +printk (KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset " ); +pr_cont_cgroup_name (cs->css.cgroup); +pr_cont ("\n" ); } }
@@ -2619,19 +2618,17 @@ void cpuset_print_task_mems_allowed(struct task_struct *tsk)/* Statically allocated to prevent using excess stack. */ static char cpuset_nodelist[CPUSET_NODELIST_LEN ];static DEFINE_SPINLOCK (cpuset_buffer_lock); -struct cgroup *cgrp =task_cs (tsk)->css.cgroup; -rcu_read_lock ();spin_lock (&cpuset_buffer_lock);nodelist_scnprintf (cpuset_nodelist,CPUSET_NODELIST_LEN , tsk->mems_allowed); -printk (KERN_INFO "%s cpuset=%s mems_allowed=%s\n" , - tsk->comm,cgroup_name (cgrp), cpuset_nodelist); +printk (KERN_INFO "%s cpuset=" , tsk->comm); +pr_cont_cgroup_name (cgrp); +pr_cont (" mems_allowed=%s\n" , cpuset_nodelist);spin_unlock (&cpuset_buffer_lock); -rcu_read_unlock (); }/*
@@ -2681,12 +2678,12 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v) {struct pid *pid;struct task_struct *tsk; -char *buf; +char *buf, *p;struct cgroup_subsys_state *css;int retval; retval = -ENOMEM ; - buf =kmalloc (PAGE_SIZE ,GFP_KERNEL ); + buf =kmalloc (PATH_MAX ,GFP_KERNEL );if (!buf) goto out;
@@ -2696,14 +2693,16 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v)if (!tsk) goto out_free; + retval = -ENAMETOOLONG ;rcu_read_lock (); css =task_css (tsk, cpuset_cgrp_id); - retval =cgroup_path (css->cgroup, buf,PAGE_SIZE ); + p =cgroup_path (css->cgroup, buf,PATH_MAX );rcu_read_unlock (); -if (retval <0 ) +if (!p) goto out_put_task; -seq_puts (m, buf); +seq_puts (m, p);seq_putc (m,'\n' ); + retval =0 ; out_put_task:put_task_struct (tsk); out_free:
kernel/sched/debug.c +1 -2
@@ -111,8 +111,7 @@ static char *task_group_path(struct task_group *tg)if (autogroup_path (tg, group_path,PATH_MAX ))return group_path; -cgroup_path (tg->css.cgroup, group_path,PATH_MAX ); - return group_path; + return cgroup_path(tg->css.cgroup, group_path, PATH_MAX); }#endif
mm/memcontrol.c +18 -50
107 lines not on this page · raw message
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH v2 6/8 cgroup: remove cgroup->name
In reply to Tejun HeoFrom 77d1305150b68913a314757065211188a1aed0c7 Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Wed, 29 Jan 2014 11:02:33 -0500
cgroup->name handling became quite complicated over time involving dedicated struct cgroup_name for RCU protection. Now that cgroup is on kernfs, we can drop all of it and simply use kernfs_name/path() and friends. Replace cgroup->name and all related code with kernfs name/path constructs.
* Reimplement cgroup_name() and cgroup_path() as thin wrappers on top of kernfs counterparts, which involves semantic changes. pr_cont_cgroup_name() and pr_cont_cgroup_path() added.
* cgroup->name handling dropped from cgroup_rename().
* All users of cgroup_name/path() updated to the new semantics. Users which were formatting the string just to printk them are converted to use pr_cont_cgroup_name/path() instead, which simplifies things quite a bit. As cgroup_name() no longer requires RCU read lock around it, RCU lockings which were protecting only cgroup_name() are removed.
v2: Comment above oom_info_lock updated as suggested by Michal.
--- block/blk-cgroup.h | 12 ++-- fs/kernfs/dir.c | 1 + include/linux/cgroup.h | 55 +++++++++--------- kernel/cgroup.c | 148 ++++++++++++------------------------------------- kernel/cpuset.c | 27 +++++---- kernel/sched/debug.c | 3 +- mm/memcontrol.c | 68 ++++++----------------- 7 files changed, 103 insertions(+), 211 deletions(-)
block/blk-cgroup.h +8 -4
@@ -241,12 +241,16 @@ static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd)*/ static inline int blkg_path (struct blkcg_gq *blkg,char *buf,int buflen) { -int ret; +char *p; - ret =cgroup_path (blkg->blkcg->css.cgroup, buf, buflen); -if (ret) + p =cgroup_path (blkg->blkcg->css.cgroup, buf, buflen); +if (!p) {strncpy (buf,"<unavailable>" , buflen); -return ret; +return -ENAMETOOLONG ; + } + +memmove (buf, p, buf + buflen - p); +return 0 ; }/**
fs/kernfs/dir.c +1 -0
@@ -112,6 +112,7 @@ char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)spin_unlock_irqrestore (&kernfs_rename_lock, flags);return p; } +EXPORT_SYMBOL_GPL (kernfs_path);/** * pr_cont_kernfs_name - pr_cont name of a kernfs_node
include/linux/cgroup.h +28 -27
84 lines not on this page · raw message
kernel/cgroup.c +34 -114
307 lines not on this page · raw message
kernel/cpuset.c +13 -14
@@ -2088,10 +2088,9 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs) parent =parent_cs (parent);if (cgroup_transfer_tasks (parent->css.cgroup, cs->css.cgroup)) { -rcu_read_lock (); -printk (KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset %s\n" , -cgroup_name (cs->css.cgroup)); -rcu_read_unlock (); +printk (KERN_ERR "cpuset: failed to transfer tasks out of empty cpuset " ); +pr_cont_cgroup_name (cs->css.cgroup); +pr_cont ("\n" ); } }
@@ -2619,19 +2618,17 @@ void cpuset_print_task_mems_allowed(struct task_struct *tsk)/* Statically allocated to prevent using excess stack. */ static char cpuset_nodelist[CPUSET_NODELIST_LEN ];static DEFINE_SPINLOCK (cpuset_buffer_lock); -struct cgroup *cgrp =task_cs (tsk)->css.cgroup; -rcu_read_lock ();spin_lock (&cpuset_buffer_lock);nodelist_scnprintf (cpuset_nodelist,CPUSET_NODELIST_LEN , tsk->mems_allowed); -printk (KERN_INFO "%s cpuset=%s mems_allowed=%s\n" , - tsk->comm,cgroup_name (cgrp), cpuset_nodelist); +printk (KERN_INFO "%s cpuset=" , tsk->comm); +pr_cont_cgroup_name (cgrp); +pr_cont (" mems_allowed=%s\n" , cpuset_nodelist);spin_unlock (&cpuset_buffer_lock); -rcu_read_unlock (); }/*
@@ -2681,12 +2678,12 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v) {struct pid *pid;struct task_struct *tsk; -char *buf; +char *buf, *p;struct cgroup_subsys_state *css;int retval; retval = -ENOMEM ; - buf =kmalloc (PAGE_SIZE ,GFP_KERNEL ); + buf =kmalloc (PATH_MAX ,GFP_KERNEL );if (!buf) goto out;
@@ -2696,14 +2693,16 @@ int proc_cpuset_show(struct seq_file *m, void *unused_v)if (!tsk) goto out_free; + retval = -ENAMETOOLONG ;rcu_read_lock (); css =task_css (tsk, cpuset_cgrp_id); - retval =cgroup_path (css->cgroup, buf,PAGE_SIZE ); + p =cgroup_path (css->cgroup, buf,PATH_MAX );rcu_read_unlock (); -if (retval <0 ) +if (!p) goto out_put_task; -seq_puts (m, buf); +seq_puts (m, p);seq_putc (m,'\n' ); + retval =0 ; out_put_task:put_task_struct (tsk); out_free:
kernel/sched/debug.c +1 -2
@@ -111,8 +111,7 @@ static char *task_group_path(struct task_group *tg)if (autogroup_path (tg, group_path,PATH_MAX ))return group_path; -cgroup_path (tg->css.cgroup, group_path,PATH_MAX ); - return group_path; + return cgroup_path(tg->css.cgroup, group_path, PATH_MAX); }#endif
mm/memcontrol.c +18 -50
107 lines not on this page · raw message
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 7/8 cgroup: rename cgroupfs_root->number_of_cgroups to ->nr_cgrps and make it atomic_t
In reply to Tejun Heoroot->number_of_cgroups is currently an integer protected with cgroup_mutex. Except for sanity checks and proc reporting, the only place it's used is to check whether the root has any child during remount; however, this is a bit flawed as the counter is not decremented when the cgroup is unlinked but when it's released, meaning that there could be an extended period where all cgroups are removed but remount is still not allowed because some internal objects are lingering. While not perfect either, it'd be better to use emptiness test on root->top_cgroup.children.
This patch updates cgroup_remount() to test top_cgroup's children instead, which makes number_of_cgroups only actual usage statistics printing in proc implemented in proc_cgroupstats_show(). Let's shorten its name and make it an atomic_t so that we don't have to worry about its synchronization. It's purely auxiliary at this point.
--- include/linux/cgroup.h | 4 ++-- kernel/cgroup.c | 16 +++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-)
include/linux/cgroup.h +2 -2
@@ -288,8 +288,8 @@ struct cgroupfs_root {/* The root cgroup for this hierarchy */ struct cgroup top_cgroup; -/* Tracks how many cgroups are currently defined in hierarchy.*/ -int number_of_cgroups; +/* Number of cgroups in the hierarchy, used only for /proc/cgroups */ +atomic_t nr_cgrps;/* A list running through the active hierarchies */ struct list_head root_list;
kernel/cgroup.c +7 -9
@@ -758,7 +758,7 @@ static void cgroup_put_root(struct cgroupfs_root *root) }mutex_lock (&cgroup_mutex); -BUG_ON (root->number_of_cgroups !=1 ); +BUG_ON (atomic_read (&root->nr_cgrps) !=1 );BUG_ON (!list_empty (&cgrp->children));/* Rebind all subsystems back to the default hierarchy */
@@ -928,9 +928,7 @@ static void cgroup_free_fn(struct work_struct *work) { struct cgroup *cgrp = container_of(work, struct cgroup, destroy_work); -mutex_lock (&cgroup_mutex); - cgrp->root->number_of_cgroups--; -mutex_unlock (&cgroup_mutex); +atomic_dec (&cgrp->root->nr_cgrps);/* * We get a ref to the parent, and put the ref when this cgroup is
@@ -1318,7 +1316,7 @@ static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data) }/* remounting is not allowed for populated hierarchies */ -if (root->number_of_cgroups >1 ) { +if (!list_empty (&root->top_cgroup.children)) { ret = -EBUSY ; goto out_unlock; }
@@ -1358,7 +1356,7 @@ static void init_cgroup_root(struct cgroupfs_root *root)atomic_set (&root->refcnt,1 );INIT_LIST_HEAD (&root->root_list); - root->number_of_cgroups =1 ; +atomic_set (&root->nr_cgrps,1 ); cgrp->root = root;init_cgroup_housekeeping (cgrp);idr_init (&root->cgroup_idr);
@@ -1458,7 +1456,7 @@ static int cgroup_setup_root(struct cgroupfs_root *root)write_unlock (&css_set_lock);BUG_ON (!list_empty (&root_cgrp->children)); -BUG_ON (root->number_of_cgroups !=1 ); +BUG_ON (atomic_read (&root->nr_cgrps) !=1 );kernfs_activate (root_cgrp->kn); ret =0 ;
@@ -3691,7 +3689,7 @@ static long cgroup_create(struct cgroup *parent, const char *name,/* allocation complete, commit to creation */ list_add_tail_rcu (&cgrp->sibling, &cgrp->parent->children); - root->number_of_cgroups++; +atomic_inc (&root->nr_cgrps);/* * Grab a reference on the root and parent so that they don't get
@@ -4259,7 +4257,7 @@ static int proc_cgroupstats_show(struct seq_file *m, void *v)for_each_subsys (ss, i)seq_printf (m,"%s\t%d\t%d\t%d\n" , ss->name, ss->root->hierarchy_id, - ss->root->number_of_cgroups, !ss->disabled); +atomic_read (&ss->root->nr_cgrps), !ss->disabled);mutex_unlock (&cgroup_mutex);return 0 ;
Signature · 1 line
1.8.5.3
Tejun Heo
maintainerPATCH 8/8 cgroup: remove cgroupfs_root->refcnt
In reply to Tejun HeoCurrently, cgroupfs_root and its ->top_cgroup are separated reference counted and the latter's is ignored. There's no reason to do this separately. This patch removes cgroupfs_root->refcnt and destroys cgroupfs_root when the top_cgroup is released.
* cgroup_put() updated to ignore cgroup_is_dead() test for top cgroups. cgroup_free_fn() updated to handle root destruction when releasing a top cgroup.
* As root destruction is now bounced through cgroup destruction, it is asynchronous. Update cgroup_mount() so that it waits for pending release which is currently implemented using msleep(). Converting this to proper wait_queue isn't hard but likely unnecessary.
--- include/linux/cgroup.h | 4 +-- kernel/cgroup.c | 86 ++++++++++++++++++++++---------------------------- 2 files changed, 39 insertions(+), 51 deletions(-)
include/linux/cgroup.h +1 -3
@@ -280,12 +280,10 @@ struct cgroupfs_root {/* The bitmask of subsystems attached to this hierarchy */ unsigned long subsys_mask; -atomic_t refcnt; -/* Unique id for this hierarchy. */ int hierarchy_id; -/* The root cgroup for this hierarchy */ +/* The root cgroup. Root is destroyed on its release. */ struct cgroup top_cgroup;/* Number of cgroups in the hierarchy, used only for /proc/cgroups */
kernel/cgroup.c +38 -48
156 lines not on this page · raw message
Signature · 1 line
1.8.5.3