Skip to content

Commit

Permalink
block: fix trace completion for chained bio
Browse files Browse the repository at this point in the history
[ Upstream commit 60b6a7e ]

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 <fbbaf700e7b1> ("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: fbbaf70 ("block: trace completion of all bios.")
Reviewed-by: Wade Liang <wadel@synology.com>
Reviewed-by: BingJing Chang <bingjingc@synology.com>
Signed-off-by: Edward Hsieh <edwardh@synology.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20210624123030.27014-1-edwardh@synology.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Edward Hsieh authored and gregkh committed Jul 14, 2021
1 parent ca46916 commit 577072d
Showing 1 changed file with 6 additions and 7 deletions.
13 changes: 6 additions & 7 deletions block/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1412,8 +1412,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)
{
Expand All @@ -1426,6 +1425,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
Expand All @@ -1439,11 +1443,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);
Expand Down

0 comments on commit 577072d

Please sign in to comment.