Commit 313ab753 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: add and use helper for unlinking inode during log replay

During log replay there is this pattern of running delayed items after
every inode unlink. To avoid repeating this several times, move the
logic into an helper function and use it instead of calling
btrfs_unlink_inode() followed by btrfs_run_delayed_items().
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 06bae876
......@@ -899,6 +899,26 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
return ret;
}
static int unlink_inode_for_log_replay(struct btrfs_trans_handle *trans,
struct btrfs_inode *dir,
struct btrfs_inode *inode,
const char *name,
int name_len)
{
int ret;
ret = btrfs_unlink_inode(trans, dir, inode, name, name_len);
if (ret)
return ret;
/*
* Whenever we need to check if a name exists or not, we check the
* fs/subvolume tree. So after an unlink we must run delayed items, so
* that future checks for a name during log replay see that the name
* does not exists anymore.
*/
return btrfs_run_delayed_items(trans);
}
/*
* when cleaning up conflicts between the directory names in the
* subvolume, directory names in the log and directory names in the
......@@ -941,12 +961,8 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
if (ret)
goto out;
ret = btrfs_unlink_inode(trans, dir, BTRFS_I(inode), name,
ret = unlink_inode_for_log_replay(trans, dir, BTRFS_I(inode), name,
name_len);
if (ret)
goto out;
else
ret = btrfs_run_delayed_items(trans);
out:
kfree(name);
iput(inode);
......@@ -1106,12 +1122,9 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
inc_nlink(&inode->vfs_inode);
btrfs_release_path(path);
ret = btrfs_unlink_inode(trans, dir, inode,
ret = unlink_inode_for_log_replay(trans, dir, inode,
victim_name, victim_name_len);
kfree(victim_name);
if (ret)
return ret;
ret = btrfs_run_delayed_items(trans);
if (ret)
return ret;
*search_done = 1;
......@@ -1178,14 +1191,11 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
inc_nlink(&inode->vfs_inode);
btrfs_release_path(path);
ret = btrfs_unlink_inode(trans,
ret = unlink_inode_for_log_replay(trans,
BTRFS_I(victim_parent),
inode,
victim_name,
victim_name_len);
if (!ret)
ret = btrfs_run_delayed_items(
trans);
}
iput(victim_parent);
kfree(victim_name);
......@@ -1340,19 +1350,10 @@ static int unlink_old_inode_refs(struct btrfs_trans_handle *trans,
kfree(name);
goto out;
}
ret = btrfs_unlink_inode(trans, BTRFS_I(dir),
ret = unlink_inode_for_log_replay(trans, BTRFS_I(dir),
inode, name, namelen);
kfree(name);
iput(dir);
/*
* Whenever we need to check if a name exists or not, we
* check the subvolume tree. So after an unlink we must
* run delayed items, so that future checks for a name
* during log replay see that the name does not exists
* anymore.
*/
if (!ret)
ret = btrfs_run_delayed_items(trans);
if (ret)
goto out;
goto again;
......@@ -1448,7 +1449,7 @@ static int add_link(struct btrfs_trans_handle *trans,
ret = -ENOENT;
goto out;
}
ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(other_inode),
ret = unlink_inode_for_log_replay(trans, BTRFS_I(dir), BTRFS_I(other_inode),
name, namelen);
if (ret)
goto out;
......@@ -1458,10 +1459,6 @@ static int add_link(struct btrfs_trans_handle *trans,
*/
if (other_inode->i_nlink == 0)
inc_nlink(other_inode);
ret = btrfs_run_delayed_items(trans);
if (ret)
goto out;
add_link:
ret = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
name, namelen, 0, ref_index);
......@@ -1594,7 +1591,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
ret = btrfs_inode_ref_exists(inode, dir, key->type,
name, namelen);
if (ret > 0) {
ret = btrfs_unlink_inode(trans,
ret = unlink_inode_for_log_replay(trans,
BTRFS_I(dir),
BTRFS_I(inode),
name, namelen);
......@@ -1605,15 +1602,6 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
*/
if (!ret && inode->i_nlink == 0)
inc_nlink(inode);
/*
* Whenever we need to check if a name exists or
* not, we check the subvolume tree. So after an
* unlink we must run delayed items, so that future
* checks for a name during log replay see that the
* name does not exists anymore.
*/
if (!ret)
ret = btrfs_run_delayed_items(trans);
}
if (ret < 0)
goto out;
......@@ -2350,15 +2338,8 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
goto out;
inc_nlink(inode);
ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(inode), name,
name_len);
if (ret)
goto out;
ret = btrfs_run_delayed_items(trans);
if (ret)
goto out;
ret = unlink_inode_for_log_replay(trans, BTRFS_I(dir), BTRFS_I(inode),
name, name_len);
/*
* Unlike dir item keys, dir index keys can only have one name (entry) in
* them, as there are no key collisions since each key has a unique offset
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment