Commit 679b098b authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: refactor directory tree root predicates



Metadata directory trees make reasoning about the parent of a file more
difficult.  Traditionally, user files are children of sb_rootino, and
metadata files are "children" of the superblock.  Now, we add a third
possibility -- some metadata files can be children of sb_metadirino, but
the classic ones (rt free space data and quotas) are left alone.

Let's add some helper functions (instead of open-coding the logic
everywhere) to make scrub logic easier to understand.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent be42fc13
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -1452,3 +1452,32 @@ xchk_inode_is_allocated(
	rcu_read_unlock();
	return error;
}

/* Is this inode a root directory for either tree? */
bool
xchk_inode_is_dirtree_root(const struct xfs_inode *ip)
{
	struct xfs_mount	*mp = ip->i_mount;

	return ip == mp->m_rootip ||
		(xfs_has_metadir(mp) && ip == mp->m_metadirip);
}

/* Does the superblock point down to this inode? */
bool
xchk_inode_is_sb_rooted(const struct xfs_inode *ip)
{
	return xchk_inode_is_dirtree_root(ip) ||
	       xfs_is_sb_inum(ip->i_mount, ip->i_ino);
}

/* What is the root directory inumber for this inode? */
xfs_ino_t
xchk_inode_rootdir_inum(const struct xfs_inode *ip)
{
	struct xfs_mount	*mp = ip->i_mount;

	if (xfs_is_metadir_inode(ip))
		return mp->m_metadirip->i_ino;
	return mp->m_rootip->i_ino;
}
+4 −0
Original line number Diff line number Diff line
@@ -242,4 +242,8 @@ void xchk_fsgates_enable(struct xfs_scrub *sc, unsigned int scrub_fshooks);
int xchk_inode_is_allocated(struct xfs_scrub *sc, xfs_agino_t agino,
		bool *inuse);

bool xchk_inode_is_dirtree_root(const struct xfs_inode *ip);
bool xchk_inode_is_sb_rooted(const struct xfs_inode *ip);
xfs_ino_t xchk_inode_rootdir_inum(const struct xfs_inode *ip);

#endif	/* __XFS_SCRUB_COMMON_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -253,7 +253,7 @@ xchk_dir_actor(
		 * If this is ".." in the root inode, check that the inum
		 * matches this dir.
		 */
		if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino)
		if (xchk_inode_is_dirtree_root(dp) && ino != dp->i_ino)
			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
	}

+1 −1
Original line number Diff line number Diff line
@@ -1270,7 +1270,7 @@ xrep_dir_scan_dirtree(
	int			error;

	/* Roots of directory trees are their own parents. */
	if (sc->ip == sc->mp->m_rootip)
	if (xchk_inode_is_dirtree_root(sc->ip))
		xrep_findparent_scan_found(&rd->pscan, sc->ip->i_ino);

	/*
+14 −1
Original line number Diff line number Diff line
@@ -917,7 +917,7 @@ xchk_dirtree(
	 * scan, because the hook doesn't detach until after sc->ip gets
	 * released during teardown.
	 */
	dl->root_ino = sc->mp->m_rootip->i_ino;
	dl->root_ino = xchk_inode_rootdir_inum(sc->ip);
	dl->scan_ino = sc->ip->i_ino;

	trace_xchk_dirtree_start(sc->ip, sc->sm, 0);
@@ -983,3 +983,16 @@ xchk_dirtree(
	trace_xchk_dirtree_done(sc->ip, sc->sm, error);
	return error;
}

/* Does the directory targetted by this scrub have no parents? */
bool
xchk_dirtree_parentless(const struct xchk_dirtree *dl)
{
	struct xfs_scrub	*sc = dl->sc;

	if (xchk_inode_is_dirtree_root(sc->ip))
		return true;
	if (VFS_I(sc->ip)->i_nlink == 0)
		return true;
	return false;
}
Loading