All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch] barrier support for blk{front,back}
@ 2006-09-08 17:34 Gerd Hoffmann
  2006-09-09 19:59 ` Ian Pratt
  0 siblings, 1 reply; 3+ messages in thread
From: Gerd Hoffmann @ 2006-09-08 17:34 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 1124 bytes --]

  Hi,

This patch adds support for barriers to blk{back,front} drivers.

protocol changes:
 * There is a new operation (BLKIF_OP_WRITE_BARRIER)
   to pass on barrier requests.
 * There is a new state (BLKIF_RSP_EOPNOTSUPP) to indicate
   unsupported operations (barrier writes may fail depending
   on the underlying block device).
 * A new xenstore node named "feature-barrier" indicates the
   backend is able to handle barrier writes.  The value can
   be 1 (all is fine) or 0 (underlying block device doesn't
   support barriers).

blkback changes:  Add "feature-barrier" node to indicate barrier
support, pass incoming barrier requests to the block layer using
submit_bio(WRITE_BARRIER, bio).  Some error handling fixes to
properly pass through barrier write failures, so the frontend
can turn off barriers then.

blkfront changes:  Check if the backend sets "feature-barrier", if
present switch to QUEUE_ORDERED_DRAIN mode.  Send off barrier
requests to the backend using the new BLKIF_OP_WRITE_BARRIER
operation.  Also some error handling for the EOPNOTSUPP case.

cheers,

  Gerd

-- 
Gerd Hoffmann <kraxel@suse.de>

[-- Attachment #2: block-barriers.diff --]
[-- Type: text/x-patch, Size: 13980 bytes --]

Add support for barriers to blk{back,front} drivers.

protocol changes:
 * There is a new operation (BLKIF_OP_WRITE_BARRIER)
   to pass on barrier requests.
 * There is a new state (BLKIF_RSP_EOPNOTSUPP) to indicate
   unsupported operations (barrier writes may fail depending
   on the underlying block device).
 * A new xenstore node named "feature-barrier" indicates the
   backend is able to handle barrier writes.  The value can
   be 1 (all is fine) or 0 (underlying block device doesn't
   support barriers).

blkback changes:  Add "feature-barrier" node to indicate barrier
support, pass incoming barrier requests to the block layer using
submit_bio(WRITE_BARRIER, bio).  Some error handling fixes to
properly pass through barrier write failures, so the frontend
can turn off barriers then.

blkfront changes:  Check if the backend sets "feature-barrier", if
present switch to QUEUE_ORDERED_DRAIN mode.  Send off barrier
requests to the backend using the new BLKIF_OP_WRITE_BARRIER
operation.  Also some error handling for the EOPNOTSUPP case.

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
---
 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c   |   41 ++++++++++++++-----
 linux-2.6-xen-sparse/drivers/xen/blkback/common.h    |    3 +
 linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c       |    2 
 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c    |   31 ++++++++++++++
 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c |   30 +++++++++++--
 linux-2.6-xen-sparse/drivers/xen/blkfront/block.h    |    2 
 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c      |   20 ++++++++-
 xen/include/public/io/blkif.h                        |   10 ++--
 8 files changed, 117 insertions(+), 22 deletions(-)

Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
@@ -191,9 +191,9 @@ static void fast_flush_area(pending_req_
 
 static void print_stats(blkif_t *blkif)
 {
-	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d\n",
+	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d  |  br %4d\n",
 	       current->comm, blkif->st_oo_req,
-	       blkif->st_rd_req, blkif->st_wr_req);
+	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req);
 	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
 	blkif->st_rd_req = 0;
 	blkif->st_wr_req = 0;
@@ -243,12 +243,17 @@ int blkif_schedule(void *arg)
  * COMPLETION CALLBACK -- Called as bh->b_end_io()
  */
 
-static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
+static void __end_block_io_op(pending_req_t *pending_req, int error)
 {
 	/* An error fails the entire request. */
-	if (!uptodate) {
-		DPRINTK("Buffer not up-to-date at end of operation\n");
+	if (error) {
+		DPRINTK("Buffer not up-to-date at end of operation, error=%d\n", error);
 		pending_req->status = BLKIF_RSP_ERROR;
+		if (pending_req->operation == BLKIF_OP_WRITE_BARRIER  &&  error == -EOPNOTSUPP) {
+			pending_req->status = BLKIF_RSP_EOPNOTSUPP;
+			blkback_barrier(pending_req->blkif->be, 0);
+			printk("blkback: write barrier op failed, not supported\n");
+		}
 	}
 
 	if (atomic_dec_and_test(&pending_req->pendcnt)) {
@@ -264,7 +269,7 @@ static int end_block_io_op(struct bio *b
 {
 	if (bio->bi_size != 0)
 		return 1;
-	__end_block_io_op(bio->bi_private, !error);
+	__end_block_io_op(bio->bi_private, error);
 	bio_put(bio);
 	return error;
 }
@@ -321,6 +326,9 @@ static int do_block_io_op(blkif_t *blkif
 			blkif->st_rd_req++;
 			dispatch_rw_block_io(blkif, req, pending_req);
 			break;
+		case BLKIF_OP_WRITE_BARRIER:
+			blkif->st_br_req++;
+			/* fall through */
 		case BLKIF_OP_WRITE:
 			blkif->st_wr_req++;
 			dispatch_rw_block_io(blkif, req, pending_req);
@@ -342,7 +350,6 @@ static void dispatch_rw_block_io(blkif_t
 				 pending_req_t *pending_req)
 {
 	extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
-	int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
 	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 	struct phys_req preq;
 	struct { 
@@ -351,6 +358,22 @@ static void dispatch_rw_block_io(blkif_t
 	unsigned int nseg;
 	struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 	int ret, i, nbio = 0;
+	int operation;
+
+	switch (req->operation) {
+	case BLKIF_OP_READ:
+		operation = READ;
+		break;
+	case BLKIF_OP_WRITE:
+		operation = WRITE;
+		break;
+	case BLKIF_OP_WRITE_BARRIER:
+		operation = WRITE_BARRIER;
+		break;
+	default:
+		operation = 0; /* make gcc happy */
+		BUG();
+	}
 
 	/* Check that number of segments is sane. */
 	nseg = req->nr_segments;
@@ -366,7 +389,7 @@ static void dispatch_rw_block_io(blkif_t
 
 	pending_req->blkif     = blkif;
 	pending_req->id        = req->id;
-	pending_req->operation = operation;
+	pending_req->operation = req->operation;
 	pending_req->status    = BLKIF_RSP_OKAY;
 	pending_req->nr_pages  = nseg;
 
@@ -382,7 +405,7 @@ static void dispatch_rw_block_io(blkif_t
 		preq.nr_sects += seg[i].nsec;
 
 		flags = GNTMAP_host_map;
-		if ( operation == WRITE )
+		if ( operation != READ )
 			flags |= GNTMAP_readonly;
 		gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
 				  req->seg[i].gref, blkif->domid);
Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/common.h
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkback/common.h
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/common.h
@@ -87,6 +87,7 @@ typedef struct blkif_st {
 	int                 st_rd_req;
 	int                 st_wr_req;
 	int                 st_oo_req;
+	int                 st_br_req;
 
 	wait_queue_head_t waiting_to_free;
 
@@ -131,4 +132,6 @@ void blkif_xenbus_init(void);
 irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
 int blkif_schedule(void *arg);
 
+int blkback_barrier(struct backend_info *be, int state);
+
 #endif /* __BLKIF__BACKEND__COMMON_H__ */
Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
@@ -91,11 +91,13 @@ static void update_blkif_status(blkif_t 
 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);
 
 static struct attribute *vbdstat_attrs[] = {
 	&dev_attr_oo_req.attr,
 	&dev_attr_rd_req.attr,
 	&dev_attr_wr_req.attr,
+	&dev_attr_br_req.attr,
 	NULL
 };
 
@@ -165,6 +167,31 @@ static int blkback_remove(struct xenbus_
 	return 0;
 }
 
+int blkback_barrier(struct backend_info *be, int state)
+{
+	struct xenbus_device *dev = be->dev;
+	struct xenbus_transaction xbt;
+	int err;
+
+	do {
+		err = xenbus_transaction_start(&xbt);
+		if (err) {
+			xenbus_dev_fatal(dev, err, "starting transaction");
+			return -1;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
+				    "%d", state);
+		if (err) {
+			xenbus_transaction_end(xbt, 1);
+			xenbus_dev_fatal(dev, err, "writing feature-barrier");
+			return -1;
+		}
+
+		err = xenbus_transaction_end(xbt, 0);
+	} while (err == -EAGAIN);
+	return 0;
+}
 
 /**
  * Entry point to this code when a new device is created.  Allocate the basic
@@ -201,6 +228,10 @@ static int blkback_probe(struct xenbus_d
 	if (err)
 		goto fail;
 
+	err = blkback_barrier(be, 1);
+	if (err)
+		goto fail;
+
 	err = xenbus_switch_state(dev, XenbusStateInitWait);
 	if (err)
 		goto fail;
Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
@@ -316,6 +316,12 @@ static void connect(struct blkfront_info
 		return;
 	}
 
+	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			    "feature-barrier", "%lu", &info->feature_barrier,
+			    NULL);
+	if (err)
+		info->feature_barrier = 0;
+
 	err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
 	if (err) {
 		xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
@@ -542,11 +548,14 @@ static int blkif_queue_request(struct re
 	info->shadow[id].request = (unsigned long)req;
 
 	ring_req->id = id;
-	ring_req->operation = rq_data_dir(req) ?
-		BLKIF_OP_WRITE : BLKIF_OP_READ;
 	ring_req->sector_number = (blkif_sector_t)req->sector;
 	ring_req->handle = info->handle;
 
+	ring_req->operation = rq_data_dir(req) ?
+		BLKIF_OP_WRITE : BLKIF_OP_READ;
+	if (blk_barrier_rq(req))
+		ring_req->operation = BLKIF_OP_WRITE_BARRIER;
+
 	ring_req->nr_segments = 0;
 	rq_for_each_bio (bio, req) {
 		bio_for_each_segment (bvec, bio, idx) {
@@ -643,6 +652,7 @@ static irqreturn_t blkif_int(int irq, vo
 	RING_IDX i, rp;
 	unsigned long flags;
 	struct blkfront_info *info = (struct blkfront_info *)dev_id;
+	int uptodate;
 
 	spin_lock_irqsave(&blkif_io_lock, flags);
 
@@ -667,19 +677,27 @@ static irqreturn_t blkif_int(int irq, vo
 
 		ADD_ID_TO_FREELIST(info, id);
 
+		uptodate = (bret->status == BLKIF_RSP_OKAY);
 		switch (bret->operation) {
+		case BLKIF_OP_WRITE_BARRIER:
+			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+				printk("blkfront: %s: write barrier op failed\n",
+				       info->gd->disk_name);
+				uptodate = -EOPNOTSUPP;
+				info->feature_barrier = 0;
+			        xlvbd_barrier(info);
+			}
+			/* fall through */
 		case BLKIF_OP_READ:
 		case BLKIF_OP_WRITE:
 			if (unlikely(bret->status != BLKIF_RSP_OKAY))
 				DPRINTK("Bad return from blkdev data "
 					"request: %x\n", bret->status);
 
-			ret = end_that_request_first(
-				req, (bret->status == BLKIF_RSP_OKAY),
+			ret = end_that_request_first(req, uptodate,
 				req->hard_nr_sectors);
 			BUG_ON(ret);
-			end_that_request_last(
-				req, (bret->status == BLKIF_RSP_OKAY));
+			end_that_request_last(req, uptodate);
 			break;
 		default:
 			BUG();
Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
@@ -126,6 +126,7 @@ struct blkfront_info
 	struct gnttab_free_callback callback;
 	struct blk_shadow shadow[BLK_RING_SIZE];
 	unsigned long shadow_free;
+	int feature_barrier;
 
 	/**
 	 * The number of people holding this device open.  We won't allow a
@@ -152,5 +153,6 @@ extern void do_blkif_request (request_qu
 int xlvbd_add(blkif_sector_t capacity, int device,
 	      u16 vdisk_info, u16 sector_size, struct blkfront_info *info);
 void xlvbd_del(struct blkfront_info *info);
+int xlvbd_barrier(struct blkfront_info *info);
 
 #endif /* __XEN_DRIVERS_BLOCK_H__ */
Index: build-32-unstable-11407/xen/include/public/io/blkif.h
===================================================================
--- build-32-unstable-11407.orig/xen/include/public/io/blkif.h
+++ build-32-unstable-11407/xen/include/public/io/blkif.h
@@ -29,8 +29,9 @@
 #endif
 #define blkif_sector_t uint64_t
 
-#define BLKIF_OP_READ      0
-#define BLKIF_OP_WRITE     1
+#define BLKIF_OP_READ              0
+#define BLKIF_OP_WRITE             1
+#define BLKIF_OP_WRITE_BARRIER     2
 
 /*
  * Maximum scatter/gather segments per request.
@@ -61,8 +62,9 @@ struct blkif_response {
 };
 typedef struct blkif_response blkif_response_t;
 
-#define BLKIF_RSP_ERROR  -1 /* non-specific 'error' */
-#define BLKIF_RSP_OKAY    0 /* non-specific 'okay'  */
+#define BLKIF_RSP_EOPNOTSUPP  -2 /* operation not supported (can happen on barrier writes) */
+#define BLKIF_RSP_ERROR       -1 /* non-specific 'error' */
+#define BLKIF_RSP_OKAY         0 /* non-specific 'okay'  */
 
 /*
  * Generate blkif ring structures and types.
Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
@@ -257,6 +257,10 @@ xlvbd_alloc_gendisk(int minor, blkif_sec
 	}
 
 	info->rq = gd->queue;
+	info->gd = gd;
+
+	if (info->feature_barrier)
+		xlvbd_barrier(info);
 
 	if (vdisk_info & VDISK_READONLY)
 		set_disk_ro(gd, 1);
@@ -267,8 +271,6 @@ xlvbd_alloc_gendisk(int minor, blkif_sec
 	if (vdisk_info & VDISK_CDROM)
 		gd->flags |= GENHD_FL_CD;
 
-	info->gd = gd;
-
 	return 0;
 
  out:
@@ -316,3 +318,17 @@ xlvbd_del(struct blkfront_info *info)
 	blk_cleanup_queue(info->rq);
 	info->rq = NULL;
 }
+
+int
+xlvbd_barrier(struct blkfront_info *info)
+{
+	int err;
+
+	err = blk_queue_ordered(info->rq,
+		info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, NULL);
+	if (err)
+		return err;
+	printk("blkfront: %s: barriers %s\n",
+	       info->gd->disk_name, info->feature_barrier ? "enabled" : "disabled");
+	return 0;
+}
Index: build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c
===================================================================
--- build-32-unstable-11407.orig/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c
+++ build-32-unstable-11407/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c
@@ -104,7 +104,7 @@ int vbd_translate(struct phys_req *req, 
 	struct vbd *vbd = &blkif->vbd;
 	int rc = -EACCES;
 
-	if ((operation == WRITE) && vbd->readonly)
+	if ((operation != READ) && vbd->readonly)
 		goto out;
 
 	if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [patch] barrier support for blk{front,back}
  2006-09-08 17:34 [patch] barrier support for blk{front,back} Gerd Hoffmann
@ 2006-09-09 19:59 ` Ian Pratt
  2006-09-11 22:22   ` Gerd Hoffmann
  0 siblings, 1 reply; 3+ messages in thread
From: Ian Pratt @ 2006-09-09 19:59 UTC (permalink / raw)
  To: Gerd Hoffmann, xen-devel

> This patch adds support for barriers to blk{back,front} drivers.

It's good to see barrier supported added. 

Out of interest, what was your motivation for adding it?  Which file
systems use it, and do you see a worthwhile performance gain from the
extra disk scheduling flexibility?

We are going to have to think through what the impact of this would be
in the live relocation block safety optimizations Andy Warfield
described at the summit. The simple thing is just to revert to stalling
until the backend gives the all clear if there's a barrier in the queue.

Thanks,
Ian

 
> protocol changes:
>  * There is a new operation (BLKIF_OP_WRITE_BARRIER)
>    to pass on barrier requests.
>  * There is a new state (BLKIF_RSP_EOPNOTSUPP) to indicate
>    unsupported operations (barrier writes may fail depending
>    on the underlying block device).
>  * A new xenstore node named "feature-barrier" indicates the
>    backend is able to handle barrier writes.  The value can
>    be 1 (all is fine) or 0 (underlying block device doesn't
>    support barriers).
> 
> blkback changes:  Add "feature-barrier" node to indicate barrier
> support, pass incoming barrier requests to the block layer using
> submit_bio(WRITE_BARRIER, bio).  Some error handling fixes to
> properly pass through barrier write failures, so the frontend
> can turn off barriers then.
> 
> blkfront changes:  Check if the backend sets "feature-barrier", if
> present switch to QUEUE_ORDERED_DRAIN mode.  Send off barrier
> requests to the backend using the new BLKIF_OP_WRITE_BARRIER
> operation.  Also some error handling for the EOPNOTSUPP case.
> 
> cheers,
> 
>   Gerd
> 
> --
> Gerd Hoffmann <kraxel@suse.de>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch] barrier support for blk{front,back}
  2006-09-09 19:59 ` Ian Pratt
@ 2006-09-11 22:22   ` Gerd Hoffmann
  0 siblings, 0 replies; 3+ messages in thread
From: Gerd Hoffmann @ 2006-09-11 22:22 UTC (permalink / raw)
  To: Ian Pratt; +Cc: xen-devel

[-- Attachment #1: Type: text/plain, Size: 2051 bytes --]

Ian Pratt wrote:
>> This patch adds support for barriers to blk{back,front} drivers.
> 
> It's good to see barrier supported added.
> 
> Out of interest, what was your motivation for adding it?

Trying to fix some problems of loop-file backed virtual block devices.
For SLES10 we have a patch which adds a syncronous mode to the loop
driver (by opening the file with O_SYNC).  It solves the problem of loop
doing too much buffering and screw up journaling filesystems, but is
dead slow.  When using barriers instead the performance should become
better without the risc to kill the filesystem by ignoring write
ordering.  There is also a patch in the queue (for mainline) which adds
barrier support to loop devices, attached below for reference.

> Which file systems use it, and do you see a worthwhile performance
> gain from the extra disk scheduling flexibility?

All journaling filesystems should be able to use them.  ext3 and
reiserfs do for sure, although they are not enabled by default, you need
the barrier=1 (ext3) and barrier=flush (reiser) mount options.  Don't
know what xfs and jfs are doing by default.

No benchmarks yet, sorry.  I finished the patch just the day before the
summit on my notebook, which is way to slow for serious performance
tests.  Beside that I simply had no time yet.  I can run some next week.

> We are going to have to think through what the impact of this would
> be in the live relocation block safety optimizations Andy Warfield 
> described at the summit. The simple thing is just to revert to
> stalling until the backend gives the all clear if there's a barrier
> in the queue.

Hmm, yes, the frontend driver better should take care that there isn't
an barrier request in flight.  Doing that should also reduce the risc to
corrupt the filesystem in the (already unlikely) case that the writes on
the host the machine is migrated from are ending up on disk after the
ones resubmitted from the host the machine is migrated to.

jetlagged greetings from europe,

  Gerd

-- 
Gerd Hoffmann <kraxel@suse.de>

[-- Attachment #2: loop-barrier --]
[-- Type: text/plain, Size: 1451 bytes --]

--- linux-2.6.16/drivers/block/loop.c~	2006-06-29 13:22:37.000000000 +0200
+++ linux-2.6.16/drivers/block/loop.c	2006-06-29 13:28:17.000000000 +0200
@@ -467,16 +467,58 @@
 	return ret;
 }
 
+/*
+ * This is best effort. We really wouldn't know what to do with a returned
+ * error. This code is taken from the implementation of fsync.
+ */
+static int sync_file(struct file * file)  
+{
+	struct address_space *mapping;
+	int ret;
+
+	if (!file->f_op || !file->f_op->fsync)
+		return -EOPNOTSUPP;
+
+	mapping = file->f_mapping;
+
+	ret = filemap_fdatawrite(mapping);
+	if (!ret) {
+		/*
+		 * We need to protect against concurrent writers,
+		 * which could cause livelocks in fsync_buffers_list
+		 */
+		mutex_lock(&mapping->host->i_mutex);
+		ret = file->f_op->fsync(file, file->f_dentry, 1);
+		mutex_unlock(&mapping->host->i_mutex);
+
+		filemap_fdatawait(mapping);
+	}
+
+	return ret;
+}
+
 static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
 {
 	loff_t pos;
 	int ret;
+	int sync = bio_sync(bio);
+	int barrier = bio_barrier(bio);
+
+	if (barrier) {
+		ret = sync_file(lo->lo_backing_file);
+		if (unlikely(ret))
+			return ret;
+	}
 
 	pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
 	if (bio_rw(bio) == WRITE)
 		ret = lo_send(lo, bio, lo->lo_blocksize, pos);
 	else
 		ret = lo_receive(lo, bio, lo->lo_blocksize, pos);
+
+	if ((barrier || sync) && !ret)
+		ret = sync_file(lo->lo_backing_file);
+
 	return ret;
 }
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-09-11 22:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-08 17:34 [patch] barrier support for blk{front,back} Gerd Hoffmann
2006-09-09 19:59 ` Ian Pratt
2006-09-11 22:22   ` Gerd Hoffmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.