blk-throttle: Free up a group only after one rcu grace period
Vivek Goyal [Thu, 19 May 2011 19:38:27 +0000 (15:38 -0400)]
Soon we will allow accessing a throtl_grp under rcu_read_lock(). Hence
start freeing up throtl_grp after one rcu grace period.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>

block/blk-throttle.c

index b9412d1..90ad407 100644 (file)
@@ -78,6 +78,8 @@ struct throtl_grp {
 
        /* Some throttle limits got updated for the group */
        int limits_changed;
+
+       struct rcu_head rcu_head;
 };
 
 struct throtl_data
@@ -151,12 +153,30 @@ static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
        return tg;
 }
 
+static void throtl_free_tg(struct rcu_head *head)
+{
+       struct throtl_grp *tg;
+
+       tg = container_of(head, struct throtl_grp, rcu_head);
+       kfree(tg);
+}
+
 static void throtl_put_tg(struct throtl_grp *tg)
 {
        BUG_ON(atomic_read(&tg->ref) <= 0);
        if (!atomic_dec_and_test(&tg->ref))
                return;
-       kfree(tg);
+
+       /*
+        * 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(&tg->rcu_head, throtl_free_tg);
 }
 
 static void throtl_init_group(struct throtl_grp *tg)