Skip to contentSkip to conversation

Minimal controller code for a quick start

PATCH In review Pavel Emelyanov 4 participants 9 messages Feb 7, 2008 – Feb 8, 2008 Documentation

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Minimal controller code for a quick start

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

I propose to put this minimal controller into Documentation directory to let people copy-n-paste a) from a known place and
b) a small piece of code.

Besides, many people learn better reading an example rather than/along with a document.

---

Documentation/cgroups.txt +3 -0
index 42d7c4c..66068dc 100644
@@ -531,6 +531,9 @@ 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).
 
+For a quick start you may want to look at the
+Documentation/controllers/example.c file.
+
 4. Questions
 ============
 
Documentation/controllers/example.c new file +134 -0

134 lines not on this page · raw message

#1 lore raw
Quoted 11 lines · Pavel Emelyanov

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

I propose to put this minimal controller into Documentation directory to let people copy-n-paste a) from a known place and
b) a small piece of code.

Besides, many people learn better reading an example rather than/along with a document.

While on the subject, could someone document struct cgroup_subsys. In particular, I've wondered why we have: cgroup_subsys::can_attach() and not use a return value in cgroup_subsys::attach()?

#2 lore raw
Quoted 2 lines · Peter Zijlstra

While on the subject, could someone document struct cgroup_subsys.

There's documentation for all the methods in Documentation/cgroup.txt

Quoted 2 lines

particular, I've wondered why we have: cgroup_subsys::can_attach() and not use a return value in cgroup_subsys::attach()?

We could do in theory do that, but it would make the recovery logic in cgroup.c:attach_task() more complex - it would have to be able to deal with undoing a partial attach. It seems simpler to just split it into two phases, given that most cgroups don't appear to have attachment conditions anyway.

Paul

#3 lore raw
Quoted 5 lines · Paul Menage
Quoted 2 lines · Peter Zijlstra

While on the subject, could someone document struct cgroup_subsys.

There's documentation for all the methods in Documentation/cgroup.txt

Hehe, and here I was looking for in-code comments. OK I'll read the thing.

#4 lore raw
In reply to Peter Zijlstra
Quoted 11 lines · Peter Zijlstra
Quoted 9 lines · Pavel Emelyanov

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

I propose to put this minimal controller into Documentation directory to let people copy-n-paste a) from a known place and
b) a small piece of code.

Quoted 6 lines
Quoted 2 lines

Besides, many people learn better reading an example rather than/along with a document.

While on the subject, could someone document struct cgroup_subsys. In particular, I've wondered why we have: cgroup_subsys::can_attach() and

The point of can_attach() is to decide whether an attach should be permitted. kernel/ns_cgroup.c defines it.

Quoted 1 line

not use a return value in cgroup_subsys::attach()?

IIUC, by the point ->attach() is called, the task has already been placed in the new cgroup, and we're just asking each subsystem to update any relevant accounting.

-serge

#5 lore raw
In reply to Pavel Emelyanov
Quoted 4 lines · Pavel Emelyanov

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

Good idea.

Quoted 28 lines
Documentation/controllers/example.c new file +28 -0
+
+static ssize_t foo_bar_read(struct cgroup *cg, struct cftype *cft,
+               struct file *file, char __user *userbuf,
+               size_t nbytes, loff_t *ppos)
+{
+       struct foo_cgroup *foo;
+
+       foo = foo_from_cgroup(cg);
+
+       /*
+        * produce some output
+        */
+
+       return nbytes;
+}
+
+static ssize_t foo_bar_write(struct cgroup *cg, struct cftype *cft,
+               struct file *file, const char __user *userbuf,
+               size_t nbytes, loff_t *ppos)
+{
+       struct foo_cgroup *foo;
+
+       foo = foo_from_cgroup(cg);
+
+       /*
+        * read and tune the foo
+        */
+

Documentation/controllers/example.c line 88

Quoted 10 lines
Documentation/controllers/example.c new file +10 -0
+       return nbytes;
+}
+
+static struct cftype foo_files[] = {
+       {
+               .name = "bar",
+               .read = foo_bar_read,
+               .write = foo_bar_write,
+       },
+};

Can you structure this example so as to encourage people to use the more formatted read/write routines, such as read_int64 and write_int64?

Documentation/controllers/example.c line 98

Quoted 6 lines
Documentation/controllers/example.c new file +6 -0
+
+static struct cgroup_subsys_state *foo_create(struct cgroup_subsys *cs,
+               struct cgroup *cg)
+{
+       struct foo_cgroup *foo;
+

Maybe add a comment here that mentions that if your cgroup needs very early initialization, you can check for cg->parent being NULL, and return a statically-constructed structure here. (And set foo_subsys.early_init = 1)

Paul

#6 lore raw
Quoted 42 lines · Paul Menage
Quoted 4 lines · Pavel Emelyanov

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

Good idea.

Quoted 34 lines
Documentation/controllers/example.c new file +34 -0
+
+static ssize_t foo_bar_read(struct cgroup *cg, struct cftype *cft,
+               struct file *file, char __user *userbuf,
+               size_t nbytes, loff_t *ppos)
+{
+       struct foo_cgroup *foo;
+
+       foo = foo_from_cgroup(cg);
+
+       /*
+        * produce some output
+        */
+
+       return nbytes;
+}
+
+static ssize_t foo_bar_write(struct cgroup *cg, struct cftype *cft,
+               struct file *file, const char __user *userbuf,
+               size_t nbytes, loff_t *ppos)
+{
+       struct foo_cgroup *foo;
+
+       foo = foo_from_cgroup(cg);
+
+       /*
+        * read and tune the foo
+        */
+
+       return nbytes;
+}
+
+static struct cftype foo_files[] = {
+       {
+               .name = "bar",
Quoted 8 lines

Documentation/controllers/example.c line 88

Quoted 4 lines
Documentation/controllers/example.c new file +4 -0
+               .read = foo_bar_read,
+               .write = foo_bar_write,
+       },
+};

Can you structure this example so as to encourage people to use the more formatted read/write routines, such as read_int64 and write_int64?

And one more for ->read_strategy hints :) Well, I thought that it should be the _minimal_ controller.

Quoted 11 lines

Documentation/controllers/example.c line 98

Quoted 6 lines
Documentation/controllers/example.c new file +6 -0
+
+static struct cgroup_subsys_state *foo_create(struct cgroup_subsys *cs,
+               struct cgroup *cg)
+{
+       struct foo_cgroup *foo;
+

Maybe add a comment here that mentions that if your cgroup needs very early initialization, you can check for cg->parent being NULL, and return a statically-constructed structure here. (And set foo_subsys.early_init = 1)

Yet again - this is rather a special feature, that your controller needs an early initialization - for a very minimal one this is not required.

Maybe we can have two examples? One is the minimal one and the other is an advanced one with ->attach callbacks, etc?

Quoted 2 lines

Paul

#7 lore raw
In reply to Pavel Emelyanov
Quoted 5 lines · Pavel Emelyanov

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

Quoted 8 lines

I propose to put this minimal controller into Documentation directory to let people copy-n-paste a) from a known place and
b) a small piece of code.

Besides, many people learn better reading an example rather than/along with a document.

Actually I thought that was the main point of kernel/cgroup_debug.c?

-serge

Quoted 161 lines

---

Documentation/cgroups.txt +3 -0
index 42d7c4c..66068dc 100644
@@ -531,6 +531,9 @@ 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).
 
+For a quick start you may want to look at the
+Documentation/controllers/example.c file.
+
 4. Questions
 ============
 
Documentation/controllers/example.c new file +134 -0
new file mode 100644
index 0000000..4a73c77
@@ -0,0 +1,134 @@
+/*
+ * Documentation/controllers/example.c - A simple controller
+ *
+ * Copy and make s/foo/$SUBSYS_NAME/g in it to get a minimal
+ * working code. Don't forget to add a SUBSYS(foo) line in the
+ * include/linux/cgroup_subsys.h file.
+ *
+ */
+
+#include <linux/cgroup.h>
+
+/*
+ * the foo main structure - it is used to store any info, that
+ * is required from the group of tasks
+ */
+
+struct foo_cgroup {
+	/*
+	 * put your fields here
+	 */
+
+	struct cgroup_subsys_state css;
+
+	/*
+	 * ... or/and here
+	 */
+};
+
+/*
+ * helpers to get the foo_cgroup from a task and a control group
+ */
+
+static inline struct foo_cgroup *foo_from_css(struct cgroup_subsys_state *css)
+{
+	return container_of(css, struct foo_cgroup, css);
+}
+
+static inline struct foo_cgroup *foo_from_cgroup(struct cgroup *cg)
+{
+	return foo_from_css(cgroup_subsys_state(cg, foo_subsys_id));
+}
+
+static inline struct foo_cgroup *foo_from_task(struct task_struct *p)
+{
+	return foo_from_css(task_subsys_state(p, foo_subsys_id));
+}
+
+/*
+ * foo files
+ */
+
+static ssize_t foo_bar_read(struct cgroup *cg, struct cftype *cft,
+		struct file *file, char __user *userbuf,
+		size_t nbytes, loff_t *ppos)
+{
+	struct foo_cgroup *foo;
+
+	foo = foo_from_cgroup(cg);
+
+	/*
+	 * produce some output
+	 */
+
+	return nbytes;
+}
+
+static ssize_t foo_bar_write(struct cgroup *cg, struct cftype *cft,
+		struct file *file, const char __user *userbuf,
+		size_t nbytes, loff_t *ppos)
+{
+	struct foo_cgroup *foo;
+
+	foo = foo_from_cgroup(cg);
+
+	/*
+	 * read and tune the foo
+	 */
+
+	return nbytes;
+}
+
+static struct cftype foo_files[] = {
+	{
+		.name = "bar",
+		.read = foo_bar_read,
+		.write = foo_bar_write,
+	},
+};
+
+/*
+ * foo subsystem basic callbacks
+ */
+
+static struct cgroup_subsys_state *foo_create(struct cgroup_subsys *cs,
+		struct cgroup *cg)
+{
+	struct foo_cgroup *foo;
+
+	foo = kmalloc(sizeof(struct foo_cgroup), GFP_KERNEL);
+	if (foo == NULL)
+		return NULL;
+
+	/*
+	 * initialize your fields
+	 */
+
+	return &foo->css;
+}
+
+static void foo_destroy(struct cgroup_subsys *cs, struct cgroup *cg)
+{
+	struct foo_cgroup *foo;
+
+	foo = foo_from_cgroup(cg);
+
+	/*
+	 * clean your fields
+	 */
+
+	kfree(foo);
+}
+
+static int foo_populate(struct cgroup_subsys *cs, struct cgroup *cg)
+{
+	return cgroup_add_files(cg, cs, foo_files, ARRAY_SIZE(foo_files));
+}
+
+struct cgroup_subsys foo_subsys = {
+	.name = "foo",
+	.subsys_id = foo_subsys_id,
+	.create = foo_create,
+	.destroy = foo_destroy,
+	.populate = foo_populate,
+};

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

#8 lore raw
Quoted 10 lines · Serge E. Hallyn
Quoted 9 lines · Pavel Emelyanov

The Documentation/cgroups.txt file contains the info on how to write some controller for cgroups subsystem, but even with this, one need to write quite a lot of code before developing the core (or copy-n-paste it from some other place).

I propose to put this minimal controller into Documentation directory to let people copy-n-paste a) from a known place and
b) a small piece of code.

Quoted 6 lines
Quoted 4 lines

Besides, many people learn better reading an example rather than/along with a document.

Actually I thought that was the main point of kernel/cgroup_debug.c?

This one doesn't show how to use generic read/write for files, but a bit more advanced read_uint/write_uiant, it doesn't declare its own cgroup with extra fields and doesn't show how to get the one from task.

Hmm... This one is even more minimal than my :)

Quoted 163 lines

-serge

Quoted 160 lines

---

Documentation/cgroups.txt +3 -0
index 42d7c4c..66068dc 100644
@@ -531,6 +531,9 @@ 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).
 
+For a quick start you may want to look at the
+Documentation/controllers/example.c file.
+
 4. Questions
 ============
 
Documentation/controllers/example.c new file +134 -0
new file mode 100644
index 0000000..4a73c77
@@ -0,0 +1,134 @@
+/*
+ * Documentation/controllers/example.c - A simple controller
+ *
+ * Copy and make s/foo/$SUBSYS_NAME/g in it to get a minimal
+ * working code. Don't forget to add a SUBSYS(foo) line in the
+ * include/linux/cgroup_subsys.h file.
+ *
+ */
+
+#include <linux/cgroup.h>
+
+/*
+ * the foo main structure - it is used to store any info, that
+ * is required from the group of tasks
+ */
+
+struct foo_cgroup {
+	/*
+	 * put your fields here
+	 */
+
+	struct cgroup_subsys_state css;
+
+	/*
+	 * ... or/and here
+	 */
+};
+
+/*
+ * helpers to get the foo_cgroup from a task and a control group
+ */
+
+static inline struct foo_cgroup *foo_from_css(struct cgroup_subsys_state *css)
+{
+	return container_of(css, struct foo_cgroup, css);
+}
+
+static inline struct foo_cgroup *foo_from_cgroup(struct cgroup *cg)
+{
+	return foo_from_css(cgroup_subsys_state(cg, foo_subsys_id));
+}
+
+static inline struct foo_cgroup *foo_from_task(struct task_struct *p)
+{
+	return foo_from_css(task_subsys_state(p, foo_subsys_id));
+}
+
+/*
+ * foo files
+ */
+
+static ssize_t foo_bar_read(struct cgroup *cg, struct cftype *cft,
+		struct file *file, char __user *userbuf,
+		size_t nbytes, loff_t *ppos)
+{
+	struct foo_cgroup *foo;
+
+	foo = foo_from_cgroup(cg);
+
+	/*
+	 * produce some output
+	 */
+
+	return nbytes;
+}
+
+static ssize_t foo_bar_write(struct cgroup *cg, struct cftype *cft,
+		struct file *file, const char __user *userbuf,
+		size_t nbytes, loff_t *ppos)
+{
+	struct foo_cgroup *foo;
+
+	foo = foo_from_cgroup(cg);
+
+	/*
+	 * read and tune the foo
+	 */
+
+	return nbytes;
+}
+
+static struct cftype foo_files[] = {
+	{
+		.name = "bar",
+		.read = foo_bar_read,
+		.write = foo_bar_write,
+	},
+};
+
+/*
+ * foo subsystem basic callbacks
+ */
+
+static struct cgroup_subsys_state *foo_create(struct cgroup_subsys *cs,
+		struct cgroup *cg)
+{
+	struct foo_cgroup *foo;
+
+	foo = kmalloc(sizeof(struct foo_cgroup), GFP_KERNEL);
+	if (foo == NULL)
+		return NULL;
+
+	/*
+	 * initialize your fields
+	 */
+
+	return &foo->css;
+}
+
+static void foo_destroy(struct cgroup_subsys *cs, struct cgroup *cg)
+{
+	struct foo_cgroup *foo;
+
+	foo = foo_from_cgroup(cg);
+
+	/*
+	 * clean your fields
+	 */
+
+	kfree(foo);
+}
+
+static int foo_populate(struct cgroup_subsys *cs, struct cgroup *cg)
+{
+	return cgroup_add_files(cg, cs, foo_files, ARRAY_SIZE(foo_files));
+}
+
+struct cgroup_subsys foo_subsys = {
+	.name = "foo",
+	.subsys_id = foo_subsys_id,
+	.create = foo_create,
+	.destroy = foo_destroy,
+	.populate = foo_populate,
+};

_______________________________________________
Containers mailing list Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
https://lists.linux-foundation.org/mailman/listinfo/containers