diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-05-04 17:07:27 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-05-05 13:43:24 -0400 |
commit | 24f567f952aa308c3352f3340b9d296fc72bd066 (patch) | |
tree | 6cbc385ed612254b9eb0a77c0934804f85697e94 | |
parent | 73d842af27b863cbc816e75003edbc287bf57130 (diff) |
xen/blkback: Add support for BLKIF_OP_FLUSH_DISKCACHE and drop BLKIF_OP_WRITE_BARRIER.
We drop the support for 'feature-barrier' and add in the support
for the 'feature-flush-cache' if the real backend storage supports
flushing.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r-- | drivers/block/xen-blkback/blkback.c | 33 | ||||
-rw-r--r-- | drivers/block/xen-blkback/common.h | 7 | ||||
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 19 |
3 files changed, 34 insertions, 25 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index eb068d0b47e..72ede0bf269 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include <asm/xen/hypercall.h> | 46 | #include <asm/xen/hypercall.h> |
47 | #include "common.h" | 47 | #include "common.h" |
48 | 48 | ||
49 | #define WRITE_BARRIER (REQ_WRITE | REQ_FLUSH | REQ_FUA) | ||
50 | |||
51 | /* | 49 | /* |
52 | * These are rather arbitrary. They are fairly large because adjacent requests | 50 | * These are rather arbitrary. They are fairly large because adjacent requests |
53 | * pulled from a communication ring are quite likely to end up being part of | 51 | * pulled from a communication ring are quite likely to end up being part of |
@@ -256,9 +254,9 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id) | |||
256 | 254 | ||
257 | static void print_stats(struct blkif_st *blkif) | 255 | static void print_stats(struct blkif_st *blkif) |
258 | { | 256 | { |
259 | printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d\n", | 257 | printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | f %4d\n", |
260 | current->comm, blkif->st_oo_req, | 258 | current->comm, blkif->st_oo_req, |
261 | blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req); | 259 | blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req); |
262 | blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); | 260 | blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); |
263 | blkif->st_rd_req = 0; | 261 | blkif->st_rd_req = 0; |
264 | blkif->st_wr_req = 0; | 262 | blkif->st_wr_req = 0; |
@@ -414,10 +412,10 @@ static int xen_blkbk_map(struct blkif_request *req, struct pending_req *pending_ | |||
414 | static void __end_block_io_op(struct pending_req *pending_req, int error) | 412 | static void __end_block_io_op(struct pending_req *pending_req, int error) |
415 | { | 413 | { |
416 | /* An error fails the entire request. */ | 414 | /* An error fails the entire request. */ |
417 | if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) && | 415 | if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) && |
418 | (error == -EOPNOTSUPP)) { | 416 | (error == -EOPNOTSUPP)) { |
419 | DPRINTK("blkback: write barrier op failed, not supported\n"); | 417 | DPRINTK("blkback: flush diskcache op failed, not supported\n"); |
420 | xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0); | 418 | xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0); |
421 | pending_req->status = BLKIF_RSP_EOPNOTSUPP; | 419 | pending_req->status = BLKIF_RSP_EOPNOTSUPP; |
422 | } else if (error) { | 420 | } else if (error) { |
423 | DPRINTK("Buffer not up-to-date at end of operation, " | 421 | DPRINTK("Buffer not up-to-date at end of operation, " |
@@ -506,13 +504,14 @@ static int do_block_io_op(struct blkif_st *blkif) | |||
506 | blkif->st_rd_req++; | 504 | blkif->st_rd_req++; |
507 | dispatch_rw_block_io(blkif, &req, pending_req); | 505 | dispatch_rw_block_io(blkif, &req, pending_req); |
508 | break; | 506 | break; |
509 | case BLKIF_OP_WRITE_BARRIER: | 507 | case BLKIF_OP_FLUSH_DISKCACHE: |
510 | blkif->st_br_req++; | 508 | blkif->st_f_req++; |
511 | /* fall through */ | 509 | /* fall through */ |
512 | case BLKIF_OP_WRITE: | 510 | case BLKIF_OP_WRITE: |
513 | blkif->st_wr_req++; | 511 | blkif->st_wr_req++; |
514 | dispatch_rw_block_io(blkif, &req, pending_req); | 512 | dispatch_rw_block_io(blkif, &req, pending_req); |
515 | break; | 513 | break; |
514 | case BLKIF_OP_WRITE_BARRIER: | ||
516 | default: | 515 | default: |
517 | /* A good sign something is wrong: sleep for a while to | 516 | /* A good sign something is wrong: sleep for a while to |
518 | * avoid excessive CPU consumption by a bad guest. */ | 517 | * avoid excessive CPU consumption by a bad guest. */ |
@@ -556,9 +555,14 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, | |||
556 | case BLKIF_OP_WRITE: | 555 | case BLKIF_OP_WRITE: |
557 | operation = WRITE_ODIRECT; | 556 | operation = WRITE_ODIRECT; |
558 | break; | 557 | break; |
559 | case BLKIF_OP_WRITE_BARRIER: | 558 | case BLKIF_OP_FLUSH_DISKCACHE: |
560 | operation = WRITE_BARRIER; | 559 | operation = WRITE_FLUSH; |
560 | /* The frontend likes to set this to -1, which vbd_translate | ||
561 | * is alergic too. */ | ||
562 | req->u.rw.sector_number = 0; | ||
561 | break; | 563 | break; |
564 | case BLKIF_OP_WRITE_BARRIER: | ||
565 | /* Should never get here. */ | ||
562 | default: | 566 | default: |
563 | operation = 0; /* make gcc happy */ | 567 | operation = 0; /* make gcc happy */ |
564 | BUG(); | 568 | BUG(); |
@@ -566,7 +570,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, | |||
566 | 570 | ||
567 | /* Check that the number of segments is sane. */ | 571 | /* Check that the number of segments is sane. */ |
568 | nseg = req->nr_segments; | 572 | nseg = req->nr_segments; |
569 | if (unlikely(nseg == 0 && operation != WRITE_BARRIER) || | 573 | if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || |
570 | unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { | 574 | unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { |
571 | DPRINTK("Bad number of segments in request (%d)\n", nseg); | 575 | DPRINTK("Bad number of segments in request (%d)\n", nseg); |
572 | /* Haven't submitted any bio's yet. */ | 576 | /* Haven't submitted any bio's yet. */ |
@@ -643,7 +647,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, | |||
643 | 647 | ||
644 | /* This will be hit if the operation was a barrier. */ | 648 | /* This will be hit if the operation was a barrier. */ |
645 | if (!bio) { | 649 | if (!bio) { |
646 | BUG_ON(operation != WRITE_BARRIER); | 650 | BUG_ON(operation != WRITE_FLUSH); |
647 | bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0); | 651 | bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0); |
648 | if (unlikely(bio == NULL)) | 652 | if (unlikely(bio == NULL)) |
649 | goto fail_put_bio; | 653 | goto fail_put_bio; |
@@ -651,7 +655,6 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, | |||
651 | bio->bi_bdev = preq.bdev; | 655 | bio->bi_bdev = preq.bdev; |
652 | bio->bi_private = pending_req; | 656 | bio->bi_private = pending_req; |
653 | bio->bi_end_io = end_block_io_op; | 657 | bio->bi_end_io = end_block_io_op; |
654 | bio->bi_sector = -1; | ||
655 | } | 658 | } |
656 | 659 | ||
657 | 660 | ||
@@ -671,7 +674,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, | |||
671 | 674 | ||
672 | if (operation == READ) | 675 | if (operation == READ) |
673 | blkif->st_rd_sect += preq.nr_sects; | 676 | blkif->st_rd_sect += preq.nr_sects; |
674 | else if (operation == WRITE || operation == WRITE_BARRIER) | 677 | else if (operation == WRITE || operation == WRITE_FLUSH) |
675 | blkif->st_wr_sect += preq.nr_sects; | 678 | blkif->st_wr_sect += preq.nr_sects; |
676 | 679 | ||
677 | return; | 680 | return; |
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 16af388268e..af93837e129 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h | |||
@@ -53,6 +53,7 @@ struct vbd { | |||
53 | u32 pdevice; /* phys device that this vbd maps to */ | 53 | u32 pdevice; /* phys device that this vbd maps to */ |
54 | struct block_device *bdev; | 54 | struct block_device *bdev; |
55 | sector_t size; /* Cached size parameter */ | 55 | sector_t size; /* Cached size parameter */ |
56 | bool flush_support; | ||
56 | }; | 57 | }; |
57 | 58 | ||
58 | struct backend_info; | 59 | struct backend_info; |
@@ -85,7 +86,7 @@ struct blkif_st { | |||
85 | int st_rd_req; | 86 | int st_rd_req; |
86 | int st_wr_req; | 87 | int st_wr_req; |
87 | int st_oo_req; | 88 | int st_oo_req; |
88 | int st_br_req; | 89 | int st_f_req; |
89 | int st_rd_sect; | 90 | int st_rd_sect; |
90 | int st_wr_sect; | 91 | int st_wr_sect; |
91 | 92 | ||
@@ -120,8 +121,8 @@ int xen_blkif_xenbus_init(void); | |||
120 | irqreturn_t xen_blkif_be_int(int irq, void *dev_id); | 121 | irqreturn_t xen_blkif_be_int(int irq, void *dev_id); |
121 | int xen_blkif_schedule(void *arg); | 122 | int xen_blkif_schedule(void *arg); |
122 | 123 | ||
123 | int xen_blkbk_barrier(struct xenbus_transaction xbt, | 124 | int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, |
124 | struct backend_info *be, int state); | 125 | struct backend_info *be, int state); |
125 | 126 | ||
126 | struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); | 127 | struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); |
127 | 128 | ||
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 64b0a1c760f..9adcf806f83 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -276,7 +276,7 @@ int __init xen_blkif_interface_init(void) | |||
276 | VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); | 276 | VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); |
277 | VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); | 277 | VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); |
278 | VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); | 278 | VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); |
279 | VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req); | 279 | VBD_SHOW(f_req, "%d\n", be->blkif->st_f_req); |
280 | VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); | 280 | VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); |
281 | VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); | 281 | VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); |
282 | 282 | ||
@@ -284,7 +284,7 @@ static struct attribute *vbdstat_attrs[] = { | |||
284 | &dev_attr_oo_req.attr, | 284 | &dev_attr_oo_req.attr, |
285 | &dev_attr_rd_req.attr, | 285 | &dev_attr_rd_req.attr, |
286 | &dev_attr_wr_req.attr, | 286 | &dev_attr_wr_req.attr, |
287 | &dev_attr_br_req.attr, | 287 | &dev_attr_f_req.attr, |
288 | &dev_attr_rd_sect.attr, | 288 | &dev_attr_rd_sect.attr, |
289 | &dev_attr_wr_sect.attr, | 289 | &dev_attr_wr_sect.attr, |
290 | NULL | 290 | NULL |
@@ -343,6 +343,7 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, | |||
343 | { | 343 | { |
344 | struct vbd *vbd; | 344 | struct vbd *vbd; |
345 | struct block_device *bdev; | 345 | struct block_device *bdev; |
346 | struct request_queue *q; | ||
346 | 347 | ||
347 | vbd = &blkif->vbd; | 348 | vbd = &blkif->vbd; |
348 | vbd->handle = handle; | 349 | vbd->handle = handle; |
@@ -375,6 +376,10 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, | |||
375 | if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) | 376 | if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) |
376 | vbd->type |= VDISK_REMOVABLE; | 377 | vbd->type |= VDISK_REMOVABLE; |
377 | 378 | ||
379 | q = bdev_get_queue(bdev); | ||
380 | if (q && q->flush_flags) | ||
381 | vbd->flush_support = true; | ||
382 | |||
378 | DPRINTK("Successful creation of handle=%04x (dom=%u)\n", | 383 | DPRINTK("Successful creation of handle=%04x (dom=%u)\n", |
379 | handle, blkif->domid); | 384 | handle, blkif->domid); |
380 | return 0; | 385 | return 0; |
@@ -406,16 +411,16 @@ static int xen_blkbk_remove(struct xenbus_device *dev) | |||
406 | return 0; | 411 | return 0; |
407 | } | 412 | } |
408 | 413 | ||
409 | int xen_blkbk_barrier(struct xenbus_transaction xbt, | 414 | int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, |
410 | struct backend_info *be, int state) | 415 | struct backend_info *be, int state) |
411 | { | 416 | { |
412 | struct xenbus_device *dev = be->dev; | 417 | struct xenbus_device *dev = be->dev; |
413 | int err; | 418 | int err; |
414 | 419 | ||
415 | err = xenbus_printf(xbt, dev->nodename, "feature-barrier", | 420 | err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache", |
416 | "%d", state); | 421 | "%d", state); |
417 | if (err) | 422 | if (err) |
418 | xenbus_dev_fatal(dev, err, "writing feature-barrier"); | 423 | xenbus_dev_fatal(dev, err, "writing feature-flush-cache"); |
419 | 424 | ||
420 | return err; | 425 | return err; |
421 | } | 426 | } |
@@ -642,7 +647,7 @@ again: | |||
642 | return; | 647 | return; |
643 | } | 648 | } |
644 | 649 | ||
645 | err = xen_blkbk_barrier(xbt, be, 1); | 650 | err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); |
646 | if (err) | 651 | if (err) |
647 | goto abort; | 652 | goto abort; |
648 | 653 | ||