block: blk-throttle should be drained regardless of q->elevator
Currently, blk_cleanup_queue() doesn't call elv_drain_elevator() if q->elevator doesn't exist; however, bio based drivers don't have elevator initialized but can still use blk-throttle. This patch moves q->elevator test inside blk_drain_queue() such that only elv_drain_elevator() is skipped if !q->elevator. -v2: loop can have registered queue which has NULL request_fn. Make sure we don't call into __blk_run_queue() in such cases. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Vivek Goyal <vgoyal@redhat.com> Fold in bug fix from Vivek. Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Родитель
ea5f4db8ec
Коммит
b855b04a0b
|
@ -365,17 +365,24 @@ void blk_drain_queue(struct request_queue *q, bool drain_all)
|
|||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
|
||||
elv_drain_elevator(q);
|
||||
/*
|
||||
* The caller might be trying to drain @q before its
|
||||
* elevator is initialized.
|
||||
*/
|
||||
if (q->elevator)
|
||||
elv_drain_elevator(q);
|
||||
|
||||
if (drain_all)
|
||||
blk_throtl_drain(q);
|
||||
|
||||
/*
|
||||
* This function might be called on a queue which failed
|
||||
* driver init after queue creation. Some drivers
|
||||
* (e.g. fd) get unhappy in such cases. Kick queue iff
|
||||
* dispatch queue has something on it.
|
||||
* driver init after queue creation or is not yet fully
|
||||
* active yet. Some drivers (e.g. fd and loop) get unhappy
|
||||
* in such cases. Kick queue iff dispatch queue has
|
||||
* something on it and @q has request_fn set.
|
||||
*/
|
||||
if (!list_empty(&q->queue_head))
|
||||
if (!list_empty(&q->queue_head) && q->request_fn)
|
||||
__blk_run_queue(q);
|
||||
|
||||
drain |= q->rq.elvpriv;
|
||||
|
@ -428,13 +435,8 @@ void blk_cleanup_queue(struct request_queue *q)
|
|||
spin_unlock_irq(lock);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
|
||||
/*
|
||||
* Drain all requests queued before DEAD marking. The caller might
|
||||
* be trying to tear down @q before its elevator is initialized, in
|
||||
* which case we don't want to call into draining.
|
||||
*/
|
||||
if (q->elevator)
|
||||
blk_drain_queue(q, true);
|
||||
/* drain all requests queued before DEAD marking */
|
||||
blk_drain_queue(q, true);
|
||||
|
||||
/* @q won't process any more request, flush async actions */
|
||||
del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
|
||||
|
@ -504,6 +506,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_LIST_HEAD(&q->queue_head);
|
||||
INIT_LIST_HEAD(&q->timeout_list);
|
||||
INIT_LIST_HEAD(&q->icq_list);
|
||||
INIT_LIST_HEAD(&q->flush_queue[0]);
|
||||
|
|
Загрузка…
Ссылка в новой задаче