Commit c40a3d38 authored by Chandan Rajendra's avatar Chandan Rajendra Committed by David Sterba

Btrfs: Compute and look up csums based on sectorsized blocks

Checksums are applicable to sectorsize units. The current code uses
bio->bv_len units to compute and look up checksums. This works on machines
where sectorsize == PAGE_SIZE. This patch makes the checksum computation and
look up code to work with sectorsize units.
Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
Signed-off-by: default avatarChandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 2e78c927
...@@ -172,6 +172,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -172,6 +172,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
u64 item_start_offset = 0; u64 item_start_offset = 0;
u64 item_last_offset = 0; u64 item_last_offset = 0;
u64 disk_bytenr; u64 disk_bytenr;
u64 page_bytes_left;
u32 diff; u32 diff;
int nblocks; int nblocks;
int bio_index = 0; int bio_index = 0;
...@@ -220,6 +221,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -220,6 +221,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
disk_bytenr = (u64)bio->bi_iter.bi_sector << 9; disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
if (dio) if (dio)
offset = logical_offset; offset = logical_offset;
page_bytes_left = bvec->bv_len;
while (bio_index < bio->bi_vcnt) { while (bio_index < bio->bi_vcnt) {
if (!dio) if (!dio)
offset = page_offset(bvec->bv_page) + bvec->bv_offset; offset = page_offset(bvec->bv_page) + bvec->bv_offset;
...@@ -243,7 +246,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -243,7 +246,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
if (BTRFS_I(inode)->root->root_key.objectid == if (BTRFS_I(inode)->root->root_key.objectid ==
BTRFS_DATA_RELOC_TREE_OBJECTID) { BTRFS_DATA_RELOC_TREE_OBJECTID) {
set_extent_bits(io_tree, offset, set_extent_bits(io_tree, offset,
offset + bvec->bv_len - 1, offset + root->sectorsize - 1,
EXTENT_NODATASUM, GFP_NOFS); EXTENT_NODATASUM, GFP_NOFS);
} else { } else {
btrfs_info(BTRFS_I(inode)->root->fs_info, btrfs_info(BTRFS_I(inode)->root->fs_info,
...@@ -281,11 +284,17 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, ...@@ -281,11 +284,17 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
found: found:
csum += count * csum_size; csum += count * csum_size;
nblocks -= count; nblocks -= count;
bio_index += count;
while (count--) { while (count--) {
disk_bytenr += bvec->bv_len; disk_bytenr += root->sectorsize;
offset += bvec->bv_len; offset += root->sectorsize;
page_bytes_left -= root->sectorsize;
if (!page_bytes_left) {
bio_index++;
bvec++; bvec++;
page_bytes_left = bvec->bv_len;
}
} }
} }
btrfs_free_path(path); btrfs_free_path(path);
...@@ -432,6 +441,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, ...@@ -432,6 +441,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
struct bio_vec *bvec = bio->bi_io_vec; struct bio_vec *bvec = bio->bi_io_vec;
int bio_index = 0; int bio_index = 0;
int index; int index;
int nr_sectors;
int i;
unsigned long total_bytes = 0; unsigned long total_bytes = 0;
unsigned long this_sum_bytes = 0; unsigned long this_sum_bytes = 0;
u64 offset; u64 offset;
...@@ -459,9 +470,18 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, ...@@ -459,9 +470,18 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
if (!contig) if (!contig)
offset = page_offset(bvec->bv_page) + bvec->bv_offset; offset = page_offset(bvec->bv_page) + bvec->bv_offset;
data = kmap_atomic(bvec->bv_page);
nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
bvec->bv_len + root->sectorsize
- 1);
for (i = 0; i < nr_sectors; i++) {
if (offset >= ordered->file_offset + ordered->len || if (offset >= ordered->file_offset + ordered->len ||
offset < ordered->file_offset) { offset < ordered->file_offset) {
unsigned long bytes_left; unsigned long bytes_left;
kunmap_atomic(data);
sums->len = this_sum_bytes; sums->len = this_sum_bytes;
this_sum_bytes = 0; this_sum_bytes = 0;
btrfs_add_ordered_sum(inode, ordered, sums); btrfs_add_ordered_sum(inode, ordered, sums);
...@@ -473,27 +493,33 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, ...@@ -473,27 +493,33 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
GFP_NOFS); GFP_NOFS);
BUG_ON(!sums); /* -ENOMEM */ BUG_ON(!sums); /* -ENOMEM */
sums->len = bytes_left; sums->len = bytes_left;
ordered = btrfs_lookup_ordered_extent(inode, offset); ordered = btrfs_lookup_ordered_extent(inode,
BUG_ON(!ordered); /* Logic error */ offset);
sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) + ASSERT(ordered); /* Logic error */
total_bytes; sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9)
+ total_bytes;
index = 0; index = 0;
}
data = kmap_atomic(bvec->bv_page); data = kmap_atomic(bvec->bv_page);
}
sums->sums[index] = ~(u32)0; sums->sums[index] = ~(u32)0;
sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset, sums->sums[index]
= btrfs_csum_data(data + bvec->bv_offset
+ (i * root->sectorsize),
sums->sums[index], sums->sums[index],
bvec->bv_len); root->sectorsize);
kunmap_atomic(data);
btrfs_csum_final(sums->sums[index], btrfs_csum_final(sums->sums[index],
(char *)(sums->sums + index)); (char *)(sums->sums + index));
index++;
offset += root->sectorsize;
this_sum_bytes += root->sectorsize;
total_bytes += root->sectorsize;
}
kunmap_atomic(data);
bio_index++; bio_index++;
index++;
total_bytes += bvec->bv_len;
this_sum_bytes += bvec->bv_len;
offset += bvec->bv_len;
bvec++; bvec++;
} }
this_sum_bytes = 0; this_sum_bytes = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment