diff options
author | Su Yue <suy.fnst@cn.fujitsu.com> | 2017-08-28 13:26:33 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-10-16 20:33:00 +0200 |
commit | 23482e871c7fe97d4b54bc3332ac2a445d406f7c (patch) | |
tree | c0cba89978c9a29424b5f66e8460dab2ae0d8960 | |
parent | b6cae7e4e4aa4f674625bad6f5334caa6976ddc7 (diff) |
btrfs-progs: check: repair inode orphan item in lowmem mode
Introduce repair_inode_orphan_item_lowmem() to add an orphan
item if the inode refs and nlink are both zero.
repair_inode_orphan_item_lowmem() is just a wrapper function
that calls btrfs_add_orphan_item().
Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | cmds-check.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/cmds-check.c b/cmds-check.c index 5828ba00..ad0344d7 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -5078,6 +5078,48 @@ out: } /* + * Wrapper function for btrfs_add_orphan_item(). + * + * Returns 0 on success. + * Returns != 0 on error. + */ +static int repair_inode_orphan_item_lowmem(struct btrfs_root *root, + struct btrfs_path *path, u64 ino) +{ + struct btrfs_trans_handle *trans; + struct btrfs_key research_key; + int ret; + int err = 0; + + btrfs_item_key_to_cpu(path->nodes[0], &research_key, path->slots[0]); + + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + err |= ret; + goto out; + } + + btrfs_release_path(path); + ret = btrfs_add_orphan_item(trans, root, path, ino); + err |= ret; + btrfs_commit_transaction(trans, root); +out: + if (ret) + error("failed to add inode %llu as orphan item root %llu", + ino, root->root_key.objectid); + else + printf("Added inode %llu as orphan item root %llu\n", + ino, root->root_key.objectid); + + btrfs_release_path(path); + ret = btrfs_search_slot(NULL, root, &research_key, path, 0, 0); + err |= ret; + + return err; +} + +/* * Check INODE_ITEM and related ITEMs (the same inode number) * 1. check link count * 2. check inode ref/extref @@ -5228,7 +5270,14 @@ out: error("root %llu INODE[%llu] nlink(%llu) not equal to inode_refs(%llu)", root->objectid, inode_id, nlink, refs); } else if (!nlink) { - err |= ORPHAN_ITEM; + if (repair) + ret = repair_inode_orphan_item_lowmem(root, + path, inode_id); + if (!repair || ret) { + err |= ORPHAN_ITEM; + error("root %llu INODE[%llu] is orphan item", + root->objectid, inode_id); + } } if (!nbytes && !no_holes && extent_end < isize) { |