On 18.04.19 г. 17:07 ч., Josef Bacik wrote: > On Thu, Apr 18, 2019 at 03:50:00PM +0300, Nikolay Borisov wrote: >> >> >> On 18.04.19 г. 14:06 ч., Pan Bian wrote: >>> The reference count of inode is incremented by ihold. It should be >>> dropped if not used. However, the reference count is not dropped if >>> error occurs during updating the inode or deleting orphan items. This >>> patch fixes the bug. >>> >>> Signed-off-by: Pan Bian <bianpan2...@163.com> >>> --- >>> V2: move ihold just before device_initialize to make code clearer >>> --- >>> fs/btrfs/inode.c | 54 >>> +++++++++++++++++++++++++----------------------------- >>> 1 file changed, 25 insertions(+), 29 deletions(-) >>> >>> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c >>> index 82fdda8..d6630df 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) >>> @@ -6616,41 +6616,37 @@ static int btrfs_link(struct dentry *old_dentry, >>> struct inode *dir, >>> err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode), >>> 1, index); >>> >>> - if (err) { >>> - drop_inode = 1; >>> - } else { >>> - struct dentry *parent = dentry->d_parent; >>> - int ret; >>> + if (err) >>> + goto err_link; >>> >>> - err = btrfs_update_inode(trans, root, inode); >>> + err = btrfs_update_inode(trans, root, inode); >>> + if (err) >>> + goto err_link; >>> + 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; >>> - 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; >>> - } >>> + goto err_link; >>> + } >>> + BTRFS_I(inode)->last_link_trans = trans->transid; >>> + ihold(inode); > > Where is the iput for this ihold? This ihold is sort of "given" to the d_instantiate. I.e the iput happens when the respective dentry is unhashed/removed. > > Josef >