diff options
-rw-r--r-- | fs/btrfs/ctree.c | 5 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 86 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 1 |
5 files changed, 60 insertions, 36 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6ba5394834be..df090bf2eec0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -158,6 +158,8 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
158 | } else { | 158 | } else { |
159 | root_gen = 0; | 159 | root_gen = 0; |
160 | } | 160 | } |
161 | if (!(buf->flags & EXTENT_CSUM)) | ||
162 | WARN_ON(1); | ||
161 | 163 | ||
162 | WARN_ON(root->ref_cows && trans->transid != | 164 | WARN_ON(root->ref_cows && trans->transid != |
163 | root->fs_info->running_transaction->transid); | 165 | root->fs_info->running_transaction->transid); |
@@ -245,6 +247,8 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
245 | root->fs_info->generation); | 247 | root->fs_info->generation); |
246 | WARN_ON(1); | 248 | WARN_ON(1); |
247 | } | 249 | } |
250 | if (!(buf->flags & EXTENT_CSUM)) | ||
251 | WARN_ON(1); | ||
248 | 252 | ||
249 | header_trans = btrfs_header_generation(buf); | 253 | header_trans = btrfs_header_generation(buf); |
250 | spin_lock(&root->fs_info->hash_lock); | 254 | spin_lock(&root->fs_info->hash_lock); |
@@ -396,6 +400,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
396 | if (search_start == 0) | 400 | if (search_start == 0) |
397 | search_start = last_block; | 401 | search_start = last_block; |
398 | 402 | ||
403 | btrfs_verify_block_csum(root, cur); | ||
399 | err = __btrfs_cow_block(trans, root, cur, parent, i, | 404 | err = __btrfs_cow_block(trans, root, cur, parent, i, |
400 | &tmp, search_start, | 405 | &tmp, search_start, |
401 | min(16 * blocksize, | 406 | min(16 * blocksize, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5547607681f4..e40fb318ad99 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) | |||
46 | 46 | ||
47 | static struct extent_io_ops btree_extent_io_ops; | 47 | static struct extent_io_ops btree_extent_io_ops; |
48 | 48 | ||
49 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | ||
50 | u64 bytenr, u32 blocksize) | ||
51 | { | ||
52 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
53 | struct extent_buffer *eb; | ||
54 | eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree, | ||
55 | bytenr, blocksize, GFP_NOFS); | ||
56 | return eb; | ||
57 | } | ||
58 | |||
59 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, | ||
60 | u64 bytenr, u32 blocksize) | ||
61 | { | ||
62 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
63 | struct extent_buffer *eb; | ||
64 | |||
65 | eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree, | ||
66 | bytenr, blocksize, NULL, GFP_NOFS); | ||
67 | return eb; | ||
68 | } | ||
69 | |||
70 | struct extent_map *btree_get_extent(struct inode *inode, struct page *page, | 49 | struct extent_map *btree_get_extent(struct inode *inode, struct page *page, |
71 | size_t page_offset, u64 start, u64 len, | 50 | size_t page_offset, u64 start, u64 len, |
72 | int create) | 51 | int create) |
@@ -380,36 +359,29 @@ static int close_all_devices(struct btrfs_fs_info *fs_info) | |||
380 | return 0; | 359 | return 0; |
381 | } | 360 | } |
382 | 361 | ||
383 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | 362 | int btrfs_verify_block_csum(struct btrfs_root *root, |
384 | u32 blocksize) | 363 | struct extent_buffer *buf) |
385 | { | 364 | { |
386 | struct extent_buffer *buf = NULL; | ||
387 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
388 | struct extent_io_tree *io_tree; | 365 | struct extent_io_tree *io_tree; |
389 | u64 end; | 366 | u64 end; |
390 | int ret; | 367 | int ret; |
391 | 368 | ||
392 | io_tree = &BTRFS_I(btree_inode)->io_tree; | 369 | io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; |
393 | |||
394 | buf = btrfs_find_create_tree_block(root, bytenr, blocksize); | ||
395 | if (!buf) | ||
396 | return NULL; | ||
397 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 1, | ||
398 | btree_get_extent); | ||
399 | |||
400 | if (buf->flags & EXTENT_CSUM) | 370 | if (buf->flags & EXTENT_CSUM) |
401 | return buf; | 371 | return 0; |
402 | 372 | ||
403 | end = buf->start + PAGE_CACHE_SIZE - 1; | 373 | end = min_t(u64, buf->len, PAGE_CACHE_SIZE); |
374 | end = buf->start + end - 1; | ||
404 | if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { | 375 | if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { |
405 | buf->flags |= EXTENT_CSUM; | 376 | buf->flags |= EXTENT_CSUM; |
406 | return buf; | 377 | return 0; |
407 | } | 378 | } |
408 | 379 | ||
409 | lock_extent(io_tree, buf->start, end, GFP_NOFS); | 380 | lock_extent(io_tree, buf->start, end, GFP_NOFS); |
410 | 381 | ||
411 | if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { | 382 | if (test_range_bit(io_tree, buf->start, end, EXTENT_CSUM, 1)) { |
412 | buf->flags |= EXTENT_CSUM; | 383 | buf->flags |= EXTENT_CSUM; |
384 | ret = 0; | ||
413 | goto out_unlock; | 385 | goto out_unlock; |
414 | } | 386 | } |
415 | 387 | ||
@@ -419,6 +391,48 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | |||
419 | 391 | ||
420 | out_unlock: | 392 | out_unlock: |
421 | unlock_extent(io_tree, buf->start, end, GFP_NOFS); | 393 | unlock_extent(io_tree, buf->start, end, GFP_NOFS); |
394 | return ret; | ||
395 | } | ||
396 | |||
397 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | ||
398 | u64 bytenr, u32 blocksize) | ||
399 | { | ||
400 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
401 | struct extent_buffer *eb; | ||
402 | eb = find_extent_buffer(&BTRFS_I(btree_inode)->io_tree, | ||
403 | bytenr, blocksize, GFP_NOFS); | ||
404 | return eb; | ||
405 | } | ||
406 | |||
407 | struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, | ||
408 | u64 bytenr, u32 blocksize) | ||
409 | { | ||
410 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
411 | struct extent_buffer *eb; | ||
412 | |||
413 | eb = alloc_extent_buffer(&BTRFS_I(btree_inode)->io_tree, | ||
414 | bytenr, blocksize, NULL, GFP_NOFS); | ||
415 | return eb; | ||
416 | } | ||
417 | |||
418 | |||
419 | struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | ||
420 | u32 blocksize) | ||
421 | { | ||
422 | struct extent_buffer *buf = NULL; | ||
423 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
424 | struct extent_io_tree *io_tree; | ||
425 | int ret; | ||
426 | |||
427 | io_tree = &BTRFS_I(btree_inode)->io_tree; | ||
428 | |||
429 | buf = btrfs_find_create_tree_block(root, bytenr, blocksize); | ||
430 | if (!buf) | ||
431 | return NULL; | ||
432 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, buf, 0, 1, | ||
433 | btree_get_extent); | ||
434 | |||
435 | ret = btrfs_verify_block_csum(root, buf); | ||
422 | return buf; | 436 | return buf; |
423 | } | 437 | } |
424 | 438 | ||
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index b7cbc58a5553..05b88d0e75eb 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); | |||
69 | void btrfs_csum_final(u32 crc, char *result); | 69 | void btrfs_csum_final(u32 crc, char *result); |
70 | void btrfs_throttle(struct btrfs_root *root); | 70 | void btrfs_throttle(struct btrfs_root *root); |
71 | int btrfs_open_device(struct btrfs_device *dev); | 71 | int btrfs_open_device(struct btrfs_device *dev); |
72 | int btrfs_verify_block_csum(struct btrfs_root *root, | ||
73 | struct extent_buffer *buf); | ||
72 | #endif | 74 | #endif |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cf283b0271ac..a34c289aec21 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, | |||
2069 | BUG_ON(ret); | 2069 | BUG_ON(ret); |
2070 | continue; | 2070 | continue; |
2071 | } | 2071 | } |
2072 | } else if (next) { | ||
2073 | btrfs_verify_block_csum(root, next); | ||
2072 | } | 2074 | } |
2073 | WARN_ON(*level <= 0); | 2075 | WARN_ON(*level <= 0); |
2074 | if (path->nodes[*level-1]) | 2076 | if (path->nodes[*level-1]) |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 5935cbd8f2b8..256af1870eef 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, | |||
101 | path->slots[*level]++; | 101 | path->slots[*level]++; |
102 | continue; | 102 | continue; |
103 | } | 103 | } |
104 | btrfs_verify_block_csum(root, next); | ||
104 | } else { | 105 | } else { |
105 | next = read_tree_block(root, bytenr, | 106 | next = read_tree_block(root, bytenr, |
106 | btrfs_level_size(root, *level - 1)); | 107 | btrfs_level_size(root, *level - 1)); |