btrfs-progs: add extended inode ref support to btrfsck
Add a function, process_inode_extref() to be called from process_one_leaf() when an item type of BTRFS_INODE_EXTREF_KEY is encountered. Similarly to process_inode_ref(), process_inode_extref() walks an extref and adds an inode_backref structure for each reference found within. I modified fsck's inode_backref to get a type field (ref_type) which helps us internally track the exact type of backrefs found. Of course this field could be overwritten in case of disk corruption (duplicate refs) but duplicate refs themselves are tracked by btrfsck so that should not be an issue as btrfsck is written today. Signed-off-by: Mark Fasheh <mfasheh@suse.de>
This commit is contained in:
parent
905b078928
commit
86279e7ef2
53
btrfsck.c
53
btrfsck.c
|
@ -98,6 +98,7 @@ struct inode_backref {
|
|||
unsigned int found_inode_ref:1;
|
||||
unsigned int filetype:8;
|
||||
int errors;
|
||||
unsigned int ref_type;
|
||||
u64 dir;
|
||||
u64 index;
|
||||
u16 namelen;
|
||||
|
@ -471,12 +472,14 @@ static int add_inode_backref(struct cache_tree *inode_cache,
|
|||
|
||||
backref->filetype = filetype;
|
||||
backref->found_dir_item = 1;
|
||||
} else if (itemtype == BTRFS_INODE_REF_KEY) {
|
||||
} else if ((itemtype == BTRFS_INODE_REF_KEY) ||
|
||||
(itemtype == BTRFS_INODE_EXTREF_KEY)) {
|
||||
if (backref->found_inode_ref)
|
||||
backref->errors |= REF_ERR_DUP_INODE_REF;
|
||||
if (backref->found_dir_index && backref->index != index)
|
||||
backref->errors |= REF_ERR_INDEX_UNMATCH;
|
||||
|
||||
backref->ref_type = itemtype;
|
||||
backref->index = index;
|
||||
backref->found_inode_ref = 1;
|
||||
} else {
|
||||
|
@ -512,7 +515,7 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst,
|
|||
add_inode_backref(dst_cache, dst->ino,
|
||||
backref->dir, backref->index,
|
||||
backref->name, backref->namelen, 0,
|
||||
BTRFS_INODE_REF_KEY, backref->errors);
|
||||
backref->ref_type, backref->errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -916,6 +919,49 @@ static int process_inode_ref(struct extent_buffer *eb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int process_inode_extref(struct extent_buffer *eb,
|
||||
int slot, struct btrfs_key *key,
|
||||
struct shared_node *active_node)
|
||||
{
|
||||
u32 total;
|
||||
u32 cur = 0;
|
||||
u32 len;
|
||||
u32 name_len;
|
||||
u64 index;
|
||||
u64 parent;
|
||||
int error;
|
||||
struct cache_tree *inode_cache;
|
||||
struct btrfs_inode_extref *extref;
|
||||
char namebuf[BTRFS_NAME_LEN];
|
||||
|
||||
inode_cache = &active_node->inode_cache;
|
||||
|
||||
extref = btrfs_item_ptr(eb, slot, struct btrfs_inode_extref);
|
||||
total = btrfs_item_size_nr(eb, slot);
|
||||
while (cur < total) {
|
||||
name_len = btrfs_inode_extref_name_len(eb, extref);
|
||||
index = btrfs_inode_extref_index(eb, extref);
|
||||
parent = btrfs_inode_extref_parent(eb, extref);
|
||||
if (name_len <= BTRFS_NAME_LEN) {
|
||||
len = name_len;
|
||||
error = 0;
|
||||
} else {
|
||||
len = BTRFS_NAME_LEN;
|
||||
error = REF_ERR_NAME_TOO_LONG;
|
||||
}
|
||||
read_extent_buffer(eb, namebuf,
|
||||
(unsigned long)(extref + 1), len);
|
||||
add_inode_backref(inode_cache, key->objectid, parent,
|
||||
index, namebuf, len, 0, key->type, error);
|
||||
|
||||
len = sizeof(*extref) + name_len;
|
||||
extref = (struct btrfs_inode_extref *)((char *)extref + len);
|
||||
cur += len;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static u64 count_csum_range(struct btrfs_root *root, u64 start, u64 len)
|
||||
{
|
||||
struct btrfs_key key;
|
||||
|
@ -1102,6 +1148,9 @@ static int process_one_leaf(struct btrfs_root *root, struct extent_buffer *eb,
|
|||
case BTRFS_INODE_REF_KEY:
|
||||
ret = process_inode_ref(eb, i, &key, active_node);
|
||||
break;
|
||||
case BTRFS_INODE_EXTREF_KEY:
|
||||
ret = process_inode_extref(eb, i, &key, active_node);
|
||||
break;
|
||||
case BTRFS_INODE_ITEM_KEY:
|
||||
ret = process_inode_item(eb, i, &key, active_node);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue