Commit 10fe6ca8 authored by Johannes Thumshirn's avatar Johannes Thumshirn Committed by David Sterba

btrfs: don't assume compressed_bio sums to be 4 bytes

BTRFS has the implicit assumption that a checksum in compressed_bio is 4
bytes. While this is true for CRC32C, it is not for any other checksum.

Change the data type to be a byte array and adjust loop index calculation
accordingly.
Signed-off-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 1e25a2e3
...@@ -57,12 +57,14 @@ static int check_compressed_csum(struct btrfs_inode *inode, ...@@ -57,12 +57,14 @@ static int check_compressed_csum(struct btrfs_inode *inode,
struct compressed_bio *cb, struct compressed_bio *cb,
u64 disk_start) u64 disk_start)
{ {
struct btrfs_fs_info *fs_info = inode->root->fs_info;
const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
int ret; int ret;
struct page *page; struct page *page;
unsigned long i; unsigned long i;
char *kaddr; char *kaddr;
u32 csum; u32 csum;
u32 *cb_sum = &cb->sums; u8 *cb_sum = cb->sums;
if (inode->flags & BTRFS_INODE_NODATASUM) if (inode->flags & BTRFS_INODE_NODATASUM)
return 0; return 0;
...@@ -76,13 +78,13 @@ static int check_compressed_csum(struct btrfs_inode *inode, ...@@ -76,13 +78,13 @@ static int check_compressed_csum(struct btrfs_inode *inode,
btrfs_csum_final(csum, (u8 *)&csum); btrfs_csum_final(csum, (u8 *)&csum);
kunmap_atomic(kaddr); kunmap_atomic(kaddr);
if (csum != *cb_sum) { if (memcmp(&csum, cb_sum, csum_size)) {
btrfs_print_data_csum_error(inode, disk_start, csum, btrfs_print_data_csum_error(inode, disk_start, csum,
*cb_sum, cb->mirror_num); *(u32 *)cb_sum, cb->mirror_num);
ret = -EIO; ret = -EIO;
goto fail; goto fail;
} }
cb_sum++; cb_sum += csum_size;
} }
ret = 0; ret = 0;
...@@ -536,7 +538,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -536,7 +538,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
struct extent_map *em; struct extent_map *em;
blk_status_t ret = BLK_STS_RESOURCE; blk_status_t ret = BLK_STS_RESOURCE;
int faili = 0; int faili = 0;
u32 *sums; const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
u8 *sums;
em_tree = &BTRFS_I(inode)->extent_tree; em_tree = &BTRFS_I(inode)->extent_tree;
...@@ -558,7 +561,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -558,7 +561,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
cb->errors = 0; cb->errors = 0;
cb->inode = inode; cb->inode = inode;
cb->mirror_num = mirror_num; cb->mirror_num = mirror_num;
sums = &cb->sums; sums = cb->sums;
cb->start = em->orig_start; cb->start = em->orig_start;
em_len = em->len; em_len = em->len;
...@@ -617,6 +620,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -617,6 +620,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
page->mapping = NULL; page->mapping = NULL;
if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) < if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) <
PAGE_SIZE) { PAGE_SIZE) {
unsigned int nr_sectors;
ret = btrfs_bio_wq_end_io(fs_info, comp_bio, ret = btrfs_bio_wq_end_io(fs_info, comp_bio,
BTRFS_WQ_ENDIO_DATA); BTRFS_WQ_ENDIO_DATA);
BUG_ON(ret); /* -ENOMEM */ BUG_ON(ret); /* -ENOMEM */
...@@ -631,11 +636,13 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -631,11 +636,13 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
ret = btrfs_lookup_bio_sums(inode, comp_bio, ret = btrfs_lookup_bio_sums(inode, comp_bio,
(u8 *)sums); sums);
BUG_ON(ret); /* -ENOMEM */ BUG_ON(ret); /* -ENOMEM */
} }
sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size,
fs_info->sectorsize); nr_sectors = DIV_ROUND_UP(comp_bio->bi_iter.bi_size,
fs_info->sectorsize);
sums += csum_size * nr_sectors;
ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0); ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0);
if (ret) { if (ret) {
...@@ -657,7 +664,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ...@@ -657,7 +664,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
BUG_ON(ret); /* -ENOMEM */ BUG_ON(ret); /* -ENOMEM */
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
ret = btrfs_lookup_bio_sums(inode, comp_bio, (u8 *) sums); ret = btrfs_lookup_bio_sums(inode, comp_bio, sums);
BUG_ON(ret); /* -ENOMEM */ BUG_ON(ret); /* -ENOMEM */
} }
......
...@@ -61,7 +61,7 @@ struct compressed_bio { ...@@ -61,7 +61,7 @@ struct compressed_bio {
* the start of a variable length array of checksums only * the start of a variable length array of checksums only
* used by reads * used by reads
*/ */
u32 sums; u8 sums[];
}; };
static inline unsigned int btrfs_compress_type(unsigned int type_level) static inline unsigned int btrfs_compress_type(unsigned int type_level)
......
...@@ -186,7 +186,7 @@ static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio ...@@ -186,7 +186,7 @@ static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio
} }
csum = btrfs_bio->csum; csum = btrfs_bio->csum;
} else { } else {
csum = (u8 *)dst; csum = dst;
} }
if (bio->bi_iter.bi_size > PAGE_SIZE * 8) if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
......
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