Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp2997413imm; Thu, 24 May 2018 20:49:02 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpjUDpyEPO6yL4ATqv0w0sdEfwv6dhxnE6qyrwVXUT7Cy35c1j/FeDB62kYVbTdbBX55rU2 X-Received: by 2002:a62:f909:: with SMTP id o9-v6mr795634pfh.256.1527220142063; Thu, 24 May 2018 20:49:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527220142; cv=none; d=google.com; s=arc-20160816; b=G+88kpwG9dfXe3NAzco9KLOWLfmIaAZkP4XsfxjnaQpu7w2y2B9qvQtLvoptDriEVJ FlwvAf4FuKdB6PxK9igLp2le8cOMZV79RznGujrGtZVyK8f2GPN3ui8pBlWzfmxh/IZR JycNKN2Tx1iMznYzdUheCIBOHzb65E5YovCIOGJIgEWSOk9SyDmeRHo0az6TdCJkBqaj 8qGF+mvmrQlJMiVBaEFycXKAyMjug6y14yuA19FiiJK4qkuYWGV+MkC/UBp1bhr9EkAy B0jtd7P3uhRa2+4ZeiHfKIuq0J+xmlQ0Yl+zgvvqH+tyRobt+KGx6ec5R4k9npdKuESu hCbg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=WPuo4v9Jht5MsSI7ZWhB8yaGTKi430/G8fCv3eW7y6M=; b=BgSmiM6XYJI4VSWBdDzx5URqUEGvF3NZgDjOmtucZjF/qC0TKfHq9cy+fbmHlM+4EI i68aL7N76Bbv8NBJd2oFLos+OEH0V4AwTACwAJ7ZMwKtfaex34ZCbErXh+JB3kdOuwYD vHOOqSU5X+2fbOlAcwZur1EiMTWGXirQyXouqCJl+7ZxAkZSY8DW6vLjLAvcamalRbzd cQqrjI6ZtmlTWnsiCy0kY1VOa2Ww4qfmsiClNlX8IQKS+/V1HRJagGDmiWdnak8qa7U7 5GDIolPUsm6xOhBsDkS2GmM2xZRKrl0kx8ECvE7PwxQjmwLNXCK/J2azChoNdDR9FIPo vCFA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w11-v6si18119433pgv.329.2018.05.24.20.48.47; Thu, 24 May 2018 20:49:02 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755373AbeEYDsD (ORCPT + 99 others); Thu, 24 May 2018 23:48:03 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:41294 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755319AbeEYDsB (ORCPT ); Thu, 24 May 2018 23:48:01 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C1DD740203F4; Fri, 25 May 2018 03:48:00 +0000 (UTC) Received: from localhost (ovpn-12-30.pek2.redhat.com [10.72.12.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id 73A752022EF1; Fri, 25 May 2018 03:47:52 +0000 (UTC) From: Ming Lei To: Jens Axboe , Christoph Hellwig , Alexander Viro , Kent Overstreet Cc: David Sterba , Huang Ying , linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Theodore Ts'o , "Darrick J . Wong" , Coly Li , Filipe Manana , Ming Lei Subject: [RESEND PATCH V5 06/33] block: use bio_for_each_segment() to compute segments count Date: Fri, 25 May 2018 11:45:54 +0800 Message-Id: <20180525034621.31147-7-ming.lei@redhat.com> In-Reply-To: <20180525034621.31147-1-ming.lei@redhat.com> References: <20180525034621.31147-1-ming.lei@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 25 May 2018 03:48:00 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 25 May 2018 03:48:00 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'ming.lei@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Firstly it is more efficient to use bio_for_each_segment() in both blk_bio_segment_split() and __blk_recalc_rq_segments() to compute how many segments there are in the bio. Secondaly once bio_for_each_segment() is used, the bvec may need to be splitted because its length can be very longer than max segment size, so we have to split the big bvec into several segments. Thirdly during splitting multipage bvec into segments, max segment number may be reached, then the bio need to be splitted when this happens. Signed-off-by: Ming Lei --- block/blk-merge.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 545609fc4905..d157b752d965 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -97,6 +97,62 @@ static inline unsigned get_max_io_size(struct request_queue *q, return sectors; } +/* + * Split the bvec @bv into segments, and update all kinds of + * variables. + */ +static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv, + unsigned *nsegs, unsigned *last_seg_size, + unsigned *front_seg_size, unsigned *sectors) +{ + bool need_split = false; + unsigned len = bv->bv_len; + unsigned total_len = 0; + unsigned new_nsegs = 0, seg_size = 0; + + if ((*nsegs >= queue_max_segments(q)) || !len) + return need_split; + + /* + * Multipage bvec may be too big to hold in one segment, + * so the current bvec has to be splitted as multiple + * segments. + */ + while (new_nsegs + *nsegs < queue_max_segments(q)) { + seg_size = min(queue_max_segment_size(q), len); + + new_nsegs++; + total_len += seg_size; + len -= seg_size; + + if ((queue_virt_boundary(q) && ((bv->bv_offset + + total_len) & queue_virt_boundary(q))) || !len) + break; + } + + /* split in the middle of the bvec */ + if (len) + need_split = true; + + /* update front segment size */ + if (!*nsegs) { + unsigned first_seg_size = seg_size; + + if (new_nsegs > 1) + first_seg_size = queue_max_segment_size(q); + if (*front_seg_size < first_seg_size) + *front_seg_size = first_seg_size; + } + + /* update other varibles */ + *last_seg_size = seg_size; + *nsegs += new_nsegs; + if (sectors) + *sectors += total_len >> 9; + + return need_split; +} + static struct bio *blk_bio_segment_split(struct request_queue *q, struct bio *bio, struct bio_set *bs, @@ -110,7 +166,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, struct bio *new = NULL; const unsigned max_sectors = get_max_io_size(q, bio); - bio_for_each_page(bv, bio, iter) { + bio_for_each_segment(bv, bio, iter) { /* * If the queue doesn't support SG gaps and adding this * offset would create a gap, disallow it. @@ -125,8 +181,12 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, */ if (nsegs < queue_max_segments(q) && sectors < max_sectors) { - nsegs++; - sectors = max_sectors; + /* split in the middle of bvec */ + bv.bv_len = (max_sectors - sectors) << 9; + bvec_split_segs(q, &bv, &nsegs, + &seg_size, + &front_seg_size, + §ors); } goto split; } @@ -153,11 +213,12 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, if (nsegs == 1 && seg_size > front_seg_size) front_seg_size = seg_size; - nsegs++; bvprv = bv; bvprvp = &bvprv; - seg_size = bv.bv_len; - sectors += bv.bv_len >> 9; + + if (bvec_split_segs(q, &bv, &nsegs, &seg_size, + &front_seg_size, §ors)) + goto split; } @@ -225,6 +286,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, struct bio_vec bv, bvprv = { NULL }; int cluster, prev = 0; unsigned int seg_size, nr_phys_segs; + unsigned front_seg_size = bio->bi_seg_front_size; struct bio *fbio, *bbio; struct bvec_iter iter; @@ -245,7 +307,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, seg_size = 0; nr_phys_segs = 0; for_each_bio(bio) { - bio_for_each_page(bv, bio, iter) { + bio_for_each_segment(bv, bio, iter) { /* * If SG merging is disabled, each bio vector is * a segment @@ -267,20 +329,20 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, continue; } new_segment: - if (nr_phys_segs == 1 && seg_size > - fbio->bi_seg_front_size) - fbio->bi_seg_front_size = seg_size; + if (nr_phys_segs == 1 && seg_size > front_seg_size) + front_seg_size = seg_size; - nr_phys_segs++; bvprv = bv; prev = 1; - seg_size = bv.bv_len; + bvec_split_segs(q, &bv, &nr_phys_segs, &seg_size, + &front_seg_size, NULL); } bbio = bio; } - if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size) - fbio->bi_seg_front_size = seg_size; + if (nr_phys_segs == 1 && seg_size > front_seg_size) + front_seg_size = seg_size; + fbio->bi_seg_front_size = front_seg_size; if (seg_size > bbio->bi_seg_back_size) bbio->bi_seg_back_size = seg_size; -- 2.9.5