From: Liu Bo <bo.li.liu@oracle.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 2/6] Btrfs: use bio_clone_bioset_partial to simplify DIO submit
Date: Mon, 17 Apr 2017 18:16:23 -0700 [thread overview]
Message-ID: <1492478187-24875-3-git-send-email-bo.li.liu@oracle.com> (raw)
In-Reply-To: <1492478187-24875-1-git-send-email-bo.li.liu@oracle.com>
Currently when mapping bio to limit bio to a single stripe length, we
split bio by adding page to bio one by one, but later we don't modify
the vector of bio at all, thus we can use bio_clone_fast to use the
original bio vector directly.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
---
fs/btrfs/extent_io.c | 15 +++++++
fs/btrfs/extent_io.h | 1 +
fs/btrfs/inode.c | 122 +++++++++++++++++++--------------------------------
3 files changed, 62 insertions(+), 76 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 0d4aea4..1b7156c 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2726,6 +2726,21 @@ struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
return bio;
}
+struct bio *btrfs_bio_clone_partial(struct bio *orig, gfp_t gfp_mask, int offset, int size)
+{
+ struct bio *bio;
+
+ bio = bio_clone_fast(orig, gfp_mask, btrfs_bioset);
+ if (bio) {
+ struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
+ btrfs_bio->csum = NULL;
+ btrfs_bio->csum_allocated = NULL;
+ btrfs_bio->end_io = NULL;
+
+ bio_trim(bio, (offset >> 9), (size >> 9));
+ }
+ return bio;
+}
static int __must_check submit_one_bio(struct bio *bio, int mirror_num,
unsigned long bio_flags)
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 3e4fad4..3b2bc88 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -460,6 +460,7 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
gfp_t gfp_flags);
struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs);
struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask);
+struct bio *btrfs_bio_clone_partial(struct bio *orig, gfp_t gfp_mask, int offset, int size);
struct btrfs_fs_info;
struct btrfs_inode;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a18510b..6215720 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8230,16 +8230,6 @@ static void btrfs_end_dio_bio(struct bio *bio)
bio_put(bio);
}
-static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
- u64 first_sector, gfp_t gfp_flags)
-{
- struct bio *bio;
- bio = btrfs_bio_alloc(bdev, first_sector, BIO_MAX_PAGES, gfp_flags);
- if (bio)
- bio_associate_current(bio);
- return bio;
-}
-
static inline int btrfs_lookup_and_bind_dio_csum(struct inode *inode,
struct btrfs_dio_private *dip,
struct bio *bio,
@@ -8329,24 +8319,22 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
struct btrfs_root *root = BTRFS_I(inode)->root;
struct bio *bio;
struct bio *orig_bio = dip->orig_bio;
- struct bio_vec *bvec;
u64 start_sector = orig_bio->bi_iter.bi_sector;
u64 file_offset = dip->logical_offset;
- u64 submit_len = 0;
u64 map_length;
- u32 blocksize = fs_info->sectorsize;
int async_submit = 0;
- int nr_sectors;
+ int submit_len;
+ int clone_offset = 0;
+ int clone_len;
int ret;
- int i, j;
- map_length = orig_bio->bi_iter.bi_size;
+ submit_len = map_length = orig_bio->bi_iter.bi_size;
ret = btrfs_map_block(fs_info, btrfs_op(orig_bio), start_sector << 9,
&map_length, NULL, 0);
if (ret)
return -EIO;
- if (map_length >= orig_bio->bi_iter.bi_size) {
+ if (map_length >= submit_len) {
bio = orig_bio;
dip->flags |= BTRFS_DIO_ORIG_BIO_SUBMITTED;
goto submit;
@@ -8358,70 +8346,52 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
else
async_submit = 1;
- bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
- if (!bio)
- return -ENOMEM;
-
- bio->bi_opf = orig_bio->bi_opf;
- bio->bi_private = dip;
- bio->bi_end_io = btrfs_end_dio_bio;
- btrfs_io_bio(bio)->logical = file_offset;
+ /* bio split */
atomic_inc(&dip->pending_bios);
+ while (submit_len > 0) {
+ /* map_length < submit_len, it's a int */
+ clone_len = min(submit_len, (int)map_length);
+ bio = btrfs_bio_clone_partial(orig_bio, GFP_NOFS, clone_offset, clone_len);
+ if (!bio)
+ goto out_err;
+ /* the above clone call also clone blkcg of orig_bio */
+
+ bio->bi_private = dip;
+ bio->bi_end_io = btrfs_end_dio_bio;
+ btrfs_io_bio(bio)->logical = file_offset;
+
+ ASSERT(submit_len >= clone_len);
+ submit_len -= clone_len;
+ if (submit_len == 0)
+ break;
- bio_for_each_segment_all(bvec, orig_bio, j) {
- nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len);
- i = 0;
-next_block:
- if (unlikely(map_length < submit_len + blocksize ||
- bio_add_page(bio, bvec->bv_page, blocksize,
- bvec->bv_offset + (i * blocksize)) < blocksize)) {
- /*
- * inc the count before we submit the bio so
- * we know the end IO handler won't happen before
- * we inc the count. Otherwise, the dip might get freed
- * before we're done setting it up
- */
- atomic_inc(&dip->pending_bios);
- ret = __btrfs_submit_dio_bio(bio, inode,
- file_offset, skip_sum,
- async_submit);
- if (ret) {
- bio_put(bio);
- atomic_dec(&dip->pending_bios);
- goto out_err;
- }
-
- start_sector += submit_len >> 9;
- file_offset += submit_len;
-
- submit_len = 0;
+ /*
+ * increase the count before we submit the bio so we know the
+ * end IO handler won't happen before we increase the
+ * count. Otherwise, the dip might get freed before we're done
+ * setting it up.
+ */
+ atomic_inc(&dip->pending_bios);
- bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev,
- start_sector, GFP_NOFS);
- if (!bio)
- goto out_err;
- bio->bi_opf = orig_bio->bi_opf;
- bio->bi_private = dip;
- bio->bi_end_io = btrfs_end_dio_bio;
- btrfs_io_bio(bio)->logical = file_offset;
+ ret = __btrfs_submit_dio_bio(bio, inode,
+ file_offset, skip_sum,
+ async_submit);
+ if (ret) {
+ bio_put(bio);
+ atomic_dec(&dip->pending_bios);
+ goto out_err;
+ }
- map_length = orig_bio->bi_iter.bi_size;
- ret = btrfs_map_block(fs_info, btrfs_op(orig_bio),
- start_sector << 9,
- &map_length, NULL, 0);
- if (ret) {
- bio_put(bio);
- goto out_err;
- }
+ clone_offset += clone_len;
+ start_sector += clone_len >> 9;
+ file_offset += clone_len;
- goto next_block;
- } else {
- submit_len += blocksize;
- if (--nr_sectors) {
- i++;
- goto next_block;
- }
- }
+ map_length = submit_len;
+ ret = btrfs_map_block(fs_info, btrfs_op(orig_bio),
+ (start_sector << 9),
+ &map_length, NULL, 0);
+ if (ret)
+ goto out_err;
}
submit:
--
2.5.5
next prev parent reply other threads:[~2017-04-18 1:17 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-18 1:16 [PATCH 0/6 RFC] utilize bio_clone_fast to clean up Liu Bo
2017-04-18 1:16 ` [PATCH 1/6] Btrfs: use bio_clone_fast to clone our bio Liu Bo
2017-05-17 17:53 ` David Sterba
2017-04-18 1:16 ` Liu Bo [this message]
2017-05-11 14:16 ` [PATCH 2/6] Btrfs: use bio_clone_bioset_partial to simplify DIO submit David Sterba
2017-05-16 14:37 ` Christoph Hellwig
2017-05-16 17:15 ` Liu Bo
2017-04-18 1:16 ` [PATCH 3/6] Btrfs: change how we iterate bios in endio Liu Bo
2017-04-18 1:16 ` [PATCH 4/6] Btrfs: record error if one block has failed to retry Liu Bo
2017-05-17 18:32 ` David Sterba
2017-04-18 1:16 ` [PATCH 5/6] Btrfs: change check-integrity to use bvec_iter Liu Bo
2017-05-05 17:13 ` David Sterba
2017-04-18 1:16 ` [PATCH 6/6] Btrfs: unify naming of btrfs_io_bio Liu Bo
2017-05-17 18:32 ` David Sterba
2017-05-05 14:24 ` [PATCH 0/6 RFC] utilize bio_clone_fast to clean up David Sterba
2017-05-09 22:49 ` Liu Bo
2017-05-10 4:28 ` Liu Bo
2017-05-10 17:53 ` David Sterba
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1492478187-24875-3-git-send-email-bo.li.liu@oracle.com \
--to=bo.li.liu@oracle.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).