diff options
author | Ming Lei <tom.leiming@gmail.com> | 2014-10-21 20:30:30 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-10-21 21:00:32 -0400 |
commit | 76d8137a31139f0d69ecc4177497ad6b8d4f016c (patch) | |
tree | 194c64bc760ff1aff6c21f29b9519725b1c2fc1a /block | |
parent | 432f16e64f50fd4999a476543d04dd52f7a2d753 (diff) |
blk-merge: recaculate segment if it isn't less than max segments
The problem is introduced by commit 764f612c6c3c231b(blk-merge:
don't compute bi_phys_segments from bi_vcnt for cloned bio),
and merge is needed if number of current segment isn't less than
max segments.
Strictly speaking, bio->bi_vcnt shouldn't be used here since
it may not be accurate in cases of both cloned bio or bio cloned
from, but bio_segments() is a bit expensive, and bi_vcnt is still
the biggest number, so the approach should work.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-merge.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index ba99351c0f58..b3ac40aef46b 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -99,16 +99,17 @@ void blk_recount_segments(struct request_queue *q, struct bio *bio) | |||
99 | { | 99 | { |
100 | bool no_sg_merge = !!test_bit(QUEUE_FLAG_NO_SG_MERGE, | 100 | bool no_sg_merge = !!test_bit(QUEUE_FLAG_NO_SG_MERGE, |
101 | &q->queue_flags); | 101 | &q->queue_flags); |
102 | bool merge_not_need = bio->bi_vcnt < queue_max_segments(q); | ||
102 | 103 | ||
103 | if (no_sg_merge && !bio_flagged(bio, BIO_CLONED) && | 104 | if (no_sg_merge && !bio_flagged(bio, BIO_CLONED) && |
104 | bio->bi_vcnt < queue_max_segments(q)) | 105 | merge_not_need) |
105 | bio->bi_phys_segments = bio->bi_vcnt; | 106 | bio->bi_phys_segments = bio->bi_vcnt; |
106 | else { | 107 | else { |
107 | struct bio *nxt = bio->bi_next; | 108 | struct bio *nxt = bio->bi_next; |
108 | 109 | ||
109 | bio->bi_next = NULL; | 110 | bio->bi_next = NULL; |
110 | bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, | 111 | bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, |
111 | no_sg_merge); | 112 | no_sg_merge && merge_not_need); |
112 | bio->bi_next = nxt; | 113 | bio->bi_next = nxt; |
113 | } | 114 | } |
114 | 115 | ||