Skip to content

Commit 02e7074

Browse files
Ming Leiaxboe
authored andcommitted
blk-merge: fix blk_bio_segment_split
Commit bdced43(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: bdced43(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>
1 parent 578270b commit 02e7074

1 file changed

Lines changed: 19 additions & 3 deletions

File tree

block/blk-merge.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
7676
struct bio_vec bv, bvprv, *bvprvp = NULL;
7777
struct bvec_iter iter;
7878
unsigned seg_size = 0, nsegs = 0, sectors = 0;
79+
unsigned front_seg_size = bio->bi_seg_front_size;
80+
bool do_split = true;
81+
struct bio *new = NULL;
7982

8083
bio_for_each_segment(bv, bio, iter) {
8184
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,
111114
bvprvp = &bvprv;
112115
seg_size = bv.bv_len;
113116
sectors += bv.bv_len >> 9;
117+
118+
if (nsegs == 1 && seg_size > front_seg_size)
119+
front_seg_size = seg_size;
114120
}
115121

116-
*segs = nsegs;
117-
return NULL;
122+
do_split = false;
118123
split:
119124
*segs = nsegs;
120-
return bio_split(bio, sectors, GFP_NOIO, bs);
125+
126+
if (do_split) {
127+
new = bio_split(bio, sectors, GFP_NOIO, bs);
128+
if (new)
129+
bio = new;
130+
}
131+
132+
bio->bi_seg_front_size = front_seg_size;
133+
if (seg_size > bio->bi_seg_back_size)
134+
bio->bi_seg_back_size = seg_size;
135+
136+
return do_split ? new : NULL;
121137
}
122138

123139
void blk_queue_split(struct request_queue *q, struct bio **bio,

0 commit comments

Comments
 (0)