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: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Filipe Manana 2022-02-28 16:29:29 +00:00 committed by David Sterba
parent 06bae87663
commit 313ab75399

View File

@ -899,6 +899,26 @@ out:
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 @@ again:
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 @@ again:
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 @@ again:
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,8 +1449,8 @@ 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),
name, namelen);
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