diff options
Diffstat (limited to 'block/blk-flush.c')
-rw-r--r-- | block/blk-flush.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c index 671fa9da7560..93d5fd8e51eb 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -211,9 +211,14 @@ static void flush_end_io(struct request *flush_rq, int error) queued |= blk_flush_complete_seq(rq, seq, error); } - /* after populating an empty queue, kick it to avoid stall */ + /* + * Moving a request silently to empty queue_head may stall the + * queue. Kick the queue in those cases. This function is called + * from request completion path and calling directly into + * request_fn may confuse the driver. Always use kblockd. + */ if (queued) - __blk_run_queue(q); + __blk_run_queue(q, true); } /** @@ -256,7 +261,7 @@ static bool blk_kick_flush(struct request_queue *q) q->flush_rq.end_io = flush_end_io; q->flush_pending_idx ^= 1; - elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_FRONT); + elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_REQUEUE); return true; } @@ -264,9 +269,12 @@ static void flush_data_end_io(struct request *rq, int error) { struct request_queue *q = rq->q; - /* after populating an empty queue, kick it to avoid stall */ + /* + * After populating an empty queue, kick it to avoid stall. Read + * the comment in flush_end_io(). + */ if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error)) - __blk_run_queue(q); + __blk_run_queue(q, true); } /** |