Re: [PATCH 2/4] Btrfs: improve the performance of the csums lookup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 28, 2013 at 04:10:41PM +0800, Miao Xie wrote:
> It is very likely that there are several blocks in bio, it is very
> inefficient if we get their csums one by one. This patch improves
> this problem by getting the csums in batch.
> 
> According to the result of the following test, the execute time of
> __btrfs_lookup_bio_sums() is down by ~28%(300us -> 217us).
> 
>  # dd if=<mnt>/file of=/dev/null bs=1M count=1024

Looks good to me.

Reviewed-by: Liu Bo <bo.li.liu@xxxxxxxxxx>

> 
> Signed-off-by: Miao Xie <miaox@xxxxxxxxxxxxxx>
> ---
>  fs/btrfs/extent_io.c    | 31 +++++++++++++++++++++++++++++++
>  fs/btrfs/extent_io.h    |  2 ++
>  fs/btrfs/file-item.c    | 45 ++++++++++++++++++++++++++-------------------
>  fs/btrfs/ordered-data.c | 24 ++++++++++++++----------
>  fs/btrfs/ordered-data.h |  3 ++-
>  5 files changed, 75 insertions(+), 30 deletions(-)
> 
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index f173c5a..3da8da5 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -1744,6 +1744,37 @@ out:
>  	return ret;
>  }
>  
> +void cache_csums(struct extent_io_tree *tree, u64 start, u32 csums[],
> +		 int count, int sectorsize)
> +{
> +	struct rb_node *node;
> +	struct extent_state *state, *next;
> +
> +	spin_lock(&tree->lock);
> +	/*
> +	 * this search will find all the extents that end after
> +	 * our range starts.
> +	 */
> +	node = tree_search(tree, start);
> +	BUG_ON(!node);
> +
> +	state = rb_entry(node, struct extent_state, rb_node);
> +	BUG_ON(state->start != start);
> +
> +	while (count) {
> +		BUG_ON(state->end + 1 - state->start != sectorsize);
> +
> +		state->private = *csums++;
> +		count--;
> +		next = next_state(state);
> +
> +		BUG_ON(count && (!next || next->start != state->end + 1));
> +
> +		state = next;
> +	}
> +	spin_unlock(&tree->lock);
> +}
> +
>  int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private)
>  {
>  	struct rb_node *node;
> diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
> index 6068a19..b95fb6a 100644
> --- a/fs/btrfs/extent_io.h
> +++ b/fs/btrfs/extent_io.h
> @@ -261,6 +261,8 @@ int extent_readpages(struct extent_io_tree *tree,
>  int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
>  		__u64 start, __u64 len, get_extent_t *get_extent);
>  int set_state_private(struct extent_io_tree *tree, u64 start, u64 private);
> +void cache_csums(struct extent_io_tree *tree, u64 start, u32 csums[],
> +		 int count, int sectorsize);
>  int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private);
>  void set_page_extent_mapped(struct page *page);
>  
> diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
> index b7e529d..3e2f080 100644
> --- a/fs/btrfs/file-item.c
> +++ b/fs/btrfs/file-item.c
> @@ -175,7 +175,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
>  				   struct inode *inode, struct bio *bio,
>  				   u64 logical_offset, u32 *dst, int dio)
>  {
> -	u32 sum;
> +	u32 sum[16];
> +	int len;
>  	struct bio_vec *bvec = bio->bi_io_vec;
>  	int bio_index = 0;
>  	u64 offset = 0;
> @@ -184,7 +185,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
>  	u64 disk_bytenr;
>  	u32 diff;
>  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
> -	int ret;
> +	int count;
> +	int index;
>  	struct btrfs_path *path;
>  	struct btrfs_csum_item *item = NULL;
>  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
> @@ -212,10 +214,11 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
>  	if (dio)
>  		offset = logical_offset;
>  	while (bio_index < bio->bi_vcnt) {
> +		len = min_t(int, ARRAY_SIZE(sum), bio->bi_vcnt - bio_index);
>  		if (!dio)
>  			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
> -		ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum);
> -		if (ret == 0)
> +		count = btrfs_find_ordered_sum(inode, offset, disk_bytenr, sum, len);
> +		if (count)
>  			goto found;
>  
>  		if (!item || disk_bytenr < item_start_offset ||
> @@ -228,10 +231,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
>  			item = btrfs_lookup_csum(NULL, root->fs_info->csum_root,
>  						 path, disk_bytenr, 0);
>  			if (IS_ERR(item)) {
> -				ret = PTR_ERR(item);
> -				if (ret == -ENOENT || ret == -EFBIG)
> -					ret = 0;
> -				sum = 0;
> +				count = 1;
> +				sum[0] = 0;
>  				if (BTRFS_I(inode)->root->root_key.objectid ==
>  				    BTRFS_DATA_RELOC_TREE_OBJECTID) {
>  					set_extent_bits(io_tree, offset,
> @@ -267,19 +268,25 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
>  		diff = disk_bytenr - item_start_offset;
>  		diff = diff / root->sectorsize;
>  		diff = diff * csum_size;
> -
> -		read_extent_buffer(path->nodes[0], &sum,
> +		count = min_t(int, len, (item_last_offset - disk_bytenr) /
> +					root->sectorsize);
> +		read_extent_buffer(path->nodes[0], sum,
>  				   ((unsigned long)item) + diff,
> -				   csum_size);
> +				   csum_size * count);
>  found:
> -		if (dst)
> -			*dst++ = sum;
> -		else
> -			set_state_private(io_tree, offset, sum);
> -		disk_bytenr += bvec->bv_len;
> -		offset += bvec->bv_len;
> -		bio_index++;
> -		bvec++;
> +		if (dst) {
> +			for (index = 0; index < count; index++)
> +				*dst++ = sum[index];
> +		} else {
> +			cache_csums(io_tree, offset, sum, count,
> +				    root->sectorsize);
> +		}
> +		while (count--) {
> +			disk_bytenr += bvec->bv_len;
> +			offset += bvec->bv_len;
> +			bio_index++;
> +			bvec++;
> +		}
>  	}
>  	btrfs_free_path(path);
>  	return 0;
> diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
> index dc08d77..2b959b6 100644
> --- a/fs/btrfs/ordered-data.c
> +++ b/fs/btrfs/ordered-data.c
> @@ -984,7 +984,7 @@ out:
>   * be reclaimed before their checksum is actually put into the btree
>   */
>  int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
> -			   u32 *sum)
> +			   u32 *sum, int len)
>  {
>  	struct btrfs_ordered_sum *ordered_sum;
>  	struct btrfs_sector_sum *sector_sums;
> @@ -993,22 +993,26 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
>  	unsigned long num_sectors;
>  	unsigned long i;
>  	u32 sectorsize = BTRFS_I(inode)->root->sectorsize;
> -	int ret = 1;
> +	int index = 0;
>  
>  	ordered = btrfs_lookup_ordered_extent(inode, offset);
>  	if (!ordered)
> -		return 1;
> +		return 0;
>  
>  	spin_lock_irq(&tree->lock);
>  	list_for_each_entry_reverse(ordered_sum, &ordered->list, list) {
> -		if (disk_bytenr >= ordered_sum->bytenr) {
> +		if (disk_bytenr >= ordered_sum->bytenr &&
> +		    disk_bytenr < ordered_sum->bytenr + ordered_sum->len) {
> +			i = (disk_bytenr - ordered_sum->bytenr) / sectorsize;
> +			sector_sums = ordered_sum->sums + i;
>  			num_sectors = ordered_sum->len / sectorsize;
> -			sector_sums = ordered_sum->sums;
> -			for (i = 0; i < num_sectors; i++) {
> +			for (; i < num_sectors; i++) {
>  				if (sector_sums[i].bytenr == disk_bytenr) {
> -					*sum = sector_sums[i].sum;
> -					ret = 0;
> -					goto out;
> +					sum[index] = sector_sums[i].sum;
> +					index++;
> +					if (index == len)
> +						goto out;
> +					disk_bytenr += sectorsize;
>  				}
>  			}
>  		}
> @@ -1016,7 +1020,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
>  out:
>  	spin_unlock_irq(&tree->lock);
>  	btrfs_put_ordered_extent(ordered);
> -	return ret;
> +	return index;
>  }
>  
>  
> diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
> index 8eadfe4..58b0e3b 100644
> --- a/fs/btrfs/ordered-data.h
> +++ b/fs/btrfs/ordered-data.h
> @@ -196,7 +196,8 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(struct inode *inode,
>  							u64 len);
>  int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
>  				struct btrfs_ordered_extent *ordered);
> -int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum);
> +int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
> +			   u32 *sum, int len);
>  int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans,
>  				 struct btrfs_root *root, int wait);
>  void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
> -- 
> 1.8.0.1
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux