Merge tag 'omap-for-v3.11/fixes-against-rc1' of git://git.kernel.org/pub/scm/linux...
[firefly-linux-kernel-4.4.55.git] / block / blk-cgroup.c
index b950306838adaad44a7c9e947a44f7cafbbb6fd9..290792a13e3cc184f0ea67176589050e6323b675 100644 (file)
@@ -51,18 +51,8 @@ static void blkg_free(struct blkcg_gq *blkg)
        if (!blkg)
                return;
 
-       for (i = 0; i < BLKCG_MAX_POLS; i++) {
-               struct blkcg_policy *pol = blkcg_policy[i];
-               struct blkg_policy_data *pd = blkg->pd[i];
-
-               if (!pd)
-                       continue;
-
-               if (pol && pol->pd_exit_fn)
-                       pol->pd_exit_fn(blkg);
-
-               kfree(pd);
-       }
+       for (i = 0; i < BLKCG_MAX_POLS; i++)
+               kfree(blkg->pd[i]);
 
        blk_exit_rl(&blkg->rl);
        kfree(blkg);
@@ -114,10 +104,6 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
                blkg->pd[i] = pd;
                pd->blkg = blkg;
                pd->plid = i;
-
-               /* invoke per-policy init */
-               if (pol->pd_init_fn)
-                       pol->pd_init_fn(blkg);
        }
 
        return blkg;
@@ -214,7 +200,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
        }
        blkg = new_blkg;
 
-       /* link parent and insert */
+       /* link parent */
        if (blkcg_parent(blkcg)) {
                blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false);
                if (WARN_ON_ONCE(!blkg->parent)) {
@@ -224,6 +210,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
                blkg_get(blkg->parent);
        }
 
+       /* invoke per-policy init */
+       for (i = 0; i < BLKCG_MAX_POLS; i++) {
+               struct blkcg_policy *pol = blkcg_policy[i];
+
+               if (blkg->pd[i] && pol->pd_init_fn)
+                       pol->pd_init_fn(blkg);
+       }
+
+       /* insert */
        spin_lock(&blkcg->lock);
        ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg);
        if (likely(!ret)) {
@@ -374,30 +369,38 @@ static void blkg_destroy_all(struct request_queue *q)
        q->root_rl.blkg = NULL;
 }
 
-static void blkg_rcu_free(struct rcu_head *rcu_head)
+/*
+ * A group is RCU protected, but having an rcu lock does not mean that one
+ * can access all the fields of blkg and assume these are valid.  For
+ * example, don't try to follow throtl_data and request queue links.
+ *
+ * Having a reference to blkg under an rcu allows accesses to only values
+ * local to groups like group stats and group rate limits.
+ */
+void __blkg_release_rcu(struct rcu_head *rcu_head)
 {
-       blkg_free(container_of(rcu_head, struct blkcg_gq, rcu_head));
-}
+       struct blkcg_gq *blkg = container_of(rcu_head, struct blkcg_gq, rcu_head);
+       int i;
+
+       /* tell policies that this one is being freed */
+       for (i = 0; i < BLKCG_MAX_POLS; i++) {
+               struct blkcg_policy *pol = blkcg_policy[i];
+
+               if (blkg->pd[i] && pol->pd_exit_fn)
+                       pol->pd_exit_fn(blkg);
+       }
 
-void __blkg_release(struct blkcg_gq *blkg)
-{
        /* release the blkcg and parent blkg refs this blkg has been holding */
        css_put(&blkg->blkcg->css);
-       if (blkg->parent)
+       if (blkg->parent) {
+               spin_lock_irq(blkg->q->queue_lock);
                blkg_put(blkg->parent);
+               spin_unlock_irq(blkg->q->queue_lock);
+       }
 
-       /*
-        * A group is freed in rcu manner. But having an rcu lock does not
-        * mean that one can access all the fields of blkg and assume these
-        * are valid. For example, don't try to follow throtl_data and
-        * request queue links.
-        *
-        * Having a reference to blkg under an rcu allows acess to only
-        * values local to groups like group stats and group rate limits
-        */
-       call_rcu(&blkg->rcu_head, blkg_rcu_free);
+       blkg_free(blkg);
 }
-EXPORT_SYMBOL_GPL(__blkg_release);
+EXPORT_SYMBOL_GPL(__blkg_release_rcu);
 
 /*
  * The next function used by blk_queue_for_each_rl().  It's a bit tricky
@@ -908,14 +911,6 @@ struct cgroup_subsys blkio_subsys = {
        .subsys_id = blkio_subsys_id,
        .base_cftypes = blkcg_files,
        .module = THIS_MODULE,
-
-       /*
-        * blkio subsystem is utterly broken in terms of hierarchy support.
-        * It treats all cgroups equally regardless of where they're
-        * located in the hierarchy - all cgroups are treated as if they're
-        * right below the root.  Fix it and remove the following.
-        */
-       .broken_hierarchy = true,
 };
 EXPORT_SYMBOL_GPL(blkio_subsys);