[PATCH 2/6] xfs: don't stash removename operations with unknown ftype
"Darrick J. Wong" <[email protected]>
| Newsgroups | org.kernel.vger.stable,org.kernel.vger.linux-xfs |
|---|---|
| Message-ID | <178760940721.944084.7350116310283813250.stgit@frogsfrogsfrogs> |
From: Darrick J. Wong <[email protected]> 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. Cc: <[email protected]> # v6.10 Fixes: 8559b21a64d983 ("xfs: implement live updates for directory repairs") Signed-off-by: "Darrick J. Wong" <[email protected]> Assisted-by: LOLLM # finding obvious bugs --- fs/xfs/scrub/dir_repair.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/fs/xfs/scrub/dir_repair.c b/fs/xfs/scrub/dir_repair.c index 0c1224d05d579a..31a23c5f386ae6 100644 --- a/fs/xfs/scrub/dir_repair.c +++ b/fs/xfs/scrub/dir_repair.c @@ -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;