aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Thumshirn <jthumshirn@suse.de>2019-05-22 04:19:02 -0400
committerDavid Sterba <dsterba@suse.com>2019-07-01 07:35:01 -0400
commit10fe6ca80d9d25eca9fd6d98eccf6c795532fe96 (patch)
treeed36a8a59ff0e86913f9b9492d5a743e769f3404
parent1e25a2e3ca0dab0ed1030570e95d98af47113eae (diff)
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: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/compression.c27
-rw-r--r--fs/btrfs/compression.h2
-rw-r--r--fs/btrfs/file-item.c2
3 files changed, 19 insertions, 12 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index a8e551ca8798..92291f266324 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -57,12 +57,14 @@ static int check_compressed_csum(struct btrfs_inode *inode,
57 struct compressed_bio *cb, 57 struct compressed_bio *cb,
58 u64 disk_start) 58 u64 disk_start)
59{ 59{
60 struct btrfs_fs_info *fs_info = inode->root->fs_info;
61 const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
60 int ret; 62 int ret;
61 struct page *page; 63 struct page *page;
62 unsigned long i; 64 unsigned long i;
63 char *kaddr; 65 char *kaddr;
64 u32 csum; 66 u32 csum;
65 u32 *cb_sum = &cb->sums; 67 u8 *cb_sum = cb->sums;
66 68
67 if (inode->flags & BTRFS_INODE_NODATASUM) 69 if (inode->flags & BTRFS_INODE_NODATASUM)
68 return 0; 70 return 0;
@@ -76,13 +78,13 @@ static int check_compressed_csum(struct btrfs_inode *inode,
76 btrfs_csum_final(csum, (u8 *)&csum); 78 btrfs_csum_final(csum, (u8 *)&csum);
77 kunmap_atomic(kaddr); 79 kunmap_atomic(kaddr);
78 80
79 if (csum != *cb_sum) { 81 if (memcmp(&csum, cb_sum, csum_size)) {
80 btrfs_print_data_csum_error(inode, disk_start, csum, 82 btrfs_print_data_csum_error(inode, disk_start, csum,
81 *cb_sum, cb->mirror_num); 83 *(u32 *)cb_sum, cb->mirror_num);
82 ret = -EIO; 84 ret = -EIO;
83 goto fail; 85 goto fail;
84 } 86 }
85 cb_sum++; 87 cb_sum += csum_size;
86 88
87 } 89 }
88 ret = 0; 90 ret = 0;
@@ -536,7 +538,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
536 struct extent_map *em; 538 struct extent_map *em;
537 blk_status_t ret = BLK_STS_RESOURCE; 539 blk_status_t ret = BLK_STS_RESOURCE;
538 int faili = 0; 540 int faili = 0;
539 u32 *sums; 541 const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
542 u8 *sums;
540 543
541 em_tree = &BTRFS_I(inode)->extent_tree; 544 em_tree = &BTRFS_I(inode)->extent_tree;
542 545
@@ -558,7 +561,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
558 cb->errors = 0; 561 cb->errors = 0;
559 cb->inode = inode; 562 cb->inode = inode;
560 cb->mirror_num = mirror_num; 563 cb->mirror_num = mirror_num;
561 sums = &cb->sums; 564 sums = cb->sums;
562 565
563 cb->start = em->orig_start; 566 cb->start = em->orig_start;
564 em_len = em->len; 567 em_len = em->len;
@@ -617,6 +620,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
617 page->mapping = NULL; 620 page->mapping = NULL;
618 if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) < 621 if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) <
619 PAGE_SIZE) { 622 PAGE_SIZE) {
623 unsigned int nr_sectors;
624
620 ret = btrfs_bio_wq_end_io(fs_info, comp_bio, 625 ret = btrfs_bio_wq_end_io(fs_info, comp_bio,
621 BTRFS_WQ_ENDIO_DATA); 626 BTRFS_WQ_ENDIO_DATA);
622 BUG_ON(ret); /* -ENOMEM */ 627 BUG_ON(ret); /* -ENOMEM */
@@ -631,11 +636,13 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
631 636
632 if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { 637 if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
633 ret = btrfs_lookup_bio_sums(inode, comp_bio, 638 ret = btrfs_lookup_bio_sums(inode, comp_bio,
634 (u8 *)sums); 639 sums);
635 BUG_ON(ret); /* -ENOMEM */ 640 BUG_ON(ret); /* -ENOMEM */
636 } 641 }
637 sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size, 642
638 fs_info->sectorsize); 643 nr_sectors = DIV_ROUND_UP(comp_bio->bi_iter.bi_size,
644 fs_info->sectorsize);
645 sums += csum_size * nr_sectors;
639 646
640 ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0); 647 ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0);
641 if (ret) { 648 if (ret) {
@@ -657,7 +664,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
657 BUG_ON(ret); /* -ENOMEM */ 664 BUG_ON(ret); /* -ENOMEM */
658 665
659 if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { 666 if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
660 ret = btrfs_lookup_bio_sums(inode, comp_bio, (u8 *) sums); 667 ret = btrfs_lookup_bio_sums(inode, comp_bio, sums);
661 BUG_ON(ret); /* -ENOMEM */ 668 BUG_ON(ret); /* -ENOMEM */
662 } 669 }
663 670
diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h
index 9976fe0f7526..191e5f4e3523 100644
--- a/fs/btrfs/compression.h
+++ b/fs/btrfs/compression.h
@@ -61,7 +61,7 @@ struct compressed_bio {
61 * the start of a variable length array of checksums only 61 * the start of a variable length array of checksums only
62 * used by reads 62 * used by reads
63 */ 63 */
64 u32 sums; 64 u8 sums[];
65}; 65};
66 66
67static inline unsigned int btrfs_compress_type(unsigned int type_level) 67static inline unsigned int btrfs_compress_type(unsigned int type_level)
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 0464dd4c0579..de89fd1310a6 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -186,7 +186,7 @@ static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio
186 } 186 }
187 csum = btrfs_bio->csum; 187 csum = btrfs_bio->csum;
188 } else { 188 } else {
189 csum = (u8 *)dst; 189 csum = dst;
190 } 190 }
191 191
192 if (bio->bi_iter.bi_size > PAGE_SIZE * 8) 192 if (bio->bi_iter.bi_size > PAGE_SIZE * 8)