diff options
author | Vivek Goyal <vgoyal@redhat.com> | 2011-05-19 21:38:27 +0200 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-05-20 20:34:52 +0200 |
commit | 4843c69d496a8d2e4caab6182fe016b9a79136e0 (patch) | |
tree | 0812bb95cfc7769a3ccd90d84f303bed861c9c0a /block/blk-throttle.c | |
parent | blk-throttle: Use helper function to add root throtl group to lists (diff) | |
download | linux-4843c69d496a8d2e4caab6182fe016b9a79136e0.tar.xz linux-4843c69d496a8d2e4caab6182fe016b9a79136e0.zip |
blk-throttle: Free up a group only after one rcu grace period
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>
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r-- | block/blk-throttle.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index b9412d1cea9e..90ad40735f73 100644 --- a/block/blk-throttle.c +++ b/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) |