aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-merge.c20
-rw-r--r--include/linux/bio.h7
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 }
79new_segment: 79new_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 */