From patchwork Tue Dec 27 15:56:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 9489601 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 1D539601D2 for ; Tue, 27 Dec 2016 16:13:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F5C0223B2 for ; Tue, 27 Dec 2016 16:13:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0360825D99; Tue, 27 Dec 2016 16:13:00 +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.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, 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 7BDC5201BC for ; Tue, 27 Dec 2016 16:12:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755242AbcL0QM4 (ORCPT ); Tue, 27 Dec 2016 11:12:56 -0500 Received: from mail-pg0-f68.google.com ([74.125.83.68]:35886 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932926AbcL0QG3 (ORCPT ); Tue, 27 Dec 2016 11:06:29 -0500 Received: by mail-pg0-f68.google.com with SMTP id n5so12810744pgh.3; Tue, 27 Dec 2016 08:06:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fLxVEjN+yfSycV0pLfMQmOCiDeU+j/HhwjG+4acG4rI=; b=vfDFJ7uSfRzhe5ibJ/ifDfINTluZOFzshEE4J16K1dC0bDU7ttkO9X8vnDx96zLPWJ iCLLVi9Gb5PvcApQNXAsNr9jXSVtAzEcQAHBSSOLStZiY04qGdOrMtKhWl58bJGmAZ5h WOdGf5ZnnArjWA7beQ7qXBWwcAREwpfO6RkF9QNMBGzR4L7uAebTBYFpHgRQ7CkutmV3 8S8xKJziq1/9SR3BqEqWMabslcbwMW8RrKVCAm3FxNlf6MPlP+6RaCUQGFZkK1c78N/G LdkSxaTyYax+Hsbj6ukulUpMolkmQrjIKGxLkBBaPybuVKk73WqeulsKOCi4tJ7IO2W9 xZAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fLxVEjN+yfSycV0pLfMQmOCiDeU+j/HhwjG+4acG4rI=; b=e5/8Z+kFAxmOrP2uLH7Yw9cn8NPVyaMgvassByp1md11A4Epnx4m5pnSgWija+C/Ok OV18o9yQdr13VYf6APOHW3AqefUm81qfXFZcBBflPCaYz4HnO6c7hRgvIXqn26D+oak3 SjhGiC+xLme5FCe+DAQEnP+KZPzeO4JI/5EmDG4olLsCRhzYsORX83KNJl7LTv7UARL9 0FvDshS3PkEUehnlgpu5IGGGbzxcuu9eo1EVk8XPKbZrVaCQTw+gzf2v0VesAMPvNQeg E+3jJDmW2eO5fwqf/0/iQal6/rHtXjuDqn4N9qMQkitILAFMM92K69UDVk75RU3O8pVs SfcA== X-Gm-Message-State: AIkVDXIq5YSWOdtbM1JYw4GDdZU12CxVKiOZ4rbUxLngPKAS+gk8dQJIbD998POd0NlTew== X-Received: by 10.98.93.77 with SMTP id r74mr16591760pfb.70.1482854424812; Tue, 27 Dec 2016 08:00:24 -0800 (PST) Received: from localhost ([45.35.47.137]) by smtp.gmail.com with ESMTPSA id a68sm91332079pgc.31.2016.12.27.08.00.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 27 Dec 2016 08:00:23 -0800 (PST) From: Ming Lei To: Jens Axboe , linux-kernel@vger.kernel.org Cc: linux-block@vger.kernel.org, Christoph Hellwig , Ming Lei , Jens Axboe , Mike Christie , Hannes Reinecke , Kent Overstreet , Chaitanya Kulkarni Subject: [PATCH v1 17/54] block: introduce bio_clone_sp() Date: Tue, 27 Dec 2016 23:56:06 +0800 Message-Id: <1482854250-13481-18-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1482854250-13481-1-git-send-email-tom.leiming@gmail.com> References: <1482854250-13481-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 10398969353b..a76ed8a780de 100644 --- a/block/bio.c +++ b/block/bio.c @@ -630,16 +630,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 @@ -663,7 +669,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; @@ -680,8 +691,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; } @@ -699,7 +714,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 2bd4e6f2087a..0f2859f96468 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -219,7 +219,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; @@ -241,12 +241,26 @@ static inline unsigned bio_segments(struct bio *bio) break; } - 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: @@ -419,10 +433,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); @@ -433,6 +461,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);