diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/xen-blkfront.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 6d912ab47292..ae5f92b5752e 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -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) { |