From: Chris Mason <mason@suse.com>

In order for filesystems to detect asynchronous ordered write failures for
buffers sent via submit_bh, they need a bit they can test for in the buffer
head.  This adds BH_Eopnotsupp and the related buffer operations

end_buffer_write_sync is changed to avoid a printk for BH_Eoptnotsupp
related failures, since the FS is responsible for a retry.

sync_dirty_buffer is changed to test for BH_Eopnotsupp and return
-EOPNOTSUPP to the caller

Some of this came from Jens Axboe

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/buffer.c                 |   10 ++++++++--
 25-akpm/include/linux/buffer_head.h |    2 ++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff -puN fs/buffer.c~add-bh_eopnotsupp-for-testing fs/buffer.c
--- 25/fs/buffer.c~add-bh_eopnotsupp-for-testing	2004-07-11 14:26:06.849610544 -0700
+++ 25-akpm/fs/buffer.c	2004-07-11 14:26:06.856609480 -0700
@@ -213,7 +213,7 @@ void end_buffer_write_sync(struct buffer
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (printk_ratelimit()) {
+		if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
 			buffer_io_error(bh);
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
@@ -2756,8 +2756,10 @@ static int end_bio_bh_io_sync(struct bio
 	if (bio->bi_size)
 		return 1;
 
-	if (err == -EOPNOTSUPP)
+	if (err == -EOPNOTSUPP) {
 		set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
+		set_bit(BH_Eopnotsupp, &bh->b_state);
+	}
 
 	bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
 	bio_put(bio);
@@ -2882,6 +2884,10 @@ int sync_dirty_buffer(struct buffer_head
 		bh->b_end_io = end_buffer_write_sync;
 		ret = submit_bh(WRITE, bh);
 		wait_on_buffer(bh);
+		if (buffer_eopnotsupp(bh)) {
+			clear_buffer_eopnotsupp(bh);
+			ret = -EOPNOTSUPP;
+		}
 		if (!ret && !buffer_uptodate(bh))
 			ret = -EIO;
 	} else {
diff -puN include/linux/buffer_head.h~add-bh_eopnotsupp-for-testing include/linux/buffer_head.h
--- 25/include/linux/buffer_head.h~add-bh_eopnotsupp-for-testing	2004-07-11 14:26:06.850610392 -0700
+++ 25-akpm/include/linux/buffer_head.h	2004-07-11 14:26:06.856609480 -0700
@@ -27,6 +27,7 @@ enum bh_state_bits {
 	BH_Boundary,	/* Block is followed by a discontiguity */
 	BH_Write_EIO,	/* I/O error on write */
 	BH_Ordered,	/* ordered write */
+	BH_Eopnotsupp,	/* operation not supported (barrier) */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
@@ -113,6 +114,7 @@ BUFFER_FNS(Delay, delay)
 BUFFER_FNS(Boundary, boundary)
 BUFFER_FNS(Write_EIO, write_io_error)
 BUFFER_FNS(Ordered, ordered)
+BUFFER_FNS(Eopnotsupp, eopnotsupp)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
 #define touch_buffer(bh)	mark_page_accessed(bh->b_page)
_