|
@@ -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,
|
|
@@ -297,7 +296,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;
|
|
@@ -368,34 +366,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]++;
|
|
@@ -417,23 +409,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);
|
|
|
|
|
@@ -444,7 +433,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)
|
|
@@ -463,28 +453,27 @@ 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(data + bvec->bv_offset,
|
|
|
- sector_sum->sum,
|
|
|
- bvec->bv_len);
|
|
|
+ sums->sums[index] = ~(u32)0;
|
|
|
+ sums->sums[index] = btrfs_csum_data(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++;
|
|
|
}
|
|
@@ -672,62 +661,46 @@ 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;
|
|
|
+ leaf = path->nodes[0];
|
|
|
+ item_end = btrfs_item_ptr(leaf, path->slots[0],
|
|
|
+ struct btrfs_csum_item);
|
|
|
+ item_end = (struct btrfs_csum_item *)((char *)item_end +
|
|
|
+ btrfs_item_size_nr(leaf, path->slots[0]));
|
|
|
goto found;
|
|
|
}
|
|
|
ret = PTR_ERR(item);
|
|
@@ -807,8 +780,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);
|
|
|
|
|
@@ -822,6 +794,7 @@ again:
|
|
|
diff *= csum_size;
|
|
|
|
|
|
btrfs_extend_item(root, path, diff);
|
|
|
+ ret = 0;
|
|
|
goto csum;
|
|
|
}
|
|
|
|
|
@@ -831,8 +804,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);
|
|
@@ -853,31 +825,25 @@ insert:
|
|
|
WARN_ON(1);
|
|
|
goto fail_unlock;
|
|
|
}
|
|
|
-csum:
|
|
|
leaf = path->nodes[0];
|
|
|
+csum:
|
|
|
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) {
|