mirror of
https://github.com/kdave/btrfs-progs
synced 2025-05-05 09:28:03 +00:00
btrfs-progs: check: introduce function to find inode_ref
Introduce a new function find_inode_ref() to find INODE_REF/INODE_EXTREF for the given key, and check it with the specified DIR_ITEM/DIR_INDEX match. Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
ec7b85da52
commit
cf4ada1f13
149
cmds-check.c
149
cmds-check.c
@ -3830,6 +3830,7 @@ out:
|
|||||||
#define ROOT_DIR_ERROR (1<<1) /* bad ROOT_DIR */
|
#define ROOT_DIR_ERROR (1<<1) /* bad ROOT_DIR */
|
||||||
#define DIR_ITEM_MISSING (1<<2) /* DIR_ITEM not found */
|
#define DIR_ITEM_MISSING (1<<2) /* DIR_ITEM not found */
|
||||||
#define DIR_ITEM_MISMATCH (1<<3) /* DIR_ITEM found but not match */
|
#define DIR_ITEM_MISMATCH (1<<3) /* DIR_ITEM found but not match */
|
||||||
|
#define INODE_REF_MISSING (1<<4) /* INODE_REF/INODE_EXTREF not found */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find DIR_ITEM/DIR_INDEX for the given key and check it with the specified
|
* Find DIR_ITEM/DIR_INDEX for the given key and check it with the specified
|
||||||
@ -4119,6 +4120,154 @@ next:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find INODE_REF/INODE_EXTREF for the given key and check it with the specified
|
||||||
|
* DIR_ITEM/DIR_INDEX match.
|
||||||
|
*
|
||||||
|
* @root: the root of the fs/file tree
|
||||||
|
* @key: the key of the INODE_REF/INODE_EXTREF
|
||||||
|
* @name: the name in the INODE_REF/INODE_EXTREF
|
||||||
|
* @namelen: the length of name in the INODE_REF/INODE_EXTREF
|
||||||
|
* @index: the index in the INODE_REF/INODE_EXTREF, for DIR_ITEM set index
|
||||||
|
* to (u64)-1
|
||||||
|
* @ext_ref: the EXTENDED_IREF feature
|
||||||
|
*
|
||||||
|
* Return 0 if no error occurred.
|
||||||
|
* Return >0 for error bitmap
|
||||||
|
*/
|
||||||
|
static int find_inode_ref(struct btrfs_root *root, struct btrfs_key *key,
|
||||||
|
char *name, int namelen, u64 index,
|
||||||
|
unsigned int ext_ref)
|
||||||
|
{
|
||||||
|
struct btrfs_path path;
|
||||||
|
struct btrfs_inode_ref *ref;
|
||||||
|
struct btrfs_inode_extref *extref;
|
||||||
|
struct extent_buffer *node;
|
||||||
|
char ref_namebuf[BTRFS_NAME_LEN] = {0};
|
||||||
|
u32 total;
|
||||||
|
u32 cur = 0;
|
||||||
|
u32 len;
|
||||||
|
u32 ref_namelen;
|
||||||
|
u64 ref_index;
|
||||||
|
u64 parent;
|
||||||
|
u64 dir_id;
|
||||||
|
int slot;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
btrfs_init_path(&path);
|
||||||
|
ret = btrfs_search_slot(NULL, root, key, &path, 0, 0);
|
||||||
|
if (ret) {
|
||||||
|
ret = INODE_REF_MISSING;
|
||||||
|
goto extref;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = path.nodes[0];
|
||||||
|
slot = path.slots[0];
|
||||||
|
|
||||||
|
ref = btrfs_item_ptr(node, slot, struct btrfs_inode_ref);
|
||||||
|
total = btrfs_item_size_nr(node, slot);
|
||||||
|
|
||||||
|
/* Iterate all entry of INODE_REF */
|
||||||
|
while (cur < total) {
|
||||||
|
ret = INODE_REF_MISSING;
|
||||||
|
|
||||||
|
ref_namelen = btrfs_inode_ref_name_len(node, ref);
|
||||||
|
ref_index = btrfs_inode_ref_index(node, ref);
|
||||||
|
if (index != (u64)-1 && index != ref_index)
|
||||||
|
goto next_ref;
|
||||||
|
|
||||||
|
if (ref_namelen <= BTRFS_NAME_LEN) {
|
||||||
|
len = ref_namelen;
|
||||||
|
} else {
|
||||||
|
len = BTRFS_NAME_LEN;
|
||||||
|
warning("root %llu INODE %s[%llu %llu] name too long",
|
||||||
|
root->objectid,
|
||||||
|
key->type == BTRFS_INODE_REF_KEY ?
|
||||||
|
"REF" : "EXTREF",
|
||||||
|
key->objectid, key->offset);
|
||||||
|
}
|
||||||
|
read_extent_buffer(node, ref_namebuf, (unsigned long)(ref + 1),
|
||||||
|
len);
|
||||||
|
|
||||||
|
if (len != namelen || strncmp(ref_namebuf, name, len))
|
||||||
|
goto next_ref;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
next_ref:
|
||||||
|
len = sizeof(*ref) + ref_namelen;
|
||||||
|
ref = (struct btrfs_inode_ref *)((char *)ref + len);
|
||||||
|
cur += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
extref:
|
||||||
|
/* Skip if not support EXTENDED_IREF feature */
|
||||||
|
if (!ext_ref)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
btrfs_release_path(&path);
|
||||||
|
btrfs_init_path(&path);
|
||||||
|
|
||||||
|
dir_id = key->offset;
|
||||||
|
key->type = BTRFS_INODE_EXTREF_KEY;
|
||||||
|
key->offset = btrfs_extref_hash(dir_id, name, namelen);
|
||||||
|
|
||||||
|
ret = btrfs_search_slot(NULL, root, key, &path, 0, 0);
|
||||||
|
if (ret) {
|
||||||
|
ret = INODE_REF_MISSING;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = path.nodes[0];
|
||||||
|
slot = path.slots[0];
|
||||||
|
|
||||||
|
extref = btrfs_item_ptr(node, slot, struct btrfs_inode_extref);
|
||||||
|
cur = 0;
|
||||||
|
total = btrfs_item_size_nr(node, slot);
|
||||||
|
|
||||||
|
/* Iterate all entry of INODE_EXTREF */
|
||||||
|
while (cur < total) {
|
||||||
|
ret = INODE_REF_MISSING;
|
||||||
|
|
||||||
|
ref_namelen = btrfs_inode_extref_name_len(node, extref);
|
||||||
|
ref_index = btrfs_inode_extref_index(node, extref);
|
||||||
|
parent = btrfs_inode_extref_parent(node, extref);
|
||||||
|
if (index != (u64)-1 && index != ref_index)
|
||||||
|
goto next_extref;
|
||||||
|
|
||||||
|
if (parent != dir_id)
|
||||||
|
goto next_extref;
|
||||||
|
|
||||||
|
if (ref_namelen <= BTRFS_NAME_LEN) {
|
||||||
|
len = ref_namelen;
|
||||||
|
} else {
|
||||||
|
len = BTRFS_NAME_LEN;
|
||||||
|
warning("Warning: root %llu INODE %s[%llu %llu] name too long\n",
|
||||||
|
root->objectid,
|
||||||
|
key->type == BTRFS_INODE_REF_KEY ?
|
||||||
|
"REF" : "EXTREF",
|
||||||
|
key->objectid, key->offset);
|
||||||
|
}
|
||||||
|
read_extent_buffer(node, ref_namebuf,
|
||||||
|
(unsigned long)(extref + 1), len);
|
||||||
|
|
||||||
|
if (len != namelen || strncmp(ref_namebuf, name, len))
|
||||||
|
goto next_extref;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
next_extref:
|
||||||
|
len = sizeof(*extref) + ref_namelen;
|
||||||
|
extref = (struct btrfs_inode_extref *)((char *)extref + len);
|
||||||
|
cur += len;
|
||||||
|
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
btrfs_release_path(&path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int all_backpointers_checked(struct extent_record *rec, int print_errs)
|
static int all_backpointers_checked(struct extent_record *rec, int print_errs)
|
||||||
{
|
{
|
||||||
struct list_head *cur = rec->backrefs.next;
|
struct list_head *cur = rec->backrefs.next;
|
||||||
|
Loading…
Reference in New Issue
Block a user