aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-10-10 00:42:22 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-10-13 09:48:36 -0400
commit29bde093787f3bdf7b9b4270ada6be7c8076e36b (patch)
tree4fff697e0acb2471b1bd575cbd006fa4efc3937d /drivers/block
parent469738e675524b6aa029ecd46bdda3f878b12eff (diff)
xen/blkback: Support 'feature-barrier' aka old-style BARRIER requests.
We emulate the barrier requests by draining the outstanding bio's and then sending the WRITE_FLUSH command. To drain the I/Os we use the refcnt that is used during disconnect to wait for all the I/Os before disconnecting from the frontend. We latch on its value and if it reaches either the threshold for disconnect or when there are no more outstanding I/Os, then we have drained all I/Os. Suggested-by: Christopher Hellwig <hch@infradead.org> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/xen-blkback/blkback.c37
-rw-r--r--drivers/block/xen-blkback/common.h5
-rw-r--r--drivers/block/xen-blkback/xenbus.c18
3 files changed, 58 insertions, 2 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index e0dab614049c..184b1335c8e9 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -452,6 +452,23 @@ static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
452 make_response(blkif, req->id, req->operation, status); 452 make_response(blkif, req->id, req->operation, status);
453} 453}
454 454
455static void xen_blk_drain_io(struct xen_blkif *blkif)
456{
457 atomic_set(&blkif->drain, 1);
458 do {
459 wait_for_completion_interruptible_timeout(
460 &blkif->drain_complete, HZ);
461
462 if (!atomic_read(&blkif->drain))
463 break;
464 /* The initial value is one, and one refcnt taken at the
465 * start of the xen_blkif_schedule thread. */
466 if (atomic_read(&blkif->refcnt) <= 2)
467 break;
468 } while (!kthread_should_stop());
469 atomic_set(&blkif->drain, 0);
470}
471
455/* 472/*
456 * Completion callback on the bio's. Called as bh->b_end_io() 473 * Completion callback on the bio's. Called as bh->b_end_io()
457 */ 474 */
@@ -464,6 +481,11 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
464 pr_debug(DRV_PFX "flush diskcache op failed, not supported\n"); 481 pr_debug(DRV_PFX "flush diskcache op failed, not supported\n");
465 xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0); 482 xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0);
466 pending_req->status = BLKIF_RSP_EOPNOTSUPP; 483 pending_req->status = BLKIF_RSP_EOPNOTSUPP;
484 } else if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
485 (error == -EOPNOTSUPP)) {
486 pr_debug(DRV_PFX "write barrier op failed, not supported\n");
487 xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0);
488 pending_req->status = BLKIF_RSP_EOPNOTSUPP;
467 } else if (error) { 489 } else if (error) {
468 pr_debug(DRV_PFX "Buffer not up-to-date at end of operation," 490 pr_debug(DRV_PFX "Buffer not up-to-date at end of operation,"
469 " error=%d\n", error); 491 " error=%d\n", error);
@@ -481,6 +503,10 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
481 pending_req->operation, pending_req->status); 503 pending_req->operation, pending_req->status);
482 xen_blkif_put(pending_req->blkif); 504 xen_blkif_put(pending_req->blkif);
483 free_req(pending_req); 505 free_req(pending_req);
506 if (atomic_read(&pending_req->blkif->refcnt) <= 2) {
507 if (atomic_read(&pending_req->blkif->drain))
508 complete(&pending_req->blkif->drain_complete);
509 }
484 } 510 }
485} 511}
486 512
@@ -574,7 +600,6 @@ do_block_io_op(struct xen_blkif *blkif)
574 600
575 return more_to_do; 601 return more_to_do;
576} 602}
577
578/* 603/*
579 * Transmutation of the 'struct blkif_request' to a proper 'struct bio' 604 * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
580 * and call the 'submit_bio' to pass it to the underlying storage. 605 * and call the 'submit_bio' to pass it to the underlying storage.
@@ -591,6 +616,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
591 int i, nbio = 0; 616 int i, nbio = 0;
592 int operation; 617 int operation;
593 struct blk_plug plug; 618 struct blk_plug plug;
619 bool drain = false;
594 620
595 switch (req->operation) { 621 switch (req->operation) {
596 case BLKIF_OP_READ: 622 case BLKIF_OP_READ:
@@ -601,6 +627,8 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
601 blkif->st_wr_req++; 627 blkif->st_wr_req++;
602 operation = WRITE_ODIRECT; 628 operation = WRITE_ODIRECT;
603 break; 629 break;
630 case BLKIF_OP_WRITE_BARRIER:
631 drain = true;
604 case BLKIF_OP_FLUSH_DISKCACHE: 632 case BLKIF_OP_FLUSH_DISKCACHE:
605 blkif->st_f_req++; 633 blkif->st_f_req++;
606 operation = WRITE_FLUSH; 634 operation = WRITE_FLUSH;
@@ -609,7 +637,6 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
609 blkif->st_ds_req++; 637 blkif->st_ds_req++;
610 operation = REQ_DISCARD; 638 operation = REQ_DISCARD;
611 break; 639 break;
612 case BLKIF_OP_WRITE_BARRIER:
613 default: 640 default:
614 operation = 0; /* make gcc happy */ 641 operation = 0; /* make gcc happy */
615 goto fail_response; 642 goto fail_response;
@@ -668,6 +695,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
668 } 695 }
669 } 696 }
670 697
698 /* Wait on all outstanding I/O's and once that has been completed
699 * issue the WRITE_FLUSH.
700 */
701 if (drain)
702 xen_blk_drain_io(pending_req->blkif);
703
671 /* 704 /*
672 * If we have failed at this point, we need to undo the M2P override, 705 * If we have failed at this point, we need to undo the M2P override,
673 * set gnttab_set_unmap_op on all of the grant references and perform 706 * set gnttab_set_unmap_op on all of the grant references and perform
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 1b1bc4458685..e638457d9de4 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -181,6 +181,9 @@ struct xen_blkif {
181 atomic_t refcnt; 181 atomic_t refcnt;
182 182
183 wait_queue_head_t wq; 183 wait_queue_head_t wq;
184 /* for barrier (drain) requests */
185 struct completion drain_complete;
186 atomic_t drain;
184 /* One thread per one blkif. */ 187 /* One thread per one blkif. */
185 struct task_struct *xenblkd; 188 struct task_struct *xenblkd;
186 unsigned int waiting_reqs; 189 unsigned int waiting_reqs;
@@ -229,6 +232,8 @@ int xen_blkif_schedule(void *arg);
229int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, 232int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
230 struct backend_info *be, int state); 233 struct backend_info *be, int state);
231 234
235int xen_blkbk_barrier(struct xenbus_transaction xbt,
236 struct backend_info *be, int state);
232struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); 237struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
233 238
234static inline void blkif_get_x86_32_req(struct blkif_request *dst, 239static inline void blkif_get_x86_32_req(struct blkif_request *dst,
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 1c44b3254134..a6d43030b107 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -114,6 +114,8 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
114 spin_lock_init(&blkif->blk_ring_lock); 114 spin_lock_init(&blkif->blk_ring_lock);
115 atomic_set(&blkif->refcnt, 1); 115 atomic_set(&blkif->refcnt, 1);
116 init_waitqueue_head(&blkif->wq); 116 init_waitqueue_head(&blkif->wq);
117 init_completion(&blkif->drain_complete);
118 atomic_set(&blkif->drain, 0);
117 blkif->st_print = jiffies; 119 blkif->st_print = jiffies;
118 init_waitqueue_head(&blkif->waiting_to_free); 120 init_waitqueue_head(&blkif->waiting_to_free);
119 121
@@ -474,6 +476,19 @@ kfree:
474out: 476out:
475 return err; 477 return err;
476} 478}
479int xen_blkbk_barrier(struct xenbus_transaction xbt,
480 struct backend_info *be, int state)
481{
482 struct xenbus_device *dev = be->dev;
483 int err;
484
485 err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
486 "%d", state);
487 if (err)
488 xenbus_dev_fatal(dev, err, "writing feature-barrier");
489
490 return err;
491}
477 492
478/* 493/*
479 * Entry point to this code when a new device is created. Allocate the basic 494 * Entry point to this code when a new device is created. Allocate the basic
@@ -708,6 +723,9 @@ again:
708 723
709 err = xen_blkbk_discard(xbt, be); 724 err = xen_blkbk_discard(xbt, be);
710 725
726 /* If we can't advertise it is OK. */
727 err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
728
711 err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", 729 err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
712 (unsigned long long)vbd_sz(&be->blkif->vbd)); 730 (unsigned long long)vbd_sz(&be->blkif->vbd));
713 if (err) { 731 if (err) {