aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorMing Lei <tom.leiming@gmail.com>2015-06-04 10:25:04 -0400
committerJens Axboe <axboe@fb.com>2015-06-09 17:32:38 -0400
commitc3b4afca7023b5aa0531912364246e67f79b3010 (patch)
tree2bf7586a979548fb0fc950e5b84b646f96360ea6 /block
parentd4a4f75cd8f29cd9464a5a32e9224a91571d6649 (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.c8
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 */
1603static void blk_mq_exit_hctx(struct request_queue *q, 1604static 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