From 730f3610c2b973149c3cef2886b40744655e22dc Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Thu, 19 May 2011 15:38:27 -0400 Subject: [PATCH] --- yaml --- r: 251157 b: refs/heads/master c: 4843c69d496a8d2e4caab6182fe016b9a79136e0 h: refs/heads/master i: 251155: e7d8ed992f031a80b8aa0de6546809fb27a0844b v: v3 --- [refs] | 2 +- trunk/block/blk-throttle.c | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index a174096fa1ce..95f1b0745684 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5617cbef7723952cbdff28c7a10ff8a254945f4f +refs/heads/master: 4843c69d496a8d2e4caab6182fe016b9a79136e0 diff --git a/trunk/block/blk-throttle.c b/trunk/block/blk-throttle.c index b9412d1cea9e..90ad40735f73 100644 --- a/trunk/block/blk-throttle.c +++ b/trunk/block/blk-throttle.c @@ -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)