diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-09-12 18:43:54 +0800 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-09-17 13:38:50 -0700 |
commit | 23ea8e5a07673127d05cb5cf6f9914d7a53e0847 (patch) | |
tree | 58199f4b68c72a1a6c4d0be4cf6ab917ecdcb070 /fs/btrfs/inode.c | |
parent | c3929c3624e1764855e5a452728aec201b18b42a (diff) | |
download | op-kernel-dev-23ea8e5a07673127d05cb5cf6f9914d7a53e0847.zip op-kernel-dev-23ea8e5a07673127d05cb5cf6f9914d7a53e0847.tar.gz |
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: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 75c6de2..fca9442 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7240,7 +7240,8 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) struct inode *inode = dip->inode; struct btrfs_root *root = BTRFS_I(inode)->root; 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; int i; @@ -7282,6 +7283,9 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) if (err) clear_bit(BIO_UPTODATE, &dio_bio->bi_flags); dio_end_io(dio_bio, err); + + if (io_bio->end_io) + io_bio->end_io(io_bio, err); bio_put(bio); } @@ -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); if (ret) goto err; - } else if (!skip_sum) { - ret = btrfs_lookup_bio_sums_dio(root, inode, dip, bio, + } else { + /* + * 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); if (ret) goto err; } - map: ret = btrfs_map_bio(root, rw, bio, 0, async_submit); err: @@ -7448,7 +7459,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, u64 submit_len = 0; u64 map_length; int nr_pages = 0; - int ret = 0; + int ret; int async_submit = 0; map_length = orig_bio->bi_iter.bi_size; @@ -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_dio_private *dip; struct bio *io_bio; + struct btrfs_io_bio *btrfs_bio; int skip_sum; - int sum_len; int write = rw & REQ_WRITE; int ret = 0; - u16 csum_size; skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; @@ -7566,16 +7576,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, goto free_ordered; } - if (!skip_sum && !write) { - 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); + dip = kmalloc(sizeof(*dip), GFP_NOFS); if (!dip) { ret = -ENOMEM; goto free_io_bio; @@ -7601,6 +7602,9 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, if (!ret) return; + btrfs_bio = btrfs_io_bio(io_bio); + if (btrfs_bio->end_io) + btrfs_bio->end_io(btrfs_bio, ret); free_io_bio: bio_put(io_bio); |