diff options
-rw-r--r-- | block/blk-merge.c | 20 | ||||
-rw-r--r-- | include/linux/bio.h | 7 |
2 files changed, 25 insertions, 2 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index 908d3e11ac52..8681cd6f9911 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -77,12 +77,20 @@ void blk_recalc_rq_segments(struct request *rq) | |||
77 | continue; | 77 | continue; |
78 | } | 78 | } |
79 | new_segment: | 79 | new_segment: |
80 | if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size) | ||
81 | rq->bio->bi_seg_front_size = seg_size; | ||
82 | |||
80 | nr_phys_segs++; | 83 | nr_phys_segs++; |
81 | bvprv = bv; | 84 | bvprv = bv; |
82 | seg_size = bv->bv_len; | 85 | seg_size = bv->bv_len; |
83 | highprv = high; | 86 | highprv = high; |
84 | } | 87 | } |
85 | 88 | ||
89 | if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size) | ||
90 | rq->bio->bi_seg_front_size = seg_size; | ||
91 | if (seg_size > rq->biotail->bi_seg_back_size) | ||
92 | rq->biotail->bi_seg_back_size = seg_size; | ||
93 | |||
86 | rq->nr_phys_segments = nr_phys_segs; | 94 | rq->nr_phys_segments = nr_phys_segs; |
87 | } | 95 | } |
88 | 96 | ||
@@ -106,7 +114,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, | |||
106 | if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) | 114 | if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) |
107 | return 0; | 115 | return 0; |
108 | 116 | ||
109 | if (bio->bi_size + nxt->bi_size > q->max_segment_size) | 117 | if (bio->bi_seg_back_size + nxt->bi_seg_front_size > |
118 | q->max_segment_size) | ||
110 | return 0; | 119 | return 0; |
111 | 120 | ||
112 | if (!bio_has_data(bio)) | 121 | if (!bio_has_data(bio)) |
@@ -309,6 +318,8 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, | |||
309 | struct request *next) | 318 | struct request *next) |
310 | { | 319 | { |
311 | int total_phys_segments; | 320 | int total_phys_segments; |
321 | unsigned int seg_size = | ||
322 | req->biotail->bi_seg_back_size + next->bio->bi_seg_front_size; | ||
312 | 323 | ||
313 | /* | 324 | /* |
314 | * First check if the either of the requests are re-queued | 325 | * First check if the either of the requests are re-queued |
@@ -324,8 +335,13 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, | |||
324 | return 0; | 335 | return 0; |
325 | 336 | ||
326 | total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; | 337 | total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; |
327 | if (blk_phys_contig_segment(q, req->biotail, next->bio)) | 338 | if (blk_phys_contig_segment(q, req->biotail, next->bio)) { |
339 | if (req->nr_phys_segments == 1) | ||
340 | req->bio->bi_seg_front_size = seg_size; | ||
341 | if (next->nr_phys_segments == 1) | ||
342 | next->biotail->bi_seg_back_size = seg_size; | ||
328 | total_phys_segments--; | 343 | total_phys_segments--; |
344 | } | ||
329 | 345 | ||
330 | if (total_phys_segments > q->max_phys_segments) | 346 | if (total_phys_segments > q->max_phys_segments) |
331 | return 0; | 347 | return 0; |
diff --git a/include/linux/bio.h b/include/linux/bio.h index ff5b4cf9e2da..dc3cec386a99 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -79,6 +79,13 @@ struct bio { | |||
79 | 79 | ||
80 | unsigned int bi_size; /* residual I/O count */ | 80 | unsigned int bi_size; /* residual I/O count */ |
81 | 81 | ||
82 | /* | ||
83 | * To keep track of the max segment size, we account for the | ||
84 | * sizes of the first and last mergeable segments in this bio. | ||
85 | */ | ||
86 | unsigned int bi_seg_front_size; | ||
87 | unsigned int bi_seg_back_size; | ||
88 | |||
82 | unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ | 89 | unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ |
83 | 90 | ||
84 | unsigned int bi_comp_cpu; /* completion CPU */ | 91 | unsigned int bi_comp_cpu; /* completion CPU */ |