diff options
author | Johannes Thumshirn <jthumshirn@suse.de> | 2019-06-03 10:58:57 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2019-07-01 07:35:02 -0400 |
commit | d5178578bcd461cc79118c7a139882350fe505aa (patch) | |
tree | b6ee534e6aca76d6aee0c18ecf01fd7b7f576449 | |
parent | 6d97c6e31b553bc9f58b83ac3c4c79c17affbda8 (diff) |
btrfs: directly call into crypto framework for checksumming
Currently btrfs_csum_data() relied on the crc32c() wrapper around the
crypto framework for calculating the CRCs.
As we have our own crypto_shash structure in the fs_info now, we can
directly call into the crypto framework without going trough the wrapper.
This way we can even remove the btrfs_csum_data() and btrfs_csum_final()
wrappers.
The module dependency on crc32c is preserved via MODULE_SOFTDEP("pre:
crc32c"), which was previously provided by LIBCRC32C config option doing
the same.
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/Kconfig | 3 | ||||
-rw-r--r-- | fs/btrfs/check-integrity.c | 11 | ||||
-rw-r--r-- | fs/btrfs/compression.c | 17 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 46 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 18 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 23 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 30 | ||||
-rw-r--r-- | fs/btrfs/super.c | 1 |
9 files changed, 89 insertions, 62 deletions
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig index 23537bc8c827..212b4a854f2c 100644 --- a/fs/btrfs/Kconfig +++ b/fs/btrfs/Kconfig | |||
@@ -2,7 +2,8 @@ | |||
2 | 2 | ||
3 | config BTRFS_FS | 3 | config BTRFS_FS |
4 | tristate "Btrfs filesystem support" | 4 | tristate "Btrfs filesystem support" |
5 | select LIBCRC32C | 5 | select CRYPTO |
6 | select CRYPTO_CRC32C | ||
6 | select ZLIB_INFLATE | 7 | select ZLIB_INFLATE |
7 | select ZLIB_DEFLATE | 8 | select ZLIB_DEFLATE |
8 | select LZO_COMPRESS | 9 | select LZO_COMPRESS |
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 85774e2fa3e5..81a9731959a9 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c | |||
@@ -83,7 +83,7 @@ | |||
83 | #include <linux/blkdev.h> | 83 | #include <linux/blkdev.h> |
84 | #include <linux/mm.h> | 84 | #include <linux/mm.h> |
85 | #include <linux/string.h> | 85 | #include <linux/string.h> |
86 | #include <linux/crc32c.h> | 86 | #include <crypto/hash.h> |
87 | #include "ctree.h" | 87 | #include "ctree.h" |
88 | #include "disk-io.h" | 88 | #include "disk-io.h" |
89 | #include "transaction.h" | 89 | #include "transaction.h" |
@@ -1710,9 +1710,9 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state, | |||
1710 | char **datav, unsigned int num_pages) | 1710 | char **datav, unsigned int num_pages) |
1711 | { | 1711 | { |
1712 | struct btrfs_fs_info *fs_info = state->fs_info; | 1712 | struct btrfs_fs_info *fs_info = state->fs_info; |
1713 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1713 | struct btrfs_header *h; | 1714 | struct btrfs_header *h; |
1714 | u8 csum[BTRFS_CSUM_SIZE]; | 1715 | u8 csum[BTRFS_CSUM_SIZE]; |
1715 | u32 crc = ~(u32)0; | ||
1716 | unsigned int i; | 1716 | unsigned int i; |
1717 | 1717 | ||
1718 | if (num_pages * PAGE_SIZE < state->metablock_size) | 1718 | if (num_pages * PAGE_SIZE < state->metablock_size) |
@@ -1723,14 +1723,17 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state, | |||
1723 | if (memcmp(h->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE)) | 1723 | if (memcmp(h->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE)) |
1724 | return 1; | 1724 | return 1; |
1725 | 1725 | ||
1726 | shash->tfm = fs_info->csum_shash; | ||
1727 | crypto_shash_init(shash); | ||
1728 | |||
1726 | for (i = 0; i < num_pages; i++) { | 1729 | for (i = 0; i < num_pages; i++) { |
1727 | u8 *data = i ? datav[i] : (datav[i] + BTRFS_CSUM_SIZE); | 1730 | u8 *data = i ? datav[i] : (datav[i] + BTRFS_CSUM_SIZE); |
1728 | size_t sublen = i ? PAGE_SIZE : | 1731 | size_t sublen = i ? PAGE_SIZE : |
1729 | (PAGE_SIZE - BTRFS_CSUM_SIZE); | 1732 | (PAGE_SIZE - BTRFS_CSUM_SIZE); |
1730 | 1733 | ||
1731 | crc = btrfs_csum_data(data, crc, sublen); | 1734 | crypto_shash_update(shash, data, sublen); |
1732 | } | 1735 | } |
1733 | btrfs_csum_final(crc, csum); | 1736 | crypto_shash_final(shash, csum); |
1734 | if (memcmp(csum, h->csum, state->csum_size)) | 1737 | if (memcmp(csum, h->csum, state->csum_size)) |
1735 | return 1; | 1738 | return 1; |
1736 | 1739 | ||
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 92291f266324..935c0c564c02 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" |
@@ -58,29 +59,33 @@ static int check_compressed_csum(struct btrfs_inode *inode, | |||
58 | u64 disk_start) | 59 | u64 disk_start) |
59 | { | 60 | { |
60 | struct btrfs_fs_info *fs_info = inode->root->fs_info; | 61 | struct btrfs_fs_info *fs_info = inode->root->fs_info; |
62 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
61 | const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); | 63 | const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); |
62 | int ret; | 64 | int ret; |
63 | struct page *page; | 65 | struct page *page; |
64 | unsigned long i; | 66 | unsigned long i; |
65 | char *kaddr; | 67 | char *kaddr; |
66 | u32 csum; | 68 | u8 csum[BTRFS_CSUM_SIZE]; |
67 | u8 *cb_sum = cb->sums; | 69 | u8 *cb_sum = cb->sums; |
68 | 70 | ||
69 | if (inode->flags & BTRFS_INODE_NODATASUM) | 71 | if (inode->flags & BTRFS_INODE_NODATASUM) |
70 | return 0; | 72 | return 0; |
71 | 73 | ||
74 | shash->tfm = fs_info->csum_shash; | ||
75 | |||
72 | for (i = 0; i < cb->nr_pages; i++) { | 76 | for (i = 0; i < cb->nr_pages; i++) { |
73 | page = cb->compressed_pages[i]; | 77 | page = cb->compressed_pages[i]; |
74 | csum = ~(u32)0; | ||
75 | 78 | ||
79 | crypto_shash_init(shash); | ||
76 | kaddr = kmap_atomic(page); | 80 | kaddr = kmap_atomic(page); |
77 | csum = btrfs_csum_data(kaddr, csum, PAGE_SIZE); | 81 | crypto_shash_update(shash, kaddr, PAGE_SIZE); |
78 | btrfs_csum_final(csum, (u8 *)&csum); | ||
79 | kunmap_atomic(kaddr); | 82 | kunmap_atomic(kaddr); |
83 | crypto_shash_final(shash, (u8 *)&csum); | ||
80 | 84 | ||
81 | if (memcmp(&csum, cb_sum, csum_size)) { | 85 | if (memcmp(&csum, cb_sum, csum_size)) { |
82 | btrfs_print_data_csum_error(inode, disk_start, csum, | 86 | btrfs_print_data_csum_error(inode, disk_start, |
83 | *(u32 *)cb_sum, cb->mirror_num); | 87 | *(u32 *)csum, *(u32 *)cb_sum, |
88 | cb->mirror_num); | ||
84 | ret = -EIO; | 89 | ret = -EIO; |
85 | goto fail; | 90 | goto fail; |
86 | } | 91 | } |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 34222bbe4b48..6c7dc24d4031 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -246,16 +246,6 @@ out: | |||
246 | return em; | 246 | return em; |
247 | } | 247 | } |
248 | 248 | ||
249 | u32 btrfs_csum_data(const char *data, u32 seed, size_t len) | ||
250 | { | ||
251 | return crc32c(seed, data, len); | ||
252 | } | ||
253 | |||
254 | void btrfs_csum_final(u32 crc, u8 *result) | ||
255 | { | ||
256 | put_unaligned_le32(~crc, result); | ||
257 | } | ||
258 | |||
259 | /* | 249 | /* |
260 | * Compute the csum of a btree block and store the result to provided buffer. | 250 | * Compute the csum of a btree block and store the result to provided buffer. |
261 | * | 251 | * |
@@ -263,6 +253,8 @@ void btrfs_csum_final(u32 crc, u8 *result) | |||
263 | */ | 253 | */ |
264 | static int csum_tree_block(struct extent_buffer *buf, u8 *result) | 254 | static int csum_tree_block(struct extent_buffer *buf, u8 *result) |
265 | { | 255 | { |
256 | struct btrfs_fs_info *fs_info = buf->fs_info; | ||
257 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
266 | unsigned long len; | 258 | unsigned long len; |
267 | unsigned long cur_len; | 259 | unsigned long cur_len; |
268 | unsigned long offset = BTRFS_CSUM_SIZE; | 260 | unsigned long offset = BTRFS_CSUM_SIZE; |
@@ -270,9 +262,12 @@ static int csum_tree_block(struct extent_buffer *buf, u8 *result) | |||
270 | unsigned long map_start; | 262 | unsigned long map_start; |
271 | unsigned long map_len; | 263 | unsigned long map_len; |
272 | int err; | 264 | int err; |
273 | u32 crc = ~(u32)0; | 265 | |
266 | shash->tfm = fs_info->csum_shash; | ||
267 | crypto_shash_init(shash); | ||
274 | 268 | ||
275 | len = buf->len - offset; | 269 | len = buf->len - offset; |
270 | |||
276 | while (len > 0) { | 271 | while (len > 0) { |
277 | /* | 272 | /* |
278 | * Note: we don't need to check for the err == 1 case here, as | 273 | * Note: we don't need to check for the err == 1 case here, as |
@@ -285,14 +280,13 @@ static int csum_tree_block(struct extent_buffer *buf, u8 *result) | |||
285 | if (WARN_ON(err)) | 280 | if (WARN_ON(err)) |
286 | return err; | 281 | return err; |
287 | cur_len = min(len, map_len - (offset - map_start)); | 282 | cur_len = min(len, map_len - (offset - map_start)); |
288 | crc = btrfs_csum_data(kaddr + offset - map_start, | 283 | crypto_shash_update(shash, kaddr + offset - map_start, cur_len); |
289 | crc, cur_len); | ||
290 | len -= cur_len; | 284 | len -= cur_len; |
291 | offset += cur_len; | 285 | offset += cur_len; |
292 | } | 286 | } |
293 | memset(result, 0, BTRFS_CSUM_SIZE); | 287 | memset(result, 0, BTRFS_CSUM_SIZE); |
294 | 288 | ||
295 | btrfs_csum_final(crc, result); | 289 | crypto_shash_final(shash, result); |
296 | 290 | ||
297 | return 0; | 291 | return 0; |
298 | } | 292 | } |
@@ -372,17 +366,20 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, | |||
372 | { | 366 | { |
373 | struct btrfs_super_block *disk_sb = | 367 | struct btrfs_super_block *disk_sb = |
374 | (struct btrfs_super_block *)raw_disk_sb; | 368 | (struct btrfs_super_block *)raw_disk_sb; |
375 | u32 crc = ~(u32)0; | ||
376 | char result[BTRFS_CSUM_SIZE]; | 369 | char result[BTRFS_CSUM_SIZE]; |
370 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
371 | |||
372 | shash->tfm = fs_info->csum_shash; | ||
373 | crypto_shash_init(shash); | ||
377 | 374 | ||
378 | /* | 375 | /* |
379 | * The super_block structure does not span the whole | 376 | * The super_block structure does not span the whole |
380 | * BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is | 377 | * BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is |
381 | * filled with zeros and is included in the checksum. | 378 | * filled with zeros and is included in the checksum. |
382 | */ | 379 | */ |
383 | crc = btrfs_csum_data(raw_disk_sb + BTRFS_CSUM_SIZE, | 380 | crypto_shash_update(shash, raw_disk_sb + BTRFS_CSUM_SIZE, |
384 | crc, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); | 381 | BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); |
385 | btrfs_csum_final(crc, result); | 382 | crypto_shash_final(shash, result); |
386 | 383 | ||
387 | if (memcmp(disk_sb->csum, result, btrfs_super_csum_size(disk_sb))) | 384 | if (memcmp(disk_sb->csum, result, btrfs_super_csum_size(disk_sb))) |
388 | return 1; | 385 | return 1; |
@@ -3512,17 +3509,20 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) | |||
3512 | static int write_dev_supers(struct btrfs_device *device, | 3509 | static int write_dev_supers(struct btrfs_device *device, |
3513 | struct btrfs_super_block *sb, int max_mirrors) | 3510 | struct btrfs_super_block *sb, int max_mirrors) |
3514 | { | 3511 | { |
3512 | struct btrfs_fs_info *fs_info = device->fs_info; | ||
3513 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
3515 | struct buffer_head *bh; | 3514 | struct buffer_head *bh; |
3516 | int i; | 3515 | int i; |
3517 | int ret; | 3516 | int ret; |
3518 | int errors = 0; | 3517 | int errors = 0; |
3519 | u32 crc; | ||
3520 | u64 bytenr; | 3518 | u64 bytenr; |
3521 | int op_flags; | 3519 | int op_flags; |
3522 | 3520 | ||
3523 | if (max_mirrors == 0) | 3521 | if (max_mirrors == 0) |
3524 | max_mirrors = BTRFS_SUPER_MIRROR_MAX; | 3522 | max_mirrors = BTRFS_SUPER_MIRROR_MAX; |
3525 | 3523 | ||
3524 | shash->tfm = fs_info->csum_shash; | ||
3525 | |||
3526 | for (i = 0; i < max_mirrors; i++) { | 3526 | for (i = 0; i < max_mirrors; i++) { |
3527 | bytenr = btrfs_sb_offset(i); | 3527 | bytenr = btrfs_sb_offset(i); |
3528 | if (bytenr + BTRFS_SUPER_INFO_SIZE >= | 3528 | if (bytenr + BTRFS_SUPER_INFO_SIZE >= |
@@ -3531,10 +3531,10 @@ static int write_dev_supers(struct btrfs_device *device, | |||
3531 | 3531 | ||
3532 | btrfs_set_super_bytenr(sb, bytenr); | 3532 | btrfs_set_super_bytenr(sb, bytenr); |
3533 | 3533 | ||
3534 | crc = ~(u32)0; | 3534 | crypto_shash_init(shash); |
3535 | crc = btrfs_csum_data((const char *)sb + BTRFS_CSUM_SIZE, crc, | 3535 | crypto_shash_update(shash, (const char *)sb + BTRFS_CSUM_SIZE, |
3536 | BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); | 3536 | BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); |
3537 | btrfs_csum_final(crc, sb->csum); | 3537 | crypto_shash_final(shash, sb->csum); |
3538 | 3538 | ||
3539 | /* One reference for us, and we leave it for the caller */ | 3539 | /* One reference for us, and we leave it for the caller */ |
3540 | bh = __getblk(device->bdev, bytenr / BTRFS_BDEV_BLOCKSIZE, | 3540 | bh = __getblk(device->bdev, bytenr / BTRFS_BDEV_BLOCKSIZE, |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index a0161aa1ea0b..e80f7c45a307 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -115,8 +115,6 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, | |||
115 | int atomic); | 115 | int atomic); |
116 | int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid, int level, | 116 | int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid, int level, |
117 | struct btrfs_key *first_key); | 117 | struct btrfs_key *first_key); |
118 | u32 btrfs_csum_data(const char *data, u32 seed, size_t len); | ||
119 | void btrfs_csum_final(u32 crc, u8 *result); | ||
120 | blk_status_t btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, | 118 | blk_status_t btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, |
121 | enum btrfs_wq_endio_type metadata); | 119 | enum btrfs_wq_endio_type metadata); |
122 | blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, | 120 | blk_status_t btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct bio *bio, |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index de89fd1310a6..1a599f50837b 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/pagemap.h> | 8 | #include <linux/pagemap.h> |
9 | #include <linux/highmem.h> | 9 | #include <linux/highmem.h> |
10 | #include <linux/sched/mm.h> | 10 | #include <linux/sched/mm.h> |
11 | #include <crypto/hash.h> | ||
11 | #include "ctree.h" | 12 | #include "ctree.h" |
12 | #include "disk-io.h" | 13 | #include "disk-io.h" |
13 | #include "transaction.h" | 14 | #include "transaction.h" |
@@ -432,6 +433,7 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, | |||
432 | u64 file_start, int contig) | 433 | u64 file_start, int contig) |
433 | { | 434 | { |
434 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); | 435 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
436 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
435 | struct btrfs_ordered_sum *sums; | 437 | struct btrfs_ordered_sum *sums; |
436 | struct btrfs_ordered_extent *ordered = NULL; | 438 | struct btrfs_ordered_extent *ordered = NULL; |
437 | char *data; | 439 | char *data; |
@@ -465,6 +467,8 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, | |||
465 | sums->bytenr = (u64)bio->bi_iter.bi_sector << 9; | 467 | sums->bytenr = (u64)bio->bi_iter.bi_sector << 9; |
466 | index = 0; | 468 | index = 0; |
467 | 469 | ||
470 | shash->tfm = fs_info->csum_shash; | ||
471 | |||
468 | bio_for_each_segment(bvec, bio, iter) { | 472 | bio_for_each_segment(bvec, bio, iter) { |
469 | if (!contig) | 473 | if (!contig) |
470 | offset = page_offset(bvec.bv_page) + bvec.bv_offset; | 474 | offset = page_offset(bvec.bv_page) + bvec.bv_offset; |
@@ -479,8 +483,6 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, | |||
479 | - 1); | 483 | - 1); |
480 | 484 | ||
481 | for (i = 0; i < nr_sectors; i++) { | 485 | for (i = 0; i < nr_sectors; i++) { |
482 | u32 tmp; | ||
483 | |||
484 | if (offset >= ordered->file_offset + ordered->len || | 486 | if (offset >= ordered->file_offset + ordered->len || |
485 | offset < ordered->file_offset) { | 487 | offset < ordered->file_offset) { |
486 | unsigned long bytes_left; | 488 | unsigned long bytes_left; |
@@ -506,15 +508,13 @@ blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, | |||
506 | index = 0; | 508 | index = 0; |
507 | } | 509 | } |
508 | 510 | ||
509 | memset(&sums->sums[index], 0xff, csum_size); | 511 | crypto_shash_init(shash); |
510 | data = kmap_atomic(bvec.bv_page); | 512 | data = kmap_atomic(bvec.bv_page); |
511 | tmp = btrfs_csum_data(data + bvec.bv_offset | 513 | crypto_shash_update(shash, data + bvec.bv_offset |
512 | + (i * fs_info->sectorsize), | 514 | + (i * fs_info->sectorsize), |
513 | *(u32 *)&sums->sums[index], | 515 | fs_info->sectorsize); |
514 | fs_info->sectorsize); | ||
515 | kunmap_atomic(data); | 516 | kunmap_atomic(data); |
516 | btrfs_csum_final(tmp, | 517 | crypto_shash_final(shash, (char *)(sums->sums + index)); |
517 | (char *)(sums->sums + index)); | ||
518 | index += csum_size; | 518 | index += csum_size; |
519 | offset += fs_info->sectorsize; | 519 | offset += fs_info->sectorsize; |
520 | this_sum_bytes += fs_info->sectorsize; | 520 | this_sum_bytes += fs_info->sectorsize; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9137bafc9376..3d356a0f8990 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3203,23 +3203,30 @@ static int __readpage_endio_check(struct inode *inode, | |||
3203 | int icsum, struct page *page, | 3203 | int icsum, struct page *page, |
3204 | int pgoff, u64 start, size_t len) | 3204 | int pgoff, u64 start, size_t len) |
3205 | { | 3205 | { |
3206 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); | ||
3207 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
3206 | char *kaddr; | 3208 | char *kaddr; |
3207 | u32 csum_expected; | 3209 | u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); |
3208 | u32 csum = ~(u32)0; | 3210 | u8 *csum_expected; |
3211 | u8 csum[BTRFS_CSUM_SIZE]; | ||
3209 | 3212 | ||
3210 | csum_expected = *(((u32 *)io_bio->csum) + icsum); | 3213 | csum_expected = ((u8 *)io_bio->csum) + icsum * csum_size; |
3211 | 3214 | ||
3212 | kaddr = kmap_atomic(page); | 3215 | kaddr = kmap_atomic(page); |
3213 | csum = btrfs_csum_data(kaddr + pgoff, csum, len); | 3216 | shash->tfm = fs_info->csum_shash; |
3214 | btrfs_csum_final(csum, (u8 *)&csum); | 3217 | |
3215 | if (csum != csum_expected) | 3218 | crypto_shash_init(shash); |
3219 | crypto_shash_update(shash, kaddr + pgoff, len); | ||
3220 | crypto_shash_final(shash, csum); | ||
3221 | |||
3222 | if (memcmp(csum, csum_expected, csum_size)) | ||
3216 | goto zeroit; | 3223 | goto zeroit; |
3217 | 3224 | ||
3218 | kunmap_atomic(kaddr); | 3225 | kunmap_atomic(kaddr); |
3219 | return 0; | 3226 | return 0; |
3220 | zeroit: | 3227 | zeroit: |
3221 | btrfs_print_data_csum_error(BTRFS_I(inode), start, csum, csum_expected, | 3228 | btrfs_print_data_csum_error(BTRFS_I(inode), start, *(u32 *)csum, |
3222 | io_bio->mirror_num); | 3229 | *(u32 *)csum_expected, io_bio->mirror_num); |
3223 | memset(kaddr + pgoff, 1, len); | 3230 | memset(kaddr + pgoff, 1, len); |
3224 | flush_dcache_page(page); | 3231 | flush_dcache_page(page); |
3225 | kunmap_atomic(kaddr); | 3232 | kunmap_atomic(kaddr); |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 0e77bffd2a5a..9f0297d529d4 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/blkdev.h> | 6 | #include <linux/blkdev.h> |
7 | #include <linux/ratelimit.h> | 7 | #include <linux/ratelimit.h> |
8 | #include <linux/sched/mm.h> | 8 | #include <linux/sched/mm.h> |
9 | #include <crypto/hash.h> | ||
9 | #include "ctree.h" | 10 | #include "ctree.h" |
10 | #include "volumes.h" | 11 | #include "volumes.h" |
11 | #include "disk-io.h" | 12 | #include "disk-io.h" |
@@ -1787,11 +1788,12 @@ static int scrub_checksum(struct scrub_block *sblock) | |||
1787 | static int scrub_checksum_data(struct scrub_block *sblock) | 1788 | static int scrub_checksum_data(struct scrub_block *sblock) |
1788 | { | 1789 | { |
1789 | struct scrub_ctx *sctx = sblock->sctx; | 1790 | struct scrub_ctx *sctx = sblock->sctx; |
1791 | struct btrfs_fs_info *fs_info = sctx->fs_info; | ||
1792 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1790 | u8 csum[BTRFS_CSUM_SIZE]; | 1793 | u8 csum[BTRFS_CSUM_SIZE]; |
1791 | u8 *on_disk_csum; | 1794 | u8 *on_disk_csum; |
1792 | struct page *page; | 1795 | struct page *page; |
1793 | void *buffer; | 1796 | void *buffer; |
1794 | u32 crc = ~(u32)0; | ||
1795 | u64 len; | 1797 | u64 len; |
1796 | int index; | 1798 | int index; |
1797 | 1799 | ||
@@ -1799,6 +1801,9 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1799 | if (!sblock->pagev[0]->have_csum) | 1801 | if (!sblock->pagev[0]->have_csum) |
1800 | return 0; | 1802 | return 0; |
1801 | 1803 | ||
1804 | shash->tfm = fs_info->csum_shash; | ||
1805 | crypto_shash_init(shash); | ||
1806 | |||
1802 | on_disk_csum = sblock->pagev[0]->csum; | 1807 | on_disk_csum = sblock->pagev[0]->csum; |
1803 | page = sblock->pagev[0]->page; | 1808 | page = sblock->pagev[0]->page; |
1804 | buffer = kmap_atomic(page); | 1809 | buffer = kmap_atomic(page); |
@@ -1808,7 +1813,7 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1808 | for (;;) { | 1813 | for (;;) { |
1809 | u64 l = min_t(u64, len, PAGE_SIZE); | 1814 | u64 l = min_t(u64, len, PAGE_SIZE); |
1810 | 1815 | ||
1811 | crc = btrfs_csum_data(buffer, crc, l); | 1816 | crypto_shash_update(shash, buffer, l); |
1812 | kunmap_atomic(buffer); | 1817 | kunmap_atomic(buffer); |
1813 | len -= l; | 1818 | len -= l; |
1814 | if (len == 0) | 1819 | if (len == 0) |
@@ -1820,7 +1825,7 @@ static int scrub_checksum_data(struct scrub_block *sblock) | |||
1820 | buffer = kmap_atomic(page); | 1825 | buffer = kmap_atomic(page); |
1821 | } | 1826 | } |
1822 | 1827 | ||
1823 | btrfs_csum_final(crc, csum); | 1828 | crypto_shash_final(shash, csum); |
1824 | if (memcmp(csum, on_disk_csum, sctx->csum_size)) | 1829 | if (memcmp(csum, on_disk_csum, sctx->csum_size)) |
1825 | sblock->checksum_error = 1; | 1830 | sblock->checksum_error = 1; |
1826 | 1831 | ||
@@ -1832,16 +1837,19 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1832 | struct scrub_ctx *sctx = sblock->sctx; | 1837 | struct scrub_ctx *sctx = sblock->sctx; |
1833 | struct btrfs_header *h; | 1838 | struct btrfs_header *h; |
1834 | struct btrfs_fs_info *fs_info = sctx->fs_info; | 1839 | struct btrfs_fs_info *fs_info = sctx->fs_info; |
1840 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1835 | u8 calculated_csum[BTRFS_CSUM_SIZE]; | 1841 | u8 calculated_csum[BTRFS_CSUM_SIZE]; |
1836 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; | 1842 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; |
1837 | struct page *page; | 1843 | struct page *page; |
1838 | void *mapped_buffer; | 1844 | void *mapped_buffer; |
1839 | u64 mapped_size; | 1845 | u64 mapped_size; |
1840 | void *p; | 1846 | void *p; |
1841 | u32 crc = ~(u32)0; | ||
1842 | u64 len; | 1847 | u64 len; |
1843 | int index; | 1848 | int index; |
1844 | 1849 | ||
1850 | shash->tfm = fs_info->csum_shash; | ||
1851 | crypto_shash_init(shash); | ||
1852 | |||
1845 | BUG_ON(sblock->page_count < 1); | 1853 | BUG_ON(sblock->page_count < 1); |
1846 | page = sblock->pagev[0]->page; | 1854 | page = sblock->pagev[0]->page; |
1847 | mapped_buffer = kmap_atomic(page); | 1855 | mapped_buffer = kmap_atomic(page); |
@@ -1875,7 +1883,7 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1875 | for (;;) { | 1883 | for (;;) { |
1876 | u64 l = min_t(u64, len, mapped_size); | 1884 | u64 l = min_t(u64, len, mapped_size); |
1877 | 1885 | ||
1878 | crc = btrfs_csum_data(p, crc, l); | 1886 | crypto_shash_update(shash, p, l); |
1879 | kunmap_atomic(mapped_buffer); | 1887 | kunmap_atomic(mapped_buffer); |
1880 | len -= l; | 1888 | len -= l; |
1881 | if (len == 0) | 1889 | if (len == 0) |
@@ -1889,7 +1897,7 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock) | |||
1889 | p = mapped_buffer; | 1897 | p = mapped_buffer; |
1890 | } | 1898 | } |
1891 | 1899 | ||
1892 | btrfs_csum_final(crc, calculated_csum); | 1900 | crypto_shash_final(shash, calculated_csum); |
1893 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) | 1901 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) |
1894 | sblock->checksum_error = 1; | 1902 | sblock->checksum_error = 1; |
1895 | 1903 | ||
@@ -1900,18 +1908,22 @@ static int scrub_checksum_super(struct scrub_block *sblock) | |||
1900 | { | 1908 | { |
1901 | struct btrfs_super_block *s; | 1909 | struct btrfs_super_block *s; |
1902 | struct scrub_ctx *sctx = sblock->sctx; | 1910 | struct scrub_ctx *sctx = sblock->sctx; |
1911 | struct btrfs_fs_info *fs_info = sctx->fs_info; | ||
1912 | SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); | ||
1903 | u8 calculated_csum[BTRFS_CSUM_SIZE]; | 1913 | u8 calculated_csum[BTRFS_CSUM_SIZE]; |
1904 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; | 1914 | u8 on_disk_csum[BTRFS_CSUM_SIZE]; |
1905 | struct page *page; | 1915 | struct page *page; |
1906 | void *mapped_buffer; | 1916 | void *mapped_buffer; |
1907 | u64 mapped_size; | 1917 | u64 mapped_size; |
1908 | void *p; | 1918 | void *p; |
1909 | u32 crc = ~(u32)0; | ||
1910 | int fail_gen = 0; | 1919 | int fail_gen = 0; |
1911 | int fail_cor = 0; | 1920 | int fail_cor = 0; |
1912 | u64 len; | 1921 | u64 len; |
1913 | int index; | 1922 | int index; |
1914 | 1923 | ||
1924 | shash->tfm = fs_info->csum_shash; | ||
1925 | crypto_shash_init(shash); | ||
1926 | |||
1915 | BUG_ON(sblock->page_count < 1); | 1927 | BUG_ON(sblock->page_count < 1); |
1916 | page = sblock->pagev[0]->page; | 1928 | page = sblock->pagev[0]->page; |
1917 | mapped_buffer = kmap_atomic(page); | 1929 | mapped_buffer = kmap_atomic(page); |
@@ -1934,7 +1946,7 @@ static int scrub_checksum_super(struct scrub_block *sblock) | |||
1934 | for (;;) { | 1946 | for (;;) { |
1935 | u64 l = min_t(u64, len, mapped_size); | 1947 | u64 l = min_t(u64, len, mapped_size); |
1936 | 1948 | ||
1937 | crc = btrfs_csum_data(p, crc, l); | 1949 | crypto_shash_update(shash, p, l); |
1938 | kunmap_atomic(mapped_buffer); | 1950 | kunmap_atomic(mapped_buffer); |
1939 | len -= l; | 1951 | len -= l; |
1940 | if (len == 0) | 1952 | if (len == 0) |
@@ -1948,7 +1960,7 @@ static int scrub_checksum_super(struct scrub_block *sblock) | |||
1948 | p = mapped_buffer; | 1960 | p = mapped_buffer; |
1949 | } | 1961 | } |
1950 | 1962 | ||
1951 | btrfs_csum_final(crc, calculated_csum); | 1963 | crypto_shash_final(shash, calculated_csum); |
1952 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) | 1964 | if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size)) |
1953 | ++fail_cor; | 1965 | ++fail_cor; |
1954 | 1966 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 526dbae5c4cf..6e196b8a0820 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -2464,3 +2464,4 @@ late_initcall(init_btrfs_fs); | |||
2464 | module_exit(exit_btrfs_fs) | 2464 | module_exit(exit_btrfs_fs) |
2465 | 2465 | ||
2466 | MODULE_LICENSE("GPL"); | 2466 | MODULE_LICENSE("GPL"); |
2467 | MODULE_SOFTDEP("pre: crc32c"); | ||