xfs: don't ever put nlink > 0 inodes on the unlinked list
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 13 Feb 2019 19:15:17 +0000 (11:15 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Fri, 15 Feb 2019 06:42:57 +0000 (22:42 -0800)
commitc4a6bf7f6cc7eb4cce120fb7eb1e1fb8b2d65e09
treedff307aa199ea8d0c4169b16413e9363810c1ea9
parent15a268d9f263ed3a0601a1296568241a5a3da7aa
xfs: don't ever put nlink > 0 inodes on the unlinked list

When XFS creates an O_TMPFILE file, the inode is created with nlink = 1,
put on the unlinked list, and then the VFS sets nlink = 0 in d_tmpfile.
If we crash before anything logs the inode (it's dirty incore but the
vfs doesn't tell us it's dirty so we never log that change), the iunlink
processing part of recovery will then explode with a pile of:

XFS: Assertion failed: VFS_I(ip)->i_nlink == 0, file:
fs/xfs/xfs_log_recover.c, line: 5072

Worse yet, since nlink is nonzero, the inodes also don't get cleaned up
and they just leak until the next xfs_repair run.

Therefore, change xfs_iunlink to require that inodes being put on the
unlinked list have nlink == 0, change the tmpfile callers to instantiate
nodes that way, and set the nlink to 1 just prior to calling d_tmpfile.
Fix the comment for xfs_iunlink while we're at it.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_inode.c
fs/xfs/xfs_iops.c