diff options
Diffstat (limited to 'fs/btrfs/compression.c')
-rw-r--r-- | fs/btrfs/compression.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 84dd4a8980c5..60c47b417a4b 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/sched/mm.h> | 18 | #include <linux/sched/mm.h> |
19 | #include <linux/log2.h> | 19 | #include <linux/log2.h> |
20 | #include <crypto/hash.h> | ||
20 | #include "ctree.h" | 21 | #include "ctree.h" |
21 | #include "disk-io.h" | 22 | #include "disk-io.h" |
22 | #include "transaction.h" | 23 | #include "transaction.h" |
@@ -42,6 +43,22 @@ const char* btrfs_compress_type2str(enum btrfs_compression_type type) | |||
42 | return NULL; | 43 | return NULL; |
43 | } | 44 | } |
44 | 45 | ||
46 | bool btrfs_compress_is_valid_type(const char *str, size_t len) | ||
47 | { | ||
48 | int i; | ||
49 | |||
50 | for (i = 1; i < ARRAY_SIZE(btrfs_compress_types); i++) { | ||
51 | size_t comp_len = strlen(btrfs_compress_types[i]); | ||
52 | |||
53 | if (len < comp_len) | ||
54 | continue; | ||
55 | |||
56 | if (!strncmp(btrfs_compress_types[i], str, comp_len)) | ||
57 | return true; | ||
58 | } | ||
59 | return false; | ||
60 | } | ||
61 | |||
45 | static int btrfs_decompress_bio(struct compressed_bio *cb); | 62 | static int btrfs_decompress_bio(struct compressed_bio *cb); |
46 | 63 | ||
47 | static inline int compressed_bio_size(struct btrfs_fs_info *fs_info, | 64 | static inline int compressed_bio_size(struct btrfs_fs_info *fs_info, |
@@ -57,32 +74,37 @@ static int check_compressed_csum(struct btrfs_inode *inode, | |||
57 | struct compressed_bio *cb, | 74 | struct compressed_bio *cb, |
58 | u64 disk_start) | 75 | u64 disk_start) |
59 | { | 76 | { |
77 | struct btrfs_fs_info *fs_info = inode->root->fs_info; | ||
78 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
79 | const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); | ||
60 | int ret; | 80 | int ret; |
61 | struct page *page; | 81 | struct page *page; |
62 | unsigned long i; | 82 | unsigned long i; |
63 | char *kaddr; | 83 | char *kaddr; |
64 | u32 csum; | 84 | u8 csum[BTRFS_CSUM_SIZE]; |
65 | u32 *cb_sum = &cb->sums; | 85 | u8 *cb_sum = cb->sums; |
66 | 86 | ||
67 | if (inode->flags & BTRFS_INODE_NODATASUM) | 87 | if (inode->flags & BTRFS_INODE_NODATASUM) |
68 | return 0; | 88 | return 0; |
69 | 89 | ||
90 | shash->tfm = fs_info->csum_shash; | ||
91 | |||
70 | for (i = 0; i < cb->nr_pages; i++) { | 92 | for (i = 0; i < cb->nr_pages; i++) { |
71 | page = cb->compressed_pages[i]; | 93 | page = cb->compressed_pages[i]; |
72 | csum = ~(u32)0; | ||
73 | 94 | ||
95 | crypto_shash_init(shash); | ||
74 | kaddr = kmap_atomic(page); | 96 | kaddr = kmap_atomic(page); |
75 | csum = btrfs_csum_data(kaddr, csum, PAGE_SIZE); | 97 | crypto_shash_update(shash, kaddr, PAGE_SIZE); |
76 | btrfs_csum_final(csum, (u8 *)&csum); | ||
77 | kunmap_atomic(kaddr); | 98 | kunmap_atomic(kaddr); |
99 | crypto_shash_final(shash, (u8 *)&csum); | ||
78 | 100 | ||
79 | if (csum != *cb_sum) { | 101 | if (memcmp(&csum, cb_sum, csum_size)) { |
80 | btrfs_print_data_csum_error(inode, disk_start, csum, | 102 | btrfs_print_data_csum_error(inode, disk_start, |
81 | *cb_sum, cb->mirror_num); | 103 | csum, cb_sum, cb->mirror_num); |
82 | ret = -EIO; | 104 | ret = -EIO; |
83 | goto fail; | 105 | goto fail; |
84 | } | 106 | } |
85 | cb_sum++; | 107 | cb_sum += csum_size; |
86 | 108 | ||
87 | } | 109 | } |
88 | ret = 0; | 110 | ret = 0; |
@@ -318,7 +340,8 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
318 | 340 | ||
319 | bdev = fs_info->fs_devices->latest_bdev; | 341 | bdev = fs_info->fs_devices->latest_bdev; |
320 | 342 | ||
321 | bio = btrfs_bio_alloc(bdev, first_byte); | 343 | bio = btrfs_bio_alloc(first_byte); |
344 | bio_set_dev(bio, bdev); | ||
322 | bio->bi_opf = REQ_OP_WRITE | write_flags; | 345 | bio->bi_opf = REQ_OP_WRITE | write_flags; |
323 | bio->bi_private = cb; | 346 | bio->bi_private = cb; |
324 | bio->bi_end_io = end_compressed_bio_write; | 347 | bio->bi_end_io = end_compressed_bio_write; |
@@ -360,7 +383,8 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
360 | bio_endio(bio); | 383 | bio_endio(bio); |
361 | } | 384 | } |
362 | 385 | ||
363 | bio = btrfs_bio_alloc(bdev, first_byte); | 386 | bio = btrfs_bio_alloc(first_byte); |
387 | bio_set_dev(bio, bdev); | ||
364 | bio->bi_opf = REQ_OP_WRITE | write_flags; | 388 | bio->bi_opf = REQ_OP_WRITE | write_flags; |
365 | bio->bi_private = cb; | 389 | bio->bi_private = cb; |
366 | bio->bi_end_io = end_compressed_bio_write; | 390 | bio->bi_end_io = end_compressed_bio_write; |
@@ -536,7 +560,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
536 | struct extent_map *em; | 560 | struct extent_map *em; |
537 | blk_status_t ret = BLK_STS_RESOURCE; | 561 | blk_status_t ret = BLK_STS_RESOURCE; |
538 | int faili = 0; | 562 | int faili = 0; |
539 | u32 *sums; | 563 | const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); |
564 | u8 *sums; | ||
540 | 565 | ||
541 | em_tree = &BTRFS_I(inode)->extent_tree; | 566 | em_tree = &BTRFS_I(inode)->extent_tree; |
542 | 567 | ||
@@ -558,7 +583,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
558 | cb->errors = 0; | 583 | cb->errors = 0; |
559 | cb->inode = inode; | 584 | cb->inode = inode; |
560 | cb->mirror_num = mirror_num; | 585 | cb->mirror_num = mirror_num; |
561 | sums = &cb->sums; | 586 | sums = cb->sums; |
562 | 587 | ||
563 | cb->start = em->orig_start; | 588 | cb->start = em->orig_start; |
564 | em_len = em->len; | 589 | em_len = em->len; |
@@ -597,7 +622,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
597 | /* include any pages we added in add_ra-bio_pages */ | 622 | /* include any pages we added in add_ra-bio_pages */ |
598 | cb->len = bio->bi_iter.bi_size; | 623 | cb->len = bio->bi_iter.bi_size; |
599 | 624 | ||
600 | comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte); | 625 | comp_bio = btrfs_bio_alloc(cur_disk_byte); |
626 | bio_set_dev(comp_bio, bdev); | ||
601 | comp_bio->bi_opf = REQ_OP_READ; | 627 | comp_bio->bi_opf = REQ_OP_READ; |
602 | comp_bio->bi_private = cb; | 628 | comp_bio->bi_private = cb; |
603 | comp_bio->bi_end_io = end_compressed_bio_read; | 629 | comp_bio->bi_end_io = end_compressed_bio_read; |
@@ -617,6 +643,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
617 | page->mapping = NULL; | 643 | page->mapping = NULL; |
618 | if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) < | 644 | if (submit || bio_add_page(comp_bio, page, PAGE_SIZE, 0) < |
619 | PAGE_SIZE) { | 645 | PAGE_SIZE) { |
646 | unsigned int nr_sectors; | ||
647 | |||
620 | ret = btrfs_bio_wq_end_io(fs_info, comp_bio, | 648 | ret = btrfs_bio_wq_end_io(fs_info, comp_bio, |
621 | BTRFS_WQ_ENDIO_DATA); | 649 | BTRFS_WQ_ENDIO_DATA); |
622 | BUG_ON(ret); /* -ENOMEM */ | 650 | BUG_ON(ret); /* -ENOMEM */ |
@@ -634,8 +662,10 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
634 | sums); | 662 | sums); |
635 | BUG_ON(ret); /* -ENOMEM */ | 663 | BUG_ON(ret); /* -ENOMEM */ |
636 | } | 664 | } |
637 | sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size, | 665 | |
638 | fs_info->sectorsize); | 666 | nr_sectors = DIV_ROUND_UP(comp_bio->bi_iter.bi_size, |
667 | fs_info->sectorsize); | ||
668 | sums += csum_size * nr_sectors; | ||
639 | 669 | ||
640 | ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0); | 670 | ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0); |
641 | if (ret) { | 671 | if (ret) { |
@@ -643,7 +673,8 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
643 | bio_endio(comp_bio); | 673 | bio_endio(comp_bio); |
644 | } | 674 | } |
645 | 675 | ||
646 | comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte); | 676 | comp_bio = btrfs_bio_alloc(cur_disk_byte); |
677 | bio_set_dev(comp_bio, bdev); | ||
647 | comp_bio->bi_opf = REQ_OP_READ; | 678 | comp_bio->bi_opf = REQ_OP_READ; |
648 | comp_bio->bi_private = cb; | 679 | comp_bio->bi_private = cb; |
649 | comp_bio->bi_end_io = end_compressed_bio_read; | 680 | comp_bio->bi_end_io = end_compressed_bio_read; |