aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-core.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 /block/blk-core.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 'block/blk-core.c')
-rw-r--r--block/blk-core.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 627ed0c593fb..7ef15b947b91 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -143,9 +143,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
143 unsigned int nbytes, int error) 143 unsigned int nbytes, int error)
144{ 144{
145 if (error) 145 if (error)
146 clear_bit(BIO_UPTODATE, &bio->bi_flags); 146 bio->bi_error = error;
147 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
148 error = -EIO;
149 147
150 if (unlikely(rq->cmd_flags & REQ_QUIET)) 148 if (unlikely(rq->cmd_flags & REQ_QUIET))
151 set_bit(BIO_QUIET, &bio->bi_flags); 149 set_bit(BIO_QUIET, &bio->bi_flags);
@@ -154,7 +152,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
154 152
155 /* don't actually finish bio if it's part of flush sequence */ 153 /* don't actually finish bio if it's part of flush sequence */
156 if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) 154 if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
157 bio_endio(bio, error); 155 bio_endio(bio);
158} 156}
159 157
160void blk_dump_rq_flags(struct request *rq, char *msg) 158void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -1620,7 +1618,8 @@ static void blk_queue_bio(struct request_queue *q, struct bio *bio)
1620 blk_queue_bounce(q, &bio); 1618 blk_queue_bounce(q, &bio);
1621 1619
1622 if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) { 1620 if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
1623 bio_endio(bio, -EIO); 1621 bio->bi_error = -EIO;
1622 bio_endio(bio);
1624 return; 1623 return;
1625 } 1624 }
1626 1625
@@ -1673,7 +1672,8 @@ get_rq:
1673 */ 1672 */
1674 req = get_request(q, rw_flags, bio, GFP_NOIO); 1673 req = get_request(q, rw_flags, bio, GFP_NOIO);
1675 if (IS_ERR(req)) { 1674 if (IS_ERR(req)) {
1676 bio_endio(bio, PTR_ERR(req)); /* @q is dead */ 1675 bio->bi_error = PTR_ERR(req);
1676 bio_endio(bio);
1677 goto out_unlock; 1677 goto out_unlock;
1678 } 1678 }
1679 1679
@@ -1896,7 +1896,8 @@ generic_make_request_checks(struct bio *bio)
1896 return true; 1896 return true;
1897 1897
1898end_io: 1898end_io:
1899 bio_endio(bio, err); 1899 bio->bi_error = err;
1900 bio_endio(bio);
1900 return false; 1901 return false;
1901} 1902}
1902 1903