On Thu, Mar 28, 2013 at 04:11:38PM +0800, Miao Xie wrote:
> bytenr in btrfs_sector_sum is unnecessary, because the extents that
> btrfs_sector_sum points to are continuous,we can find out the expected
> checksums by btrfs_ordered_sum's bytenr and the offset, so we can
> remove btrfs_sector_sum's bytenr.
> 
> After removing bytenr, we don't use the while loop to get the checksums
> one by one. Now, we can get several checksum value at one time. By this
> way, the performance of write is improved by ~74% on my SSD (31MB/s -> 54MB/s)
> 
> test command:
>  # dd if=/dev/zero of=/mnt/btrfs/file0 bs=1M count=1024 oflag=sync

Looks good to me.

Reviewed-by: Liu Bo <[email protected]>

> 
> Signed-off-by: Miao Xie <[email protected]>
> ---
>  fs/btrfs/file-item.c    | 144 
> ++++++++++++++++++------------------------------
>  fs/btrfs/ordered-data.c |  21 +++----
>  fs/btrfs/ordered-data.h |  25 ++-------
>  fs/btrfs/relocation.c   |  10 ----
>  fs/btrfs/scrub.c        |  16 ++----
>  5 files changed, 72 insertions(+), 144 deletions(-)
> 
> diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
> index 3e2f080..9a447bc 100644
> --- a/fs/btrfs/file-item.c
> +++ b/fs/btrfs/file-item.c
> @@ -34,8 +34,7 @@
>  
>  #define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \
>                                  sizeof(struct btrfs_ordered_sum)) / \
> -                                sizeof(struct btrfs_sector_sum) * \
> -                                (r)->sectorsize - (r)->sectorsize)
> +                                sizeof(u32) * (r)->sectorsize)
>  
>  int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
>                            struct btrfs_root *root,
> @@ -311,7 +310,6 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 
> start, u64 end,
>       struct btrfs_path *path;
>       struct extent_buffer *leaf;
>       struct btrfs_ordered_sum *sums;
> -     struct btrfs_sector_sum *sector_sum;
>       struct btrfs_csum_item *item;
>       LIST_HEAD(tmplist);
>       unsigned long offset;
> @@ -385,34 +383,28 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, 
> u64 start, u64 end,
>                                     struct btrfs_csum_item);
>               while (start < csum_end) {
>                       size = min_t(size_t, csum_end - start,
> -                                     MAX_ORDERED_SUM_BYTES(root));
> +                                  MAX_ORDERED_SUM_BYTES(root));
>                       sums = kzalloc(btrfs_ordered_sum_size(root, size),
> -                                     GFP_NOFS);
> +                                    GFP_NOFS);
>                       if (!sums) {
>                               ret = -ENOMEM;
>                               goto fail;
>                       }
>  
> -                     sector_sum = sums->sums;
>                       sums->bytenr = start;
> -                     sums->len = size;
> +                     sums->len = (int)size;
>  
>                       offset = (start - key.offset) >>
>                               root->fs_info->sb->s_blocksize_bits;
>                       offset *= csum_size;
> +                     size >>= root->fs_info->sb->s_blocksize_bits;
>  
> -                     while (size > 0) {
> -                             read_extent_buffer(path->nodes[0],
> -                                             &sector_sum->sum,
> -                                             ((unsigned long)item) +
> -                                             offset, csum_size);
> -                             sector_sum->bytenr = start;
> -
> -                             size -= root->sectorsize;
> -                             start += root->sectorsize;
> -                             offset += csum_size;
> -                             sector_sum++;
> -                     }
> +                     read_extent_buffer(path->nodes[0],
> +                                        sums->sums,
> +                                        ((unsigned long)item) + offset,
> +                                        csum_size * size);
> +
> +                     start += root->sectorsize * size;
>                       list_add_tail(&sums->list, &tmplist);
>               }
>               path->slots[0]++;
> @@ -434,23 +426,20 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct 
> inode *inode,
>                      struct bio *bio, u64 file_start, int contig)
>  {
>       struct btrfs_ordered_sum *sums;
> -     struct btrfs_sector_sum *sector_sum;
>       struct btrfs_ordered_extent *ordered;
>       char *data;
>       struct bio_vec *bvec = bio->bi_io_vec;
>       int bio_index = 0;
> +     int index;
>       unsigned long total_bytes = 0;
>       unsigned long this_sum_bytes = 0;
>       u64 offset;
> -     u64 disk_bytenr;
>  
>       WARN_ON(bio->bi_vcnt <= 0);
>       sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS);
>       if (!sums)
>               return -ENOMEM;
>  
> -     sector_sum = sums->sums;
> -     disk_bytenr = (u64)bio->bi_sector << 9;
>       sums->len = bio->bi_size;
>       INIT_LIST_HEAD(&sums->list);
>  
> @@ -461,7 +450,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct 
> inode *inode,
>  
>       ordered = btrfs_lookup_ordered_extent(inode, offset);
>       BUG_ON(!ordered); /* Logic error */
> -     sums->bytenr = ordered->start;
> +     sums->bytenr = (u64)bio->bi_sector << 9;
> +     index = 0;
>  
>       while (bio_index < bio->bi_vcnt) {
>               if (!contig)
> @@ -480,29 +470,28 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct 
> inode *inode,
>                       sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
>                                      GFP_NOFS);
>                       BUG_ON(!sums); /* -ENOMEM */
> -                     sector_sum = sums->sums;
>                       sums->len = bytes_left;
>                       ordered = btrfs_lookup_ordered_extent(inode, offset);
>                       BUG_ON(!ordered); /* Logic error */
> -                     sums->bytenr = ordered->start;
> +                     sums->bytenr = ((u64)bio->bi_sector << 9) +
> +                                    total_bytes;
> +                     index = 0;
>               }
>  
>               data = kmap_atomic(bvec->bv_page);
> -             sector_sum->sum = ~(u32)0;
> -             sector_sum->sum = btrfs_csum_data(root,
> -                                               data + bvec->bv_offset,
> -                                               sector_sum->sum,
> -                                               bvec->bv_len);
> +             sums->sums[index] = ~(u32)0;
> +             sums->sums[index] = btrfs_csum_data(root,
> +                                                 data + bvec->bv_offset,
> +                                                 sums->sums[index],
> +                                                 bvec->bv_len);
>               kunmap_atomic(data);
> -             btrfs_csum_final(sector_sum->sum,
> -                              (char *)&sector_sum->sum);
> -             sector_sum->bytenr = disk_bytenr;
> +             btrfs_csum_final(sums->sums[index],
> +                              (char *)(sums->sums + index));
>  
> -             sector_sum++;
>               bio_index++;
> +             index++;
>               total_bytes += bvec->bv_len;
>               this_sum_bytes += bvec->bv_len;
> -             disk_bytenr += bvec->bv_len;
>               offset += bvec->bv_len;
>               bvec++;
>       }
> @@ -691,63 +680,42 @@ out:
>       return ret;
>  }
>  
> -static u64 btrfs_sector_sum_left(struct btrfs_ordered_sum *sums,
> -                              struct btrfs_sector_sum *sector_sum,
> -                              u64 total_bytes, u64 sectorsize)
> -{
> -     u64 tmp = sectorsize;
> -     u64 next_sector = sector_sum->bytenr;
> -     struct btrfs_sector_sum *next = sector_sum + 1;
> -
> -     while ((tmp + total_bytes) < sums->len) {
> -             if (next_sector + sectorsize != next->bytenr)
> -                     break;
> -             tmp += sectorsize;
> -             next_sector = next->bytenr;
> -             next++;
> -     }
> -     return tmp;
> -}
> -
>  int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
>                          struct btrfs_root *root,
>                          struct btrfs_ordered_sum *sums)
>  {
> -     u64 bytenr;
> -     int ret;
>       struct btrfs_key file_key;
>       struct btrfs_key found_key;
> -     u64 next_offset;
> -     u64 total_bytes = 0;
> -     int found_next;
>       struct btrfs_path *path;
>       struct btrfs_csum_item *item;
>       struct btrfs_csum_item *item_end;
>       struct extent_buffer *leaf = NULL;
> +     u64 next_offset;
> +     u64 total_bytes = 0;
>       u64 csum_offset;
> -     struct btrfs_sector_sum *sector_sum;
> +     u64 bytenr;
>       u32 nritems;
>       u32 ins_size;
> +     int index = 0;
> +     int found_next;
> +     int ret;
>       u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
>  
>       path = btrfs_alloc_path();
>       if (!path)
>               return -ENOMEM;
> -
> -     sector_sum = sums->sums;
>  again:
>       next_offset = (u64)-1;
>       found_next = 0;
> +     bytenr = sums->bytenr + total_bytes;
>       file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
> -     file_key.offset = sector_sum->bytenr;
> -     bytenr = sector_sum->bytenr;
> +     file_key.offset = bytenr;
>       btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
>  
> -     item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1);
> +     item = btrfs_lookup_csum(trans, root, path, bytenr, 1);
>       if (!IS_ERR(item)) {
> -             leaf = path->nodes[0];
> -             ret = 0;
> -             goto found;
> +             csum_offset = 0;
> +             goto csum;
>       }
>       ret = PTR_ERR(item);
>       if (ret != -EFBIG && ret != -ENOENT)
> @@ -826,8 +794,7 @@ again:
>  
>               free_space = btrfs_leaf_free_space(root, leaf) -
>                                        sizeof(struct btrfs_item) - csum_size;
> -             tmp = btrfs_sector_sum_left(sums, sector_sum, total_bytes,
> -                                         root->sectorsize);
> +             tmp = sums->len - total_bytes;
>               tmp >>= root->fs_info->sb->s_blocksize_bits;
>               WARN_ON(tmp < 1);
>  
> @@ -850,8 +817,7 @@ insert:
>       if (found_next) {
>               u64 tmp;
>  
> -             tmp = btrfs_sector_sum_left(sums, sector_sum, total_bytes,
> -                                         root->sectorsize);
> +             tmp = sums->len - total_bytes;
>               tmp >>= root->fs_info->sb->s_blocksize_bits;
>               tmp = min(tmp, (next_offset - file_key.offset) >>
>                                        root->fs_info->sb->s_blocksize_bits);
> @@ -873,30 +839,26 @@ insert:
>               goto fail_unlock;
>       }
>  csum:
> +     ret = 0;
>       leaf = path->nodes[0];
> +
>       item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
> -     ret = 0;
> +     item_end = (struct btrfs_csum_item *)((unsigned char *)item +
> +                                   btrfs_item_size_nr(leaf, path->slots[0]));
>       item = (struct btrfs_csum_item *)((unsigned char *)item +
>                                         csum_offset * csum_size);
> -found:
> -     item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
> -     item_end = (struct btrfs_csum_item *)((unsigned char *)item_end +
> -                                   btrfs_item_size_nr(leaf, path->slots[0]));
> -next_sector:
>  
> -     write_extent_buffer(leaf, &sector_sum->sum, (unsigned long)item, 
> csum_size);
> -
> -     total_bytes += root->sectorsize;
> -     sector_sum++;
> -     if (total_bytes < sums->len) {
> -             item = (struct btrfs_csum_item *)((char *)item +
> -                                               csum_size);
> -             if (item < item_end && bytenr + PAGE_CACHE_SIZE ==
> -                 sector_sum->bytenr) {
> -                     bytenr = sector_sum->bytenr;
> -                     goto next_sector;
> -             }
> -     }
> +     ins_size = (u32)(sums->len - total_bytes) >>
> +                root->fs_info->sb->s_blocksize_bits;
> +     ins_size *= csum_size;
> +     ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item,
> +                           ins_size);
> +     write_extent_buffer(leaf, sums->sums + index, (unsigned long)item,
> +                         ins_size);
> +
> +     ins_size /= csum_size;
> +     total_bytes += ins_size * root->sectorsize;
> +     index += ins_size;
>  
>       btrfs_mark_buffer_dirty(path->nodes[0]);
>       if (total_bytes < sums->len) {
> diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
> index 2b959b6..23bb43a 100644
> --- a/fs/btrfs/ordered-data.c
> +++ b/fs/btrfs/ordered-data.c
> @@ -987,7 +987,6 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 
> offset, u64 disk_bytenr,
>                          u32 *sum, int len)
>  {
>       struct btrfs_ordered_sum *ordered_sum;
> -     struct btrfs_sector_sum *sector_sums;
>       struct btrfs_ordered_extent *ordered;
>       struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
>       unsigned long num_sectors;
> @@ -1004,17 +1003,15 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 
> offset, u64 disk_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;
> -                     for (; i < num_sectors; i++) {
> -                             if (sector_sums[i].bytenr == disk_bytenr) {
> -                                     sum[index] = sector_sums[i].sum;
> -                                     index++;
> -                                     if (index == len)
> -                                             goto out;
> -                                     disk_bytenr += sectorsize;
> -                             }
> -                     }
> +                     num_sectors = ordered_sum->len / sectorsize - i;
> +                     num_sectors = min_t(int, len - index, num_sectors);
> +                     memcpy(sum + index, ordered_sum->sums + i,
> +                            num_sectors);
> +
> +                     index += (int)num_sectors;
> +                     if (index == len)
> +                             goto out;
> +                     disk_bytenr += num_sectors * sectorsize;
>               }
>       }
>  out:
> diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
> index 58b0e3b..888bcbb 100644
> --- a/fs/btrfs/ordered-data.h
> +++ b/fs/btrfs/ordered-data.h
> @@ -26,18 +26,6 @@ struct btrfs_ordered_inode_tree {
>       struct rb_node *last;
>  };
>  
> -/*
> - * these are used to collect checksums done just before bios submission.
> - * They are attached via a list into the ordered extent, and
> - * checksum items are inserted into the tree after all the blocks in
> - * the ordered extent are on disk
> - */
> -struct btrfs_sector_sum {
> -     /* bytenr on disk */
> -     u64 bytenr;
> -     u32 sum;
> -};
> -
>  struct btrfs_ordered_sum {
>       /* bytenr is the start of this extent on disk */
>       u64 bytenr;
> @@ -45,10 +33,10 @@ struct btrfs_ordered_sum {
>       /*
>        * this is the length in bytes covered by the sums array below.
>        */
> -     unsigned long len;
> +     int len;
>       struct list_head list;
> -     /* last field is a variable length array of btrfs_sector_sums */
> -     struct btrfs_sector_sum sums[];
> +     /* last field is a variable length array of csums */
> +     u32 sums[];
>  };
>  
>  /*
> @@ -149,11 +137,8 @@ struct btrfs_ordered_extent {
>  static inline int btrfs_ordered_sum_size(struct btrfs_root *root,
>                                        unsigned long bytes)
>  {
> -     unsigned long num_sectors = (bytes + root->sectorsize - 1) /
> -             root->sectorsize;
> -     num_sectors++;
> -     return sizeof(struct btrfs_ordered_sum) +
> -             num_sectors * sizeof(struct btrfs_sector_sum);
> +     int num_sectors = (int)DIV_ROUND_UP(bytes, root->sectorsize);
> +     return sizeof(struct btrfs_ordered_sum) + num_sectors * sizeof(u32);
>  }
>  
>  static inline void
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 3ebe879..5928142 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -4335,10 +4335,8 @@ out:
>  int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)
>  {
>       struct btrfs_ordered_sum *sums;
> -     struct btrfs_sector_sum *sector_sum;
>       struct btrfs_ordered_extent *ordered;
>       struct btrfs_root *root = BTRFS_I(inode)->root;
> -     size_t offset;
>       int ret;
>       u64 disk_bytenr;
>       LIST_HEAD(list);
> @@ -4356,16 +4354,8 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 
> file_pos, u64 len)
>               sums = list_entry(list.next, struct btrfs_ordered_sum, list);
>               list_del_init(&sums->list);
>  
> -             sector_sum = sums->sums;
>               sums->bytenr = ordered->start;
>  
> -             offset = 0;
> -             while (offset < sums->len) {
> -                     sector_sum->bytenr += ordered->start - disk_bytenr;
> -                     sector_sum++;
> -                     offset += root->sectorsize;
> -             }
> -
>               btrfs_add_ordered_sum(inode, ordered, sums);
>       }
>  out:
> diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
> index 53c3501..6c292b1 100644
> --- a/fs/btrfs/scrub.c
> +++ b/fs/btrfs/scrub.c
> @@ -2128,8 +2128,7 @@ static int scrub_find_csum(struct scrub_ctx *sctx, u64 
> logical, u64 len,
>                          u8 *csum)
>  {
>       struct btrfs_ordered_sum *sum = NULL;
> -     int ret = 0;
> -     unsigned long i;
> +     unsigned long index;
>       unsigned long num_sectors;
>  
>       while (!list_empty(&sctx->csum_list)) {
> @@ -2148,19 +2147,14 @@ static int scrub_find_csum(struct scrub_ctx *sctx, 
> u64 logical, u64 len,
>       if (!sum)
>               return 0;
>  
> +     index = (logical - sum->bytenr) / sctx->sectorsize;
>       num_sectors = sum->len / sctx->sectorsize;
> -     for (i = 0; i < num_sectors; ++i) {
> -             if (sum->sums[i].bytenr == logical) {
> -                     memcpy(csum, &sum->sums[i].sum, sctx->csum_size);
> -                     ret = 1;
> -                     break;
> -             }
> -     }
> -     if (ret && i == num_sectors - 1) {
> +     memcpy(csum, sum->sums + index, sctx->csum_size);
> +     if (index == num_sectors - 1) {
>               list_del(&sum->list);
>               kfree(sum);
>       }
> -     return ret;
> +     return 1;
>  }
>  
>  /* scrub extent tries to collect up to 64 kB for each bio */
> -- 
> 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

Reply via email to