diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 82fdda8ff5ab..5cc6529a549f 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6579,7 +6579,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); u64 index; int err; - int drop_inode = 0; + int log_mode; /* do not allow sys_link's with other subvols of the same device */ if (root->root_key.objectid != BTRFS_I(inode)->root->root_key.objectid) @@ -6610,47 +6610,42 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, inc_nlink(inode); inode_inc_iversion(inode); inode->i_ctime = current_time(inode); - ihold(inode); set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags); err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode), 1, index); + if (err) + goto fail; - if (err) { - drop_inode = 1; - } else { - struct dentry *parent = dentry->d_parent; - int ret; - - err = btrfs_update_inode(trans, root, inode); + err = btrfs_update_inode(trans, root, inode); + if (err) + 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. + */ + err = btrfs_orphan_del(trans, BTRFS_I(inode)); + if (err) + goto fail; + } + BTRFS_I(inode)->last_link_trans = trans->transid; + log_mode = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, + dentry->d_parent, true, NULL); + if (log_mode == BTRFS_NEED_TRANS_COMMIT) { + err = btrfs_commit_transaction(trans); + trans = NULL; if (err) 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. - */ - err = btrfs_orphan_del(trans, BTRFS_I(inode)); - if (err) - goto fail; - } - BTRFS_I(inode)->last_link_trans = trans->transid; - d_instantiate(dentry, inode); - ret = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent, - true, NULL); - if (ret == BTRFS_NEED_TRANS_COMMIT) { - err = btrfs_commit_transaction(trans); - trans = NULL; - } } + ihold(inode); + d_instantiate(dentry, inode); fail: if (trans) btrfs_end_transaction(trans); - if (drop_inode) { + if (err) inode_dec_link_count(inode); - iput(inode); - } btrfs_btree_balance_dirty(fs_info); return err; }