Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 243153
b: refs/heads/master
c: a826d6d
h: refs/heads/master
i:
  243151: e1e98f0
v: v3
  • Loading branch information
Josef Bacik committed Mar 17, 2011
1 parent b8450d8 commit d72d0a8
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 125 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 850265335f792f5d39ab24e5fb7160bac28d77e5
refs/heads/master: a826d6dcb32d811b4c81df57a5ef1367516586b0
123 changes: 0 additions & 123 deletions trunk/fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,122 +732,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root,
return btrfs_item_offset_nr(leaf, nr - 1);
}

/*
* extra debugging checks to make sure all the items in a key are
* well formed and in the proper order
*/
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
int level)
{
struct extent_buffer *parent = NULL;
struct extent_buffer *node = path->nodes[level];
struct btrfs_disk_key parent_key;
struct btrfs_disk_key node_key;
int parent_slot;
int slot;
struct btrfs_key cpukey;
u32 nritems = btrfs_header_nritems(node);

if (path->nodes[level + 1])
parent = path->nodes[level + 1];

slot = path->slots[level];
BUG_ON(nritems == 0);
if (parent) {
parent_slot = path->slots[level + 1];
btrfs_node_key(parent, &parent_key, parent_slot);
btrfs_node_key(node, &node_key, 0);
BUG_ON(memcmp(&parent_key, &node_key,
sizeof(struct btrfs_disk_key)));
BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
btrfs_header_bytenr(node));
}
BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
if (slot != 0) {
btrfs_node_key_to_cpu(node, &cpukey, slot - 1);
btrfs_node_key(node, &node_key, slot);
BUG_ON(comp_keys(&node_key, &cpukey) <= 0);
}
if (slot < nritems - 1) {
btrfs_node_key_to_cpu(node, &cpukey, slot + 1);
btrfs_node_key(node, &node_key, slot);
BUG_ON(comp_keys(&node_key, &cpukey) >= 0);
}
return 0;
}

/*
* extra checking to make sure all the items in a leaf are
* well formed and in the proper order
*/
static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
int level)
{
struct extent_buffer *leaf = path->nodes[level];
struct extent_buffer *parent = NULL;
int parent_slot;
struct btrfs_key cpukey;
struct btrfs_disk_key parent_key;
struct btrfs_disk_key leaf_key;
int slot = path->slots[0];

u32 nritems = btrfs_header_nritems(leaf);

if (path->nodes[level + 1])
parent = path->nodes[level + 1];

if (nritems == 0)
return 0;

if (parent) {
parent_slot = path->slots[level + 1];
btrfs_node_key(parent, &parent_key, parent_slot);
btrfs_item_key(leaf, &leaf_key, 0);

BUG_ON(memcmp(&parent_key, &leaf_key,
sizeof(struct btrfs_disk_key)));
BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
btrfs_header_bytenr(leaf));
}
if (slot != 0 && slot < nritems - 1) {
btrfs_item_key(leaf, &leaf_key, slot);
btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1);
if (comp_keys(&leaf_key, &cpukey) <= 0) {
btrfs_print_leaf(root, leaf);
printk(KERN_CRIT "slot %d offset bad key\n", slot);
BUG_ON(1);
}
if (btrfs_item_offset_nr(leaf, slot - 1) !=
btrfs_item_end_nr(leaf, slot)) {
btrfs_print_leaf(root, leaf);
printk(KERN_CRIT "slot %d offset bad\n", slot);
BUG_ON(1);
}
}
if (slot < nritems - 1) {
btrfs_item_key(leaf, &leaf_key, slot);
btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1);
BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0);
if (btrfs_item_offset_nr(leaf, slot) !=
btrfs_item_end_nr(leaf, slot + 1)) {
btrfs_print_leaf(root, leaf);
printk(KERN_CRIT "slot %d offset bad\n", slot);
BUG_ON(1);
}
}
BUG_ON(btrfs_item_offset_nr(leaf, 0) +
btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root));
return 0;
}

static noinline int check_block(struct btrfs_root *root,
struct btrfs_path *path, int level)
{
return 0;
if (level == 0)
return check_leaf(root, path, level);
return check_node(root, path, level);
}

/*
* search for key in the extent_buffer. The items start at offset p,
Expand Down Expand Up @@ -1188,7 +1072,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
}
}
/* double check we haven't messed things up */
check_block(root, path, level);
if (orig_ptr !=
btrfs_node_blockptr(path->nodes[level], path->slots[level]))
BUG();
Expand Down Expand Up @@ -1798,12 +1681,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
if (!cow)
btrfs_unlock_up_safe(p, level + 1);

ret = check_block(root, p, level);
if (ret) {
ret = -1;
goto done;
}

ret = bin_search(b, key, level, &slot);

if (level != 0) {
Expand Down
90 changes: 89 additions & 1 deletion trunk/fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
int num_copies = 0;
int mirror_num = 0;

clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
while (1) {
ret = read_extent_buffer_pages(io_tree, eb, start, 1,
Expand All @@ -331,6 +332,14 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
!verify_parent_transid(io_tree, eb, parent_transid))
return ret;

/*
* This buffer's crc is fine, but its contents are corrupted, so
* there is no reason to read the other copies, they won't be
* any less wrong.
*/
if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags))
return ret;

num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
eb->start, eb->len);
if (num_copies == 1)
Expand Down Expand Up @@ -419,6 +428,73 @@ static int check_tree_block_fsid(struct btrfs_root *root,
return ret;
}

#define CORRUPT(reason, eb, root, slot) \
printk(KERN_CRIT "btrfs: corrupt leaf, %s: block=%llu," \
"root=%llu, slot=%d\n", reason, \
(unsigned long long)btrfs_header_bytenr(eb), \
(unsigned long long)root->objectid, slot)

static noinline int check_leaf(struct btrfs_root *root,
struct extent_buffer *leaf)
{
struct btrfs_key key;
struct btrfs_key leaf_key;
u32 nritems = btrfs_header_nritems(leaf);
int slot;

if (nritems == 0)
return 0;

/* Check the 0 item */
if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
BTRFS_LEAF_DATA_SIZE(root)) {
CORRUPT("invalid item offset size pair", leaf, root, 0);
return -EIO;
}

/*
* Check to make sure each items keys are in the correct order and their
* offsets make sense. We only have to loop through nritems-1 because
* we check the current slot against the next slot, which verifies the
* next slot's offset+size makes sense and that the current's slot
* offset is correct.
*/
for (slot = 0; slot < nritems - 1; slot++) {
btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
btrfs_item_key_to_cpu(leaf, &key, slot + 1);

/* Make sure the keys are in the right order */
if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
CORRUPT("bad key order", leaf, root, slot);
return -EIO;
}

/*
* Make sure the offset and ends are right, remember that the
* item data starts at the end of the leaf and grows towards the
* front.
*/
if (btrfs_item_offset_nr(leaf, slot) !=
btrfs_item_end_nr(leaf, slot + 1)) {
CORRUPT("slot offset bad", leaf, root, slot);
return -EIO;
}

/*
* Check to make sure that we don't point outside of the leaf,
* just incase all the items are consistent to eachother, but
* all point outside of the leaf.
*/
if (btrfs_item_end_nr(leaf, slot) >
BTRFS_LEAF_DATA_SIZE(root)) {
CORRUPT("slot end outside of leaf", leaf, root, slot);
return -EIO;
}
}

return 0;
}

#ifdef CONFIG_DEBUG_LOCK_ALLOC
void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
{
Expand Down Expand Up @@ -485,8 +561,20 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
btrfs_set_buffer_lockdep_class(eb, found_level);

ret = csum_tree_block(root, eb, 1);
if (ret)
if (ret) {
ret = -EIO;
goto err;
}

/*
* If this is a leaf block and it is corrupt, set the corrupt bit so
* that we don't try and read the other copies of this block, just
* return -EIO.
*/
if (found_level == 0 && check_leaf(root, eb)) {
set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
ret = -EIO;
}

end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
end = eb->start + end - 1;
Expand Down
5 changes: 5 additions & 0 deletions trunk/fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -4754,6 +4754,11 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
}
}
out:
/*
* Deleting the buffer, clear the corrupt flag since it doesn't matter
* anymore.
*/
clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
btrfs_put_block_group(cache);
}

Expand Down
1 change: 1 addition & 0 deletions trunk/fs/btrfs/extent_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#define EXTENT_BUFFER_UPTODATE 0
#define EXTENT_BUFFER_BLOCKING 1
#define EXTENT_BUFFER_DIRTY 2
#define EXTENT_BUFFER_CORRUPT 3

/* these are flags for extent_clear_unlock_delalloc */
#define EXTENT_CLEAR_UNLOCK_PAGE 0x1
Expand Down

0 comments on commit d72d0a8

Please sign in to comment.