diff options
author | Ming Lei <tom.leiming@gmail.com> | 2015-06-04 10:25:04 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-06-09 17:32:38 -0400 |
commit | c3b4afca7023b5aa0531912364246e67f79b3010 (patch) | |
tree | 2bf7586a979548fb0fc950e5b84b646f96360ea6 /block | |
parent | d4a4f75cd8f29cd9464a5a32e9224a91571d6649 (diff) |
blk-mq: free hctx->ctxs in queue's release handler
Now blk_cleanup_queue() can be called before calling
del_gendisk()[1], inside which hctx->ctxs is touched
from blk_mq_unregister_hctx(), but the variable has
been freed by blk_cleanup_queue() at that time.
So this patch moves freeing of hctx->ctxs into queue's
release handler for fixing the oops reported by Stefan.
[1], 6cd18e711dd8075 (block: destroy bdi before blockdev is
unregistered)
Reported-by: Stefan Seyfried <stefan.seyfried@googlemail.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org (v4.0)
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-mq.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index e68b71b85a7e..594eea04266e 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -1600,6 +1600,7 @@ static int blk_mq_hctx_notify(void *data, unsigned long action, | |||
1600 | return NOTIFY_OK; | 1600 | return NOTIFY_OK; |
1601 | } | 1601 | } |
1602 | 1602 | ||
1603 | /* hctx->ctxs will be freed in queue's release handler */ | ||
1603 | static void blk_mq_exit_hctx(struct request_queue *q, | 1604 | static void blk_mq_exit_hctx(struct request_queue *q, |
1604 | struct blk_mq_tag_set *set, | 1605 | struct blk_mq_tag_set *set, |
1605 | struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx) | 1606 | struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx) |
@@ -1618,7 +1619,6 @@ static void blk_mq_exit_hctx(struct request_queue *q, | |||
1618 | 1619 | ||
1619 | blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier); | 1620 | blk_mq_unregister_cpu_notifier(&hctx->cpu_notifier); |
1620 | blk_free_flush_queue(hctx->fq); | 1621 | blk_free_flush_queue(hctx->fq); |
1621 | kfree(hctx->ctxs); | ||
1622 | blk_mq_free_bitmap(&hctx->ctx_map); | 1622 | blk_mq_free_bitmap(&hctx->ctx_map); |
1623 | } | 1623 | } |
1624 | 1624 | ||
@@ -1891,8 +1891,12 @@ void blk_mq_release(struct request_queue *q) | |||
1891 | unsigned int i; | 1891 | unsigned int i; |
1892 | 1892 | ||
1893 | /* hctx kobj stays in hctx */ | 1893 | /* hctx kobj stays in hctx */ |
1894 | queue_for_each_hw_ctx(q, hctx, i) | 1894 | queue_for_each_hw_ctx(q, hctx, i) { |
1895 | if (!hctx) | ||
1896 | continue; | ||
1897 | kfree(hctx->ctxs); | ||
1895 | kfree(hctx); | 1898 | kfree(hctx); |
1899 | } | ||
1896 | 1900 | ||
1897 | kfree(q->queue_hw_ctx); | 1901 | kfree(q->queue_hw_ctx); |
1898 | 1902 | ||