From patchwork Sat Oct 29 08:08:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 9403195 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C17BC60588 for ; Sat, 29 Oct 2016 08:15:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADF0E2A597 for ; Sat, 29 Oct 2016 08:15:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A043A2A5ED; Sat, 29 Oct 2016 08:15:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 206B32A597 for ; Sat, 29 Oct 2016 08:15:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1034089AbcJ2IOq (ORCPT ); Sat, 29 Oct 2016 04:14:46 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:35150 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1033989AbcJ2IOi (ORCPT ); Sat, 29 Oct 2016 04:14:38 -0400 Received: by mail-pf0-f195.google.com with SMTP id s8so3382211pfj.2; Sat, 29 Oct 2016 01:14:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Bhp31+gudmlwg+zaYhJQUzqDMK6jOnkH5ePQRjecVa8=; b=jXJtO74BDBqtN1d8W8F7heiRFk3IcLGsjtrT/ZqBfx+CjvdRNUH5waX9XI9rznwdJ9 HpMflbVwK7Hgr9drhQW/dV0TTdeSm6GurrQ9LzhytCPbZ37d8C13xN7NEAh/keg1tItq vNwkEOOAgcr5L0ETSlP9gu+CAKt9Mo5ORYdhiH8fx29JSqPpXlAZrWm6e5V8tSEi5Qgz g1l8IMuJ0JR3I6FQzLIPLIK17gK57v2vXfcS31C1I6q5z23u0ewCIjxZ9jjk9HQwR5Ft cw/dEfDcBCnJqiEdOudwyVUy+auR4rv6EV27I4gDvEle+aopMAx8nrggxreDtBh49S5t adRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Bhp31+gudmlwg+zaYhJQUzqDMK6jOnkH5ePQRjecVa8=; b=A9ZZiAK1mF8E+p5FBygo+fJNWmzy0SRVQ9/D9+dRo1WWTEFrz1Qa8LfzPoPm4WYBDp RJPn6FcrWdLJJGLNfNfKChQria2x9mIT1HqnXNniK4GO+MCF4POBaaSjIF1p3JxrasMx O95iJ3ifInqaF/366J2aDIJLTEcwUfIaEh3RrWWEiohNgvexcVjnsUGoALdnwtj/ln5/ pmvsebyzu8J5OwettvNsODVrAobxQEWvMunP8kPnxpsXARl1APB1Yi42OBjVaZtJ10t6 WVEXqRLKnAeCFl4iEEhoL3L2TfQghO3O9sjzuqk+t+9Uq/VrQjd27rK6s3jyLCwWBvoK 3BEg== X-Gm-Message-State: ABUngvdv/l7rleP9Yuh0soKol7IT8mTOfvxZA5HLwk6bubTllaK+EMPHHcNfje23XxgNOg== X-Received: by 10.98.150.137 with SMTP id s9mr31817130pfk.135.1477728877940; Sat, 29 Oct 2016 01:14:37 -0700 (PDT) Received: from localhost ([45.34.23.101]) by smtp.gmail.com with ESMTPSA id fm6sm23541680pab.37.2016.10.29.01.14.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 29 Oct 2016 01:14:37 -0700 (PDT) From: Ming Lei To: Jens Axboe , linux-kernel@vger.kernel.org Cc: linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org, Christoph Hellwig , "Kirill A . Shutemov" , Ming Lei , Jens Axboe , Mike Christie , Hannes Reinecke , Keith Busch , Mike Snitzer Subject: [PATCH 34/60] block: introduce bio_clone_sp() Date: Sat, 29 Oct 2016 16:08:33 +0800 Message-Id: <1477728600-12938-35-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1477728600-12938-1-git-send-email-tom.leiming@gmail.com> References: <1477728600-12938-1-git-send-email-tom.leiming@gmail.com> Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Firstly bio_clone() and bio_clone_bioset() are changed to clone mp bvecs because our iterator helpers are capable of splitting mp bvecs into sp bvecs. But sometimes we still need cloned bio with singlepage bvecs, for example, in bio bounce/bcache(bch_data_verify), bvecs of cloned bio need to be updated. Signed-off-by: Ming Lei --- block/bio.c | 27 +++++++++++++++++++++------ include/linux/bio.h | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/block/bio.c b/block/bio.c index a49d1d89a85c..a9bf01784f37 100644 --- a/block/bio.c +++ b/block/bio.c @@ -626,16 +626,22 @@ EXPORT_SYMBOL(bio_clone_fast); * @bio_src: bio to clone * @gfp_mask: allocation priority * @bs: bio_set to allocate from + * @sp_bvecs: if clone to singlepage bvecs. * * Clone bio. Caller will own the returned bio, but not the actual data it * points to. Reference count of returned bio will be one. + * + * If @sp_bvecs is true, the caller must make sure number of singlepage + * bvecs is less than maximum bvec count. + * */ -struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, - struct bio_set *bs) +struct bio *__bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, + struct bio_set *bs, bool sp_bvecs) { struct bvec_iter iter; struct bio_vec bv; struct bio *bio; + unsigned segs; /* * Pre immutable biovecs, __bio_clone() used to just do a memcpy from @@ -659,7 +665,12 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, * __bio_clone_fast() anyways. */ - bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); + if (sp_bvecs) + segs = bio_segments(bio_src); + else + segs = bio_segments_mp(bio_src); + + bio = bio_alloc_bioset(gfp_mask, segs, bs); if (!bio) return NULL; bio->bi_bdev = bio_src->bi_bdev; @@ -675,8 +686,12 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; break; default: - bio_for_each_segment(bv, bio_src, iter) - bio->bi_io_vec[bio->bi_vcnt++] = bv; + if (sp_bvecs) + bio_for_each_segment(bv, bio_src, iter) + bio->bi_io_vec[bio->bi_vcnt++] = bv; + else + bio_for_each_segment_mp(bv, bio_src, iter) + bio->bi_io_vec[bio->bi_vcnt++] = bv; break; } @@ -694,7 +709,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, return bio; } -EXPORT_SYMBOL(bio_clone_bioset); +EXPORT_SYMBOL(__bio_clone_bioset); /** * bio_add_pc_page - attempt to add page to bio diff --git a/include/linux/bio.h b/include/linux/bio.h index 17852ba0e40f..ec1c0f2aaa19 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -217,7 +217,7 @@ static inline void bio_advance_iter_mp(struct bio *bio, struct bvec_iter *iter, #define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len) -static inline unsigned bio_segments(struct bio *bio) +static inline unsigned __bio_segments(struct bio *bio, bool mp) { unsigned segs = 0; struct bio_vec bv; @@ -237,12 +237,26 @@ static inline unsigned bio_segments(struct bio *bio) if (bio_op(bio) == REQ_OP_WRITE_SAME) return 1; - bio_for_each_segment(bv, bio, iter) - segs++; + if (!mp) + bio_for_each_segment(bv, bio, iter) + segs++; + else + bio_for_each_segment_mp(bv, bio, iter) + segs++; return segs; } +static inline unsigned bio_segments(struct bio *bio) +{ + return __bio_segments(bio, false); +} + +static inline unsigned bio_segments_mp(struct bio *bio) +{ + return __bio_segments(bio, true); +} + /* * get a reference to a bio, so it won't disappear. the intended use is * something like: @@ -415,10 +429,24 @@ extern void bio_put(struct bio *); extern void __bio_clone_fast(struct bio *, struct bio *); extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *); -extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); +extern struct bio *__bio_clone_bioset(struct bio *, gfp_t, + struct bio_set *bs, bool); extern struct bio_set *fs_bio_set; +/* at default we clone bio with multipage bvecs */ +static inline struct bio *bio_clone_bioset(struct bio *bio, gfp_t gfp, + struct bio_set *bs) +{ + return __bio_clone_bioset(bio, gfp, bs, false); +} + +static inline struct bio *bio_clone_bioset_sp(struct bio *bio, gfp_t gfp, + struct bio_set *bs) +{ + return __bio_clone_bioset(bio, gfp, bs, true); +} + static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs) { return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); @@ -429,6 +457,12 @@ static inline struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) return bio_clone_bioset(bio, gfp_mask, fs_bio_set); } +/* Sometimes we have to clone one bio with singlepage bvec */ +static inline struct bio *bio_clone_sp(struct bio *bio, gfp_t gfp_mask) +{ + return __bio_clone_bioset(bio, gfp_mask, fs_bio_set, true); +} + static inline struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs) { return bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);