xen/blkfront: Use QUEUE_ORDERED_DRAIN for old backends
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Wed, 28 Jul 2010 17:49:29 +0000 (10:49 -0700)
committerJens Axboe <jaxboe@fusionio.com>
Sat, 7 Aug 2010 16:52:53 +0000 (18:52 +0200)
If there's no feature-barrier key in xenstore, then it means its a fairly
old backend which does uncached in-order writes, which means ORDERED_DRAIN
is appropriate.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
drivers/block/xen-blkfront.c

index 6d912ab..ae5f92b 100644 (file)
@@ -420,26 +420,22 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
 static int xlvbd_barrier(struct blkfront_info *info)
 {
        int err;
-       unsigned ordered = QUEUE_ORDERED_NONE;
+       const char *barrier;
 
-       /*
-        * If we don't have barrier support, then there's really no
-        * way to guarantee write ordering, so we really just have to
-        * send writes to the backend and hope for the best.  If
-        * barriers are supported then we can treat them as proper
-        * ordering tags.
-        */
-       if (info->feature_barrier)
-               ordered = QUEUE_ORDERED_TAG;
+       switch (info->feature_barrier) {
+       case QUEUE_ORDERED_DRAIN:       barrier = "enabled (drain)"; break;
+       case QUEUE_ORDERED_TAG:         barrier = "enabled (tag)"; break;
+       case QUEUE_ORDERED_NONE:        barrier = "disabled"; break;
+       default:                        return -EINVAL;
+       }
 
-       err = blk_queue_ordered(info->rq, ordered);
+       err = blk_queue_ordered(info->rq, info->feature_barrier);
 
        if (err)
                return err;
 
        printk(KERN_INFO "blkfront: %s: barriers %s\n",
-              info->gd->disk_name,
-              info->feature_barrier ? "enabled" : "disabled");
+              info->gd->disk_name, barrier);
        return 0;
 }
 
@@ -665,7 +661,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                                printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
                                       info->gd->disk_name);
                                error = -EOPNOTSUPP;
-                               info->feature_barrier = 0;
+                               info->feature_barrier = QUEUE_ORDERED_NONE;
                                xlvbd_barrier(info);
                        }
                        /* fall through */
@@ -1003,6 +999,7 @@ static void blkfront_connect(struct blkfront_info *info)
        unsigned long sector_size;
        unsigned int binfo;
        int err;
+       int barrier;
 
        switch (info->connected) {
        case BLKIF_STATE_CONNECTED:
@@ -1043,10 +1040,26 @@ static void blkfront_connect(struct blkfront_info *info)
        }
 
        err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-                           "feature-barrier", "%lu", &info->feature_barrier,
+                           "feature-barrier", "%lu", &barrier,
                            NULL);
+
+       /*
+        * If there's no "feature-barrier" defined, then it means
+        * we're dealing with a very old backend which writes
+        * synchronously; draining will do what needs to get done.
+        *
+        * If there are barriers, then we can do full queued writes
+        * with tagged barriers.
+        *
+        * If barriers are not supported, then there's no much we can
+        * do, so just set ordering to NONE.
+        */
        if (err)
-               info->feature_barrier = 0;
+               info->feature_barrier = QUEUE_ORDERED_DRAIN;
+       else if (barrier)
+               info->feature_barrier = QUEUE_ORDERED_TAG;
+       else
+               info->feature_barrier = QUEUE_ORDERED_NONE;
 
        err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
        if (err) {