diff options
author | Tejun Heo <tj@kernel.org> | 2012-03-05 16:15:01 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-03-06 15:27:22 -0500 |
commit | 2a7f124414b35645049e9c1b125a6f0b470aa5ae (patch) | |
tree | 298d9bc310dc46baed69baf88f083c6db35f0964 /block/blk-throttle.c | |
parent | 72e06c255181537d0b3e1f657a9ed81655d745b1 (diff) |
blkcg: move rcu_read_lock() outside of blkio_group get functions
rcu_read_lock() in throtl_get_tb() and cfq_get_cfqg() holds onto
@blkcg while looking up blkg. For API cleanup, the next patch will
make the caller responsible for determining @blkcg to look blkg from
and let them specify it as a parameter. Move rcu read locking out to
the callers to prepare for the change.
-v2: Originally this patch was described as a fix for RCU read locking
bug around @blkg, which Vivek pointed out to be incorrect. It
was from misunderstanding the role of rcu locking as protecting
@blkg not @blkcg. Patch description updated.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r-- | block/blk-throttle.c | 18 |
1 files changed, 6 insertions, 12 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 3699ab40d494..9beaac7fb397 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
@@ -313,25 +313,23 @@ static struct throtl_grp * throtl_get_tg(struct throtl_data *td) | |||
313 | if (unlikely(blk_queue_bypass(q))) | 313 | if (unlikely(blk_queue_bypass(q))) |
314 | return NULL; | 314 | return NULL; |
315 | 315 | ||
316 | rcu_read_lock(); | ||
317 | blkcg = task_blkio_cgroup(current); | 316 | blkcg = task_blkio_cgroup(current); |
318 | tg = throtl_find_tg(td, blkcg); | 317 | tg = throtl_find_tg(td, blkcg); |
319 | if (tg) { | 318 | if (tg) |
320 | rcu_read_unlock(); | ||
321 | return tg; | 319 | return tg; |
322 | } | ||
323 | 320 | ||
324 | /* | 321 | /* |
325 | * Need to allocate a group. Allocation of group also needs allocation | 322 | * Need to allocate a group. Allocation of group also needs allocation |
326 | * of per cpu stats which in-turn takes a mutex() and can block. Hence | 323 | * of per cpu stats which in-turn takes a mutex() and can block. Hence |
327 | * we need to drop rcu lock and queue_lock before we call alloc. | 324 | * we need to drop rcu lock and queue_lock before we call alloc. |
328 | */ | 325 | */ |
329 | rcu_read_unlock(); | ||
330 | spin_unlock_irq(q->queue_lock); | 326 | spin_unlock_irq(q->queue_lock); |
327 | rcu_read_unlock(); | ||
331 | 328 | ||
332 | tg = throtl_alloc_tg(td); | 329 | tg = throtl_alloc_tg(td); |
333 | 330 | ||
334 | /* Group allocated and queue is still alive. take the lock */ | 331 | /* Group allocated and queue is still alive. take the lock */ |
332 | rcu_read_lock(); | ||
335 | spin_lock_irq(q->queue_lock); | 333 | spin_lock_irq(q->queue_lock); |
336 | 334 | ||
337 | /* Make sure @q is still alive */ | 335 | /* Make sure @q is still alive */ |
@@ -343,7 +341,6 @@ static struct throtl_grp * throtl_get_tg(struct throtl_data *td) | |||
343 | /* | 341 | /* |
344 | * Initialize the new group. After sleeping, read the blkcg again. | 342 | * Initialize the new group. After sleeping, read the blkcg again. |
345 | */ | 343 | */ |
346 | rcu_read_lock(); | ||
347 | blkcg = task_blkio_cgroup(current); | 344 | blkcg = task_blkio_cgroup(current); |
348 | 345 | ||
349 | /* | 346 | /* |
@@ -354,7 +351,6 @@ static struct throtl_grp * throtl_get_tg(struct throtl_data *td) | |||
354 | 351 | ||
355 | if (__tg) { | 352 | if (__tg) { |
356 | kfree(tg); | 353 | kfree(tg); |
357 | rcu_read_unlock(); | ||
358 | return __tg; | 354 | return __tg; |
359 | } | 355 | } |
360 | 356 | ||
@@ -365,7 +361,6 @@ static struct throtl_grp * throtl_get_tg(struct throtl_data *td) | |||
365 | } | 361 | } |
366 | 362 | ||
367 | throtl_init_add_tg_lists(td, tg, blkcg); | 363 | throtl_init_add_tg_lists(td, tg, blkcg); |
368 | rcu_read_unlock(); | ||
369 | return tg; | 364 | return tg; |
370 | } | 365 | } |
371 | 366 | ||
@@ -1150,7 +1145,6 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) | |||
1150 | * basic fields like stats and io rates. If a group has no rules, | 1145 | * basic fields like stats and io rates. If a group has no rules, |
1151 | * just update the dispatch stats in lockless manner and return. | 1146 | * just update the dispatch stats in lockless manner and return. |
1152 | */ | 1147 | */ |
1153 | |||
1154 | rcu_read_lock(); | 1148 | rcu_read_lock(); |
1155 | blkcg = task_blkio_cgroup(current); | 1149 | blkcg = task_blkio_cgroup(current); |
1156 | tg = throtl_find_tg(td, blkcg); | 1150 | tg = throtl_find_tg(td, blkcg); |
@@ -1160,11 +1154,9 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) | |||
1160 | if (tg_no_rule_group(tg, rw)) { | 1154 | if (tg_no_rule_group(tg, rw)) { |
1161 | blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, | 1155 | blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, |
1162 | rw, rw_is_sync(bio->bi_rw)); | 1156 | rw, rw_is_sync(bio->bi_rw)); |
1163 | rcu_read_unlock(); | 1157 | goto out_unlock_rcu; |
1164 | goto out; | ||
1165 | } | 1158 | } |
1166 | } | 1159 | } |
1167 | rcu_read_unlock(); | ||
1168 | 1160 | ||
1169 | /* | 1161 | /* |
1170 | * Either group has not been allocated yet or it is not an unlimited | 1162 | * Either group has not been allocated yet or it is not an unlimited |
@@ -1222,6 +1214,8 @@ queue_bio: | |||
1222 | 1214 | ||
1223 | out_unlock: | 1215 | out_unlock: |
1224 | spin_unlock_irq(q->queue_lock); | 1216 | spin_unlock_irq(q->queue_lock); |
1217 | out_unlock_rcu: | ||
1218 | rcu_read_unlock(); | ||
1225 | out: | 1219 | out: |
1226 | return throttled; | 1220 | return throttled; |
1227 | } | 1221 | } |