aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/blk-throttle.c22
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 {
78 78
79 /* Some throttle limits got updated for the group */ 79 /* Some throttle limits got updated for the group */
80 int limits_changed; 80 int limits_changed;
81
82 struct rcu_head rcu_head;
81}; 83};
82 84
83struct throtl_data 85struct throtl_data
@@ -151,12 +153,30 @@ static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
151 return tg; 153 return tg;
152} 154}
153 155
156static void throtl_free_tg(struct rcu_head *head)
157{
158 struct throtl_grp *tg;
159
160 tg = container_of(head, struct throtl_grp, rcu_head);
161 kfree(tg);
162}
163
154static void throtl_put_tg(struct throtl_grp *tg) 164static void throtl_put_tg(struct throtl_grp *tg)
155{ 165{
156 BUG_ON(atomic_read(&tg->ref) <= 0); 166 BUG_ON(atomic_read(&tg->ref) <= 0);
157 if (!atomic_dec_and_test(&tg->ref)) 167 if (!atomic_dec_and_test(&tg->ref))
158 return; 168 return;
159 kfree(tg); 169
170 /*
171 * A group is freed in rcu manner. But having an rcu lock does not
172 * mean that one can access all the fields of blkg and assume these
173 * are valid. For example, don't try to follow throtl_data and
174 * request queue links.
175 *
176 * Having a reference to blkg under an rcu allows acess to only
177 * values local to groups like group stats and group rate limits
178 */
179 call_rcu(&tg->rcu_head, throtl_free_tg);
160} 180}
161 181
162static void throtl_init_group(struct throtl_grp *tg) 182static void throtl_init_group(struct throtl_grp *tg)