diff options
Diffstat (limited to 'fs/btrfs/file-item.c')
| -rw-r--r-- | fs/btrfs/file-item.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 94aa53b38721..ec160202be3e 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -684,6 +684,24 @@ out: | |||
| 684 | return ret; | 684 | return ret; |
| 685 | } | 685 | } |
| 686 | 686 | ||
| 687 | static u64 btrfs_sector_sum_left(struct btrfs_ordered_sum *sums, | ||
| 688 | struct btrfs_sector_sum *sector_sum, | ||
| 689 | u64 total_bytes, u64 sectorsize) | ||
| 690 | { | ||
| 691 | u64 tmp = sectorsize; | ||
| 692 | u64 next_sector = sector_sum->bytenr; | ||
| 693 | struct btrfs_sector_sum *next = sector_sum + 1; | ||
| 694 | |||
| 695 | while ((tmp + total_bytes) < sums->len) { | ||
| 696 | if (next_sector + sectorsize != next->bytenr) | ||
| 697 | break; | ||
| 698 | tmp += sectorsize; | ||
| 699 | next_sector = next->bytenr; | ||
| 700 | next++; | ||
| 701 | } | ||
| 702 | return tmp; | ||
| 703 | } | ||
| 704 | |||
| 687 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, | 705 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, |
| 688 | struct btrfs_root *root, | 706 | struct btrfs_root *root, |
| 689 | struct btrfs_ordered_sum *sums) | 707 | struct btrfs_ordered_sum *sums) |
| @@ -789,20 +807,32 @@ again: | |||
| 789 | goto insert; | 807 | goto insert; |
| 790 | } | 808 | } |
| 791 | 809 | ||
| 792 | if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) / | 810 | if (csum_offset == btrfs_item_size_nr(leaf, path->slots[0]) / |
| 793 | csum_size) { | 811 | csum_size) { |
| 794 | u32 diff = (csum_offset + 1) * csum_size; | 812 | int extend_nr; |
| 813 | u64 tmp; | ||
| 814 | u32 diff; | ||
| 815 | u32 free_space; | ||
| 795 | 816 | ||
| 796 | /* | 817 | if (btrfs_leaf_free_space(root, leaf) < |
| 797 | * is the item big enough already? we dropped our lock | 818 | sizeof(struct btrfs_item) + csum_size * 2) |
| 798 | * before and need to recheck | 819 | goto insert; |
| 799 | */ | 820 | |
| 800 | if (diff < btrfs_item_size_nr(leaf, path->slots[0])) | 821 | free_space = btrfs_leaf_free_space(root, leaf) - |
| 801 | goto csum; | 822 | sizeof(struct btrfs_item) - csum_size; |
| 823 | tmp = btrfs_sector_sum_left(sums, sector_sum, total_bytes, | ||
| 824 | root->sectorsize); | ||
| 825 | tmp >>= root->fs_info->sb->s_blocksize_bits; | ||
| 826 | WARN_ON(tmp < 1); | ||
| 827 | |||
| 828 | extend_nr = max_t(int, 1, (int)tmp); | ||
| 829 | diff = (csum_offset + extend_nr) * csum_size; | ||
| 830 | diff = min(diff, MAX_CSUM_ITEMS(root, csum_size) * csum_size); | ||
| 802 | 831 | ||
| 803 | diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); | 832 | diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); |
| 804 | if (diff != csum_size) | 833 | diff = min(free_space, diff); |
| 805 | goto insert; | 834 | diff /= csum_size; |
| 835 | diff *= csum_size; | ||
| 806 | 836 | ||
| 807 | btrfs_extend_item(trans, root, path, diff); | 837 | btrfs_extend_item(trans, root, path, diff); |
| 808 | goto csum; | 838 | goto csum; |
| @@ -812,19 +842,14 @@ insert: | |||
| 812 | btrfs_release_path(path); | 842 | btrfs_release_path(path); |
| 813 | csum_offset = 0; | 843 | csum_offset = 0; |
| 814 | if (found_next) { | 844 | if (found_next) { |
| 815 | u64 tmp = total_bytes + root->sectorsize; | 845 | u64 tmp; |
| 816 | u64 next_sector = sector_sum->bytenr; | ||
| 817 | struct btrfs_sector_sum *next = sector_sum + 1; | ||
| 818 | 846 | ||
| 819 | while (tmp < sums->len) { | 847 | tmp = btrfs_sector_sum_left(sums, sector_sum, total_bytes, |
| 820 | if (next_sector + root->sectorsize != next->bytenr) | 848 | root->sectorsize); |
| 821 | break; | ||
| 822 | tmp += root->sectorsize; | ||
| 823 | next_sector = next->bytenr; | ||
| 824 | next++; | ||
| 825 | } | ||
| 826 | tmp = min(tmp, next_offset - file_key.offset); | ||
| 827 | tmp >>= root->fs_info->sb->s_blocksize_bits; | 849 | tmp >>= root->fs_info->sb->s_blocksize_bits; |
| 850 | tmp = min(tmp, (next_offset - file_key.offset) >> | ||
| 851 | root->fs_info->sb->s_blocksize_bits); | ||
| 852 | |||
| 828 | tmp = max((u64)1, tmp); | 853 | tmp = max((u64)1, tmp); |
| 829 | tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); | 854 | tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); |
| 830 | ins_size = csum_size * tmp; | 855 | ins_size = csum_size * tmp; |
