mirror of https://gitee.com/openkylin/linux.git
block: Add warning for bi_next not NULL in bio_endio()
Recently found a bug where a driver left bi_next not NULL and then called bio_endio(), and then the submitter of the bio used bio_copy_data() which was treating src and dst as lists of bios. Fixed that bug by splitting out bio_list_copy_data(), but in case other things are depending on bi_next in weird ways, add a warning to help avoid more bugs like that in the future. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
6e6e811d74
commit
0ba99ca483
|
@ -1775,6 +1775,9 @@ void bio_endio(struct bio *bio)
|
|||
if (!bio_integrity_endio(bio))
|
||||
return;
|
||||
|
||||
if (WARN_ONCE(bio->bi_next, "driver left bi_next not NULL"))
|
||||
bio->bi_next = NULL;
|
||||
|
||||
/*
|
||||
* Need to have a real endio function for chained bios, otherwise
|
||||
* various corner cases will break (like stacking block devices that
|
||||
|
|
|
@ -279,6 +279,10 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
|
|||
bio_advance(bio, nbytes);
|
||||
|
||||
/* don't actually finish bio if it's part of flush sequence */
|
||||
/*
|
||||
* XXX this code looks suspicious - it's not consistent with advancing
|
||||
* req->bio in caller
|
||||
*/
|
||||
if (bio->bi_iter.bi_size == 0 && !(rq->rq_flags & RQF_FLUSH_SEQ))
|
||||
bio_endio(bio);
|
||||
}
|
||||
|
@ -3083,8 +3087,10 @@ bool blk_update_request(struct request *req, blk_status_t error,
|
|||
struct bio *bio = req->bio;
|
||||
unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes);
|
||||
|
||||
if (bio_bytes == bio->bi_iter.bi_size)
|
||||
if (bio_bytes == bio->bi_iter.bi_size) {
|
||||
req->bio = bio->bi_next;
|
||||
bio->bi_next = NULL;
|
||||
}
|
||||
|
||||
/* Completion has already been traced */
|
||||
bio_clear_flag(bio, BIO_TRACE_COMPLETION);
|
||||
|
|
Loading…
Reference in New Issue