aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-mq.c
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2015-04-20 22:00:19 -0400
committerJens Axboe <axboe@fb.com>2015-04-23 12:27:35 -0400
commitf054b56c951bf1731ba7314a4c7f1cc0b2977cc9 (patch)
tree90cdfbaea772655ade496e030aae8c7c0a871945 /block/blk-mq.c
parent9283b42e46c2646dff1bec47e2dd683add7f9972 (diff)
blk-mq: fix race between timeout and CPU hotplug
Firstly during CPU hotplug, even queue is freezed, timeout handler still may come and access hctx->tags, which may cause use after free, so this patch deactivates timeout handler inside CPU hotplug notifier. Secondly, tags can be shared by more than one queues, so we have to check if the hctx has been unmapped, otherwise still use-after-free on tags can be triggered. Cc: <stable@vger.kernel.org> Reported-by: Dongsu Park <dongsu.park@profitbricks.com> Tested-by: Dongsu Park <dongsu.park@profitbricks.com> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-mq.c')
-rw-r--r--block/blk-mq.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index ade8a2d1b0aa..1fccb98aa28f 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -677,8 +677,11 @@ static void blk_mq_rq_timer(unsigned long priv)
677 data.next = blk_rq_timeout(round_jiffies_up(data.next)); 677 data.next = blk_rq_timeout(round_jiffies_up(data.next));
678 mod_timer(&q->timeout, data.next); 678 mod_timer(&q->timeout, data.next);
679 } else { 679 } else {
680 queue_for_each_hw_ctx(q, hctx, i) 680 queue_for_each_hw_ctx(q, hctx, i) {
681 blk_mq_tag_idle(hctx); 681 /* the hctx may be unmapped, so check it here */
682 if (blk_mq_hw_queue_mapped(hctx))
683 blk_mq_tag_idle(hctx);
684 }
682 } 685 }
683} 686}
684 687
@@ -2090,9 +2093,16 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
2090 */ 2093 */
2091 list_for_each_entry(q, &all_q_list, all_q_node) 2094 list_for_each_entry(q, &all_q_list, all_q_node)
2092 blk_mq_freeze_queue_start(q); 2095 blk_mq_freeze_queue_start(q);
2093 list_for_each_entry(q, &all_q_list, all_q_node) 2096 list_for_each_entry(q, &all_q_list, all_q_node) {
2094 blk_mq_freeze_queue_wait(q); 2097 blk_mq_freeze_queue_wait(q);
2095 2098
2099 /*
2100 * timeout handler can't touch hw queue during the
2101 * reinitialization
2102 */
2103 del_timer_sync(&q->timeout);
2104 }
2105
2096 list_for_each_entry(q, &all_q_list, all_q_node) 2106 list_for_each_entry(q, &all_q_list, all_q_node)
2097 blk_mq_queue_reinit(q); 2107 blk_mq_queue_reinit(q);
2098 2108