Commit 725130ba authored by Liu Bo's avatar Liu Bo Committed by David Sterba

Btrfs: use bio_clone_bioset_partial to simplify DIO submit

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: default avatarLiu Bo <bo.li.liu@oracle.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 2f8e9140
...@@ -8380,16 +8380,6 @@ static void btrfs_end_dio_bio(struct bio *bio) ...@@ -8380,16 +8380,6 @@ static void btrfs_end_dio_bio(struct bio *bio)
bio_put(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, static inline int btrfs_lookup_and_bind_dio_csum(struct inode *inode,
struct btrfs_dio_private *dip, struct btrfs_dio_private *dip,
struct bio *bio, struct bio *bio,
...@@ -8479,24 +8469,23 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, ...@@ -8479,24 +8469,23 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct bio *bio; struct bio *bio;
struct bio *orig_bio = dip->orig_bio; struct bio *orig_bio = dip->orig_bio;
struct bio_vec *bvec;
u64 start_sector = orig_bio->bi_iter.bi_sector; u64 start_sector = orig_bio->bi_iter.bi_sector;
u64 file_offset = dip->logical_offset; u64 file_offset = dip->logical_offset;
u64 submit_len = 0;
u64 map_length; u64 map_length;
u32 blocksize = fs_info->sectorsize;
int async_submit = 0; int async_submit = 0;
int nr_sectors; u64 submit_len;
int clone_offset = 0;
int clone_len;
int ret; int ret;
int i, j;
map_length = orig_bio->bi_iter.bi_size; map_length = orig_bio->bi_iter.bi_size;
submit_len = map_length;
ret = btrfs_map_block(fs_info, btrfs_op(orig_bio), start_sector << 9, ret = btrfs_map_block(fs_info, btrfs_op(orig_bio), start_sector << 9,
&map_length, NULL, 0); &map_length, NULL, 0);
if (ret) if (ret)
return -EIO; return -EIO;
if (map_length >= orig_bio->bi_iter.bi_size) { if (map_length >= submit_len) {
bio = orig_bio; bio = orig_bio;
dip->flags |= BTRFS_DIO_ORIG_BIO_SUBMITTED; dip->flags |= BTRFS_DIO_ORIG_BIO_SUBMITTED;
goto submit; goto submit;
...@@ -8508,70 +8497,52 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, ...@@ -8508,70 +8497,52 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
else else
async_submit = 1; async_submit = 1;
bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); /* bio split */
if (!bio) ASSERT(map_length <= INT_MAX);
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;
atomic_inc(&dip->pending_bios); atomic_inc(&dip->pending_bios);
while (submit_len > 0) {
clone_len = min_t(int, submit_len, map_length);
bio_for_each_segment_all(bvec, orig_bio, j) { /*
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len); * This will never fail as it's passing GPF_NOFS and
i = 0; * the allocation is backed by btrfs_bioset.
next_block: */
if (unlikely(map_length < submit_len + blocksize || bio = btrfs_bio_clone_partial(orig_bio, GFP_NOFS, clone_offset,
bio_add_page(bio, bvec->bv_page, blocksize, clone_len);
bvec->bv_offset + (i * blocksize)) < blocksize)) { bio->bi_private = dip;
/* bio->bi_end_io = btrfs_end_dio_bio;
* inc the count before we submit the bio so btrfs_io_bio(bio)->logical = file_offset;
* we know the end IO handler won't happen before
* we inc the count. Otherwise, the dip might get freed ASSERT(submit_len >= clone_len);
* before we're done setting it up submit_len -= clone_len;
*/ if (submit_len == 0)
atomic_inc(&dip->pending_bios); break;
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, ret = __btrfs_submit_dio_bio(bio, inode, file_offset, skip_sum,
start_sector, GFP_NOFS); async_submit);
if (!bio) if (ret) {
goto out_err; bio_put(bio);
bio->bi_opf = orig_bio->bi_opf; atomic_dec(&dip->pending_bios);
bio->bi_private = dip; goto out_err;
bio->bi_end_io = btrfs_end_dio_bio; }
btrfs_io_bio(bio)->logical = file_offset;
map_length = orig_bio->bi_iter.bi_size; clone_offset += clone_len;
ret = btrfs_map_block(fs_info, btrfs_op(orig_bio), start_sector += clone_len >> 9;
start_sector << 9, file_offset += clone_len;
&map_length, NULL, 0);
if (ret) {
bio_put(bio);
goto out_err;
}
goto next_block; map_length = submit_len;
} else { ret = btrfs_map_block(fs_info, btrfs_op(orig_bio),
submit_len += blocksize; start_sector << 9, &map_length, NULL, 0);
if (--nr_sectors) { if (ret)
i++; goto out_err;
goto next_block;
}
}
} }
submit: submit:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment