summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c5
-rw-r--r--fs/btrfs/disk-io.c86
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c2
-rw-r--r--fs/btrfs/tree-defrag.c1
5 files changed, 60 insertions, 36 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 6ba5394834b..df090bf2eec 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -158,6 +158,8 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
} else {
root_gen = 0;
}
+ if (!(buf->flags & EXTENT_CSUM))
+ WARN_ON(1);
WARN_ON(root->ref_cows && trans->transid !=
root->fs_info->running_transaction->transid);
@@ -245,6 +247,8 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
root->fs_info->generation);
WARN_ON(1);
}
+ if (!(buf->flags & EXTENT_CSUM))
+ WARN_ON(1);
header_trans = btrfs_header_generation(buf);
spin_lock(&root->fs_info->hash_lock);
@@ -396,6 +400,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
if (search_start == 0)
search_start = last_block;
+ btrfs_verify_block_csum(root, cur);
err = __btrfs_cow_block(trans, root, cur, parent, i,
&tmp, search_start,
min(16 * blocksize,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5547607681f..e40fb318ad9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -46,27 +46,6 @@ static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
static struct extent_io_ops btree_extent_io_ops;
-struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
- u64 bytenr, u32 blocksize)
-{
- struct inode *btree_inode = root->fs_info->btree_inode;
- struct extent_buffer *eb;
- eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree,
- bytenr, blocksize, GFP_NOFS);
- return eb;
-}
-
-struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
- u64 bytenr, u32 blocksize)
-{
- struct inode *btree_inode = root->fs_info->btree_inode;
- struct extent_buffer *eb;
-
- eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree,
- bytenr, blocksize, NULL, GFP_NOFS);
- return eb;
-}
-
struct extent_map *btree_get_extent(struct inode *inode, struct page *page,
size_t page_offset, u64 start, u64 len,
int create)
@@ -380,36 +359,29 @@ static int close_all_devices(struct btrfs_fs_info *fs_info)
return 0;
}
-struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
- u32 blocksize)
+int btrfs_verify_block_csum(struct btrfs_root *root,
+ struct extent_buffer *buf)
{
- struct extent_buffer *buf = NULL;
- struct inode *btree_inode = root->fs_info->btree_inode;
struct extent_io_tree *io_tree;
u64 end;
int ret;
- io_tree = &BTRFS_I(btree_inode)->io_tree;
-
- buf = btrfs_find_create_tree_block(root, bytenr, blocksize);
- if (!buf)
- return NULL;
- read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 1,
- btree_get_extent);
-
+ io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
if (buf->flags & EXTENT_CSUM)
- return buf;
+ return 0;
- end = buf->start + PAGE_CACHE_SIZE - 1;
+ end = min_t(u64, buf->len, PAGE_CACHE_SIZE);
+ end = buf->start + end - 1;
if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) {
buf->flags |= EXTENT_CSUM;
- return buf;
+ return 0;
}
lock_extent(io_tree, buf->start, end, GFP_NOFS);
if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) {
buf->flags |= EXTENT_CSUM;
+ ret = 0;
goto out_unlock;
}
@@ -419,6 +391,48 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
out_unlock:
unlock_extent(io_tree, buf->start, end, GFP_NOFS);
+ return ret;
+}
+
+struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
+ u64 bytenr, u32 blocksize)
+{
+ struct inode *btree_inode = root->fs_info->btree_inode;
+ struct extent_buffer *eb;
+ eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree,
+ bytenr, blocksize, GFP_NOFS);
+ return eb;
+}
+
+struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
+ u64 bytenr, u32 blocksize)
+{
+ struct inode *btree_inode = root->fs_info->btree_inode;
+ struct extent_buffer *eb;
+
+ eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree,
+ bytenr, blocksize, NULL, GFP_NOFS);
+ return eb;
+}
+
+
+struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
+ u32 blocksize)
+{
+ struct extent_buffer *buf = NULL;
+ struct inode *btree_inode = root->fs_info->btree_inode;
+ struct extent_io_tree *io_tree;
+ int ret;
+
+ io_tree = &BTRFS_I(btree_inode)->io_tree;
+
+ buf = btrfs_find_create_tree_block(root, bytenr, blocksize);
+ if (!buf)
+ return NULL;
+ read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 1,
+ btree_get_extent);
+
+ ret = btrfs_verify_block_csum(root, buf);
return buf;
}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index b7cbc58a555..05b88d0e75e 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -69,4 +69,6 @@ u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
void btrfs_csum_final(u32 crc, char *result);
void btrfs_throttle(struct btrfs_root *root);
int btrfs_open_device(struct btrfs_device *dev);
+int btrfs_verify_block_csum(struct btrfs_root *root,
+ struct extent_buffer *buf);
#endif
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index cf283b0271a..a34c289aec2 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2069,6 +2069,8 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
BUG_ON(ret);
continue;
}
+ } else if (next) {
+ btrfs_verify_block_csum(root, next);
}
WARN_ON(*level <= 0);
if (path->nodes[*level-1])
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 5935cbd8f2b..256af1870ee 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -101,6 +101,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
path->slots[*level]++;
continue;
}
+ btrfs_verify_block_csum(root, next);
} else {
next = read_tree_block(root, bytenr,
btrfs_level_size(root, *level - 1));