xfs: don't stash removename operations with unknown ftype

LOLLM notices that the behavior of xrep_dir_replay_update changes based
on the ftype recorded in the stashed removename information.  It also
notices that the unlink iops sometimes set that ftype to FT_UNKNOWN
because the regular directory tree update code paths don't need to know
the ftype of the child.

Unfortunately, this results in incorrect link counts, which eventually
trips link count errors in later phases of xfs_scrub, or in xfs_repair.
Fix this by creating a second xfs_name with the type set correctly.

Cc: stable@vger.kernel.org # v6.10
Fixes: 8559b21a64 ("xfs: implement live updates for directory repairs")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
Darrick J. Wong 2026-08-26 22:31:25 -07:00 committed by Carlos Maiolino
parent 9f84792b40
commit 865b751e75

View File

@ -1381,9 +1381,24 @@ xrep_dir_live_update(
if (p->delta > 0)
error = xrep_dir_stash_createname(rd, p->name,
I_INO(p->ip));
else
error = xrep_dir_stash_removename(rd, p->name,
else {
/*
* xfs_dentry_to_name in unlink or rename-exchange can
* pass us names with ftype FT_UNKNOWN, but we really
* must know the ftype of the child that is being
* removed so that we can do nlink updates correctly
* without holding inode references.
*/
struct xfs_name name = {
.name = p->name->name,
.len = p->name->len,
.type = xfs_mode_to_ftype(
VFS_IC(p->ip)->i_mode),
};
error = xrep_dir_stash_removename(rd, &name,
I_INO(p->ip));
}
mutex_unlock(&rd->pscan.lock);
if (error)
goto out_abort;