Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / include / linux / cgroup.h
index c9bbcb2..8f78073 100644 (file)
@@ -37,16 +37,24 @@ extern void cgroup_post_fork(struct task_struct *p);
 extern void cgroup_exit(struct task_struct *p, int run_callbacks);
 extern int cgroupstats_build(struct cgroupstats *stats,
                                struct dentry *dentry);
+extern int cgroup_load_subsys(struct cgroup_subsys *ss);
+extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
 
 extern const struct file_operations proc_cgroup_operations;
 
-/* Define the enumeration of all cgroup subsystems */
+/* Define the enumeration of all builtin cgroup subsystems */
 #define SUBSYS(_x) _x ## _subsys_id,
 enum cgroup_subsys_id {
 #include <linux/cgroup_subsys.h>
-       CGROUP_SUBSYS_COUNT
+       CGROUP_BUILTIN_SUBSYS_COUNT
 };
 #undef SUBSYS
+/*
+ * This define indicates the maximum number of subsystems that can be loaded
+ * at once. We limit to this many since cgroupfs_root has subsys_bits to keep
+ * track of all of them.
+ */
+#define CGROUP_SUBSYS_COUNT (BITS_PER_BYTE*sizeof(unsigned long))
 
 /* Per-subsystem/per-cgroup state maintained by the system. */
 struct cgroup_subsys_state {
@@ -76,6 +84,12 @@ enum {
        CSS_REMOVED, /* This CSS is dead */
 };
 
+/* Caller must verify that the css is not for root cgroup */
+static inline void __css_get(struct cgroup_subsys_state *css, int count)
+{
+       atomic_add(count, &css->refcnt);
+}
+
 /*
  * Call css_get() to hold a reference on the css; it can be used
  * for a reference obtained via:
@@ -87,7 +101,7 @@ static inline void css_get(struct cgroup_subsys_state *css)
 {
        /* We don't need to reference count the root state */
        if (!test_bit(CSS_ROOT, &css->flags))
-               atomic_inc(&css->refcnt);
+               __css_get(css, 1);
 }
 
 static inline bool css_is_removed(struct cgroup_subsys_state *css)
@@ -118,11 +132,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
  * css_get() or css_tryget()
  */
 
-extern void __css_put(struct cgroup_subsys_state *css);
+extern void __css_put(struct cgroup_subsys_state *css, int count);
 static inline void css_put(struct cgroup_subsys_state *css)
 {
        if (!test_bit(CSS_ROOT, &css->flags))
-               __css_put(css);
+               __css_put(css, 1);
 }
 
 /* bits in struct cgroup flags field */
@@ -221,6 +235,10 @@ struct cgroup {
 
        /* For RCU-protected deletion */
        struct rcu_head rcu_head;
+
+       /* List of events which userspace want to recieve */
+       struct list_head event_list;
+       spinlock_t event_list_lock;
 };
 
 /*
@@ -258,7 +276,8 @@ struct css_set {
        /*
         * Set of subsystem states, one for each subsystem. This array
         * is immutable after creation apart from the init_css_set
-        * during subsystem registration (at boot time).
+        * during subsystem registration (at boot time) and modular subsystem
+        * loading/unloading.
         */
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
 
@@ -363,6 +382,23 @@ struct cftype {
        int (*trigger)(struct cgroup *cgrp, unsigned int event);
 
        int (*release)(struct inode *inode, struct file *file);
+
+       /*
+        * register_event() callback will be used to add new userspace
+        * waiter for changes related to the cftype. Implement it if
+        * you want to provide this functionality. Use eventfd_signal()
+        * on eventfd to send notification to userspace.
+        */
+       int (*register_event)(struct cgroup *cgrp, struct cftype *cft,
+                       struct eventfd_ctx *eventfd, const char *args);
+       /*
+        * unregister_event() callback will be called when userspace
+        * closes the eventfd or on cgroup removing.
+        * This callback must be implemented, if you want provide
+        * notification functionality.
+        */
+       int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft,
+                       struct eventfd_ctx *eventfd);
 };
 
 struct cgroup_scanner {
@@ -428,6 +464,8 @@ struct cgroup_subsys {
        void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
        int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
                          struct task_struct *tsk, bool threadgroup);
+       void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+                         struct task_struct *tsk, bool threadgroup);
        void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
                        struct cgroup *old_cgrp, struct task_struct *tsk,
                        bool threadgroup);
@@ -472,6 +510,9 @@ struct cgroup_subsys {
        /* used when use_id == true */
        struct idr idr;
        spinlock_t id_lock;
+
+       /* should be defined only by modular subsystems */
+       struct module *module;
 };
 
 #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
@@ -489,6 +530,7 @@ static inline struct cgroup_subsys_state *task_subsys_state(
 {
        return rcu_dereference_check(task->cgroups->subsys[subsys_id],
                                     rcu_read_lock_held() ||
+                                    lockdep_is_held(&task->alloc_lock) ||
                                     cgroup_lock_is_held());
 }