|
@@ -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]);
|