diff options
Diffstat (limited to 'include/linux/cgroup.h')
| -rw-r--r-- | include/linux/cgroup.h | 88 |
1 files changed, 79 insertions, 9 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 0008dee66514..0c991023ee47 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 | void (*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; |
| @@ -483,10 +525,21 @@ static inline struct cgroup_subsys_state *cgroup_subsys_state( | |||
| 483 | return cgrp->subsys[subsys_id]; | 525 | return cgrp->subsys[subsys_id]; |
| 484 | } | 526 | } |
| 485 | 527 | ||
| 486 | static inline struct cgroup_subsys_state *task_subsys_state( | 528 | /* |
| 487 | struct task_struct *task, int subsys_id) | 529 | * function to get the cgroup_subsys_state which allows for extra |
| 530 | * rcu_dereference_check() conditions, such as locks used during the | ||
| 531 | * cgroup_subsys::attach() methods. | ||
| 532 | */ | ||
| 533 | #define task_subsys_state_check(task, subsys_id, __c) \ | ||
| 534 | rcu_dereference_check(task->cgroups->subsys[subsys_id], \ | ||
| 535 | rcu_read_lock_held() || \ | ||
| 536 | lockdep_is_held(&task->alloc_lock) || \ | ||
| 537 | cgroup_lock_is_held() || (__c)) | ||
| 538 | |||
| 539 | static inline struct cgroup_subsys_state * | ||
| 540 | task_subsys_state(struct task_struct *task, int subsys_id) | ||
| 488 | { | 541 | { |
| 489 | return rcu_dereference(task->cgroups->subsys[subsys_id]); | 542 | return task_subsys_state_check(task, subsys_id, false); |
| 490 | } | 543 | } |
| 491 | 544 | ||
| 492 | static inline struct cgroup* task_cgroup(struct task_struct *task, | 545 | static inline struct cgroup* task_cgroup(struct task_struct *task, |
| @@ -525,6 +578,12 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp, | |||
| 525 | void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it); | 578 | void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it); |
| 526 | int cgroup_scan_tasks(struct cgroup_scanner *scan); | 579 | int cgroup_scan_tasks(struct cgroup_scanner *scan); |
| 527 | int cgroup_attach_task(struct cgroup *, struct task_struct *); | 580 | int cgroup_attach_task(struct cgroup *, struct task_struct *); |
| 581 | int cgroup_attach_task_all(struct task_struct *from, struct task_struct *); | ||
| 582 | |||
| 583 | static inline int cgroup_attach_task_current_cg(struct task_struct *tsk) | ||
| 584 | { | ||
| 585 | return cgroup_attach_task_all(current, tsk); | ||
| 586 | } | ||
| 528 | 587 | ||
| 529 | /* | 588 | /* |
| 530 | * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works | 589 | * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works |
| @@ -581,6 +640,17 @@ static inline int cgroupstats_build(struct cgroupstats *stats, | |||
| 581 | return -EINVAL; | 640 | return -EINVAL; |
| 582 | } | 641 | } |
| 583 | 642 | ||
| 643 | /* No cgroups - nothing to do */ | ||
| 644 | static inline int cgroup_attach_task_all(struct task_struct *from, | ||
| 645 | struct task_struct *t) | ||
| 646 | { | ||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | static inline int cgroup_attach_task_current_cg(struct task_struct *t) | ||
| 650 | { | ||
| 651 | return 0; | ||
| 652 | } | ||
| 653 | |||
| 584 | #endif /* !CONFIG_CGROUPS */ | 654 | #endif /* !CONFIG_CGROUPS */ |
| 585 | 655 | ||
| 586 | #endif /* _LINUX_CGROUP_H */ | 656 | #endif /* _LINUX_CGROUP_H */ |
