cgroup: pass around cgroup_subsys_state instead of cgroup in subsystem methods
[linux-2.6-block.git] / include / linux / cgroup.h
index fd097ecfcd9747849365a0590f91c64f0f7a4479..9c2b9dd9121dda768886b2ed977f388dd38d2cf9 100644 (file)
@@ -66,13 +66,12 @@ enum cgroup_subsys_id {
 
 /* Per-subsystem/per-cgroup state maintained by the system. */
 struct cgroup_subsys_state {
-       /*
-        * The cgroup that this subsystem is attached to. Useful
-        * for subsystems that want to know about the cgroup
-        * hierarchy structure
-        */
+       /* the cgroup that this css is attached to */
        struct cgroup *cgroup;
 
+       /* the cgroup subsystem that this css is attached to */
+       struct cgroup_subsys *ss;
+
        /* reference count - access via css_[try]get() and css_put() */
        struct percpu_ref refcnt;
 
@@ -161,7 +160,13 @@ struct cgroup_name {
 struct cgroup {
        unsigned long flags;            /* "unsigned long" so bitops work */
 
-       int id;                         /* ida allocated in-hierarchy ID */
+       /*
+        * idr allocated in-hierarchy ID.
+        *
+        * The ID of the root cgroup is always 0, and a new cgroup
+        * will be assigned with a smallest available ID.
+        */
+       int id;
 
        /*
         * We link our 'sibling' struct into our parent's 'children'.
@@ -278,6 +283,8 @@ enum {
         *
         * - memcg: use_hierarchy is on by default and the cgroup file for
         *   the flag is not created.
+        *
+        * - blkcg: blk-throttle becomes properly hierarchical.
         */
        CGRP_ROOT_SANE_BEHAVIOR = (1 << 0),
 
@@ -320,7 +327,7 @@ struct cgroupfs_root {
        unsigned long flags;
 
        /* IDs for cgroups in this hierarchy */
-       struct ida cgroup_ida;
+       struct idr cgroup_idr;
 
        /* The path to use for release notifications. */
        char release_agent_path[PATH_MAX];
@@ -392,8 +399,8 @@ struct cgroup_map_cb {
 
 /* cftype->flags */
 enum {
-       CFTYPE_ONLY_ON_ROOT     = (1 << 0),     /* only create on root cg */
-       CFTYPE_NOT_ON_ROOT      = (1 << 1),     /* don't create on root cg */
+       CFTYPE_ONLY_ON_ROOT     = (1 << 0),     /* only create on root cgrp */
+       CFTYPE_NOT_ON_ROOT      = (1 << 1),     /* don't create on root cgrp */
        CFTYPE_INSANE           = (1 << 2),     /* don't create if sane_behavior */
 };
 
@@ -511,7 +518,7 @@ struct cftype_set {
 };
 
 struct cgroup_scanner {
-       struct cgroup *cg;
+       struct cgroup *cgrp;
        int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan);
        void (*process_task)(struct task_struct *p,
                        struct cgroup_scanner *scan);
@@ -540,8 +547,7 @@ int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
 
 int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen);
-int task_cgroup_path_from_hierarchy(struct task_struct *task, int hierarchy_id,
-                                   char *buf, size_t buflen);
+int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
 
 int cgroup_task_count(const struct cgroup *cgrp);
 
@@ -573,18 +579,22 @@ int cgroup_taskset_size(struct cgroup_taskset *tset);
  */
 
 struct cgroup_subsys {
-       struct cgroup_subsys_state *(*css_alloc)(struct cgroup *cgrp);
-       int (*css_online)(struct cgroup *cgrp);
-       void (*css_offline)(struct cgroup *cgrp);
-       void (*css_free)(struct cgroup *cgrp);
-
-       int (*can_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
-       void (*cancel_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
-       void (*attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);
+       struct cgroup_subsys_state *(*css_alloc)(struct cgroup_subsys_state *parent_css);
+       int (*css_online)(struct cgroup_subsys_state *css);
+       void (*css_offline)(struct cgroup_subsys_state *css);
+       void (*css_free)(struct cgroup_subsys_state *css);
+
+       int (*can_attach)(struct cgroup_subsys_state *css,
+                         struct cgroup_taskset *tset);
+       void (*cancel_attach)(struct cgroup_subsys_state *css,
+                             struct cgroup_taskset *tset);
+       void (*attach)(struct cgroup_subsys_state *css,
+                      struct cgroup_taskset *tset);
        void (*fork)(struct task_struct *task);
-       void (*exit)(struct cgroup *cgrp, struct cgroup *old_cgrp,
+       void (*exit)(struct cgroup_subsys_state *css,
+                    struct cgroup_subsys_state *old_css,
                     struct task_struct *task);
-       void (*bind)(struct cgroup *root);
+       void (*bind)(struct cgroup_subsys_state *root_css);
 
        int subsys_id;
        int disabled;
@@ -640,8 +650,30 @@ struct cgroup_subsys {
 #undef IS_SUBSYS_ENABLED
 #undef SUBSYS
 
-static inline struct cgroup_subsys_state *cgroup_subsys_state(
-       struct cgroup *cgrp, int subsys_id)
+/**
+ * css_parent - find the parent css
+ * @css: the target cgroup_subsys_state
+ *
+ * Return the parent css of @css.  This function is guaranteed to return
+ * non-NULL parent as long as @css isn't the root.
+ */
+static inline
+struct cgroup_subsys_state *css_parent(struct cgroup_subsys_state *css)
+{
+       struct cgroup *parent_cgrp = css->cgroup->parent;
+
+       return parent_cgrp ? parent_cgrp->subsys[css->ss->subsys_id] : NULL;
+}
+
+/**
+ * cgroup_css - obtain a cgroup's css for the specified subsystem
+ * @cgrp: the cgroup of interest
+ * @subsys_id: the subsystem of interest
+ *
+ * Return @cgrp's css (cgroup_subsys_state) associated with @subsys_id.
+ */
+static inline struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp,
+                                                    int subsys_id)
 {
        return cgrp->subsys[subsys_id];
 }
@@ -671,7 +703,7 @@ extern struct mutex cgroup_mutex;
 #endif
 
 /**
- * task_subsys_state_check - obtain css for (task, subsys) w/ extra access conds
+ * task_css_check - obtain css for (task, subsys) w/ extra access conds
  * @task: the target task
  * @subsys_id: the target subsystem ID
  * @__c: extra condition expression to be passed to rcu_dereference_check()
@@ -679,7 +711,7 @@ extern struct mutex cgroup_mutex;
  * Return the cgroup_subsys_state for the (@task, @subsys_id) pair.  The
  * synchronization rules are the same as task_css_set_check().
  */
-#define task_subsys_state_check(task, subsys_id, __c)                  \
+#define task_css_check(task, subsys_id, __c)                           \
        task_css_set_check((task), (__c))->subsys[(subsys_id)]
 
 /**
@@ -694,22 +726,40 @@ static inline struct css_set *task_css_set(struct task_struct *task)
 }
 
 /**
- * task_subsys_state - obtain css for (task, subsys)
+ * task_css - obtain css for (task, subsys)
  * @task: the target task
  * @subsys_id: the target subsystem ID
  *
- * See task_subsys_state_check().
+ * See task_css_check().
  */
-static inline struct cgroup_subsys_state *
-task_subsys_state(struct task_struct *task, int subsys_id)
+static inline struct cgroup_subsys_state *task_css(struct task_struct *task,
+                                                  int subsys_id)
+{
+       return task_css_check(task, subsys_id, false);
+}
+
+static inline struct cgroup *task_cgroup(struct task_struct *task,
+                                        int subsys_id)
 {
-       return task_subsys_state_check(task, subsys_id, false);
+       return task_css(task, subsys_id)->cgroup;
 }
 
-static inline struct cgroup* task_cgroup(struct task_struct *task,
-                                              int subsys_id)
+/**
+ * cgroup_from_id - lookup cgroup by id
+ * @ss: cgroup subsys to be looked into
+ * @id: the cgroup id
+ *
+ * Returns the cgroup if there's valid one with @id, otherwise returns NULL.
+ * Should be called under rcu_read_lock().
+ */
+static inline struct cgroup *cgroup_from_id(struct cgroup_subsys *ss, int id)
 {
-       return task_subsys_state(task, subsys_id)->cgroup;
+#ifdef CONFIG_PROVE_RCU
+       rcu_lockdep_assert(rcu_read_lock_held() ||
+                          lockdep_is_held(&cgroup_mutex),
+                          "cgroup_from_id() needs proper protection");
+#endif
+       return idr_find(&ss->root->cgroup_idr, id);
 }
 
 struct cgroup *cgroup_next_sibling(struct cgroup *pos);