Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp8485760imu; Thu, 15 Nov 2018 12:21:27 -0800 (PST) X-Google-Smtp-Source: AJdET5cvsmPCg4DF029D4p8TJ7GYLVbu58tF+BVTKWC0P1OclajXMTrpOYudSKKNAhcWCnZaOeXE X-Received: by 2002:a63:c42:: with SMTP id 2mr7175321pgm.372.1542313287031; Thu, 15 Nov 2018 12:21:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542313286; cv=none; d=google.com; s=arc-20160816; b=qTTZsbD1SJf80C1x8jCCbG7xDUF3vEAXr6yfvkzFS386Wn0/i/gHF58uen5r0l0NjO xFNhw0/NOhTS1rG9hVD01Kw15HbzXfcR7aRqZuK1Xomg331bHz/deJ/Et1p9Y2cWoG91 71UJJoP/5Xmuu3gF41aArN9uvzT+tm2skktExBh002OFZlrQVGbxgwrvu4AbkK60kejf uPKVQxihcilCmehxhg5lngU4idLU9T4ziIHKV5xOvbzngGrD2iujZqQvZ1KNfx326RLP DK++ev5SNlAQCBYnqfSPPau3KvT3HbFj5eTToVyhcNVRUH4s4RRaszThdFtCTyVoaj+m kkAg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature; bh=DjOESrPx+LNX18fh9qfhKZ+KPyRBzNVp6MIp26IMeXY=; b=b+ZOLnDZfG++2EUKWLzVXwTBeV7tiEbtdVUg4sYisKJ/5N+l58EAwTW3BmSVl8Ik6r 8WjLGxyvtFCwe4WgwPOf/NTr4k46xTsTEh9nJmbaU1rUUDa0rtbNWeuK4aG6eXaz9LVO BQdD8GT/gcibDAQ+3w32+s9bSCOFf7q0iq9zfIMfZTC03GQwdfwXTyeu8sz+tvXpp38P bE2iX2pmlHgDdHb1FaN3DecZutP3MZ8Lehr3JAMzKKMd576nr+I4ksJTk9oKRmVDhsuV OXTfzcjYY2h6xEUlX88kmMBjRaAXJ6Ui/zcSDumoXd0Fs4jDNqkA19X69Ose2TlZW2HW ZztA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@osandov-com.20150623.gappssmtp.com header.s=20150623 header.b="uI/+pM0r"; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p9si25068440pgc.448.2018.11.15.12.21.11; Thu, 15 Nov 2018 12:21:26 -0800 (PST) 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; dkim=pass header.i=@osandov-com.20150623.gappssmtp.com header.s=20150623 header.b="uI/+pM0r"; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388979AbeKPG3u (ORCPT + 99 others); Fri, 16 Nov 2018 01:29:50 -0500 Received: from mail-pf1-f196.google.com ([209.85.210.196]:39628 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729484AbeKPG3t (ORCPT ); Fri, 16 Nov 2018 01:29:49 -0500 Received: by mail-pf1-f196.google.com with SMTP id c72so5539070pfc.6 for ; Thu, 15 Nov 2018 12:20:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=DjOESrPx+LNX18fh9qfhKZ+KPyRBzNVp6MIp26IMeXY=; b=uI/+pM0rn1iRPxN5FCtrq1SbFlHuUR18/4dsIL4bsMQhabDgi4ZdSzX2Mfe3XjsNY6 4xQVm6vhr3p/PDRuutZ6VLpjOwi9mFZPDHQx0rB5UyG36UukDTCzePLW/v9wHyzWXmw6 3iZj2IDB2P6v7SdxGUDwwve4RBxhs4dBxxVg8jnpI2qlLc2xjMwvqL5kU/9e7PSAOizB b5OL49aW0fD7MULdwpyDUNWc8iFy219aQu5r5fJmQWtARH8vxLVZa791D8sgq2RdhJhF /8Dky+e1W5d6XNa5MVm3fJyyOYnjGqh/evPg8z/4hrklwK47hYtiOxVOjBDiEGeC5+e5 ifww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=DjOESrPx+LNX18fh9qfhKZ+KPyRBzNVp6MIp26IMeXY=; b=T+fPRwSBAj4OAjjYe/LMa/+Dh469/lU/2lRPF5OaM6WpG/bK42dcsUMm6zge+sWKjq kC+rCXdWYrn+dyAHcK1PGRBBwRX4XI8KI8gikln6lAa7jpmouHHp7PuKfwFujp5CaljW jiIviVO1W3QX7C3IRW3JaJTsuAYHpy3vd+tFvQAOTmWBDy9ltkvN9FpnR+A/xl7JArhQ duMLkI2jGl8xWVZisvAWT0pJpHHYB0bMuzqPFdntQHw8vDBjXJ+o0YZ8Vh3qzmGQ1Tha orVlhcejGqBUerODAJkYf0Y9wek9WccdID7krixZoG9Q4DrwNIBjW6IdMYkD59lhvflr 7S1Q== X-Gm-Message-State: AGRZ1gKGUiHu2nJOtosXy3FY1RVo0dalm8gHGXVdosXrmKPFliY0qzzN KWRFyyO0DR/T0L9ed7Dm3SWIKA== X-Received: by 2002:a62:2741:: with SMTP id n62-v6mr8098091pfn.138.1542313230689; Thu, 15 Nov 2018 12:20:30 -0800 (PST) Received: from vader ([64.114.255.97]) by smtp.gmail.com with ESMTPSA id u127-v6sm29173365pfb.47.2018.11.15.12.20.29 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 15 Nov 2018 12:20:30 -0800 (PST) Date: Thu, 15 Nov 2018 12:20:28 -0800 From: Omar Sandoval To: Ming Lei Cc: Jens Axboe , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Dave Chinner , Kent Overstreet , Mike Snitzer , dm-devel@redhat.com, Alexander Viro , linux-fsdevel@vger.kernel.org, Shaohua Li , linux-raid@vger.kernel.org, linux-erofs@lists.ozlabs.org, David Sterba , linux-btrfs@vger.kernel.org, "Darrick J . Wong" , linux-xfs@vger.kernel.org, Gao Xiang , Christoph Hellwig , Theodore Ts'o , linux-ext4@vger.kernel.org, Coly Li , linux-bcache@vger.kernel.org, Boaz Harrosh , Bob Peterson , cluster-devel@redhat.com Subject: Re: [PATCH V10 03/19] block: use bio_for_each_bvec() to compute multi-page bvec count Message-ID: <20181115202028.GC9348@vader> References: <20181115085306.9910-1-ming.lei@redhat.com> <20181115085306.9910-4-ming.lei@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20181115085306.9910-4-ming.lei@redhat.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Nov 15, 2018 at 04:52:50PM +0800, Ming Lei wrote: > First it is more efficient to use bio_for_each_bvec() in both > blk_bio_segment_split() and __blk_recalc_rq_segments() to compute how > many multi-page bvecs there are in the bio. > > Secondly once bio_for_each_bvec() 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 when splitting multi-page bvec into segments, the max segment > limit may be reached, so the bio split need to be considered under > this situation too. > > Cc: Dave Chinner > Cc: Kent Overstreet > Cc: Mike Snitzer > Cc: dm-devel@redhat.com > Cc: Alexander Viro > Cc: linux-fsdevel@vger.kernel.org > Cc: Shaohua Li > Cc: linux-raid@vger.kernel.org > Cc: linux-erofs@lists.ozlabs.org > Cc: David Sterba > Cc: linux-btrfs@vger.kernel.org > Cc: Darrick J. Wong > Cc: linux-xfs@vger.kernel.org > Cc: Gao Xiang > Cc: Christoph Hellwig > Cc: Theodore Ts'o > Cc: linux-ext4@vger.kernel.org > Cc: Coly Li > Cc: linux-bcache@vger.kernel.org > Cc: Boaz Harrosh > Cc: Bob Peterson > Cc: cluster-devel@redhat.com > 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 91b2af332a84..6f7deb94a23f 100644 > --- a/block/blk-merge.c > +++ b/block/blk-merge.c > @@ -160,6 +160,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; "unsigned int" here and everywhere else. > + 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; Checking queue_virt_boundary(q) != 0 is superfluous, and the len check could just control the loop, i.e., while (len && 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 ((bv->bv_offset + total_len) & queue_virt_boundary(q)) break; } And if you rewrite it this way, I _think_ you can get rid of this special case: if ((*nsegs >= queue_max_segments(q)) || !len) return need_split; above. > + } > + > + /* split in the middle of the bvec */ > + if (len) > + need_split = true; need_split is unnecessary, just return len != 0. > + > + /* 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, > @@ -173,7 +229,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_segment(bv, bio, iter) { > + bio_for_each_bvec(bv, bio, iter) { > /* > * If the queue doesn't support SG gaps and adding this > * offset would create a gap, disallow it. > @@ -188,8 +244,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; > } > @@ -214,11 +274,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; Hm, do we still need to check this here now that we're updating front_seg_size inside of bvec_split_segs()? > > - 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)) What happened to the indent alignment here? > + goto split; > > } > > @@ -296,6 +357,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; > > @@ -316,7 +378,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_segment(bv, bio, iter) { > + bio_for_each_bvec(bv, bio, iter) { > /* > * If SG merging is disabled, each bio vector is > * a segment > @@ -336,20 +398,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; Same comment as in blk_bio_segment_split(), do we still need to check this if we're updating front_seg_size in bvec_split_segs()? > > - 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 >