aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c123
-rw-r--r--fs/btrfs/disk-io.c90
-rw-r--r--fs/btrfs/extent-tree.c5
-rw-r--r--fs/btrfs/extent_io.h1
4 files changed, 95 insertions, 124 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index b5baff0dccfe..73e53009e126 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -732,122 +732,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root,
732 return btrfs_item_offset_nr(leaf, nr - 1); 732 return btrfs_item_offset_nr(leaf, nr - 1);
733} 733}
734 734
735/*
736 * extra debugging checks to make sure all the items in a key are
737 * well formed and in the proper order
738 */
739static int check_node(struct btrfs_root *root, struct btrfs_path *path,
740 int level)
741{
742 struct extent_buffer *parent = NULL;
743 struct extent_buffer *node = path->nodes[level];
744 struct btrfs_disk_key parent_key;
745 struct btrfs_disk_key node_key;
746 int parent_slot;
747 int slot;
748 struct btrfs_key cpukey;
749 u32 nritems = btrfs_header_nritems(node);
750
751 if (path->nodes[level + 1])
752 parent = path->nodes[level + 1];
753
754 slot = path->slots[level];
755 BUG_ON(nritems == 0);
756 if (parent) {
757 parent_slot = path->slots[level + 1];
758 btrfs_node_key(parent, &parent_key, parent_slot);
759 btrfs_node_key(node, &node_key, 0);
760 BUG_ON(memcmp(&parent_key, &node_key,
761 sizeof(struct btrfs_disk_key)));
762 BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
763 btrfs_header_bytenr(node));
764 }
765 BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
766 if (slot != 0) {
767 btrfs_node_key_to_cpu(node, &cpukey, slot - 1);
768 btrfs_node_key(node, &node_key, slot);
769 BUG_ON(comp_keys(&node_key, &cpukey) <= 0);
770 }
771 if (slot < nritems - 1) {
772 btrfs_node_key_to_cpu(node, &cpukey, slot + 1);
773 btrfs_node_key(node, &node_key, slot);
774 BUG_ON(comp_keys(&node_key, &cpukey) >= 0);
775 }
776 return 0;
777}
778
779/*
780 * extra checking to make sure all the items in a leaf are
781 * well formed and in the proper order
782 */
783static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
784 int level)
785{
786 struct extent_buffer *leaf = path->nodes[level];
787 struct extent_buffer *parent = NULL;
788 int parent_slot;
789 struct btrfs_key cpukey;
790 struct btrfs_disk_key parent_key;
791 struct btrfs_disk_key leaf_key;
792 int slot = path->slots[0];
793
794 u32 nritems = btrfs_header_nritems(leaf);
795
796 if (path->nodes[level + 1])
797 parent = path->nodes[level + 1];
798
799 if (nritems == 0)
800 return 0;
801
802 if (parent) {
803 parent_slot = path->slots[level + 1];
804 btrfs_node_key(parent, &parent_key, parent_slot);
805 btrfs_item_key(leaf, &leaf_key, 0);
806
807 BUG_ON(memcmp(&parent_key, &leaf_key,
808 sizeof(struct btrfs_disk_key)));
809 BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
810 btrfs_header_bytenr(leaf));
811 }
812 if (slot != 0 && slot < nritems - 1) {
813 btrfs_item_key(leaf, &leaf_key, slot);
814 btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1);
815 if (comp_keys(&leaf_key, &cpukey) <= 0) {
816 btrfs_print_leaf(root, leaf);
817 printk(KERN_CRIT "slot %d offset bad key\n", slot);
818 BUG_ON(1);
819 }
820 if (btrfs_item_offset_nr(leaf, slot - 1) !=
821 btrfs_item_end_nr(leaf, slot)) {
822 btrfs_print_leaf(root, leaf);
823 printk(KERN_CRIT "slot %d offset bad\n", slot);
824 BUG_ON(1);
825 }
826 }
827 if (slot < nritems - 1) {
828 btrfs_item_key(leaf, &leaf_key, slot);
829 btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1);
830 BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0);
831 if (btrfs_item_offset_nr(leaf, slot) !=
832 btrfs_item_end_nr(leaf, slot + 1)) {
833 btrfs_print_leaf(root, leaf);
834 printk(KERN_CRIT "slot %d offset bad\n", slot);
835 BUG_ON(1);
836 }
837 }
838 BUG_ON(btrfs_item_offset_nr(leaf, 0) +
839 btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root));
840 return 0;
841}
842
843static noinline int check_block(struct btrfs_root *root,
844 struct btrfs_path *path, int level)
845{
846 return 0;
847 if (level == 0)
848 return check_leaf(root, path, level);
849 return check_node(root, path, level);
850}
851 735
852/* 736/*
853 * search for key in the extent_buffer. The items start at offset p, 737 * search for key in the extent_buffer. The items start at offset p,
@@ -1188,7 +1072,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1188 } 1072 }
1189 } 1073 }
1190 /* double check we haven't messed things up */ 1074 /* double check we haven't messed things up */
1191 check_block(root, path, level);
1192 if (orig_ptr != 1075 if (orig_ptr !=
1193 btrfs_node_blockptr(path->nodes[level], path->slots[level])) 1076 btrfs_node_blockptr(path->nodes[level], path->slots[level]))
1194 BUG(); 1077 BUG();
@@ -1798,12 +1681,6 @@ cow_done:
1798 if (!cow) 1681 if (!cow)
1799 btrfs_unlock_up_safe(p, level + 1); 1682 btrfs_unlock_up_safe(p, level + 1);
1800 1683
1801 ret = check_block(root, p, level);
1802 if (ret) {
1803 ret = -1;
1804 goto done;
1805 }
1806
1807 ret = bin_search(b, key, level, &slot); 1684 ret = bin_search(b, key, level, &slot);
1808 1685
1809 if (level != 0) { 1686 if (level != 0) {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 495b1ac45f8c..9f31e110b481 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -323,6 +323,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
323 int num_copies = 0; 323 int num_copies = 0;
324 int mirror_num = 0; 324 int mirror_num = 0;
325 325
326 clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
326 io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; 327 io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
327 while (1) { 328 while (1) {
328 ret = read_extent_buffer_pages(io_tree, eb, start, 1, 329 ret = read_extent_buffer_pages(io_tree, eb, start, 1,
@@ -331,6 +332,14 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
331 !verify_parent_transid(io_tree, eb, parent_transid)) 332 !verify_parent_transid(io_tree, eb, parent_transid))
332 return ret; 333 return ret;
333 334
335 /*
336 * This buffer's crc is fine, but its contents are corrupted, so
337 * there is no reason to read the other copies, they won't be
338 * any less wrong.
339 */
340 if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags))
341 return ret;
342
334 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, 343 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
335 eb->start, eb->len); 344 eb->start, eb->len);
336 if (num_copies == 1) 345 if (num_copies == 1)
@@ -419,6 +428,73 @@ static int check_tree_block_fsid(struct btrfs_root *root,
419 return ret; 428 return ret;
420} 429}
421 430
431#define CORRUPT(reason, eb, root, slot) \
432 printk(KERN_CRIT "btrfs: corrupt leaf, %s: block=%llu," \
433 "root=%llu, slot=%d\n", reason, \
434 (unsigned long long)btrfs_header_bytenr(eb), \
435 (unsigned long long)root->objectid, slot)
436
437static noinline int check_leaf(struct btrfs_root *root,
438 struct extent_buffer *leaf)
439{
440 struct btrfs_key key;
441 struct btrfs_key leaf_key;
442 u32 nritems = btrfs_header_nritems(leaf);
443 int slot;
444
445 if (nritems == 0)
446 return 0;
447
448 /* Check the 0 item */
449 if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
450 BTRFS_LEAF_DATA_SIZE(root)) {
451 CORRUPT("invalid item offset size pair", leaf, root, 0);
452 return -EIO;
453 }
454
455 /*
456 * Check to make sure each items keys are in the correct order and their
457 * offsets make sense. We only have to loop through nritems-1 because
458 * we check the current slot against the next slot, which verifies the
459 * next slot's offset+size makes sense and that the current's slot
460 * offset is correct.
461 */
462 for (slot = 0; slot < nritems - 1; slot++) {
463 btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
464 btrfs_item_key_to_cpu(leaf, &key, slot + 1);
465
466 /* Make sure the keys are in the right order */
467 if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
468 CORRUPT("bad key order", leaf, root, slot);
469 return -EIO;
470 }
471
472 /*
473 * Make sure the offset and ends are right, remember that the
474 * item data starts at the end of the leaf and grows towards the
475 * front.
476 */
477 if (btrfs_item_offset_nr(leaf, slot) !=
478 btrfs_item_end_nr(leaf, slot + 1)) {
479 CORRUPT("slot offset bad", leaf, root, slot);
480 return -EIO;
481 }
482
483 /*
484 * Check to make sure that we don't point outside of the leaf,
485 * just incase all the items are consistent to eachother, but
486 * all point outside of the leaf.
487 */
488 if (btrfs_item_end_nr(leaf, slot) >
489 BTRFS_LEAF_DATA_SIZE(root)) {
490 CORRUPT("slot end outside of leaf", leaf, root, slot);
491 return -EIO;
492 }
493 }
494
495 return 0;
496}
497
422#ifdef CONFIG_DEBUG_LOCK_ALLOC 498#ifdef CONFIG_DEBUG_LOCK_ALLOC
423void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level) 499void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
424{ 500{
@@ -485,8 +561,20 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
485 btrfs_set_buffer_lockdep_class(eb, found_level); 561 btrfs_set_buffer_lockdep_class(eb, found_level);
486 562
487 ret = csum_tree_block(root, eb, 1); 563 ret = csum_tree_block(root, eb, 1);
488 if (ret) 564 if (ret) {
489 ret = -EIO; 565 ret = -EIO;
566 goto err;
567 }
568
569 /*
570 * If this is a leaf block and it is corrupt, set the corrupt bit so
571 * that we don't try and read the other copies of this block, just
572 * return -EIO.
573 */
574 if (found_level == 0 && check_leaf(root, eb)) {
575 set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
576 ret = -EIO;
577 }
490 578
491 end = min_t(u64, eb->len, PAGE_CACHE_SIZE); 579 end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
492 end = eb->start + end - 1; 580 end = eb->start + end - 1;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a8f4e8d2ba60..cd794c35a636 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4754,6 +4754,11 @@ pin:
4754 } 4754 }
4755 } 4755 }
4756out: 4756out:
4757 /*
4758 * Deleting the buffer, clear the corrupt flag since it doesn't matter
4759 * anymore.
4760 */
4761 clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
4757 btrfs_put_block_group(cache); 4762 btrfs_put_block_group(cache);
4758} 4763}
4759 4764
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 9318dfefd59c..f62c5442835d 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -31,6 +31,7 @@
31#define EXTENT_BUFFER_UPTODATE 0 31#define EXTENT_BUFFER_UPTODATE 0
32#define EXTENT_BUFFER_BLOCKING 1 32#define EXTENT_BUFFER_BLOCKING 1
33#define EXTENT_BUFFER_DIRTY 2 33#define EXTENT_BUFFER_DIRTY 2
34#define EXTENT_BUFFER_CORRUPT 3
34 35
35/* these are flags for extent_clear_unlock_delalloc */ 36/* these are flags for extent_clear_unlock_delalloc */
36#define EXTENT_CLEAR_UNLOCK_PAGE 0x1 37#define EXTENT_CLEAR_UNLOCK_PAGE 0x1