diff options
author | Ming Lei <tom.leiming@gmail.com> | 2014-11-12 00:15:41 +0800 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-11-11 16:24:15 -0700 |
commit | 7f60dcaaf91e911002007c7ae885ff6ef0f36c0d (patch) | |
tree | f2bff26f97cc3123ea2741714d0b1ba0658e16ba | |
parent | 92697dc9471b8655a2f1203fa351bc37b2d46a26 (diff) |
block: blk-merge: fix blk_recount_segments()
For cloned bio, bio->bi_vcnt can't be used at all, and we
have resort to bio_segments() to figure out how many
segment there are in the bio.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | block/blk-merge.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/block/blk-merge.c b/block/blk-merge.c index b3ac40aef46b..89b97b5e0881 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -97,19 +97,22 @@ void blk_recalc_rq_segments(struct request *rq) void blk_recount_segments(struct request_queue *q, struct bio *bio) { - bool no_sg_merge = !!test_bit(QUEUE_FLAG_NO_SG_MERGE, - &q->queue_flags); - bool merge_not_need = bio->bi_vcnt < queue_max_segments(q); + unsigned short seg_cnt; + + /* estimate segment number by bi_vcnt for non-cloned bio */ + if (bio_flagged(bio, BIO_CLONED)) + seg_cnt = bio_segments(bio); + else + seg_cnt = bio->bi_vcnt; - if (no_sg_merge && !bio_flagged(bio, BIO_CLONED) && - merge_not_need) - bio->bi_phys_segments = bio->bi_vcnt; + if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags) && + (seg_cnt < queue_max_segments(q))) + bio->bi_phys_segments = seg_cnt; else { struct bio *nxt = bio->bi_next; bio->bi_next = NULL; - bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, - no_sg_merge && merge_not_need); + bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, false); bio->bi_next = nxt; } |