Skip to contentSkip to conversation

cgroups: Bindable cgroup subsystems

PATCH New Li Zefan 2 participants 13 messages Dec 15, 2010 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore

Li Zefan

author
#0 lore raw

v2 cover cgroups: Bindable cgroup subsystems

Stephane posted a patchset to add perf_cgroup subsystem, so perf can be used to monitor all threads belonging to a cgroup.

But if you already mounted a cgroup hierarchy but without perf_cgroup and the hierarchy has sub-cgroups, you can't bind perf_cgroup to it, and thus you're not able to use per-cgroup perf feature.

This patchset alleviates the pain, and then a subsytem can be bound/unbound to/from a hierarchy which has sub-cgroups in it.

Some subsystems still can't take advantage of this patchset, memcgroup and cpuset for example.

For cpuset, if a hierarchy has a sub-cgroup and the cgroup has tasks, we can't decide sub-cgroup's cpuset.mems and cpuset.cpus automatically if we try to bind cpuset to this hierarchy.

For memcgroup, memcgroup uses css_get/put(), and due to some complexity, for now bindable subsystems should not use css_get/put().

Usage:

# mount -t cgroup -o cpuset xxx /mnt
# mkdir /mnt/tmp
# echo $$ > /mnt/tmp/tasks

(add cpuacct to the hierarchy)

# mount -o remount,cpuset,cpuacct xxx /mnt

(remove it from the hierarchy)

# mount -o remount,cpuset xxx /mnt

There's another limitation, cpuacct should not be bound to any mounted hierarchy before the above operation. But that's not a problem, as you can remove it from a hierarchy and bind it to another one.

Changelog v2:

- Fix some bugs.
- Spit can_bind flag to bindable and unbindable flags
- Provide a __css_tryget() so a bindable subsystem can pin a cgroup via it.
- ...

---
 Documentation/cgroups/cgroups.txt |   37 +++-
 include/linux/cgroup.h            |   39 +++-
 kernel/cgroup.c                   |  391 +++++++++++++++++++++++++++++++------
 kernel/cgroup_freezer.c           |    1 +
 kernel/sched.c                    |    2 +
 security/device_cgroup.c          |    2 +
 6 files changed, 398 insertions(+), 74 deletions(-)
author
#1 lore raw

PATCH v2 1/6 cgroups: Shrink struct cgroup_subsys

On x86_32, sizeof(struct cgroup_subsys) shrinks from 276 bytes to 264.

---
 include/linux/cgroup.h |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)
include/linux/cgroup.h +6 -4
index ed4ba11..63d953d 100644
@@ -481,14 +481,16 @@ struct cgroup_subsys {
 	void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
 
 	int subsys_id;
-	int active;
-	int disabled;
-	int early_init;
+
+	bool active:1;
+	bool disabled:1;
+	bool early_init:1;
 	/*
 	 * True if this subsys uses ID. ID is not available before cgroup_init()
 	 * (not available in early_init time.)
 	 */
-	bool use_id;
+	bool use_id:1;
+
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
 
Signature · 1 line
1.6.3

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw

PATCH v2 1/6 cgroups: Shrink struct cgroup_subsys

On x86_32, sizeof(struct cgroup_subsys) shrinks from 276 bytes to 264.

---
 include/linux/cgroup.h |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)
include/linux/cgroup.h +6 -4
index ed4ba11..63d953d 100644
@@ -481,14 +481,16 @@ struct cgroup_subsys {
 	void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
 
 	int subsys_id;
-	int active;
-	int disabled;
-	int early_init;
+
+	bool active:1;
+	bool disabled:1;
+	bool early_init:1;
 	/*
 	 * True if this subsys uses ID. ID is not available before cgroup_init()
 	 * (not available in early_init time.)
 	 */
-	bool use_id;
+	bool use_id:1;
+
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
 
Signature · 1 line
1.6.3
#4 lore raw

PATCH v2 2/6 cgroups: Allow to bind a subsystem to a cgroup hierarchy

In reply to a message not in the archive

Stephane posted a patchset to add perf_cgroup subsystem, so perf can be used to monitor all threads belonging to a cgroup.

But if you already mounted a cgroup hierarchy but without perf_cgroup and the hierarchy has sub-cgroups, you can't bind perf_cgroup to it, and thus you're not able to use per-cgroup perf feature.

This patch alleviates the pain, and then a subsytem can be bind to a hierarchy which has sub-cgroups in it.

Matt also commented that users will appreciate this feature.

For a cgroup subsystem to become bindable, the bindable flag of struct cgroup_subsys should be set.

But for some constraints, not all subsystems can take advantage of this patch. For example, we can't decide a cgroup's cpuset.mems and cpuset.cpus automatically, so cpuset is not bindable.

Usage:

  # mount -t cgroup -o cpuset xxx /mnt
  # mkdir /mnt/tmp
  # echo $$ > /mnt/tmp/tasks

(assume cpuacct is bindable, and we add cpuacct to the hierarchy)

  # mount -o remount,cpuset,cpuacct xxx /mnt

Changelog v2:

- Add more code comments.
- Use rcu_assign_pointer in hierarchy_update_css_sets().
- Fix to nullify css pointers in hierarchy_attach_css_failed().
- Fix to call post_clone() for newly-created css.

---
 include/linux/cgroup.h |    5 +
 kernel/cgroup.c        |  273 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 221 insertions(+), 57 deletions(-)
include/linux/cgroup.h +5 -0
index 63d953d..d8c4e22 100644
@@ -490,6 +490,11 @@ struct cgroup_subsys {
 	 * (not available in early_init time.)
 	 */
 	bool use_id:1;
+	/*
+	 * Indicate if this subsystem can be bound to a cgroup hierarchy
+	 * which has child cgroups.
+	 */
+	bool bindable:1;
 
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
kernel/cgroup.c +216 -57

364 lines not on this page · raw message

Signature · 1 line
1.6.3
#5 lore raw

PATCH v2 3/6 cgroups: Allow to unbind subsystem from a cgroup hierarchy

In reply to a message not in the archive

This allows us to unbind a cgroup subsystem from a hierarchy which has sub-cgroups in it.

If a subsystem is to support unbinding, when pinning a cgroup via css refcnt, it should use __css_tryget() instead of css_get().

Usage:

 # mount -t cgroup -o cpuset,cpuacct xxx /mnt
 # mkdir /mnt/tmp
 # echo $$ > /mnt/tmp/tasks

(remove it from the hierarchy)

 # mount -o remount,cpuset xxx /mnt

Changelog v2:

- Allow a cgroup subsystem to use css refcnt.
- Add more code comments.
- Use rcu_assign_pointer() in hierarchy_update_css_sets().
- Split can_bind flag to bindable and unbindable flags.

---
 include/linux/cgroup.h |   17 ++++++
 kernel/cgroup.c        |  139 +++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 138 insertions(+), 18 deletions(-)
include/linux/cgroup.h +17 -0
index d8c4e22..17579b2 100644
@@ -110,6 +110,18 @@ static inline bool css_is_removed(struct cgroup_subsys_state *css)
 }
 
 /*
+ * For a subsystem which supports unbinding, call this to get css
+ * refcnt. Called with rcu_read_lock or cgroup_mutex held.
+ */
+
+static inline bool __css_tryget(struct cgroup_subsys_state *css)
+{
+	if (test_bit(CSS_ROOT, &css->flags))
+		return true;
+	return atomic_inc_not_zero(&css->refcnt);
+}
+
+/*
  * Call css_tryget() to take a reference on a css if your existing
  * (known-valid) reference isn't already ref-counted. Returns false if
  * the css has been destroyed.
@@ -495,6 +507,11 @@ struct cgroup_subsys {
 	 * which has child cgroups.
 	 */
 	bool bindable:1;
+	/*
+	 * Indicate if this subsystem can be removed from a cgroup hierarchy
+	 * which has child cgroups.
+	 */
+	bool unbindable:1;
 
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
kernel/cgroup.c +121 -18

196 lines not on this page · raw message

Signature · 1 line
1.6.3
#6 lore raw

PATCH v2 4/6 cgroups: Mark some subsystems bindable/unbindable

In reply to a message not in the archive

For those subsystems (debug, cpuacct, net_cls and devices), setting the bindable/unbindable flag is sufficient.

Set freezer subsystem as bindable but not unbindable, because sub-cgroups' can be in FROZEN state.

---
 kernel/cgroup.c          |    6 +++++-
 kernel/cgroup_freezer.c  |    1 +
 kernel/sched.c           |    2 ++
 security/device_cgroup.c |    2 ++
 4 files changed, 10 insertions(+), 1 deletions(-)
kernel/cgroup.c +5 -1
index 463575d..fa2c5de 100644
@@ -1063,6 +1063,8 @@ static int hierarchy_reset_css_refs(struct cgroup *cgrp, void *data)
 	int i;
 
 	for_each_set_bit(i, &removed_bits, CGROUP_SUBSYS_COUNT) {
+		struct cgroup_subsys_state *css = cgrp->subsys[i];
+
 		if (atomic_read(&css->refcnt) == 0)
 			atomic_set(&css->refcnt, 1);
 	}
@@ -1086,7 +1088,7 @@ static int hierarchy_clear_css_refs(struct cgroup *cgrp, void *data)
 	}
 	return 0;
 failed:
-	hierarchy_reset_css_refs(struct cgroup *cgrp, void *data);
+	hierarchy_reset_css_refs(cgrp, data);
 	return -EBUSY;
 }
 
@@ -5201,5 +5203,7 @@ struct cgroup_subsys debug_subsys = {
 	.destroy = debug_destroy,
 	.populate = debug_populate,
 	.subsys_id = debug_subsys_id,
+	.bindable = true,
+	.unbindable = true,
 };
 #endif /* CONFIG_CGROUP_DEBUG */
kernel/cgroup_freezer.c +1 -0
index e7bebb7..213ecd9 100644
@@ -393,4 +393,5 @@ struct cgroup_subsys freezer_subsys = {
 	.attach		= NULL,
 	.fork		= freezer_fork,
 	.exit		= NULL,
+	.bindable	= true,
 };
kernel/sched.c +2 -0
index dc91a4d..930ee2e 100644
@@ -9346,6 +9346,8 @@ struct cgroup_subsys cpuacct_subsys = {
 	.destroy = cpuacct_destroy,
 	.populate = cpuacct_populate,
 	.subsys_id = cpuacct_subsys_id,
+	.bindable = true,
+	.unbindable = true,
 };
 #endif	/* CONFIG_CGROUP_CPUACCT */
 
security/device_cgroup.c +2 -0
index 8d9c48f..51321e9 100644
@@ -473,6 +473,8 @@ struct cgroup_subsys devices_subsys = {
 	.destroy = devcgroup_destroy,
 	.populate = devcgroup_populate,
 	.subsys_id = devices_subsys_id,
+	.bindable = true,
+	.unbindable = true,
 };
 
 int devcgroup_inode_permission(struct inode *inode, int mask)
Signature · 1 line
1.6.3
#7 lore raw

PATCH v2 5/6 cgroups: Triger BUG if a bindable subsystem calls css_get()

In reply to a message not in the archive

For now unbindable subsystems should not use css_get/put(), so check this misuse.

---
 include/linux/cgroup.h |    7 +++++--
 kernel/cgroup.c        |    5 +++++
 2 files changed, 10 insertions(+), 2 deletions(-)
include/linux/cgroup.h +5 -2
index 17579b2..e8ad9f1 100644
@@ -80,13 +80,15 @@ struct cgroup_subsys_state {
 
 /* bits in struct cgroup_subsys_state flags field */
 enum {
-	CSS_ROOT, /* This CSS is the root of the subsystem */
-	CSS_REMOVED, /* This CSS is dead */
+	CSS_ROOT,	/* This CSS is the root of the subsystem */
+	CSS_REMOVED,	/* This CSS is dead */
+	CSS_NO_GET,	/* Forbid calling css_get/put() */
 };
 
 /* Caller must verify that the css is not for root cgroup */
 static inline void __css_get(struct cgroup_subsys_state *css, int count)
 {
+	BUG_ON(test_bit(CSS_NO_GET, &css->flags));
 	atomic_add(count, &css->refcnt);
 }
 
@@ -131,6 +133,7 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
 {
 	if (test_bit(CSS_ROOT, &css->flags))
 		return true;
+	BUG_ON(test_bit(CSS_NO_GET, &css->flags));
 	while (!atomic_inc_not_zero(&css->refcnt)) {
 		if (test_bit(CSS_REMOVED, &css->flags))
 			return false;
kernel/cgroup.c +5 -0
index fa2c5de..d49a459 100644
@@ -938,6 +938,11 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
 	atomic_set(&css->refcnt, 1);
 	css->flags = 0;
 	css->id = NULL;
+
+	/* For now, unbindable subsystems should not call css_get/put(). */
+	if (ss->unbindable)
+		set_bit(CSS_NO_GET, &css->flags);
+
 	if (cgrp == dummytop)
 		set_bit(CSS_ROOT, &css->flags);
 	BUG_ON(cgrp->subsys[ss->subsys_id]);
Signature · 1 line
1.6.3
#8 lore raw

PATCH v2 6/6 cgroups: Update documentation for bindable subsystems

In reply to a message not in the archive

Provide a usage example, update the bind() callback API, etc.

---
 Documentation/cgroups/cgroups.txt |   37 +++++++++++++++++++++++++++++--------
 1 files changed, 29 insertions(+), 8 deletions(-)
Documentation/cgroups/cgroups.txt +29 -8
index 190018b..4e772cc 100644
@@ -363,17 +363,23 @@ Note this will add ns to the hierarchy but won't remove memory or
 cpuset, because the new options are appended to the old ones:
 # mount -o remount,ns /dev/cgroup
 
+For some subsystems you can bind them to a mounted hierarchy or
+remove them from it, even if there're sub-cgroups in it:
+# mount -t cgroup -o freezer hier1 /dev/cgroup
+# echo $$ > /dev/cgroup/my_cgroup
+# mount -o freezer,cpuset hier1 /dev/cgroup
+(failed)
+# mount -o freezer,cpuacct hier1 /dev/cgroup
+# mount -o cpuacct hier1 /dev/cgroup
+
+Note cpuacct should be sit in the default hierarchy before remount.
+
 To Specify a hierarchy's release_agent:
 # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
   xxx /dev/cgroup
 
 Note that specifying 'release_agent' more than once will return failure.
 
-Note that changing the set of subsystems is currently only supported
-when the hierarchy consists of a single (root) cgroup. Supporting
-the ability to arbitrarily bind/unbind subsystems from an existing
-cgroup hierarchy is intended to be implemented in the future.
-
 Then under /dev/cgroup you can find a tree that corresponds to the
 tree of the cgroups in the system. For instance, /dev/cgroup
 is the cgroup that holds the whole system.
@@ -523,6 +529,15 @@ module initcall a call to cgroup_load_subsys(), and in its exitcall a
 call to cgroup_unload_subsys(). It should also set its_subsys.module =
 THIS_MODULE in its .c file.
 
+If a subsystem has bindable flag set, normally it has to be able to
+support side-effect free movement of a task into any just-created
+cgroups. i.e. it's probably not suitable for any subsystem where
+can_attach() might return false for the newly-created cgroup, or
+attach() might have side-effects for those same cases.
+
+If a subsystem has unbindable flag set, normally it has to be able to
+support side-effect free movement of a task into the roog cgroup.
+
 Each subsystem may export the following methods. The only mandatory
 methods are create/destroy. Any others that are null are presumed to
 be successful no-ops.
@@ -627,9 +642,15 @@ void bind(struct cgroup_subsys *ss, struct cgroup *root)
 (cgroup_mutex and ss->hierarchy_mutex held by caller)
 
 Called when a cgroup subsystem is rebound to a different hierarchy
-and root cgroup. Currently this will only involve movement between
-the default hierarchy (which never has sub-cgroups) and a hierarchy
-that is being created/destroyed (and hence has no sub-cgroups).
+and root cgroup.
+
+For non-bindable subsystems, this will only involve movement
+between the default hierarchy (which never has sub-cgroups) and a
+hierarchy that is being created/destroyed (and hence has no sub-cgroups).
+
+For binadable subsystems, this may also involve movement between the
+default hierarchy and a mounted hierarchy that's populated with
+sub-cgroups.
 
 4. Questions
 ============
Signature · 1 line
1.6.3
author
#9 lore raw

PATCH v2 2/6 cgroups: Allow to bind a subsystem to a cgroup hierarchy

In reply to Li Zefan

Stephane posted a patchset to add perf_cgroup subsystem, so perf can be used to monitor all threads belonging to a cgroup.

But if you already mounted a cgroup hierarchy but without perf_cgroup and the hierarchy has sub-cgroups, you can't bind perf_cgroup to it, and thus you're not able to use per-cgroup perf feature.

This patch alleviates the pain, and then a subsytem can be bind to a hierarchy which has sub-cgroups in it.

Matt also commented that users will appreciate this feature.

For a cgroup subsystem to become bindable, the bindable flag of struct cgroup_subsys should be set.

But for some constraints, not all subsystems can take advantage of this patch. For example, we can't decide a cgroup's cpuset.mems and cpuset.cpus automatically, so cpuset is not bindable.

Usage:

  # mount -t cgroup -o cpuset xxx /mnt
  # mkdir /mnt/tmp
  # echo $$ > /mnt/tmp/tasks

(assume cpuacct is bindable, and we add cpuacct to the hierarchy)

  # mount -o remount,cpuset,cpuacct xxx /mnt

Changelog v2:

- Add more code comments.
- Use rcu_assign_pointer in hierarchy_update_css_sets().
- Fix to nullify css pointers in hierarchy_attach_css_failed().
- Fix to call post_clone() for newly-created css.

---
 include/linux/cgroup.h |    5 +
 kernel/cgroup.c        |  273 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 221 insertions(+), 57 deletions(-)
include/linux/cgroup.h +5 -0
index 63d953d..d8c4e22 100644
@@ -490,6 +490,11 @@ struct cgroup_subsys {
 	 * (not available in early_init time.)
 	 */
 	bool use_id:1;
+	/*
+	 * Indicate if this subsystem can be bound to a cgroup hierarchy
+	 * which has child cgroups.
+	 */
+	bool bindable:1;
 
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
kernel/cgroup.c +216 -57

364 lines not on this page · raw message

Signature · 1 line
1.6.3
author
#10 lore raw

PATCH v2 3/6 cgroups: Allow to unbind subsystem from a cgroup hierarchy

In reply to Li Zefan

This allows us to unbind a cgroup subsystem from a hierarchy which has sub-cgroups in it.

If a subsystem is to support unbinding, when pinning a cgroup via css refcnt, it should use __css_tryget() instead of css_get().

Usage:

 # mount -t cgroup -o cpuset,cpuacct xxx /mnt
 # mkdir /mnt/tmp
 # echo $$ > /mnt/tmp/tasks

(remove it from the hierarchy)

 # mount -o remount,cpuset xxx /mnt

Changelog v2:

- Allow a cgroup subsystem to use css refcnt.
- Add more code comments.
- Use rcu_assign_pointer() in hierarchy_update_css_sets().
- Split can_bind flag to bindable and unbindable flags.

---
 include/linux/cgroup.h |   17 ++++++
 kernel/cgroup.c        |  139 +++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 138 insertions(+), 18 deletions(-)
include/linux/cgroup.h +17 -0
index d8c4e22..17579b2 100644
@@ -110,6 +110,18 @@ static inline bool css_is_removed(struct cgroup_subsys_state *css)
 }
 
 /*
+ * For a subsystem which supports unbinding, call this to get css
+ * refcnt. Called with rcu_read_lock or cgroup_mutex held.
+ */
+
+static inline bool __css_tryget(struct cgroup_subsys_state *css)
+{
+	if (test_bit(CSS_ROOT, &css->flags))
+		return true;
+	return atomic_inc_not_zero(&css->refcnt);
+}
+
+/*
  * Call css_tryget() to take a reference on a css if your existing
  * (known-valid) reference isn't already ref-counted. Returns false if
  * the css has been destroyed.
@@ -495,6 +507,11 @@ struct cgroup_subsys {
 	 * which has child cgroups.
 	 */
 	bool bindable:1;
+	/*
+	 * Indicate if this subsystem can be removed from a cgroup hierarchy
+	 * which has child cgroups.
+	 */
+	bool unbindable:1;
 
 #define MAX_CGROUP_TYPE_NAMELEN 32
 	const char *name;
kernel/cgroup.c +121 -18

196 lines not on this page · raw message

Signature · 1 line
1.6.3
author
#11 lore raw

PATCH v2 4/6 cgroups: Mark some subsystems bindable/unbindable

In reply to Li Zefan

For those subsystems (debug, cpuacct, net_cls and devices), setting the bindable/unbindable flag is sufficient.

Set freezer subsystem as bindable but not unbindable, because sub-cgroups' can be in FROZEN state.

---
 kernel/cgroup.c          |    6 +++++-
 kernel/cgroup_freezer.c  |    1 +
 kernel/sched.c           |    2 ++
 security/device_cgroup.c |    2 ++
 4 files changed, 10 insertions(+), 1 deletions(-)
kernel/cgroup.c +5 -1
index 463575d..fa2c5de 100644
@@ -1063,6 +1063,8 @@ static int hierarchy_reset_css_refs(struct cgroup *cgrp, void *data)
 	int i;
 
 	for_each_set_bit(i, &removed_bits, CGROUP_SUBSYS_COUNT) {
+		struct cgroup_subsys_state *css = cgrp->subsys[i];
+
 		if (atomic_read(&css->refcnt) == 0)
 			atomic_set(&css->refcnt, 1);
 	}
@@ -1086,7 +1088,7 @@ static int hierarchy_clear_css_refs(struct cgroup *cgrp, void *data)
 	}
 	return 0;
 failed:
-	hierarchy_reset_css_refs(struct cgroup *cgrp, void *data);
+	hierarchy_reset_css_refs(cgrp, data);
 	return -EBUSY;
 }
 
@@ -5201,5 +5203,7 @@ struct cgroup_subsys debug_subsys = {
 	.destroy = debug_destroy,
 	.populate = debug_populate,
 	.subsys_id = debug_subsys_id,
+	.bindable = true,
+	.unbindable = true,
 };
 #endif /* CONFIG_CGROUP_DEBUG */
kernel/cgroup_freezer.c +1 -0
index e7bebb7..213ecd9 100644
@@ -393,4 +393,5 @@ struct cgroup_subsys freezer_subsys = {
 	.attach		= NULL,
 	.fork		= freezer_fork,
 	.exit		= NULL,
+	.bindable	= true,
 };
kernel/sched.c +2 -0
index dc91a4d..930ee2e 100644
@@ -9346,6 +9346,8 @@ struct cgroup_subsys cpuacct_subsys = {
 	.destroy = cpuacct_destroy,
 	.populate = cpuacct_populate,
 	.subsys_id = cpuacct_subsys_id,
+	.bindable = true,
+	.unbindable = true,
 };
 #endif	/* CONFIG_CGROUP_CPUACCT */
 
security/device_cgroup.c +2 -0
index 8d9c48f..51321e9 100644
@@ -473,6 +473,8 @@ struct cgroup_subsys devices_subsys = {
 	.destroy = devcgroup_destroy,
 	.populate = devcgroup_populate,
 	.subsys_id = devices_subsys_id,
+	.bindable = true,
+	.unbindable = true,
 };
 
 int devcgroup_inode_permission(struct inode *inode, int mask)
Signature · 1 line
1.6.3
author
#12 lore raw

PATCH v2 5/6 cgroups: Triger BUG if a bindable subsystem calls css_get()

In reply to Li Zefan

For now unbindable subsystems should not use css_get/put(), so check this misuse.

---
 include/linux/cgroup.h |    7 +++++--
 kernel/cgroup.c        |    5 +++++
 2 files changed, 10 insertions(+), 2 deletions(-)
include/linux/cgroup.h +5 -2
index 17579b2..e8ad9f1 100644
@@ -80,13 +80,15 @@ struct cgroup_subsys_state {
 
 /* bits in struct cgroup_subsys_state flags field */
 enum {
-	CSS_ROOT, /* This CSS is the root of the subsystem */
-	CSS_REMOVED, /* This CSS is dead */
+	CSS_ROOT,	/* This CSS is the root of the subsystem */
+	CSS_REMOVED,	/* This CSS is dead */
+	CSS_NO_GET,	/* Forbid calling css_get/put() */
 };
 
 /* Caller must verify that the css is not for root cgroup */
 static inline void __css_get(struct cgroup_subsys_state *css, int count)
 {
+	BUG_ON(test_bit(CSS_NO_GET, &css->flags));
 	atomic_add(count, &css->refcnt);
 }
 
@@ -131,6 +133,7 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
 {
 	if (test_bit(CSS_ROOT, &css->flags))
 		return true;
+	BUG_ON(test_bit(CSS_NO_GET, &css->flags));
 	while (!atomic_inc_not_zero(&css->refcnt)) {
 		if (test_bit(CSS_REMOVED, &css->flags))
 			return false;
kernel/cgroup.c +5 -0
index fa2c5de..d49a459 100644
@@ -938,6 +938,11 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
 	atomic_set(&css->refcnt, 1);
 	css->flags = 0;
 	css->id = NULL;
+
+	/* For now, unbindable subsystems should not call css_get/put(). */
+	if (ss->unbindable)
+		set_bit(CSS_NO_GET, &css->flags);
+
 	if (cgrp == dummytop)
 		set_bit(CSS_ROOT, &css->flags);
 	BUG_ON(cgrp->subsys[ss->subsys_id]);
Signature · 1 line
1.6.3
author
#13 lore raw

PATCH v2 6/6 cgroups: Update documentation for bindable subsystems

In reply to Li Zefan

Provide a usage example, update the bind() callback API, etc.

---
 Documentation/cgroups/cgroups.txt |   37 +++++++++++++++++++++++++++++--------
 1 files changed, 29 insertions(+), 8 deletions(-)
Documentation/cgroups/cgroups.txt +29 -8
index 190018b..4e772cc 100644
@@ -363,17 +363,23 @@ Note this will add ns to the hierarchy but won't remove memory or
 cpuset, because the new options are appended to the old ones:
 # mount -o remount,ns /dev/cgroup
 
+For some subsystems you can bind them to a mounted hierarchy or
+remove them from it, even if there're sub-cgroups in it:
+# mount -t cgroup -o freezer hier1 /dev/cgroup
+# echo $$ > /dev/cgroup/my_cgroup
+# mount -o freezer,cpuset hier1 /dev/cgroup
+(failed)
+# mount -o freezer,cpuacct hier1 /dev/cgroup
+# mount -o cpuacct hier1 /dev/cgroup
+
+Note cpuacct should be sit in the default hierarchy before remount.
+
 To Specify a hierarchy's release_agent:
 # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
   xxx /dev/cgroup
 
 Note that specifying 'release_agent' more than once will return failure.
 
-Note that changing the set of subsystems is currently only supported
-when the hierarchy consists of a single (root) cgroup. Supporting
-the ability to arbitrarily bind/unbind subsystems from an existing
-cgroup hierarchy is intended to be implemented in the future.
-
 Then under /dev/cgroup you can find a tree that corresponds to the
 tree of the cgroups in the system. For instance, /dev/cgroup
 is the cgroup that holds the whole system.
@@ -523,6 +529,15 @@ module initcall a call to cgroup_load_subsys(), and in its exitcall a
 call to cgroup_unload_subsys(). It should also set its_subsys.module =
 THIS_MODULE in its .c file.
 
+If a subsystem has bindable flag set, normally it has to be able to
+support side-effect free movement of a task into any just-created
+cgroups. i.e. it's probably not suitable for any subsystem where
+can_attach() might return false for the newly-created cgroup, or
+attach() might have side-effects for those same cases.
+
+If a subsystem has unbindable flag set, normally it has to be able to
+support side-effect free movement of a task into the roog cgroup.
+
 Each subsystem may export the following methods. The only mandatory
 methods are create/destroy. Any others that are null are presumed to
 be successful no-ops.
@@ -627,9 +642,15 @@ void bind(struct cgroup_subsys *ss, struct cgroup *root)
 (cgroup_mutex and ss->hierarchy_mutex held by caller)
 
 Called when a cgroup subsystem is rebound to a different hierarchy
-and root cgroup. Currently this will only involve movement between
-the default hierarchy (which never has sub-cgroups) and a hierarchy
-that is being created/destroyed (and hence has no sub-cgroups).
+and root cgroup.
+
+For non-bindable subsystems, this will only involve movement
+between the default hierarchy (which never has sub-cgroups) and a
+hierarchy that is being created/destroyed (and hence has no sub-cgroups).
+
+For binadable subsystems, this may also involve movement between the
+default hierarchy and a mounted hierarchy that's populated with
+sub-cgroups.
 
 4. Questions
 ============
Signature · 1 line
1.6.3