summaryrefslogtreecommitdiffstats
path: root/fs/ext4/page-io.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-07-20 09:29:37 -0400
committerJens Axboe <axboe@fb.com>2015-07-29 10:55:15 -0400
commit4246a0b63bd8f56a1469b12eafeb875b1041a451 (patch)
tree3281bb158d658ef7f208ad380c0ecee600a5ab5e /fs/ext4/page-io.c
parent0034af036554c39eefd14d835a8ec3496ac46712 (diff)
block: add a bi_error field to struct bio
Currently we have two different ways to signal an I/O error on a BIO: (1) by clearing the BIO_UPTODATE flag (2) by returning a Linux errno value to the bi_end_io callback The first one has the drawback of only communicating a single possible error (-EIO), and the second one has the drawback of not beeing persistent when bios are queued up, and are not passed along from child to parent bio in the ever more popular chaining scenario. Having both mechanisms available has the additional drawback of utterly confusing driver authors and introducing bugs where various I/O submitters only deal with one of them, and the others have to add boilerplate code to deal with both kinds of error returns. So add a new bi_error field to store an errno value directly in struct bio and remove the existing mechanisms to clean all this up. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: NeilBrown <neilb@suse.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'fs/ext4/page-io.c')
-rw-r--r--fs/ext4/page-io.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 5602450f03f6..aa95566f14be 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -61,7 +61,6 @@ static void buffer_io_error(struct buffer_head *bh)
61static void ext4_finish_bio(struct bio *bio) 61static void ext4_finish_bio(struct bio *bio)
62{ 62{
63 int i; 63 int i;
64 int error = !test_bit(BIO_UPTODATE, &bio->bi_flags);
65 struct bio_vec *bvec; 64 struct bio_vec *bvec;
66 65
67 bio_for_each_segment_all(bvec, bio, i) { 66 bio_for_each_segment_all(bvec, bio, i) {
@@ -88,7 +87,7 @@ static void ext4_finish_bio(struct bio *bio)
88 } 87 }
89#endif 88#endif
90 89
91 if (error) { 90 if (bio->bi_error) {
92 SetPageError(page); 91 SetPageError(page);
93 set_bit(AS_EIO, &page->mapping->flags); 92 set_bit(AS_EIO, &page->mapping->flags);
94 } 93 }
@@ -107,7 +106,7 @@ static void ext4_finish_bio(struct bio *bio)
107 continue; 106 continue;
108 } 107 }
109 clear_buffer_async_write(bh); 108 clear_buffer_async_write(bh);
110 if (error) 109 if (bio->bi_error)
111 buffer_io_error(bh); 110 buffer_io_error(bh);
112 } while ((bh = bh->b_this_page) != head); 111 } while ((bh = bh->b_this_page) != head);
113 bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); 112 bit_spin_unlock(BH_Uptodate_Lock, &head->b_state);
@@ -310,27 +309,25 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end)
310} 309}
311 310
312/* BIO completion function for page writeback */ 311/* BIO completion function for page writeback */
313static void ext4_end_bio(struct bio *bio, int error) 312static void ext4_end_bio(struct bio *bio)
314{ 313{
315 ext4_io_end_t *io_end = bio->bi_private; 314 ext4_io_end_t *io_end = bio->bi_private;
316 sector_t bi_sector = bio->bi_iter.bi_sector; 315 sector_t bi_sector = bio->bi_iter.bi_sector;
317 316
318 BUG_ON(!io_end); 317 BUG_ON(!io_end);
319 bio->bi_end_io = NULL; 318 bio->bi_end_io = NULL;
320 if (test_bit(BIO_UPTODATE, &bio->bi_flags))
321 error = 0;
322 319
323 if (error) { 320 if (bio->bi_error) {
324 struct inode *inode = io_end->inode; 321 struct inode *inode = io_end->inode;
325 322
326 ext4_warning(inode->i_sb, "I/O error %d writing to inode %lu " 323 ext4_warning(inode->i_sb, "I/O error %d writing to inode %lu "
327 "(offset %llu size %ld starting block %llu)", 324 "(offset %llu size %ld starting block %llu)",
328 error, inode->i_ino, 325 bio->bi_error, inode->i_ino,
329 (unsigned long long) io_end->offset, 326 (unsigned long long) io_end->offset,
330 (long) io_end->size, 327 (long) io_end->size,
331 (unsigned long long) 328 (unsigned long long)
332 bi_sector >> (inode->i_blkbits - 9)); 329 bi_sector >> (inode->i_blkbits - 9));
333 mapping_set_error(inode->i_mapping, error); 330 mapping_set_error(inode->i_mapping, bio->bi_error);
334 } 331 }
335 332
336 if (io_end->flag & EXT4_IO_END_UNWRITTEN) { 333 if (io_end->flag & EXT4_IO_END_UNWRITTEN) {