Commit 23ea8e5a authored by Miao Xie's avatar Miao Xie Committed by Chris Mason

Btrfs: load checksum data once when submitting a direct read io

The current code would load checksum data for several times when we split
a whole direct read io because of the limit of the raid stripe, it would
make us search the csum tree for several times. In fact, it just wasted time,
and made the contention of the csum tree root be more serious. This patch
improves this problem by loading the data at once.
Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent c3929c36
...@@ -263,7 +263,6 @@ struct btrfs_dio_private { ...@@ -263,7 +263,6 @@ struct btrfs_dio_private {
/* dio_bio came from fs/direct-io.c */ /* dio_bio came from fs/direct-io.c */
struct bio *dio_bio; struct bio *dio_bio;
u8 csum[0];
}; };
/* /*
......
...@@ -3719,8 +3719,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, ...@@ -3719,8 +3719,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
struct bio *bio, u32 *dst); struct bio *bio, u32 *dst);
int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
struct btrfs_dio_private *dip, struct bio *bio, struct bio *bio, u64 logical_offset);
u64 logical_offset);
int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 objectid, u64 pos, u64 objectid, u64 pos,
......
...@@ -2621,9 +2621,18 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs, ...@@ -2621,9 +2621,18 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask) struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
{ {
return bio_clone_bioset(bio, gfp_mask, btrfs_bioset); struct btrfs_io_bio *btrfs_bio;
} struct bio *new;
new = bio_clone_bioset(bio, gfp_mask, btrfs_bioset);
if (new) {
btrfs_bio = btrfs_io_bio(new);
btrfs_bio->csum = NULL;
btrfs_bio->csum_allocated = NULL;
btrfs_bio->end_io = NULL;
}
return new;
}
/* this also allocates from the btrfs_bioset */ /* this also allocates from the btrfs_bioset */
struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs) struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
......
...@@ -299,19 +299,9 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, ...@@ -299,19 +299,9 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
} }
int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
struct btrfs_dio_private *dip, struct bio *bio, struct bio *bio, u64 offset)
u64 offset)
{ {
int len = (bio->bi_iter.bi_sector << 9) - dip->disk_bytenr; return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1);
u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
int ret;
len >>= inode->i_sb->s_blocksize_bits;
len *= csum_size;
ret = __btrfs_lookup_bio_sums(root, inode, bio, offset,
(u32 *)(dip->csum + len), 1);
return ret;
} }
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
......
...@@ -7240,7 +7240,8 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) ...@@ -7240,7 +7240,8 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
struct inode *inode = dip->inode; struct inode *inode = dip->inode;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct bio *dio_bio; struct bio *dio_bio;
u32 *csums = (u32 *)dip->csum; struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
u32 *csums = (u32 *)io_bio->csum;
u64 start; u64 start;
int i; int i;
...@@ -7282,6 +7283,9 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) ...@@ -7282,6 +7283,9 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
if (err) if (err)
clear_bit(BIO_UPTODATE, &dio_bio->bi_flags); clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
dio_end_io(dio_bio, err); dio_end_io(dio_bio, err);
if (io_bio->end_io)
io_bio->end_io(io_bio, err);
bio_put(bio); bio_put(bio);
} }
...@@ -7421,13 +7425,20 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, ...@@ -7421,13 +7425,20 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1); ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1);
if (ret) if (ret)
goto err; goto err;
} else if (!skip_sum) { } else {
ret = btrfs_lookup_bio_sums_dio(root, inode, dip, bio, /*
* We have loaded all the csum data we need when we submit
* the first bio, so skip it.
*/
if (dip->logical_offset != file_offset)
goto map;
/* Load all csum data at once. */
ret = btrfs_lookup_bio_sums_dio(root, inode, dip->orig_bio,
file_offset); file_offset);
if (ret) if (ret)
goto err; goto err;
} }
map: map:
ret = btrfs_map_bio(root, rw, bio, 0, async_submit); ret = btrfs_map_bio(root, rw, bio, 0, async_submit);
err: err:
...@@ -7448,7 +7459,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, ...@@ -7448,7 +7459,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
u64 submit_len = 0; u64 submit_len = 0;
u64 map_length; u64 map_length;
int nr_pages = 0; int nr_pages = 0;
int ret = 0; int ret;
int async_submit = 0; int async_submit = 0;
map_length = orig_bio->bi_iter.bi_size; map_length = orig_bio->bi_iter.bi_size;
...@@ -7552,11 +7563,10 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, ...@@ -7552,11 +7563,10 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio,
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_dio_private *dip; struct btrfs_dio_private *dip;
struct bio *io_bio; struct bio *io_bio;
struct btrfs_io_bio *btrfs_bio;
int skip_sum; int skip_sum;
int sum_len;
int write = rw & REQ_WRITE; int write = rw & REQ_WRITE;
int ret = 0; int ret = 0;
u16 csum_size;
skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
...@@ -7566,16 +7576,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, ...@@ -7566,16 +7576,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio,
goto free_ordered; goto free_ordered;
} }
if (!skip_sum && !write) { dip = kmalloc(sizeof(*dip), GFP_NOFS);
csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
sum_len = dio_bio->bi_iter.bi_size >>
inode->i_sb->s_blocksize_bits;
sum_len *= csum_size;
} else {
sum_len = 0;
}
dip = kmalloc(sizeof(*dip) + sum_len, GFP_NOFS);
if (!dip) { if (!dip) {
ret = -ENOMEM; ret = -ENOMEM;
goto free_io_bio; goto free_io_bio;
...@@ -7601,6 +7602,9 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, ...@@ -7601,6 +7602,9 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio,
if (!ret) if (!ret)
return; return;
btrfs_bio = btrfs_io_bio(io_bio);
if (btrfs_bio->end_io)
btrfs_bio->end_io(btrfs_bio, ret);
free_io_bio: free_io_bio:
bio_put(io_bio); bio_put(io_bio);
......
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