Thread (1 message) 1 message, 1 author, 2020-01-29
DORMANTno replies

[RFC PATCH v4 3/4] Btrfs: fix inode reference count leak in btrfs_link() error path

From: Omar Sandoval <hidden>
Date: 2020-01-29 08:58:33
Subsystem: btrfs file system, filesystems (vfs and infrastructure), the rest · Maintainers: Chris Mason, David Sterba, Alexander Viro, Christian Brauner, Linus Torvalds

From: Omar Sandoval <redacted>

If btrfs_update_inode() or btrfs_orphan_del() fails in btrfs_link(),
then we don't drop the reference we got with ihold(). This results in
the "VFS: Busy inodes after unmount" crash.

The reference is needed for the new dentry, so get it right before we
instantiate the dentry.

Fixes: 79787eaab461 ("btrfs: replace many BUG_ONs with proper error handling")
[Although d_instantiate() was moved further from ihold() before that, in
commit 08c422c27f85 ("Btrfs: call d_instantiate after all ops are setup")]
Signed-off-by: Omar Sandoval <redacted>
---
 fs/btrfs/inode.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index bc7709c4f6eb..8c9a114f48f6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6801,7 +6801,6 @@ 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),
@@ -6825,6 +6824,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 			if (err)
 				goto fail;
 		}
+		ihold(inode);
 		d_instantiate(dentry, inode);
 		ret = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent,
 					 true, NULL);
@@ -6837,10 +6837,8 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 fail:
 	if (trans)
 		btrfs_end_transaction(trans);
-	if (drop_inode) {
+	if (drop_inode)
 		inode_dec_link_count(inode);
-		iput(inode);
-	}
 	btrfs_btree_balance_dirty(fs_info);
 	return err;
 }
-- 
2.25.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help