aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorKent Overstreet <koverstreet@google.com>2012-09-20 19:38:30 -0400
committerKent Overstreet <koverstreet@google.com>2013-03-23 17:15:28 -0400
commitf79ea4161434b31e351658283b24e92c3e570142 (patch)
tree56feab4c7407beaebd191a5551f491197f6fce10 /block
parent054bdf646e36c2f7dc1bf6bc6209dbbb5909164b (diff)
block: Refactor blk_update_request()
Converts it to use bio_advance(), simplifying it quite a bit in the process. Note that req_bio_endio() now always calls bio_advance() - which means it always loops over the biovec, not just on partial completions. Don't expect it to affect performance, but worth noting. Tested it by forcing partial updates, and dumping before and after on various bio/bvec fields when doing a partial update. Signed-off-by: Kent Overstreet <koverstreet@google.com> CC: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/blk-core.c80
1 files changed, 12 insertions, 68 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 074b758efc42..86a1afeef606 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -158,20 +158,10 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
158 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) 158 else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
159 error = -EIO; 159 error = -EIO;
160 160
161 if (unlikely(nbytes > bio->bi_size)) {
162 printk(KERN_ERR "%s: want %u bytes done, %u left\n",
163 __func__, nbytes, bio->bi_size);
164 nbytes = bio->bi_size;
165 }
166
167 if (unlikely(rq->cmd_flags & REQ_QUIET)) 161 if (unlikely(rq->cmd_flags & REQ_QUIET))
168 set_bit(BIO_QUIET, &bio->bi_flags); 162 set_bit(BIO_QUIET, &bio->bi_flags);
169 163
170 bio->bi_size -= nbytes; 164 bio_advance(bio, nbytes);
171 bio->bi_sector += (nbytes >> 9);
172
173 if (bio_integrity(bio))
174 bio_integrity_advance(bio, nbytes);
175 165
176 /* don't actually finish bio if it's part of flush sequence */ 166 /* don't actually finish bio if it's part of flush sequence */
177 if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ)) 167 if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
@@ -2252,8 +2242,7 @@ EXPORT_SYMBOL(blk_fetch_request);
2252 **/ 2242 **/
2253bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) 2243bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
2254{ 2244{
2255 int total_bytes, bio_nbytes, next_idx = 0; 2245 int total_bytes;
2256 struct bio *bio;
2257 2246
2258 if (!req->bio) 2247 if (!req->bio)
2259 return false; 2248 return false;
@@ -2299,56 +2288,21 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
2299 2288
2300 blk_account_io_completion(req, nr_bytes); 2289 blk_account_io_completion(req, nr_bytes);
2301 2290
2302 total_bytes = bio_nbytes = 0; 2291 total_bytes = 0;
2303 while ((bio = req->bio) != NULL) { 2292 while (req->bio) {
2304 int nbytes; 2293 struct bio *bio = req->bio;
2294 unsigned bio_bytes = min(bio->bi_size, nr_bytes);
2305 2295
2306 if (nr_bytes >= bio->bi_size) { 2296 if (bio_bytes == bio->bi_size)
2307 req->bio = bio->bi_next; 2297 req->bio = bio->bi_next;
2308 nbytes = bio->bi_size;
2309 req_bio_endio(req, bio, nbytes, error);
2310 next_idx = 0;
2311 bio_nbytes = 0;
2312 } else {
2313 int idx = bio->bi_idx + next_idx;
2314
2315 if (unlikely(idx >= bio->bi_vcnt)) {
2316 blk_dump_rq_flags(req, "__end_that");
2317 printk(KERN_ERR "%s: bio idx %d >= vcnt %d\n",
2318 __func__, idx, bio->bi_vcnt);
2319 break;
2320 }
2321
2322 nbytes = bio_iovec_idx(bio, idx)->bv_len;
2323 BIO_BUG_ON(nbytes > bio->bi_size);
2324
2325 /*
2326 * not a complete bvec done
2327 */
2328 if (unlikely(nbytes > nr_bytes)) {
2329 bio_nbytes += nr_bytes;
2330 total_bytes += nr_bytes;
2331 break;
2332 }
2333 2298
2334 /* 2299 req_bio_endio(req, bio, bio_bytes, error);
2335 * advance to the next vector
2336 */
2337 next_idx++;
2338 bio_nbytes += nbytes;
2339 }
2340 2300
2341 total_bytes += nbytes; 2301 total_bytes += bio_bytes;
2342 nr_bytes -= nbytes; 2302 nr_bytes -= bio_bytes;
2343 2303
2344 bio = req->bio; 2304 if (!nr_bytes)
2345 if (bio) { 2305 break;
2346 /*
2347 * end more in this run, or just return 'not-done'
2348 */
2349 if (unlikely(nr_bytes <= 0))
2350 break;
2351 }
2352 } 2306 }
2353 2307
2354 /* 2308 /*
@@ -2364,16 +2318,6 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
2364 return false; 2318 return false;
2365 } 2319 }
2366 2320
2367 /*
2368 * if the request wasn't completed, update state
2369 */
2370 if (bio_nbytes) {
2371 req_bio_endio(req, bio, bio_nbytes, error);
2372 bio->bi_idx += next_idx;
2373 bio_iovec(bio)->bv_offset += nr_bytes;
2374 bio_iovec(bio)->bv_len -= nr_bytes;
2375 }
2376
2377 req->__data_len -= total_bytes; 2321 req->__data_len -= total_bytes;
2378 req->buffer = bio_data(req->bio); 2322 req->buffer = bio_data(req->bio);
2379 2323