aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-03-16 13:42:43 -0400
committerJosef Bacik <josef@redhat.com>2011-03-17 14:21:37 -0400
commita826d6dcb32d811b4c81df57a5ef1367516586b0 (patch)
tree4853d5acf6cde4dfb0eeb19f5c74dc3d7934359b /fs/btrfs/disk-io.c
parent850265335f792f5d39ab24e5fb7160bac28d77e5 (diff)
Btrfs: check items for correctness as we search
Currently if we have corrupted items things will blow up in spectacular ways. So as we read in blocks and they are leaves, check the entire leaf to make sure all of the items are correct and point to valid parts in the leaf for the item data the are responsible for. If the item is corrupt we will kick back EIO and not read any of the copies since they are likely to not be correct either. This will catch generic corruptions, it will be up to the individual callers of btrfs_search_slot to make sure their items are right. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c90
1 files changed, 89 insertions, 1 deletions
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;