Commit d16b94fe authored by Chris Mason's avatar Chris Mason Committed by Linus Torvalds

[PATCH] add BH_Eopnotsupp for testing async barrier failures

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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a88cff7f
...@@ -213,7 +213,7 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate) ...@@ -213,7 +213,7 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
if (uptodate) { if (uptodate) {
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
} else { } else {
if (printk_ratelimit()) { if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
buffer_io_error(bh); buffer_io_error(bh);
printk(KERN_WARNING "lost page write due to " printk(KERN_WARNING "lost page write due to "
"I/O error on %s\n", "I/O error on %s\n",
...@@ -2756,8 +2756,10 @@ static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err) ...@@ -2756,8 +2756,10 @@ static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err)
if (bio->bi_size) if (bio->bi_size)
return 1; return 1;
if (err == -EOPNOTSUPP) if (err == -EOPNOTSUPP) {
set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); 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)); bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
bio_put(bio); bio_put(bio);
...@@ -2882,6 +2884,10 @@ int sync_dirty_buffer(struct buffer_head *bh) ...@@ -2882,6 +2884,10 @@ int sync_dirty_buffer(struct buffer_head *bh)
bh->b_end_io = end_buffer_write_sync; bh->b_end_io = end_buffer_write_sync;
ret = submit_bh(WRITE, bh); ret = submit_bh(WRITE, bh);
wait_on_buffer(bh); wait_on_buffer(bh);
if (buffer_eopnotsupp(bh)) {
clear_buffer_eopnotsupp(bh);
ret = -EOPNOTSUPP;
}
if (!ret && !buffer_uptodate(bh)) if (!ret && !buffer_uptodate(bh))
ret = -EIO; ret = -EIO;
} else { } else {
......
...@@ -27,6 +27,7 @@ enum bh_state_bits { ...@@ -27,6 +27,7 @@ enum bh_state_bits {
BH_Boundary, /* Block is followed by a discontiguity */ BH_Boundary, /* Block is followed by a discontiguity */
BH_Write_EIO, /* I/O error on write */ BH_Write_EIO, /* I/O error on write */
BH_Ordered, /* ordered write */ BH_Ordered, /* ordered write */
BH_Eopnotsupp, /* operation not supported (barrier) */
BH_PrivateStart,/* not a state bit, but the first bit available BH_PrivateStart,/* not a state bit, but the first bit available
* for private allocation by other entities * for private allocation by other entities
...@@ -113,6 +114,7 @@ BUFFER_FNS(Delay, delay) ...@@ -113,6 +114,7 @@ BUFFER_FNS(Delay, delay)
BUFFER_FNS(Boundary, boundary) BUFFER_FNS(Boundary, boundary)
BUFFER_FNS(Write_EIO, write_io_error) BUFFER_FNS(Write_EIO, write_io_error)
BUFFER_FNS(Ordered, ordered) BUFFER_FNS(Ordered, ordered)
BUFFER_FNS(Eopnotsupp, eopnotsupp)
#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK) #define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)
#define touch_buffer(bh) mark_page_accessed(bh->b_page) #define touch_buffer(bh) mark_page_accessed(bh->b_page)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment