On Thu, 28 Mar 2013 22:41:50 +0800, Liu Bo wrote: > On Thu, Mar 28, 2013 at 10:38:34PM +0800, Liu Bo wrote: >> 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 > > but the title is a bit confused because you've actually killed all of > btrfs_sector_sum.
I misused the old title, will change it later. Thanks Miao > >> >> 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], >>> - §or_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 *)§or_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, §or_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 > -- 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
