Commit d6a25b31 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

blk-mq: support partial I/O completions

Add a new blk_mq_end_io_partial function to partially complete requests
as needed by the SCSI layer.  We do this by reusing blk_update_request
to advance the bio instead of having a simplified version of it in
the blk-mq code.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent feb71dae
...@@ -283,38 +283,10 @@ void blk_mq_free_request(struct request *rq) ...@@ -283,38 +283,10 @@ void blk_mq_free_request(struct request *rq)
__blk_mq_free_request(hctx, ctx, rq); __blk_mq_free_request(hctx, ctx, rq);
} }
static void blk_mq_bio_endio(struct request *rq, struct bio *bio, int error) bool blk_mq_end_io_partial(struct request *rq, int error, unsigned int nr_bytes)
{ {
if (error) if (blk_update_request(rq, error, blk_rq_bytes(rq)))
clear_bit(BIO_UPTODATE, &bio->bi_flags); return true;
else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
error = -EIO;
if (unlikely(rq->cmd_flags & REQ_QUIET))
set_bit(BIO_QUIET, &bio->bi_flags);
/* don't actually finish bio if it's part of flush sequence */
if (!(rq->cmd_flags & REQ_FLUSH_SEQ))
bio_endio(bio, error);
}
void blk_mq_end_io(struct request *rq, int error)
{
struct bio *bio = rq->bio;
unsigned int bytes = 0;
trace_block_rq_complete(rq->q, rq);
while (bio) {
struct bio *next = bio->bi_next;
bio->bi_next = NULL;
bytes += bio->bi_iter.bi_size;
blk_mq_bio_endio(rq, bio, error);
bio = next;
}
blk_account_io_completion(rq, bytes);
blk_account_io_done(rq); blk_account_io_done(rq);
...@@ -322,8 +294,9 @@ void blk_mq_end_io(struct request *rq, int error) ...@@ -322,8 +294,9 @@ void blk_mq_end_io(struct request *rq, int error)
rq->end_io(rq, error); rq->end_io(rq, error);
else else
blk_mq_free_request(rq); blk_mq_free_request(rq);
return false;
} }
EXPORT_SYMBOL(blk_mq_end_io); EXPORT_SYMBOL(blk_mq_end_io_partial);
static void __blk_mq_complete_request_remote(void *data) static void __blk_mq_complete_request_remote(void *data)
{ {
......
...@@ -133,7 +133,13 @@ struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_ind ...@@ -133,7 +133,13 @@ struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_ind
struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_reg *, unsigned int); struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_reg *, unsigned int);
void blk_mq_free_single_hw_queue(struct blk_mq_hw_ctx *, unsigned int); void blk_mq_free_single_hw_queue(struct blk_mq_hw_ctx *, unsigned int);
void blk_mq_end_io(struct request *rq, int error); bool blk_mq_end_io_partial(struct request *rq, int error,
unsigned int nr_bytes);
static inline void blk_mq_end_io(struct request *rq, int error)
{
bool done = !blk_mq_end_io_partial(rq, error, blk_rq_bytes(rq));
BUG_ON(!done);
}
void blk_mq_complete_request(struct request *rq); void blk_mq_complete_request(struct request *rq);
......
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