Message ID | 4491c4be638869303873eded8424e524abb39c27.1536779796.git.joseph.salisbury@canonical.com |
---|---|
State | New |
Headers | show |
Series | block: Fix a race between blk_cleanup_queue() and timeout handling | expand |
On 20.09.2018 12:01, Joseph Salisbury wrote: > From: Bart Van Assche <bart.vanassche@wdc.com> > > BugLink: https://bugs.launchpad.net/bugs/1791790 > > Make sure that if the timeout timer fires after a queue has been > marked "dying" that the affected requests are finished. > > Reported-by: chenxiang (M) <chenxiang66@hisilicon.com> > Fixes: commit 287922eb0b18 ("block: defer timeouts to a workqueue") > Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> > Tested-by: chenxiang (M) <chenxiang66@hisilicon.com> > Cc: Christoph Hellwig <hch@lst.de> > Cc: Keith Busch <keith.busch@intel.com> > Cc: Hannes Reinecke <hare@suse.com> > Cc: Ming Lei <ming.lei@redhat.com> > Cc: Johannes Thumshirn <jthumshirn@suse.de> > Cc: <stable@vger.kernel.org> > Signed-off-by: Jens Axboe <axboe@kernel.dk> > (cherry picked from commit 4e9b6f20828ac880dbc1fa2fdbafae779473d1af) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- > block/blk-core.c | 2 ++ > block/blk-timeout.c | 3 --- > 2 files changed, 2 insertions(+), 3 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index be184a8..13c1e5c 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -266,6 +266,7 @@ EXPORT_SYMBOL(blk_stop_queue); > void blk_sync_queue(struct request_queue *q) > { > del_timer_sync(&q->timeout); > + cancel_work_sync(&q->timeout_work); > > if (q->mq_ops) { > struct blk_mq_hw_ctx *hctx; > @@ -701,6 +702,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) > setup_timer(&q->backing_dev_info->laptop_mode_wb_timer, > laptop_mode_timer_fn, (unsigned long) q); > setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); > + INIT_WORK(&q->timeout_work, NULL); > INIT_LIST_HEAD(&q->queue_head); > INIT_LIST_HEAD(&q->timeout_list); > INIT_LIST_HEAD(&q->icq_list); > diff --git a/block/blk-timeout.c b/block/blk-timeout.c > index 7c176f6..aedd128 100644 > --- a/block/blk-timeout.c > +++ b/block/blk-timeout.c > @@ -135,8 +135,6 @@ void blk_timeout_work(struct work_struct *work) > struct request *rq, *tmp; > int next_set = 0; > > - if (blk_queue_enter(q, true)) > - return; > spin_lock_irqsave(q->queue_lock, flags); > > list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) > @@ -146,7 +144,6 @@ void blk_timeout_work(struct work_struct *work) > mod_timer(&q->timeout, round_jiffies_up(next)); > > spin_unlock_irqrestore(q->queue_lock, flags); > - blk_queue_exit(q); > } > > /** >
On 09/20/18 12:01, Joseph Salisbury wrote: > From: Bart Van Assche <bart.vanassche@wdc.com> > > BugLink: https://bugs.launchpad.net/bugs/1791790 > > Make sure that if the timeout timer fires after a queue has been > marked "dying" that the affected requests are finished. > > Reported-by: chenxiang (M) <chenxiang66@hisilicon.com> > Fixes: commit 287922eb0b18 ("block: defer timeouts to a workqueue") > Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> > Tested-by: chenxiang (M) <chenxiang66@hisilicon.com> > Cc: Christoph Hellwig <hch@lst.de> > Cc: Keith Busch <keith.busch@intel.com> > Cc: Hannes Reinecke <hare@suse.com> > Cc: Ming Lei <ming.lei@redhat.com> > Cc: Johannes Thumshirn <jthumshirn@suse.de> > Cc: <stable@vger.kernel.org> > Signed-off-by: Jens Axboe <axboe@kernel.dk> > (cherry picked from commit 4e9b6f20828ac880dbc1fa2fdbafae779473d1af) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > block/blk-core.c | 2 ++ > block/blk-timeout.c | 3 --- > 2 files changed, 2 insertions(+), 3 deletions(-) > > diff --git a/block/blk-core.c b/block/blk-core.c > index be184a8..13c1e5c 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -266,6 +266,7 @@ EXPORT_SYMBOL(blk_stop_queue); > void blk_sync_queue(struct request_queue *q) > { > del_timer_sync(&q->timeout); > + cancel_work_sync(&q->timeout_work); > > if (q->mq_ops) { > struct blk_mq_hw_ctx *hctx; > @@ -701,6 +702,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) > setup_timer(&q->backing_dev_info->laptop_mode_wb_timer, > laptop_mode_timer_fn, (unsigned long) q); > setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); > + INIT_WORK(&q->timeout_work, NULL); > INIT_LIST_HEAD(&q->queue_head); > INIT_LIST_HEAD(&q->timeout_list); > INIT_LIST_HEAD(&q->icq_list); > diff --git a/block/blk-timeout.c b/block/blk-timeout.c > index 7c176f6..aedd128 100644 > --- a/block/blk-timeout.c > +++ b/block/blk-timeout.c > @@ -135,8 +135,6 @@ void blk_timeout_work(struct work_struct *work) > struct request *rq, *tmp; > int next_set = 0; > > - if (blk_queue_enter(q, true)) > - return; > spin_lock_irqsave(q->queue_lock, flags); > > list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) > @@ -146,7 +144,6 @@ void blk_timeout_work(struct work_struct *work) > mod_timer(&q->timeout, round_jiffies_up(next)); > > spin_unlock_irqrestore(q->queue_lock, flags); > - blk_queue_exit(q); > } > > /** >
diff --git a/block/blk-core.c b/block/blk-core.c index be184a8..13c1e5c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -266,6 +266,7 @@ EXPORT_SYMBOL(blk_stop_queue); void blk_sync_queue(struct request_queue *q) { del_timer_sync(&q->timeout); + cancel_work_sync(&q->timeout_work); if (q->mq_ops) { struct blk_mq_hw_ctx *hctx; @@ -701,6 +702,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) setup_timer(&q->backing_dev_info->laptop_mode_wb_timer, laptop_mode_timer_fn, (unsigned long) q); setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); + INIT_WORK(&q->timeout_work, NULL); INIT_LIST_HEAD(&q->queue_head); INIT_LIST_HEAD(&q->timeout_list); INIT_LIST_HEAD(&q->icq_list); diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 7c176f6..aedd128 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -135,8 +135,6 @@ void blk_timeout_work(struct work_struct *work) struct request *rq, *tmp; int next_set = 0; - if (blk_queue_enter(q, true)) - return; spin_lock_irqsave(q->queue_lock, flags); list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) @@ -146,7 +144,6 @@ void blk_timeout_work(struct work_struct *work) mod_timer(&q->timeout, round_jiffies_up(next)); spin_unlock_irqrestore(q->queue_lock, flags); - blk_queue_exit(q); } /**