|
@@ -527,22 +527,36 @@ int blk_do_ordered(struct request_queue *q, struct request **rqp)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-static int ordered_bio_endio(struct request *rq, struct bio *bio,
|
|
|
- unsigned int nbytes, int error)
|
|
|
+static void req_bio_endio(struct request *rq, struct bio *bio,
|
|
|
+ unsigned int nbytes, int error)
|
|
|
{
|
|
|
struct request_queue *q = rq->q;
|
|
|
|
|
|
- if (&q->bar_rq != rq)
|
|
|
- return 0;
|
|
|
+ if (&q->bar_rq != rq) {
|
|
|
+ if (error)
|
|
|
+ clear_bit(BIO_UPTODATE, &bio->bi_flags);
|
|
|
+ else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
|
|
|
+ error = -EIO;
|
|
|
|
|
|
- /*
|
|
|
- * Okay, this is the barrier request in progress, just
|
|
|
- * record the error;
|
|
|
- */
|
|
|
- if (error && !q->orderr)
|
|
|
- q->orderr = error;
|
|
|
+ if (unlikely(nbytes > bio->bi_size)) {
|
|
|
+ printk("%s: want %u bytes done, only %u left\n",
|
|
|
+ __FUNCTION__, nbytes, bio->bi_size);
|
|
|
+ nbytes = bio->bi_size;
|
|
|
+ }
|
|
|
|
|
|
- return 1;
|
|
|
+ bio->bi_size -= nbytes;
|
|
|
+ bio->bi_sector += (nbytes >> 9);
|
|
|
+ if (bio->bi_size == 0)
|
|
|
+ bio_endio(bio, bio->bi_size, error);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Okay, this is the barrier request in progress, just
|
|
|
+ * record the error;
|
|
|
+ */
|
|
|
+ if (error && !q->orderr)
|
|
|
+ q->orderr = error;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -3388,8 +3402,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
|
|
|
if (nr_bytes >= bio->bi_size) {
|
|
|
req->bio = bio->bi_next;
|
|
|
nbytes = bio->bi_size;
|
|
|
- if (!ordered_bio_endio(req, bio, nbytes, error))
|
|
|
- bio_endio(bio, nbytes, error);
|
|
|
+ req_bio_endio(req, bio, nbytes, error);
|
|
|
next_idx = 0;
|
|
|
bio_nbytes = 0;
|
|
|
} else {
|
|
@@ -3444,8 +3457,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
|
|
|
* if the request wasn't completed, update state
|
|
|
*/
|
|
|
if (bio_nbytes) {
|
|
|
- if (!ordered_bio_endio(req, bio, bio_nbytes, error))
|
|
|
- bio_endio(bio, bio_nbytes, error);
|
|
|
+ req_bio_endio(req, bio, bio_nbytes, error);
|
|
|
bio->bi_idx += next_idx;
|
|
|
bio_iovec(bio)->bv_offset += nr_bytes;
|
|
|
bio_iovec(bio)->bv_len -= nr_bytes;
|