diff options
Diffstat (limited to 'include/linux/cgroup.h')
-rw-r--r-- | include/linux/cgroup.h | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 0008dee66514..b8ad1ea99586 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -28,6 +28,7 @@ struct css_id; | |||
28 | extern int cgroup_init_early(void); | 28 | extern int cgroup_init_early(void); |
29 | extern int cgroup_init(void); | 29 | extern int cgroup_init(void); |
30 | extern void cgroup_lock(void); | 30 | extern void cgroup_lock(void); |
31 | extern int cgroup_lock_is_held(void); | ||
31 | extern bool cgroup_lock_live_group(struct cgroup *cgrp); | 32 | extern bool cgroup_lock_live_group(struct cgroup *cgrp); |
32 | extern void cgroup_unlock(void); | 33 | extern void cgroup_unlock(void); |
33 | extern void cgroup_fork(struct task_struct *p); | 34 | extern void cgroup_fork(struct task_struct *p); |
@@ -36,16 +37,24 @@ extern void cgroup_post_fork(struct task_struct *p); | |||
36 | extern void cgroup_exit(struct task_struct *p, int run_callbacks); | 37 | extern void cgroup_exit(struct task_struct *p, int run_callbacks); |
37 | extern int cgroupstats_build(struct cgroupstats *stats, | 38 | extern int cgroupstats_build(struct cgroupstats *stats, |
38 | struct dentry *dentry); | 39 | struct dentry *dentry); |
40 | extern int cgroup_load_subsys(struct cgroup_subsys *ss); | ||
41 | extern void cgroup_unload_subsys(struct cgroup_subsys *ss); | ||
39 | 42 | ||
40 | extern const struct file_operations proc_cgroup_operations; | 43 | extern const struct file_operations proc_cgroup_operations; |
41 | 44 | ||
42 | /* Define the enumeration of all cgroup subsystems */ | 45 | /* Define the enumeration of all builtin cgroup subsystems */ |
43 | #define SUBSYS(_x) _x ## _subsys_id, | 46 | #define SUBSYS(_x) _x ## _subsys_id, |
44 | enum cgroup_subsys_id { | 47 | enum cgroup_subsys_id { |
45 | #include <linux/cgroup_subsys.h> | 48 | #include <linux/cgroup_subsys.h> |
46 | CGROUP_SUBSYS_COUNT | 49 | CGROUP_BUILTIN_SUBSYS_COUNT |
47 | }; | 50 | }; |
48 | #undef SUBSYS | 51 | #undef SUBSYS |
52 | /* | ||
53 | * This define indicates the maximum number of subsystems that can be loaded | ||
54 | * at once. We limit to this many since cgroupfs_root has subsys_bits to keep | ||
55 | * track of all of them. | ||
56 | */ | ||
57 | #define CGROUP_SUBSYS_COUNT (BITS_PER_BYTE*sizeof(unsigned long)) | ||
49 | 58 | ||
50 | /* Per-subsystem/per-cgroup state maintained by the system. */ | 59 | /* Per-subsystem/per-cgroup state maintained by the system. */ |
51 | struct cgroup_subsys_state { | 60 | struct cgroup_subsys_state { |
@@ -75,6 +84,12 @@ enum { | |||
75 | CSS_REMOVED, /* This CSS is dead */ | 84 | CSS_REMOVED, /* This CSS is dead */ |
76 | }; | 85 | }; |
77 | 86 | ||
87 | /* Caller must verify that the css is not for root cgroup */ | ||
88 | static inline void __css_get(struct cgroup_subsys_state *css, int count) | ||
89 | { | ||
90 | atomic_add(count, &css->refcnt); | ||
91 | } | ||
92 | |||
78 | /* | 93 | /* |
79 | * Call css_get() to hold a reference on the css; it can be used | 94 | * Call css_get() to hold a reference on the css; it can be used |
80 | * for a reference obtained via: | 95 | * for a reference obtained via: |
@@ -86,7 +101,7 @@ static inline void css_get(struct cgroup_subsys_state *css) | |||
86 | { | 101 | { |
87 | /* We don't need to reference count the root state */ | 102 | /* We don't need to reference count the root state */ |
88 | if (!test_bit(CSS_ROOT, &css->flags)) | 103 | if (!test_bit(CSS_ROOT, &css->flags)) |
89 | atomic_inc(&css->refcnt); | 104 | __css_get(css, 1); |
90 | } | 105 | } |
91 | 106 | ||
92 | static inline bool css_is_removed(struct cgroup_subsys_state *css) | 107 | static inline bool css_is_removed(struct cgroup_subsys_state *css) |
@@ -117,11 +132,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css) | |||
117 | * css_get() or css_tryget() | 132 | * css_get() or css_tryget() |
118 | */ | 133 | */ |
119 | 134 | ||
120 | extern void __css_put(struct cgroup_subsys_state *css); | 135 | extern void __css_put(struct cgroup_subsys_state *css, int count); |
121 | static inline void css_put(struct cgroup_subsys_state *css) | 136 | static inline void css_put(struct cgroup_subsys_state *css) |
122 | { | 137 | { |
123 | if (!test_bit(CSS_ROOT, &css->flags)) | 138 | if (!test_bit(CSS_ROOT, &css->flags)) |
124 | __css_put(css); | 139 | __css_put(css, 1); |
125 | } | 140 | } |
126 | 141 | ||
127 | /* bits in struct cgroup flags field */ | 142 | /* bits in struct cgroup flags field */ |
@@ -220,6 +235,10 @@ struct cgroup { | |||
220 | 235 | ||
221 | /* For RCU-protected deletion */ | 236 | /* For RCU-protected deletion */ |
222 | struct rcu_head rcu_head; | 237 | struct rcu_head rcu_head; |
238 | |||
239 | /* List of events which userspace want to recieve */ | ||
240 | struct list_head event_list; | ||
241 | spinlock_t event_list_lock; | ||
223 | }; | 242 | }; |
224 | 243 | ||
225 | /* | 244 | /* |
@@ -257,7 +276,8 @@ struct css_set { | |||
257 | /* | 276 | /* |
258 | * Set of subsystem states, one for each subsystem. This array | 277 | * Set of subsystem states, one for each subsystem. This array |
259 | * is immutable after creation apart from the init_css_set | 278 | * is immutable after creation apart from the init_css_set |
260 | * during subsystem registration (at boot time). | 279 | * during subsystem registration (at boot time) and modular subsystem |
280 | * loading/unloading. | ||
261 | */ | 281 | */ |
262 | struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; | 282 | struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; |
263 | 283 | ||
@@ -362,6 +382,23 @@ struct cftype { | |||
362 | int (*trigger)(struct cgroup *cgrp, unsigned int event); | 382 | int (*trigger)(struct cgroup *cgrp, unsigned int event); |
363 | 383 | ||
364 | int (*release)(struct inode *inode, struct file *file); | 384 | int (*release)(struct inode *inode, struct file *file); |
385 | |||
386 | /* | ||
387 | * register_event() callback will be used to add new userspace | ||
388 | * waiter for changes related to the cftype. Implement it if | ||
389 | * you want to provide this functionality. Use eventfd_signal() | ||
390 | * on eventfd to send notification to userspace. | ||
391 | */ | ||
392 | int (*register_event)(struct cgroup *cgrp, struct cftype *cft, | ||
393 | struct eventfd_ctx *eventfd, const char *args); | ||
394 | /* | ||
395 | * unregister_event() callback will be called when userspace | ||
396 | * closes the eventfd or on cgroup removing. | ||
397 | * This callback must be implemented, if you want provide | ||
398 | * notification functionality. | ||
399 | */ | ||
400 | int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft, | ||
401 | struct eventfd_ctx *eventfd); | ||
365 | }; | 402 | }; |
366 | 403 | ||
367 | struct cgroup_scanner { | 404 | struct cgroup_scanner { |
@@ -427,6 +464,8 @@ struct cgroup_subsys { | |||
427 | void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); | 464 | void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); |
428 | int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 465 | int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
429 | struct task_struct *tsk, bool threadgroup); | 466 | struct task_struct *tsk, bool threadgroup); |
467 | void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | ||
468 | struct task_struct *tsk, bool threadgroup); | ||
430 | void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, | 469 | void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, |
431 | struct cgroup *old_cgrp, struct task_struct *tsk, | 470 | struct cgroup *old_cgrp, struct task_struct *tsk, |
432 | bool threadgroup); | 471 | bool threadgroup); |
@@ -471,6 +510,9 @@ struct cgroup_subsys { | |||
471 | /* used when use_id == true */ | 510 | /* used when use_id == true */ |
472 | struct idr idr; | 511 | struct idr idr; |
473 | spinlock_t id_lock; | 512 | spinlock_t id_lock; |
513 | |||
514 | /* should be defined only by modular subsystems */ | ||
515 | struct module *module; | ||
474 | }; | 516 | }; |
475 | 517 | ||
476 | #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys; | 518 | #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys; |
@@ -486,7 +528,9 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state( | |||
486 | static inline struct cgroup_subsys_state *task_subsys_state( | 528 | static inline struct cgroup_subsys_state *task_subsys_state( |
487 | struct task_struct *task, int subsys_id) | 529 | struct task_struct *task, int subsys_id) |
488 | { | 530 | { |
489 | return rcu_dereference(task->cgroups->subsys[subsys_id]); | 531 | return rcu_dereference_check(task->cgroups->subsys[subsys_id], |
532 | rcu_read_lock_held() || | ||
533 | cgroup_lock_is_held()); | ||
490 | } | 534 | } |
491 | 535 | ||
492 | static inline struct cgroup* task_cgroup(struct task_struct *task, | 536 | static inline struct cgroup* task_cgroup(struct task_struct *task, |