Add semantic checks to btrfsck for files and directories

This patch makes btrfsck check more things, including
directory items, file extents, checksumming, inode link
counts etc.

The code for these checks is similar to the code verifies
extent back references. The main difference is that
shared tree blocks are treated specially. The partial
checking results(unresolved references and/or errors)
of shared sub-trees are cached. This avoids scanning
the shared blocks several times. Thank you,

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
master
Yan Zheng 2009-01-07 14:57:12 -05:00 committed by Chris Mason
parent 50e571e5b7
commit 9a6930e9be
5 changed files with 1309 additions and 49 deletions

1329
btrfsck.c

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
int i;
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
if (!p->nodes[i])
break;
continue;
free_extent_buffer(p->nodes[i]);
}
memset(p, 0, sizeof(*p));

View File

@ -1528,6 +1528,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
u64 root_objectid, u64 ref_generation,
u64 owner, u64 empty_size, u64 hint_byte,
u64 search_end, struct btrfs_key *ins, int data);
int btrfs_lookup_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr,
u64 num_bytes, u32 *refs);
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct extent_buffer *orig_buf, struct extent_buffer *buf,
u32 *nr_extents);

View File

@ -44,6 +44,11 @@ int insert_cache_extent(struct cache_tree *tree, u64 start, u64 size);
int insert_existing_cache_extent(struct cache_tree *tree,
struct cache_extent *pe);
static inline int cache_tree_empty(struct cache_tree *tree)
{
return RB_EMPTY_ROOT(&tree->root);
}
static inline void free_cache_extent(struct cache_extent *pe)
{
free(pe);

View File

@ -801,9 +801,9 @@ int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
return 0;
}
int lookup_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr,
u64 num_bytes, u32 *refs)
int btrfs_lookup_extent_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr,
u64 num_bytes, u32 *refs)
{
struct btrfs_path *path;
int ret;
@ -2110,8 +2110,8 @@ static void noinline reada_walk_down(struct btrfs_root *root,
}
blocksize = btrfs_level_size(root, level - 1);
if (i != slot) {
ret = lookup_extent_ref(NULL, root, bytenr,
blocksize, &refs);
ret = btrfs_lookup_extent_ref(NULL, root, bytenr,
blocksize, &refs);
BUG_ON(ret);
if (refs != 1) {
skipped++;
@ -2150,9 +2150,9 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
WARN_ON(*level < 0);
WARN_ON(*level >= BTRFS_MAX_LEVEL);
ret = lookup_extent_ref(trans, root,
path->nodes[*level]->start,
path->nodes[*level]->len, &refs);
ret = btrfs_lookup_extent_ref(trans, root,
path->nodes[*level]->start,
path->nodes[*level]->len, &refs);
BUG_ON(ret);
if (refs > 1)
goto out;
@ -2179,7 +2179,8 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
blocksize = btrfs_level_size(root, *level - 1);
ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs);
ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize,
&refs);
BUG_ON(ret);
if (refs != 1) {
parent = path->nodes[*level];