Skip to contentSkip to conversation

block: fix partial zone append completion handling in req_bio_endio()

PATCH Applied Damien Le Moal 3 participants 3 messages Jan 10, 2024 Block layer

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 block: fix partial zone append completion handling in req_bio_endio()

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")

---
Changes from v1:
- Fixed typo in commit message
- Added review tags

 block/blk-mq.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
block/blk-mq.c +7 -2
index c11c97afa0bc..cd59b172c8fc 100644
@@ -772,11 +772,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);
Signature · 1 line
2.43.0
Reviewed-by on v2 1/1
#1 lore raw
Quoted 36 lines · Damien Le Moal

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")

---
Changes from v1:
- Fixed typo in commit message
- Added review tags

  block/blk-mq.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)
block/blk-mq.c +3 -1
index c11c97afa0bc..cd59b172c8fc 100644
@@ -772,11 +772,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)

block/blk-mq.c static void req_bio_endio(struct request *rq, struct bio *bio, · line 787

Quoted 10 lines
block/blk-mq.c +4 -1
+		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);

Cheers,

Hannes

maintainer Applied
#2 lore raw
In reply to Damien Le Moal
Quoted 11 lines · Damien Le Moal

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.

[...]

Applied, thanks!

[1/1] block: fix partial zone append completion handling in req_bio_endio()

      commit: 748dc0b65ec2b4b7b3dbd7befcc4a54fdcac7988

Best regards,

Signature · 1 line
Jens Axboe