xfs: fix broken i_nlink accounting for whiteout tmpfile inode
PATCH 1/1 xfs: fix broken i_nlink accounting for whiteout tmpfile inode
XFS uses the internal tmpfile() infrastructure for the whiteout inode used for RENAME_WHITEOUT operations. For tmpfile inodes, XFS allocates the inode, drops di_nlink, adds the inode to the agi unlinked list, calls d_tmpfile() which correspondingly drops i_nlink of the vfs inode, and then finishes the common inode setup (e.g., clear I_NEW and unlock).
The d_tmpfile() call was originally made inxfs_create_tmpfile(), but was pulled up out of that function as part of the following commit to resolve a deadlock issue:
330033d6 xfs: fix tmpfile/selinux deadlock and initialize security
As a result, callers of xfs_create_tmpfile() are responsible for either calling d_tmpfile() or fixing up i_nlink appropriately. The whiteout tmpfile allocation helper does neither. As a result, the vfs ->i_nlink becomes inconsistent with the on-disk ->di_nlink once xfs_rename() links it back into the source dentry and calls xfs_bumplink().
Update the assert in xfs_rename() to help detect this problem in the future and update xfs_rename_alloc_whiteout() to decrement the link count as part of the manual tmpfile inode setup.
--- fs/xfs/xfs_inode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
fs/xfs/xfs_inode.c +8 -2
@@ -2883,7 +2883,13 @@ xfs_rename_alloc_whiteout(if (error)return error; -/* Satisfy xfs_bumplink that this is a real tmpfile */ +/* +* Prepare the tmpfile inode as if it were created through the VFS. +* Otherwise, the link increment paths will complain about nlink 0->1. +* Drop the link count as done by d_tmpfile(), complete the inode setup +* and flag it as linkable. +*/ +drop_nlink (VFS_I (tmpfile));xfs_finish_inode_setup (tmpfile);VFS_I (tmpfile)->i_state |=I_LINKABLE ;
@@ -3151,7 +3157,7 @@ xfs_rename(* intermediate state on disk. */ if (wip) { -ASSERT (wip->i_d.di_nlink ==0 ); +ASSERT (VFS_I (wip)->i_nlink ==0 && wip->i_d.di_nlink ==0 ); error =xfs_bumplink (tp, wip);if (error) goto out_trans_abort;
Signature · 6 lines
1.9.3 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs