summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfsck.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/btrfsck.c b/btrfsck.c
index 6274ff76..58baade4 100644
--- a/btrfsck.c
+++ b/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;