block: fix empty barrier on write-through w/ ordered tag
authorTejun Heo <tj@kernel.org>
Fri, 28 Nov 2008 04:32:07 +0000 (13:32 +0900)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 29 Dec 2008 07:28:45 +0000 (08:28 +0100)
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>
block/blk-barrier.c

index c63044e9c4c0276165ada0dfacdc2c54196dd040..8eba4e43bb0c505c9c0e846ddd33caf0f15bfdd7 100644 (file)
@@ -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);