aboutsummaryrefslogtreecommitdiffstats
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 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
47static struct extent_io_ops btree_extent_io_ops; 47static struct extent_io_ops btree_extent_io_ops;
48 48
49struct 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
59struct 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
70struct extent_map *btree_get_extent(struct inode *inode, struct page *page, 49struct 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
383struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, 362int 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
420out_unlock: 392out_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
397struct 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
407struct 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
419struct 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);
69void btrfs_csum_final(u32 crc, char *result); 69void btrfs_csum_final(u32 crc, char *result);
70void btrfs_throttle(struct btrfs_root *root); 70void btrfs_throttle(struct btrfs_root *root);
71int btrfs_open_device(struct btrfs_device *dev); 71int btrfs_open_device(struct btrfs_device *dev);
72int 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));