summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorDamien Le Moal <dlemoal@kernel.org>2024-01-10 12:29:42 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-02-23 11:25:18 +0300
commitb2261c2e763e0f9c25d5dcd2d34920ae7de30387 (patch)
tree672ce3403fa2332856fa3a92c8732194ab1ebc0b /block
parent56f98598ddf0ebe36c002ed429cb814d0b51dceb (diff)
downloadlinux-b2261c2e763e0f9c25d5dcd2d34920ae7de30387.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>
Diffstat (limited to 'block')
-rw-r--r--block/blk-mq.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 257b0addd47e..d8b47f534df9 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -767,11 +767,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);