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 <[email protected]> > > Signed-off-by: Miao Xie <[email protected]> > --- > 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 [email protected] > 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 [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
