diff options
author | Damien Le Moal <dlemoal@kernel.org> | 2024-01-10 12:29:42 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-02-23 11:12:49 +0300 |
commit | e7d2e87abc6fddec0e661f9fd8c1657db42d674b (patch) | |
tree | ad5600cfca2f3077fe4f7ebebe945ae77ffa3810 | |
parent | bb44477d4506e52785693a39f03cdc6a2c5e8598 (diff) | |
download | linux-e7d2e87abc6fddec0e661f9fd8c1657db42d674b.tar.xz |
block: fix partial zone append completion handling in req_bio_endio()
[ Upstream commit 748dc0b65ec2b4b7b3dbd7befcc4a54fdcac7988 ]
Partial completions of zone append request is not allowed but if a zone
append completion indicates a number of completed bytes different from
the original BIO size, only the BIO status is set to error. This leads
to bio_advance() not setting the BIO size to 0 and thus to not call
bio_endio() at the end of req_bio_endio().
Make sure a partially completed zone append is failed and completed
immediately by forcing the completed number of bytes (nbytes) to be
equal to the BIO size, thus ensuring that bio_endio() is called.
Fixes: 297db731847e ("block: fix req_bio_endio append error handling")
Cc: stable@kernel.vger.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Link: https://lore.kernel.org/r/20240110092942.442334-1-dlemoal@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | block/blk-mq.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index c07e5eebcbd8..7ed6b9469f97 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -747,11 +747,16 @@ static void req_bio_endio(struct request *rq, struct bio *bio, /* * Partial zone append completions cannot be supported as the * BIO fragments may end up not being written sequentially. + * For such case, force the completed nbytes to be equal to + * the BIO size so that bio_advance() sets the BIO remaining + * size to 0 and we end up calling bio_endio() before returning. */ - if (bio->bi_iter.bi_size != nbytes) + if (bio->bi_iter.bi_size != nbytes) { bio->bi_status = BLK_STS_IOERR; - else + nbytes = bio->bi_iter.bi_size; + } else { bio->bi_iter.bi_sector = rq->__sector; + } } bio_advance(bio, nbytes); |