diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2010-07-28 13:49:29 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-08-07 12:52:53 -0400 |
commit | 7901d14144311c930918b1222aae7611284c63eb (patch) | |
tree | 53e882fd0b0588b0c43c2935d634ea97a9e1c9ed | |
parent | 4dab46ff26c6003a13ec769312c50938b93c359d (diff) |
xen/blkfront: Use QUEUE_ORDERED_DRAIN for old backends
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>
-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) | |||
420 | static int xlvbd_barrier(struct blkfront_info *info) | 420 | static int xlvbd_barrier(struct blkfront_info *info) |
421 | { | 421 | { |
422 | int err; | 422 | int err; |
423 | unsigned ordered = QUEUE_ORDERED_NONE; | 423 | const char *barrier; |
424 | 424 | ||
425 | /* | 425 | switch (info->feature_barrier) { |
426 | * If we don't have barrier support, then there's really no | 426 | case QUEUE_ORDERED_DRAIN: barrier = "enabled (drain)"; break; |
427 | * way to guarantee write ordering, so we really just have to | 427 | case QUEUE_ORDERED_TAG: barrier = "enabled (tag)"; break; |
428 | * send writes to the backend and hope for the best. If | 428 | case QUEUE_ORDERED_NONE: barrier = "disabled"; break; |
429 | * barriers are supported then we can treat them as proper | 429 | default: return -EINVAL; |
430 | * ordering tags. | 430 | } |
431 | */ | ||
432 | if (info->feature_barrier) | ||
433 | ordered = QUEUE_ORDERED_TAG; | ||
434 | 431 | ||
435 | err = blk_queue_ordered(info->rq, ordered); | 432 | err = blk_queue_ordered(info->rq, info->feature_barrier); |
436 | 433 | ||
437 | if (err) | 434 | if (err) |
438 | return err; | 435 | return err; |
439 | 436 | ||
440 | printk(KERN_INFO "blkfront: %s: barriers %s\n", | 437 | printk(KERN_INFO "blkfront: %s: barriers %s\n", |
441 | info->gd->disk_name, | 438 | info->gd->disk_name, barrier); |
442 | info->feature_barrier ? "enabled" : "disabled"); | ||
443 | return 0; | 439 | return 0; |
444 | } | 440 | } |
445 | 441 | ||
@@ -665,7 +661,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
665 | printk(KERN_WARNING "blkfront: %s: write barrier op failed\n", | 661 | printk(KERN_WARNING "blkfront: %s: write barrier op failed\n", |
666 | info->gd->disk_name); | 662 | info->gd->disk_name); |
667 | error = -EOPNOTSUPP; | 663 | error = -EOPNOTSUPP; |
668 | info->feature_barrier = 0; | 664 | info->feature_barrier = QUEUE_ORDERED_NONE; |
669 | xlvbd_barrier(info); | 665 | xlvbd_barrier(info); |
670 | } | 666 | } |
671 | /* fall through */ | 667 | /* fall through */ |
@@ -1003,6 +999,7 @@ static void blkfront_connect(struct blkfront_info *info) | |||
1003 | unsigned long sector_size; | 999 | unsigned long sector_size; |
1004 | unsigned int binfo; | 1000 | unsigned int binfo; |
1005 | int err; | 1001 | int err; |
1002 | int barrier; | ||
1006 | 1003 | ||
1007 | switch (info->connected) { | 1004 | switch (info->connected) { |
1008 | case BLKIF_STATE_CONNECTED: | 1005 | case BLKIF_STATE_CONNECTED: |
@@ -1043,10 +1040,26 @@ static void blkfront_connect(struct blkfront_info *info) | |||
1043 | } | 1040 | } |
1044 | 1041 | ||
1045 | err = xenbus_gather(XBT_NIL, info->xbdev->otherend, | 1042 | err = xenbus_gather(XBT_NIL, info->xbdev->otherend, |
1046 | "feature-barrier", "%lu", &info->feature_barrier, | 1043 | "feature-barrier", "%lu", &barrier, |
1047 | NULL); | 1044 | NULL); |
1045 | |||
1046 | /* | ||
1047 | * If there's no "feature-barrier" defined, then it means | ||
1048 | * we're dealing with a very old backend which writes | ||
1049 | * synchronously; draining will do what needs to get done. | ||
1050 | * | ||
1051 | * If there are barriers, then we can do full queued writes | ||
1052 | * with tagged barriers. | ||
1053 | * | ||
1054 | * If barriers are not supported, then there's no much we can | ||
1055 | * do, so just set ordering to NONE. | ||
1056 | */ | ||
1048 | if (err) | 1057 | if (err) |
1049 | info->feature_barrier = 0; | 1058 | info->feature_barrier = QUEUE_ORDERED_DRAIN; |
1059 | else if (barrier) | ||
1060 | info->feature_barrier = QUEUE_ORDERED_TAG; | ||
1061 | else | ||
1062 | info->feature_barrier = QUEUE_ORDERED_NONE; | ||
1050 | 1063 | ||
1051 | err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); | 1064 | err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); |
1052 | if (err) { | 1065 | if (err) { |