From: Jens Axboe Date: Fri, 20 May 2011 18:36:16 +0000 (+0200) Subject: Merge branch 'for-linus' into for-2.6.40/core X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=0eb8e885726a3a93206510092bbc7e39e272f6ef;p=linux-beck.git Merge branch 'for-linus' into for-2.6.40/core This patch merges in a fix that missed 2.6.39 final. Conflicts: block/blk.h --- 0eb8e885726a3a93206510092bbc7e39e272f6ef diff --cc block/blk.h index 1f798b5a6f19,4df474d37e6d..d6586287adc9 --- a/block/blk.h +++ b/block/blk.h @@@ -61,27 -61,9 +61,29 @@@ static inline struct request *__elv_nex rq = list_entry_rq(q->queue_head.next); return rq; } + + /* + * Flush request is running and flush request isn't queueable + * in the drive, we can hold the queue till flush request is + * finished. Even we don't do this, driver can't dispatch next + * requests and will requeue them. And this can improve + * throughput too. For example, we have request flush1, write1, + * flush 2. flush1 is dispatched, then queue is hold, write1 + * isn't inserted to queue. After flush1 is finished, flush2 + * will be dispatched. Since disk cache is already clean, + * flush2 will be finished very soon, so looks like flush2 is + * folded to flush1. + * Since the queue is hold, a flag is set to indicate the queue + * should be restarted later. Please see flush_end_io() for + * details. + */ + if (q->flush_pending_idx != q->flush_running_idx && + !queue_flush_queueable(q)) { + q->flush_queue_delayed = 1; + return NULL; + } - if (!q->elevator->ops->elevator_dispatch_fn(q, 0)) + if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags) || + !q->elevator->ops->elevator_dispatch_fn(q, 0)) return NULL; } }