blk-merge: fix blk_bio_segment_split
Commit bdced438acd83a(block: setup bi_phys_segments after splitting) introduces function of computing bio->bi_phys_segments during bio splitting. Unfortunately both bio->bi_seg_front_size and bio->bi_seg_back_size arn't computed, so too many physical segments may be obtained for one request since both the two are used to check if one segment across two bios can be possible. This patch fixes the issue by computing the two variables in blk_bio_segment_split(). Fixes: bdced438acd83a(block: setup bi_phys_segments after splitting) Reported-by: Michael Ellerman <mpe@ellerman.id.au> Reported-by: Mark Salter <msalter@redhat.com> Tested-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> Tested-by: Mark Salter <msalter@redhat.com> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
parent
578270bfbd
commit
02e707424c
1 changed files with 19 additions and 3 deletions
|
@ -76,6 +76,9 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
|
|||
struct bio_vec bv, bvprv, *bvprvp = NULL;
|
||||
struct bvec_iter iter;
|
||||
unsigned seg_size = 0, nsegs = 0, sectors = 0;
|
||||
unsigned front_seg_size = bio->bi_seg_front_size;
|
||||
bool do_split = true;
|
||||
struct bio *new = NULL;
|
||||
|
||||
bio_for_each_segment(bv, bio, iter) {
|
||||
if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
|
||||
|
@ -111,13 +114,26 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
|
|||
bvprvp = &bvprv;
|
||||
seg_size = bv.bv_len;
|
||||
sectors += bv.bv_len >> 9;
|
||||
|
||||
if (nsegs == 1 && seg_size > front_seg_size)
|
||||
front_seg_size = seg_size;
|
||||
}
|
||||
|
||||
*segs = nsegs;
|
||||
return NULL;
|
||||
do_split = false;
|
||||
split:
|
||||
*segs = nsegs;
|
||||
return bio_split(bio, sectors, GFP_NOIO, bs);
|
||||
|
||||
if (do_split) {
|
||||
new = bio_split(bio, sectors, GFP_NOIO, bs);
|
||||
if (new)
|
||||
bio = new;
|
||||
}
|
||||
|
||||
bio->bi_seg_front_size = front_seg_size;
|
||||
if (seg_size > bio->bi_seg_back_size)
|
||||
bio->bi_seg_back_size = seg_size;
|
||||
|
||||
return do_split ? new : NULL;
|
||||
}
|
||||
|
||||
void blk_queue_split(struct request_queue *q, struct bio **bio,
|
||||
|
|
Loading…
Reference in a new issue