Skip to content

Commit

Permalink
btrfs: add helper to delete a dir entry from a log tree
Browse files Browse the repository at this point in the history
Move the code that finds and deletes a logged dir entry out of
btrfs_del_dir_entries_in_log() into a helper function. This new helper
function will be used by another patch in the same series, and serves
to avoid having duplicated logic.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Filipe Manana authored and David Sterba committed Mar 14, 2022
1 parent 0292ecf commit 839061f
Showing 1 changed file with 39 additions and 31 deletions.
70 changes: 39 additions & 31 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -3508,6 +3508,41 @@ static bool inode_logged(struct btrfs_trans_handle *trans,
return false;
}

/*
* Delete a directory entry from the log if it exists.
*
* Returns < 0 on error
* 1 if the entry does not exists
* 0 if the entry existed and was successfully deleted
*/
static int del_logged_dentry(struct btrfs_trans_handle *trans,
struct btrfs_root *log,
struct btrfs_path *path,
u64 dir_ino,
const char *name, int name_len,
u64 index)
{
struct btrfs_dir_item *di;

/*
* We only log dir index items of a directory, so we don't need to look
* for dir item keys.
*/
di = btrfs_lookup_dir_index_item(trans, log, path, dir_ino,
index, name, name_len, -1);
if (IS_ERR(di))
return PTR_ERR(di);
else if (!di)
return 1;

/*
* We do not need to update the size field of the directory's
* inode item because on log replay we update the field to reflect
* all existing entries in the directory (see overwrite_item()).
*/
return btrfs_delete_one_dir_name(trans, log, path, di);
}

/*
* If both a file and directory are logged, and unlinks or renames are
* mixed in, we have a few interesting corners:
Expand All @@ -3534,12 +3569,8 @@ void btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
const char *name, int name_len,
struct btrfs_inode *dir, u64 index)
{
struct btrfs_root *log;
struct btrfs_dir_item *di;
struct btrfs_path *path;
int ret;
int err = 0;
u64 dir_ino = btrfs_ino(dir);

if (!inode_logged(trans, dir))
return;
Expand All @@ -3550,41 +3581,18 @@ void btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,

mutex_lock(&dir->log_mutex);

log = root->log_root;
path = btrfs_alloc_path();
if (!path) {
err = -ENOMEM;
ret = -ENOMEM;
goto out_unlock;
}

/*
* We only log dir index items of a directory, so we don't need to look
* for dir item keys.
*/
di = btrfs_lookup_dir_index_item(trans, log, path, dir_ino,
index, name, name_len, -1);
if (IS_ERR(di)) {
err = PTR_ERR(di);
goto fail;
}
if (di) {
ret = btrfs_delete_one_dir_name(trans, log, path, di);
if (ret) {
err = ret;
goto fail;
}
}

/*
* We do not need to update the size field of the directory's inode item
* because on log replay we update the field to reflect all existing
* entries in the directory (see overwrite_item()).
*/
fail:
ret = del_logged_dentry(trans, root->log_root, path, btrfs_ino(dir),
name, name_len, index);
btrfs_free_path(path);
out_unlock:
mutex_unlock(&dir->log_mutex);
if (err < 0)
if (ret < 0)
btrfs_set_log_full_commit(trans);
btrfs_end_log_trans(root);
}
Expand Down

0 comments on commit 839061f

Please sign in to comment.