Skip to content

Commit b9f35a2

Browse files
committed
btrfs-progs: check/original: add dedicated missing INODE_REF repair
Currently if the original mode of btrfs-check hits a missing INODE_REF, but with valid DIR_INDEX/DIR_ITEM, then it will repair it by deleting the valid DIR_INDEX, which will just make things worse. Add a dedicated repair for missing INODE_REF which will just add back the missing INODE_REF, properly fixing the problem other than making it worse. Signed-off-by: Qu Wenruo <wqu@suse.com>
1 parent 4acdcb5 commit b9f35a2

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

check/main.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,6 +2351,42 @@ static int create_inode_item(struct btrfs_root *root,
23512351
return 0;
23522352
}
23532353

2354+
static int create_inode_ref(struct btrfs_root *root,
2355+
struct inode_record *i_rec,
2356+
struct inode_backref *backref)
2357+
{
2358+
struct btrfs_trans_handle *trans;
2359+
int ret;
2360+
2361+
trans = btrfs_start_transaction(root, 1);
2362+
if (IS_ERR(trans)) {
2363+
ret = PTR_ERR(trans);
2364+
errno = -ret;
2365+
error_msg(ERROR_MSG_START_TRANS, "%m");
2366+
return ret;
2367+
}
2368+
2369+
ret = btrfs_insert_inode_ref(trans, root, backref->name, backref->namelen,
2370+
i_rec->ino, backref->dir, backref->index);
2371+
if (ret < 0) {
2372+
btrfs_commit_transaction(trans, root);
2373+
return ret;
2374+
}
2375+
ret = btrfs_commit_transaction(trans, root);
2376+
if (ret < 0) {
2377+
ret = PTR_ERR(trans);
2378+
errno = -ret;
2379+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
2380+
return ret;
2381+
}
2382+
backref->found_inode_ref = 1;
2383+
backref->errors &= ~REF_ERR_NO_INODE_REF;
2384+
printf("Added INODE_REF for root %lld ino %llu parent %llu index %llu name %.*s\n",
2385+
btrfs_root_id(root), i_rec->ino, backref->dir, backref->index,
2386+
backref->namelen, backref->name);
2387+
return 0;
2388+
}
2389+
23542390
static int repair_inode_backrefs(struct btrfs_root *root,
23552391
struct inode_record *rec,
23562392
struct cache_tree *inode_cache,
@@ -2375,6 +2411,20 @@ static int repair_inode_backrefs(struct btrfs_root *root,
23752411
if (rec->ino == root_dirid && backref->index == 0)
23762412
continue;
23772413

2414+
/*
2415+
* Have both DIR_INDEX and DIR_ITEM, but no INODE_REF.
2416+
* Add back the missing INODE_REF.
2417+
*/
2418+
if (!backref->found_inode_ref && backref->found_dir_item &&
2419+
backref->found_dir_index) {
2420+
ret = create_inode_ref(root, rec, backref);
2421+
if (ret)
2422+
break;
2423+
repaired++;
2424+
list_del(&backref->list);
2425+
free(backref);
2426+
continue;
2427+
}
23782428
if (delete &&
23792429
((backref->found_dir_index && !backref->found_inode_ref) ||
23802430
(backref->found_dir_index && backref->found_inode_ref &&

0 commit comments

Comments
 (0)