Commit ef869838 authored by Jens Axboe's avatar Jens Axboe

[PATCH] more bio updates

cleanup end_that_request_first() end_io handling, and fix bug where
partial completes didn't get accounted right wrt blk_recalc_rq_sectors()
parent f20bf018
...@@ -1904,18 +1904,19 @@ inline void blk_recalc_rq_sectors(struct request *rq, int nsect) ...@@ -1904,18 +1904,19 @@ inline void blk_recalc_rq_sectors(struct request *rq, int nsect)
int end_that_request_first(struct request *req, int uptodate, int nr_sectors) int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
{ {
int nsect, total_nsect; int total_nsect = 0, error = 0;
struct bio *bio; struct bio *bio;
req->errors = 0; req->errors = 0;
if (!uptodate) if (!uptodate) {
printk("end_request: I/O error, dev %s, sector %lu\n", printk("end_request: I/O error, dev %s, sector %lu\n",
kdevname(req->rq_dev), req->sector); kdevname(req->rq_dev), req->sector);
error = -EIO;
}
total_nsect = 0;
while ((bio = req->bio)) { while ((bio = req->bio)) {
nsect = bio_iovec(bio)->bv_len >> 9; const int nsect = bio_iovec(bio)->bv_len >> 9;
total_nsect += nsect; int new_bio = 0;
BIO_BUG_ON(bio_iovec(bio)->bv_len > bio->bi_size); BIO_BUG_ON(bio_iovec(bio)->bv_len > bio->bi_size);
...@@ -1927,36 +1928,52 @@ int end_that_request_first(struct request *req, int uptodate, int nr_sectors) ...@@ -1927,36 +1928,52 @@ int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
bio_iovec(bio)->bv_offset += partial; bio_iovec(bio)->bv_offset += partial;
bio_iovec(bio)->bv_len -= partial; bio_iovec(bio)->bv_len -= partial;
blk_recalc_rq_sectors(req, total_nsect); bio_endio(bio, partial, error);
blk_recalc_rq_segments(req); total_nsect += nr_sectors;
bio_endio(bio, partial, !uptodate ? -EIO : 0); break;
return 1;
} }
/* /*
* if bio->bi_end_io returns 0, this bio is done. move on * we are ending the last part of the bio, advance req pointer
*/ */
req->bio = bio->bi_next; if ((nsect << 9) >= bio->bi_size) {
if (bio_endio(bio, nsect << 9, !uptodate ? -EIO : 0)) { req->bio = bio->bi_next;
bio->bi_idx++; new_bio = 1;
req->bio = bio;
} }
bio_endio(bio, nsect << 9, error);
total_nsect += nsect;
nr_sectors -= nsect; nr_sectors -= nsect;
/*
* if we didn't advance the req->bio pointer, advance bi_idx
* to indicate we are now on the next bio_vec
*/
if (!new_bio)
bio->bi_idx++;
if ((bio = req->bio)) { if ((bio = req->bio)) {
/* /*
* end more in this run, or just return 'not-done' * end more in this run, or just return 'not-done'
*/ */
if (unlikely(nr_sectors <= 0)) { if (unlikely(nr_sectors <= 0))
blk_recalc_rq_sectors(req, total_nsect); break;
blk_recalc_rq_segments(req);
return 1;
}
} }
} }
return 0; /*
* completely done
*/
if (!req->bio)
return 0;
/*
* if the request wasn't completed, update state
*/
blk_recalc_rq_sectors(req, total_nsect);
blk_recalc_rq_segments(req);
return 1;
} }
void end_that_request_last(struct request *req) void end_that_request_last(struct request *req)
......
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