diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-09-12 06:43:55 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-09-17 16:38:52 -0400 |
commit | dc380aea5fa4636fc498a351eb720943bc644451 (patch) | |
tree | 9bbc8a668a1c18b828ff7fc71d6807e6df4ad538 | |
parent | 23ea8e5a07673127d05cb5cf6f9914d7a53e0847 (diff) |
Btrfs: cleanup similar code of the buffered data data check and dio read data check
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r-- | fs/btrfs/inode.c | 102 |
1 files changed, 47 insertions, 55 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fca944211bf0..70eaae127181 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2899,6 +2899,40 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, | |||
2899 | return 0; | 2899 | return 0; |
2900 | } | 2900 | } |
2901 | 2901 | ||
2902 | static int __readpage_endio_check(struct inode *inode, | ||
2903 | struct btrfs_io_bio *io_bio, | ||
2904 | int icsum, struct page *page, | ||
2905 | int pgoff, u64 start, size_t len) | ||
2906 | { | ||
2907 | char *kaddr; | ||
2908 | u32 csum_expected; | ||
2909 | u32 csum = ~(u32)0; | ||
2910 | static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, | ||
2911 | DEFAULT_RATELIMIT_BURST); | ||
2912 | |||
2913 | csum_expected = *(((u32 *)io_bio->csum) + icsum); | ||
2914 | |||
2915 | kaddr = kmap_atomic(page); | ||
2916 | csum = btrfs_csum_data(kaddr + pgoff, csum, len); | ||
2917 | btrfs_csum_final(csum, (char *)&csum); | ||
2918 | if (csum != csum_expected) | ||
2919 | goto zeroit; | ||
2920 | |||
2921 | kunmap_atomic(kaddr); | ||
2922 | return 0; | ||
2923 | zeroit: | ||
2924 | if (__ratelimit(&_rs)) | ||
2925 | btrfs_info(BTRFS_I(inode)->root->fs_info, | ||
2926 | "csum failed ino %llu off %llu csum %u expected csum %u", | ||
2927 | btrfs_ino(inode), start, csum, csum_expected); | ||
2928 | memset(kaddr + pgoff, 1, len); | ||
2929 | flush_dcache_page(page); | ||
2930 | kunmap_atomic(kaddr); | ||
2931 | if (csum_expected == 0) | ||
2932 | return 0; | ||
2933 | return -EIO; | ||
2934 | } | ||
2935 | |||
2902 | /* | 2936 | /* |
2903 | * when reads are done, we need to check csums to verify the data is correct | 2937 | * when reads are done, we need to check csums to verify the data is correct |
2904 | * if there's a match, we allow the bio to finish. If not, the code in | 2938 | * if there's a match, we allow the bio to finish. If not, the code in |
@@ -2911,20 +2945,15 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio, | |||
2911 | size_t offset = start - page_offset(page); | 2945 | size_t offset = start - page_offset(page); |
2912 | struct inode *inode = page->mapping->host; | 2946 | struct inode *inode = page->mapping->host; |
2913 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 2947 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
2914 | char *kaddr; | ||
2915 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2948 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2916 | u32 csum_expected; | ||
2917 | u32 csum = ~(u32)0; | ||
2918 | static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, | ||
2919 | DEFAULT_RATELIMIT_BURST); | ||
2920 | 2949 | ||
2921 | if (PageChecked(page)) { | 2950 | if (PageChecked(page)) { |
2922 | ClearPageChecked(page); | 2951 | ClearPageChecked(page); |
2923 | goto good; | 2952 | return 0; |
2924 | } | 2953 | } |
2925 | 2954 | ||
2926 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) | 2955 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) |
2927 | goto good; | 2956 | return 0; |
2928 | 2957 | ||
2929 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && | 2958 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && |
2930 | test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1, NULL)) { | 2959 | test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1, NULL)) { |
@@ -2934,28 +2963,8 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio, | |||
2934 | } | 2963 | } |
2935 | 2964 | ||
2936 | phy_offset >>= inode->i_sb->s_blocksize_bits; | 2965 | phy_offset >>= inode->i_sb->s_blocksize_bits; |
2937 | csum_expected = *(((u32 *)io_bio->csum) + phy_offset); | 2966 | return __readpage_endio_check(inode, io_bio, phy_offset, page, offset, |
2938 | 2967 | start, (size_t)(end - start + 1)); | |
2939 | kaddr = kmap_atomic(page); | ||
2940 | csum = btrfs_csum_data(kaddr + offset, csum, end - start + 1); | ||
2941 | btrfs_csum_final(csum, (char *)&csum); | ||
2942 | if (csum != csum_expected) | ||
2943 | goto zeroit; | ||
2944 | |||
2945 | kunmap_atomic(kaddr); | ||
2946 | good: | ||
2947 | return 0; | ||
2948 | |||
2949 | zeroit: | ||
2950 | if (__ratelimit(&_rs)) | ||
2951 | btrfs_info(root->fs_info, "csum failed ino %llu off %llu csum %u expected csum %u", | ||
2952 | btrfs_ino(page->mapping->host), start, csum, csum_expected); | ||
2953 | memset(kaddr + offset, 1, end - start + 1); | ||
2954 | flush_dcache_page(page); | ||
2955 | kunmap_atomic(kaddr); | ||
2956 | if (csum_expected == 0) | ||
2957 | return 0; | ||
2958 | return -EIO; | ||
2959 | } | 2968 | } |
2960 | 2969 | ||
2961 | struct delayed_iput { | 2970 | struct delayed_iput { |
@@ -7238,41 +7247,24 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) | |||
7238 | struct btrfs_dio_private *dip = bio->bi_private; | 7247 | struct btrfs_dio_private *dip = bio->bi_private; |
7239 | struct bio_vec *bvec; | 7248 | struct bio_vec *bvec; |
7240 | struct inode *inode = dip->inode; | 7249 | struct inode *inode = dip->inode; |
7241 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
7242 | struct bio *dio_bio; | 7250 | struct bio *dio_bio; |
7243 | struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); | 7251 | struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); |
7244 | u32 *csums = (u32 *)io_bio->csum; | ||
7245 | u64 start; | 7252 | u64 start; |
7253 | int ret; | ||
7246 | int i; | 7254 | int i; |
7247 | 7255 | ||
7256 | if (err || (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) | ||
7257 | goto skip_checksum; | ||
7258 | |||
7248 | start = dip->logical_offset; | 7259 | start = dip->logical_offset; |
7249 | bio_for_each_segment_all(bvec, bio, i) { | 7260 | bio_for_each_segment_all(bvec, bio, i) { |
7250 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { | 7261 | ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page, |
7251 | struct page *page = bvec->bv_page; | 7262 | 0, start, bvec->bv_len); |
7252 | char *kaddr; | 7263 | if (ret) |
7253 | u32 csum = ~(u32)0; | 7264 | err = -EIO; |
7254 | unsigned long flags; | ||
7255 | |||
7256 | local_irq_save(flags); | ||
7257 | kaddr = kmap_atomic(page); | ||
7258 | csum = btrfs_csum_data(kaddr + bvec->bv_offset, | ||
7259 | csum, bvec->bv_len); | ||
7260 | btrfs_csum_final(csum, (char *)&csum); | ||
7261 | kunmap_atomic(kaddr); | ||
7262 | local_irq_restore(flags); | ||
7263 | |||
7264 | flush_dcache_page(bvec->bv_page); | ||
7265 | if (csum != csums[i]) { | ||
7266 | btrfs_err(root->fs_info, "csum failed ino %llu off %llu csum %u expected csum %u", | ||
7267 | btrfs_ino(inode), start, csum, | ||
7268 | csums[i]); | ||
7269 | err = -EIO; | ||
7270 | } | ||
7271 | } | ||
7272 | |||
7273 | start += bvec->bv_len; | 7265 | start += bvec->bv_len; |
7274 | } | 7266 | } |
7275 | 7267 | skip_checksum: | |
7276 | unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, | 7268 | unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, |
7277 | dip->logical_offset + dip->bytes - 1); | 7269 | dip->logical_offset + dip->bytes - 1); |
7278 | dio_bio = dip->dio_bio; | 7270 | dio_bio = dip->dio_bio; |