diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-15 20:25:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-15 20:25:20 -0500 |
commit | 9b8ec916df67ba31614796037caf606b763e2e79 (patch) | |
tree | 686e3d85b8c5af57d54265354ffab61f4803856e | |
parent | 27cb8823e26cecd03c00d82dfb501f6c144b3445 (diff) | |
parent | 35d37c66356eed46700e0d5db87211844d43a241 (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull core block fix from Jens Axboe:
"Jan reported a problem this morning with a crash in blk-mq, and after
looking over the recent changes, it's obvious that the blk-mq-tag
waitqueue handling change is buggy. We could end up _not_ doing
finish_wait() before switching to a new waitqueue, thus corrupting the
wait task list"
* 'for-linus' of git://git.kernel.dk/linux-block:
Revert "blk-mq: Micro-optimize bt_get()"
-rw-r--r-- | block/blk-mq-tag.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index e3d4e4043b49..32e8dbb9ad1c 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c | |||
@@ -248,8 +248,8 @@ static int bt_get(struct blk_mq_alloc_data *data, | |||
248 | if (!(data->gfp & __GFP_WAIT)) | 248 | if (!(data->gfp & __GFP_WAIT)) |
249 | return -1; | 249 | return -1; |
250 | 250 | ||
251 | bs = bt_wait_ptr(bt, hctx); | ||
251 | do { | 252 | do { |
252 | bs = bt_wait_ptr(bt, hctx); | ||
253 | prepare_to_wait(&bs->wait, &wait, TASK_UNINTERRUPTIBLE); | 253 | prepare_to_wait(&bs->wait, &wait, TASK_UNINTERRUPTIBLE); |
254 | 254 | ||
255 | tag = __bt_get(hctx, bt, last_tag); | 255 | tag = __bt_get(hctx, bt, last_tag); |
@@ -285,6 +285,8 @@ static int bt_get(struct blk_mq_alloc_data *data, | |||
285 | hctx = data->hctx; | 285 | hctx = data->hctx; |
286 | bt = &hctx->tags->bitmap_tags; | 286 | bt = &hctx->tags->bitmap_tags; |
287 | } | 287 | } |
288 | finish_wait(&bs->wait, &wait); | ||
289 | bs = bt_wait_ptr(bt, hctx); | ||
288 | } while (1); | 290 | } while (1); |
289 | 291 | ||
290 | finish_wait(&bs->wait, &wait); | 292 | finish_wait(&bs->wait, &wait); |