diff options
author | Alexander Gordeev <agordeev@redhat.com> | 2014-06-17 22:37:23 +0200 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-06-18 07:13:08 +0200 |
commit | 86fb5c56cfa26de5e91c9a50e2767a695dff366e (patch) | |
tree | da76443281fb15c54d56400b25ff9279e0b9e33e /block | |
parent | blk-mq: bitmap tag: fix race on blk_mq_bitmap_tags::wake_cnt (diff) | |
download | linux-86fb5c56cfa26de5e91c9a50e2767a695dff366e.tar.xz linux-86fb5c56cfa26de5e91c9a50e2767a695dff366e.zip |
blk-mq: bitmap tag: fix races in bt_get() function
This update fixes few issues in bt_get() function:
- list_empty(&wait.task_list) check is not protected;
- was_empty check is always true which results in *every* thread
entering the loop resets bt_wait_state::wait_cnt counter rather
than every bt->wake_cnt'th thread;
- 'bt_wait_state::wait_cnt' counter update is redundant, since
it also gets reset in bt_clear_tag() function;
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ming Lei <tom.leiming@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-mq-tag.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 08fc6716d362..c1b92426c95e 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -248,18 +248,12 @@ static int bt_get(struct blk_mq_alloc_data *data, bs = bt_wait_ptr(bt, hctx); do { - bool was_empty; - - was_empty = list_empty(&wait.task_list); prepare_to_wait(&bs->wait, &wait, TASK_UNINTERRUPTIBLE); tag = __bt_get(hctx, bt, last_tag); if (tag != -1) break; - if (was_empty) - atomic_set(&bs->wait_cnt, bt->wake_cnt); - blk_mq_put_ctx(data->ctx); io_schedule(); @@ -519,10 +513,13 @@ static int bt_alloc(struct blk_mq_bitmap_tags *bt, unsigned int depth, return -ENOMEM; } - for (i = 0; i < BT_WAIT_QUEUES; i++) + bt_update_count(bt, depth); + + for (i = 0; i < BT_WAIT_QUEUES; i++) { init_waitqueue_head(&bt->bs[i].wait); + atomic_set(&bt->bs[i].wait_cnt, bt->wake_cnt); + } - bt_update_count(bt, depth); return 0; } |