Commit 60b6a7e6 authored by Edward Hsieh's avatar Edward Hsieh Committed by Jens Axboe
Browse files

block: fix trace completion for chained bio



For chained bio, trace_block_bio_complete in bio_endio is currently called
only by the parent bio once upon all chained bio completed.
However, the sector and size for the parent bio are modified in bio_split.
Therefore, the size and sector of the complete events might not match the
queue events in blktrace.

The original fix of bio completion trace <fbbaf700> ("block: trace
completion of all bios.") wants multiple complete events to correspond
to one queue event but missed this.

The issue can be reproduced by md/raid5 read with bio cross chunks.

To fix, move trace completion into the loop for every chained bio to call.

Fixes: fbbaf700 ("block: trace completion of all bios.")
Reviewed-by: default avatarWade Liang <wadel@synology.com>
Reviewed-by: default avatarBingJing Chang <bingjingc@synology.com>
Signed-off-by: default avatarEdward Hsieh <edwardh@synology.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20210624123030.27014-1-edwardh@synology.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ddcc5c54
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -1375,8 +1375,7 @@ static inline bool bio_remaining_done(struct bio *bio)
 *
 *   bio_endio() can be called several times on a bio that has been chained
 *   using bio_chain().  The ->bi_end_io() function will only be called the
 *   last time.  At this point the BLK_TA_COMPLETE tracing event will be
 *   generated if BIO_TRACE_COMPLETION is set.
 *   last time.
 **/
void bio_endio(struct bio *bio)
{
@@ -1389,6 +1388,11 @@ void bio_endio(struct bio *bio)
	if (bio->bi_bdev)
		rq_qos_done_bio(bio->bi_bdev->bd_disk->queue, bio);

	if (bio->bi_bdev && bio_flagged(bio, BIO_TRACE_COMPLETION)) {
		trace_block_bio_complete(bio->bi_bdev->bd_disk->queue, bio);
		bio_clear_flag(bio, BIO_TRACE_COMPLETION);
	}

	/*
	 * Need to have a real endio function for chained bios, otherwise
	 * various corner cases will break (like stacking block devices that
@@ -1402,11 +1406,6 @@ void bio_endio(struct bio *bio)
		goto again;
	}

	if (bio->bi_bdev && bio_flagged(bio, BIO_TRACE_COMPLETION)) {
		trace_block_bio_complete(bio->bi_bdev->bd_disk->queue, bio);
		bio_clear_flag(bio, BIO_TRACE_COMPLETION);
	}

	blk_throtl_bio_endio(bio);
	/* release cgroup info */
	bio_uninit(bio);