Minimal controller code for a quick start
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
@@ -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
Quoted 11 lines · Pavel Emelyanov
The
Documentation/cgroups.txtfile 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()?
Quoted 4 lines · Pavel Emelyanov
The
Documentation/cgroups.txtfile 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
Quoted 5 lines · Pavel Emelyanov
The
Documentation/cgroups.txtfile 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.
Signed-off-by Pavel Emelyanov <[email protected]>
Actually I thought that was the main point of kernel/cgroup_debug.c?
-serge
Quoted 161 lines
---
Documentation/cgroups.txt +3
-0@@ -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@@ -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
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 incgroup_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
Quoted 11 lines · Peter Zijlstra
Quoted 9 lines · Pavel Emelyanov
The
Documentation/cgroups.txtfile 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
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.
Quoted 42 lines · Paul Menage
Quoted 4 lines · Pavel Emelyanov
The
Documentation/cgroups.txtfile 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_int64andwrite_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->parentbeing 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
Quoted 10 lines · Serge E. Hallyn
Quoted 9 lines · Pavel Emelyanov
The
Documentation/cgroups.txtfile 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.
Signed-off-by Pavel Emelyanov <[email protected]>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@@ -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@@ -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