diff options
author | Goldwyn Rodrigues <rgoldwyn@suse.com> | 2016-12-20 06:08:54 -0600 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-01-25 09:47:19 +0100 |
commit | e325c74bb8af9efa150cb16429a94f291209604f (patch) | |
tree | d8546595c992ec3cfd39418d11ca670ecc7d903c | |
parent | 6ab6f69be3e9eef90d0da12e1362b0dd7c1315eb (diff) |
btrfs-progs: check: get the highest inode for lost+found
root->highest_inode is not accurate at the time of creating a lost+found
and it fails because the highest_inode+1 is already present. This could be
because of fixes after highest_inode is set. Instead, search
for the highest inode in the tree and use it for lost+found.
This makes root->highest_inode unnecessary and hence deleted.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | cmds-check.c | 46 | ||||
-rw-r--r-- | ctree.h | 1 | ||||
-rw-r--r-- | disk-io.c | 1 |
3 files changed, 27 insertions, 21 deletions
diff --git a/cmds-check.c b/cmds-check.c index 1dba2985..a55d00d9 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -2853,6 +2853,31 @@ out: return ret; } +static int get_highest_inode(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + u64 *highest_ino) +{ + struct btrfs_key key, found_key; + int ret; + + btrfs_init_path(path); + key.objectid = BTRFS_LAST_FREE_OBJECTID; + key.offset = -1; + key.type = BTRFS_INODE_ITEM_KEY; + ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret == 1) { + btrfs_item_key_to_cpu(path->nodes[0], &found_key, + path->slots[0] - 1); + *highest_ino = found_key.objectid; + ret = 0; + } + if (*highest_ino >= BTRFS_LAST_FREE_OBJECTID) + ret = -EOVERFLOW; + btrfs_release_path(path); + return ret; +} + static int repair_inode_nlinks(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, @@ -2898,11 +2923,9 @@ static int repair_inode_nlinks(struct btrfs_trans_handle *trans, } if (rec->found_link == 0) { - lost_found_ino = root->highest_inode; - if (lost_found_ino >= BTRFS_LAST_FREE_OBJECTID) { - ret = -EOVERFLOW; + ret = get_highest_inode(trans, root, path, &lost_found_ino); + if (ret < 0) goto out; - } lost_found_ino++; ret = btrfs_mkdir(trans, root, dir_name, strlen(dir_name), BTRFS_FIRST_FREE_OBJECTID, &lost_found_ino, @@ -3266,21 +3289,6 @@ static int check_inode_recs(struct btrfs_root *root, } /* - * We need to record the highest inode number for later 'lost+found' - * dir creation. - * We must select an ino not used/referred by any existing inode, or - * 'lost+found' ino may be a missing ino in a corrupted leaf, - * this may cause 'lost+found' dir has wrong nlinks. - */ - cache = last_cache_extent(inode_cache); - if (cache) { - node = container_of(cache, struct ptr_node, cache); - rec = node->data; - if (rec->ino > root->highest_inode) - root->highest_inode = rec->ino; - } - - /* * We need to repair backrefs first because we could change some of the * errors in the inode recs. * @@ -1177,7 +1177,6 @@ struct btrfs_root { u32 type; - u64 highest_inode; u64 last_inode_alloc; /* @@ -494,7 +494,6 @@ void btrfs_setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, root->fs_info = fs_info; root->objectid = objectid; root->last_trans = 0; - root->highest_inode = 0; root->last_inode_alloc = 0; INIT_LIST_HEAD(&root->dirty_list); |