diff options
Diffstat (limited to 'block/blk-merge.c')
| -rw-r--r-- | block/blk-merge.c | 93 |
1 files changed, 49 insertions, 44 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index b92f5b0866b0..5a244f05360f 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
| @@ -38,72 +38,77 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect) | |||
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | void blk_recalc_rq_segments(struct request *rq) | 41 | static unsigned int __blk_recalc_rq_segments(struct request_queue *q, |
| 42 | struct bio *bio) | ||
| 42 | { | 43 | { |
| 43 | int nr_phys_segs; | ||
| 44 | unsigned int phys_size; | 44 | unsigned int phys_size; |
| 45 | struct bio_vec *bv, *bvprv = NULL; | 45 | struct bio_vec *bv, *bvprv = NULL; |
| 46 | int seg_size; | 46 | int cluster, i, high, highprv = 1; |
| 47 | int cluster; | 47 | unsigned int seg_size, nr_phys_segs; |
| 48 | struct req_iterator iter; | 48 | struct bio *fbio, *bbio; |
| 49 | int high, highprv = 1; | ||
| 50 | struct request_queue *q = rq->q; | ||
| 51 | 49 | ||
| 52 | if (!rq->bio) | 50 | if (!bio) |
| 53 | return; | 51 | return 0; |
| 54 | 52 | ||
| 53 | fbio = bio; | ||
| 55 | cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); | 54 | cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); |
| 56 | seg_size = 0; | 55 | seg_size = 0; |
| 57 | phys_size = nr_phys_segs = 0; | 56 | phys_size = nr_phys_segs = 0; |
| 58 | rq_for_each_segment(bv, rq, iter) { | 57 | for_each_bio(bio) { |
| 59 | /* | 58 | bio_for_each_segment(bv, bio, i) { |
| 60 | * the trick here is making sure that a high page is never | 59 | /* |
| 61 | * considered part of another segment, since that might | 60 | * the trick here is making sure that a high page is |
| 62 | * change with the bounce page. | 61 | * never considered part of another segment, since that |
| 63 | */ | 62 | * might change with the bounce page. |
| 64 | high = page_to_pfn(bv->bv_page) > q->bounce_pfn; | 63 | */ |
| 65 | if (high || highprv) | 64 | high = page_to_pfn(bv->bv_page) > q->bounce_pfn; |
| 66 | goto new_segment; | 65 | if (high || highprv) |
| 67 | if (cluster) { | ||
| 68 | if (seg_size + bv->bv_len > q->max_segment_size) | ||
| 69 | goto new_segment; | ||
| 70 | if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) | ||
| 71 | goto new_segment; | ||
| 72 | if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) | ||
| 73 | goto new_segment; | 66 | goto new_segment; |
| 67 | if (cluster) { | ||
| 68 | if (seg_size + bv->bv_len > q->max_segment_size) | ||
| 69 | goto new_segment; | ||
| 70 | if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv)) | ||
| 71 | goto new_segment; | ||
| 72 | if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv)) | ||
| 73 | goto new_segment; | ||
| 74 | |||
| 75 | seg_size += bv->bv_len; | ||
| 76 | bvprv = bv; | ||
| 77 | continue; | ||
| 78 | } | ||
| 79 | new_segment: | ||
| 80 | if (nr_phys_segs == 1 && seg_size > | ||
| 81 | fbio->bi_seg_front_size) | ||
| 82 | fbio->bi_seg_front_size = seg_size; | ||
| 74 | 83 | ||
| 75 | seg_size += bv->bv_len; | 84 | nr_phys_segs++; |
| 76 | bvprv = bv; | 85 | bvprv = bv; |
| 77 | continue; | 86 | seg_size = bv->bv_len; |
| 87 | highprv = high; | ||
| 78 | } | 88 | } |
| 79 | new_segment: | 89 | bbio = bio; |
| 80 | if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size) | ||
| 81 | rq->bio->bi_seg_front_size = seg_size; | ||
| 82 | |||
| 83 | nr_phys_segs++; | ||
| 84 | bvprv = bv; | ||
| 85 | seg_size = bv->bv_len; | ||
| 86 | highprv = high; | ||
| 87 | } | 90 | } |
| 88 | 91 | ||
| 89 | if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size) | 92 | if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) |
| 90 | rq->bio->bi_seg_front_size = seg_size; | 93 | fbio->bi_seg_front_size = seg_size; |
| 91 | if (seg_size > rq->biotail->bi_seg_back_size) | 94 | if (seg_size > bbio->bi_seg_back_size) |
| 92 | rq->biotail->bi_seg_back_size = seg_size; | 95 | bbio->bi_seg_back_size = seg_size; |
| 96 | |||
| 97 | return nr_phys_segs; | ||
| 98 | } | ||
| 93 | 99 | ||
| 94 | rq->nr_phys_segments = nr_phys_segs; | 100 | void blk_recalc_rq_segments(struct request *rq) |
| 101 | { | ||
| 102 | rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio); | ||
| 95 | } | 103 | } |
| 96 | 104 | ||
| 97 | void blk_recount_segments(struct request_queue *q, struct bio *bio) | 105 | void blk_recount_segments(struct request_queue *q, struct bio *bio) |
| 98 | { | 106 | { |
| 99 | struct request rq; | ||
| 100 | struct bio *nxt = bio->bi_next; | 107 | struct bio *nxt = bio->bi_next; |
| 101 | rq.q = q; | 108 | |
| 102 | rq.bio = rq.biotail = bio; | ||
| 103 | bio->bi_next = NULL; | 109 | bio->bi_next = NULL; |
| 104 | blk_recalc_rq_segments(&rq); | 110 | bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio); |
| 105 | bio->bi_next = nxt; | 111 | bio->bi_next = nxt; |
| 106 | bio->bi_phys_segments = rq.nr_phys_segments; | ||
| 107 | bio->bi_flags |= (1 << BIO_SEG_VALID); | 112 | bio->bi_flags |= (1 << BIO_SEG_VALID); |
| 108 | } | 113 | } |
| 109 | EXPORT_SYMBOL(blk_recount_segments); | 114 | EXPORT_SYMBOL(blk_recount_segments); |
