2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

btrfs: simplify error handling logic for btrfs_link()

Instead of incrementing the inode's link count and refcount early before
adding the link, updating the inode and deleting orphan item, do it after
all those steps succeeded right before calling d_instantiate(). This makes
the error handling logic simpler by avoiding the need for the 'drop_inode'
variable to signal if we need to undo the link count increment and the
inode refcount increase under the 'fail' label.

This also reduces the level of indentation by one, making the code easier
to read.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Filipe Manana 2025-07-25 17:08:13 +01:00 committed by David Sterba
parent e87e953bb2
commit 5bb00879cb

View File

@ -6805,7 +6805,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
struct fscrypt_name fname;
u64 index;
int ret;
int drop_inode = 0;
/* do not allow sys_link's with other subvols of the same device */
if (btrfs_root_id(root) != btrfs_root_id(BTRFS_I(inode)->root))
@ -6837,50 +6836,44 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
/* There are several dir indexes for this inode, clear the cache. */
BTRFS_I(inode)->dir_index = 0ULL;
inc_nlink(inode);
inode_inc_iversion(inode);
inode_set_ctime_current(inode);
ihold(inode);
set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
ret = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
&fname.disk_name, 1, index);
if (ret)
goto fail;
/* Link added now we update the inode item with the new link count. */
inc_nlink(inode);
ret = btrfs_update_inode(trans, BTRFS_I(inode));
if (ret) {
drop_inode = 1;
} else {
struct dentry *parent = dentry->d_parent;
btrfs_abort_transaction(trans, ret);
goto fail;
}
ret = btrfs_update_inode(trans, BTRFS_I(inode));
if (inode->i_nlink == 1) {
/*
* If the new hard link count is 1, it's a file created with the
* open(2) O_TMPFILE flag.
*/
ret = btrfs_orphan_del(trans, BTRFS_I(inode));
if (ret) {
btrfs_abort_transaction(trans, ret);
drop_inode = 1;
goto fail;
}
if (inode->i_nlink == 1) {
/*
* If new hard link count is 1, it's a file created
* with open(2) O_TMPFILE flag.
*/
ret = btrfs_orphan_del(trans, BTRFS_I(inode));
if (ret) {
btrfs_abort_transaction(trans, ret);
drop_inode = 1;
goto fail;
}
}
d_instantiate(dentry, inode);
btrfs_log_new_name(trans, old_dentry, NULL, 0, parent);
}
/* Grab reference for the new dentry passed to d_instantiate(). */
ihold(inode);
d_instantiate(dentry, inode);
btrfs_log_new_name(trans, old_dentry, NULL, 0, dentry->d_parent);
fail:
fscrypt_free_filename(&fname);
if (trans)
btrfs_end_transaction(trans);
if (drop_inode) {
inode_dec_link_count(inode);
iput(inode);
}
btrfs_btree_balance_dirty(fs_info);
return ret;
}