Commit 87b7c205 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: confirm dotdot target before replacing it during a repair



xfs_dir_replace trips an assertion if you tell it to change a dirent to
point to an inumber that it already points at.  Look up the dotdot entry
directly to confirm that we need to make a change.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent b3c03efa
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -1638,6 +1638,7 @@ xrep_dir_swap(
	struct xrep_dir		*rd)
{
	struct xfs_scrub	*sc = rd->sc;
	xfs_ino_t		ino;
	bool			ip_local, temp_local;
	int			error = 0;

@@ -1655,14 +1656,17 @@ xrep_dir_swap(

	/*
	 * Reset the temporary directory's '..' entry to point to the parent
	 * that we found.  The temporary directory was created with the root
	 * directory as the parent, so we can skip this if repairing a
	 * subdirectory of the root.
	 * that we found.  The dirent replace code asserts if the dirent
	 * already points at the new inumber, so we look it up here.
	 *
	 * It's also possible that this replacement could also expand a sf
	 * tempdir into block format.
	 */
	if (rd->pscan.parent_ino != sc->mp->m_rootip->i_ino) {
	error = xchk_dir_lookup(sc, rd->sc->tempip, &xfs_name_dotdot, &ino);
	if (error)
		return error;

	if (rd->pscan.parent_ino != ino) {
		error = xrep_dir_replace(rd, rd->sc->tempip, &xfs_name_dotdot,
				rd->pscan.parent_ino, rd->tx.req.resblks);
		if (error)