summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-11-28 13:32:07 +0900
committerJens Axboe <jens.axboe@oracle.com>2008-12-29 08:28:45 +0100
commita185eb4bc84155fff35b602ce99602c010de9634 (patch)
treee052052cbac813166b614325b32584d8bb9beff0
parent58eea927d2de43dc6f03d1ba2c46e55854b31540 (diff)
block: fix empty barrier on write-through w/ ordered tag
Empty barrier on write-through (or no cache) w/ ordered tag has no command to execute and without any command to execute ordered tag is never issued to the device and the ordering is never achieved. Force draining for such cases. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--block/blk-barrier.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index c63044e9c4c..8eba4e43bb0 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -166,9 +166,21 @@ static inline bool start_ordered(struct request_queue *q, struct request **rqp)
* For an empty barrier, there's no actual BAR request, which
* in turn makes POSTFLUSH unnecessary. Mask them off.
*/
- if (!rq->hard_nr_sectors)
+ if (!rq->hard_nr_sectors) {
q->ordered &= ~(QUEUE_ORDERED_DO_BAR |
QUEUE_ORDERED_DO_POSTFLUSH);
+ /*
+ * Empty barrier on a write-through device w/ ordered
+ * tag has no command to issue and without any command
+ * to issue, ordering by tag can't be used. Drain
+ * instead.
+ */
+ if ((q->ordered & QUEUE_ORDERED_BY_TAG) &&
+ !(q->ordered & QUEUE_ORDERED_DO_PREFLUSH)) {
+ q->ordered &= ~QUEUE_ORDERED_BY_TAG;
+ q->ordered |= QUEUE_ORDERED_BY_DRAIN;
+ }
+ }
/* stash away the original request */
elv_dequeue_request(q, rq);