|
@@ -292,6 +292,25 @@ void blk_sync_queue(struct request_queue *q)
|
|
|
}
|
|
|
EXPORT_SYMBOL(blk_sync_queue);
|
|
|
|
|
|
+/**
|
|
|
+ * __blk_run_queue_uncond - run a queue whether or not it has been stopped
|
|
|
+ * @q: The queue to run
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Invoke request handling on a queue if there are any pending requests.
|
|
|
+ * May be used to restart request handling after a request has completed.
|
|
|
+ * This variant runs the queue whether or not the queue has been
|
|
|
+ * stopped. Must be called with the queue lock held and interrupts
|
|
|
+ * disabled. See also @blk_run_queue.
|
|
|
+ */
|
|
|
+inline void __blk_run_queue_uncond(struct request_queue *q)
|
|
|
+{
|
|
|
+ if (unlikely(blk_queue_dead(q)))
|
|
|
+ return;
|
|
|
+
|
|
|
+ q->request_fn(q);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* __blk_run_queue - run a single device queue
|
|
|
* @q: The queue to run
|
|
@@ -305,7 +324,7 @@ void __blk_run_queue(struct request_queue *q)
|
|
|
if (unlikely(blk_queue_stopped(q)))
|
|
|
return;
|
|
|
|
|
|
- q->request_fn(q);
|
|
|
+ __blk_run_queue_uncond(q);
|
|
|
}
|
|
|
EXPORT_SYMBOL(__blk_run_queue);
|
|
|
|
|
@@ -477,8 +496,8 @@ EXPORT_SYMBOL_GPL(blk_queue_bypass_end);
|
|
|
* blk_cleanup_queue - shutdown a request queue
|
|
|
* @q: request queue to shutdown
|
|
|
*
|
|
|
- * Mark @q DYING, drain all pending requests, destroy and put it. All
|
|
|
- * future requests will be failed immediately with -ENODEV.
|
|
|
+ * Mark @q DYING, drain all pending requests, mark @q DEAD, destroy and
|
|
|
+ * put it. All future requests will be failed immediately with -ENODEV.
|
|
|
*/
|
|
|
void blk_cleanup_queue(struct request_queue *q)
|
|
|
{
|
|
@@ -507,9 +526,13 @@ void blk_cleanup_queue(struct request_queue *q)
|
|
|
spin_unlock_irq(lock);
|
|
|
mutex_unlock(&q->sysfs_lock);
|
|
|
|
|
|
- /* drain all requests queued before DYING marking */
|
|
|
+ /*
|
|
|
+ * Drain all requests queued before DYING marking. Set DEAD flag to
|
|
|
+ * prevent that q->request_fn() gets invoked after draining finished.
|
|
|
+ */
|
|
|
spin_lock_irq(lock);
|
|
|
__blk_drain_queue(q, true);
|
|
|
+ queue_flag_set(QUEUE_FLAG_DEAD, q);
|
|
|
spin_unlock_irq(lock);
|
|
|
|
|
|
/* @q won't process any more request, flush async actions */
|