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>
#include <asm/xen/hypercall.h>
#include "common.h"
#include <asm/xen/hypercall.h>
#include "common.h"
-#define WRITE_BARRIER (REQ_WRITE | REQ_FLUSH | REQ_FUA)
-
/*
* These are rather arbitrary. They are fairly large because adjacent requests
* pulled from a communication ring are quite likely to end up being part of
/*
* These are rather arbitrary. They are fairly large because adjacent requests
* pulled from a communication ring are quite likely to end up being part of
static void print_stats(struct blkif_st *blkif)
{
static void print_stats(struct blkif_st *blkif)
{
- printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d\n",
+ printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | f %4d\n",
current->comm, blkif->st_oo_req,
current->comm, blkif->st_oo_req,
- blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req);
+ blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req);
blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
blkif->st_rd_req = 0;
blkif->st_wr_req = 0;
blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
blkif->st_rd_req = 0;
blkif->st_wr_req = 0;
static void __end_block_io_op(struct pending_req *pending_req, int error)
{
/* An error fails the entire request. */
static void __end_block_io_op(struct pending_req *pending_req, int error)
{
/* An error fails the entire request. */
- if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
+ if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) &&
(error == -EOPNOTSUPP)) {
(error == -EOPNOTSUPP)) {
- DPRINTK("blkback: write barrier op failed, not supported\n");
- xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0);
+ DPRINTK("blkback: flush diskcache op failed, not supported\n");
+ xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0);
pending_req->status = BLKIF_RSP_EOPNOTSUPP;
} else if (error) {
DPRINTK("Buffer not up-to-date at end of operation, "
pending_req->status = BLKIF_RSP_EOPNOTSUPP;
} else if (error) {
DPRINTK("Buffer not up-to-date at end of operation, "
blkif->st_rd_req++;
dispatch_rw_block_io(blkif, &req, pending_req);
break;
blkif->st_rd_req++;
dispatch_rw_block_io(blkif, &req, pending_req);
break;
- case BLKIF_OP_WRITE_BARRIER:
- blkif->st_br_req++;
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ blkif->st_f_req++;
/* fall through */
case BLKIF_OP_WRITE:
blkif->st_wr_req++;
dispatch_rw_block_io(blkif, &req, pending_req);
break;
/* fall through */
case BLKIF_OP_WRITE:
blkif->st_wr_req++;
dispatch_rw_block_io(blkif, &req, pending_req);
break;
+ case BLKIF_OP_WRITE_BARRIER:
default:
/* A good sign something is wrong: sleep for a while to
* avoid excessive CPU consumption by a bad guest. */
default:
/* A good sign something is wrong: sleep for a while to
* avoid excessive CPU consumption by a bad guest. */
case BLKIF_OP_WRITE:
operation = WRITE_ODIRECT;
break;
case BLKIF_OP_WRITE:
operation = WRITE_ODIRECT;
break;
- case BLKIF_OP_WRITE_BARRIER:
- operation = WRITE_BARRIER;
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ operation = WRITE_FLUSH;
+ /* The frontend likes to set this to -1, which vbd_translate
+ * is alergic too. */
+ req->u.rw.sector_number = 0;
+ case BLKIF_OP_WRITE_BARRIER:
+ /* Should never get here. */
default:
operation = 0; /* make gcc happy */
BUG();
default:
operation = 0; /* make gcc happy */
BUG();
/* Check that the number of segments is sane. */
nseg = req->nr_segments;
/* Check that the number of segments is sane. */
nseg = req->nr_segments;
- if (unlikely(nseg == 0 && operation != WRITE_BARRIER) ||
+ if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
DPRINTK("Bad number of segments in request (%d)\n", nseg);
/* Haven't submitted any bio's yet. */
unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
DPRINTK("Bad number of segments in request (%d)\n", nseg);
/* Haven't submitted any bio's yet. */
/* This will be hit if the operation was a barrier. */
if (!bio) {
/* This will be hit if the operation was a barrier. */
if (!bio) {
- BUG_ON(operation != WRITE_BARRIER);
+ BUG_ON(operation != WRITE_FLUSH);
bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0);
if (unlikely(bio == NULL))
goto fail_put_bio;
bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0);
if (unlikely(bio == NULL))
goto fail_put_bio;
bio->bi_bdev = preq.bdev;
bio->bi_private = pending_req;
bio->bi_end_io = end_block_io_op;
bio->bi_bdev = preq.bdev;
bio->bi_private = pending_req;
bio->bi_end_io = end_block_io_op;
if (operation == READ)
blkif->st_rd_sect += preq.nr_sects;
if (operation == READ)
blkif->st_rd_sect += preq.nr_sects;
- else if (operation == WRITE || operation == WRITE_BARRIER)
+ else if (operation == WRITE || operation == WRITE_FLUSH)
blkif->st_wr_sect += preq.nr_sects;
return;
blkif->st_wr_sect += preq.nr_sects;
return;
u32 pdevice; /* phys device that this vbd maps to */
struct block_device *bdev;
sector_t size; /* Cached size parameter */
u32 pdevice; /* phys device that this vbd maps to */
struct block_device *bdev;
sector_t size; /* Cached size parameter */
int st_rd_req;
int st_wr_req;
int st_oo_req;
int st_rd_req;
int st_wr_req;
int st_oo_req;
int st_rd_sect;
int st_wr_sect;
int st_rd_sect;
int st_wr_sect;
irqreturn_t xen_blkif_be_int(int irq, void *dev_id);
int xen_blkif_schedule(void *arg);
irqreturn_t xen_blkif_be_int(int irq, void *dev_id);
int xen_blkif_schedule(void *arg);
-int xen_blkbk_barrier(struct xenbus_transaction xbt,
- struct backend_info *be, int state);
+int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
+ struct backend_info *be, int state);
struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req);
VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req);
VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req);
VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req);
VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req);
VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req);
-VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req);
+VBD_SHOW(f_req, "%d\n", be->blkif->st_f_req);
VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
&dev_attr_oo_req.attr,
&dev_attr_rd_req.attr,
&dev_attr_wr_req.attr,
&dev_attr_oo_req.attr,
&dev_attr_rd_req.attr,
&dev_attr_wr_req.attr,
&dev_attr_rd_sect.attr,
&dev_attr_wr_sect.attr,
NULL
&dev_attr_rd_sect.attr,
&dev_attr_wr_sect.attr,
NULL
{
struct vbd *vbd;
struct block_device *bdev;
{
struct vbd *vbd;
struct block_device *bdev;
+ struct request_queue *q;
vbd = &blkif->vbd;
vbd->handle = handle;
vbd = &blkif->vbd;
vbd->handle = handle;
if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
vbd->type |= VDISK_REMOVABLE;
if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
vbd->type |= VDISK_REMOVABLE;
+ q = bdev_get_queue(bdev);
+ if (q && q->flush_flags)
+ vbd->flush_support = true;
+
DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
handle, blkif->domid);
return 0;
DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
handle, blkif->domid);
return 0;
-int xen_blkbk_barrier(struct xenbus_transaction xbt,
- struct backend_info *be, int state)
+int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
+ struct backend_info *be, int state)
{
struct xenbus_device *dev = be->dev;
int err;
{
struct xenbus_device *dev = be->dev;
int err;
- err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
+ err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache",
- xenbus_dev_fatal(dev, err, "writing feature-barrier");
+ xenbus_dev_fatal(dev, err, "writing feature-flush-cache");
- err = xen_blkbk_barrier(xbt, be, 1);
+ err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);