On Wed, Oct 22, 2014 at 4:05 AM, Jens Axboe <axboe@xxxxxxxxx> wrote: > On 10/17/2014 07:27 AM, Christoph Hellwig wrote: >> On Thu, Oct 16, 2014 at 11:17:39AM -0400, Brian Foster wrote: >>> Hi all, >>> >>> Hopefully this is the right list for this report... >>> >>> I hit the following kernel bug reliably by running xfstests test >>> generic/234 against XFS using 10GB LVM test/scratch volumes on top of a >>> ~100GB virtio_blk block device. The virt block device is file-backed on >>> the host. >> >> Jens, I thought the segment merging bug was fixed a while ago. Did we >> manage to not include parts of it for 3.17? > > Mings patch went in after 3.17, iirc. Ming? Sorry, that patch is wrong[1], attachment patch should fix the issue. [1] http://marc.info/?l=linux-kernel&m=141290430004361&w=2 Thanks, -- Ming Lei
From dde19549352da3fea516d89bbfa25d08b784e229 Mon Sep 17 00:00:00 2001 From: Ming Lei <tom.leiming@xxxxxxxxx> Date: Wed, 22 Oct 2014 08:30:30 +0800 Subject: [PATCH] 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@xxxxxxxxx> --- block/blk-merge.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index ba99351..b3ac40a 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) { 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); if (no_sg_merge && !bio_flagged(bio, BIO_CLONED) && - bio->bi_vcnt < queue_max_segments(q)) + merge_not_need) bio->bi_phys_segments = bio->bi_vcnt; else { struct bio *nxt = bio->bi_next; bio->bi_next = NULL; bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, - no_sg_merge); + no_sg_merge && merge_not_need); bio->bi_next = nxt; } -- 1.7.9.5