// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2020-2024 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <djwong@kernel.org>
 */
#include "xfs_platform.h"
#include "xfs_fs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_defer.h"
#include "xfs_bit.h"
#include "xfs_log_format.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_inode.h"
#include "xfs_icache.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_dir2.h"
#include "xfs_bmap_btree.h"
#include "xfs_dir2_priv.h"
#include "xfs_trans_space.h"
#include "xfs_health.h"
#include "xfs_exchmaps.h"
#include "xfs_parent.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
#include "scrub/repair.h"
#include "scrub/iscan.h"
#include "scrub/findparent.h"
#include "scrub/readdir.h"
#include "scrub/tempfile.h"
#include "scrub/listxattr.h"

/*
 * Finding the Parent of a Directory
 * =================================
 *
 * Directories have parent pointers, in the sense that each directory contains
 * a dotdot entry that points to the single allowed parent.  The brute force
 * way to find the parent of a given directory is to scan every directory in
 * the filesystem looking for a child dirent that references this directory.
 *
 * This module wraps the process of scanning the directory tree.  It requires
 * that @sc->ip is the directory whose parent we want to find, and that the
 * caller hold only the IOLOCK on that directory.  The scan itself needs to
 * take the ILOCK of each directory visited.
 *
 * Because we cannot hold @sc->ip's ILOCK during a scan of the whole fs, it is
 * necessary to use dirent hook to update the parent scan results.  Callers
 * must not read the scan results without re-taking @sc->ip's ILOCK.
 *
 * There are a few shortcuts that we can take to avoid scanning the entire
 * filesystem, such as noticing directory tree roots and querying the dentry
 * cache for parent information.
 */

struct xrep_findparent_info {
	/* The directory currently being scanned. */
	struct xfs_inode	*dp;

	/*
	 * Scrub context.  We're looking for a @dp containing a directory
	 * entry pointing to I_INO(sc->ip).
	 */
	struct xfs_scrub	*sc;

	/* Optional scan information for a xrep_findparent_scan call. */
	struct xrep_parent_scan_info *parent_scan;

	/*
	 * Parent that we've found for sc->ip.  If we're scanning the entire
	 * directory tree, we need this to ensure that we only find /one/
	 * parent directory.
	 */
	xfs_ino_t		found_parent;

	/*
	 * This is set to true if @found_parent was not observed directly from
	 * the directory scan but by noticing a change in dotdot entries after
	 * cycling the sc->ip IOLOCK.
	 */
	bool			parent_tentative;
};

/*
 * If this directory entry points to the scrub target inode, then the directory
 * we're scanning is the parent of the scrub target inode.
 */
STATIC int
xrep_findparent_dirent(
	struct xfs_scrub		*sc,
	struct xfs_inode		*dp,
	xfs_dir2_dataptr_t		dapos,
	const struct xfs_name		*name,
	xfs_ino_t			ino,
	void				*priv)
{
	struct xrep_findparent_info	*fpi = priv;
	int				error = 0;

	if (xchk_should_terminate(fpi->sc, &error))
		return error;

	if (ino != I_INO(fpi->sc->ip))
		return 0;

	/* Ignore garbage directory entry names. */
	if (name->len == 0 || !xfs_dir2_namecheck(name->name, name->len))
		return -EFSCORRUPTED;

	/*
	 * Ignore dotdot and dot entries -- we're looking for parent -> child
	 * links only.
	 */
	if (name->name[0] == '.' && (name->len == 1 ||
				     (name->len == 2 && name->name[1] == '.')))
		return 0;

	/* Uhoh, more than one parent for a dir? */
	if (fpi->found_parent != NULLFSINO &&
	    !(fpi->parent_tentative && fpi->found_parent == I_INO(fpi->dp))) {
		trace_xrep_findparent_dirent(fpi->sc->ip, 0);
		return -EFSCORRUPTED;
	}

	/* We found a potential parent; remember this. */
	trace_xrep_findparent_dirent(fpi->sc->ip, I_INO(fpi->dp));
	fpi->found_parent = I_INO(fpi->dp);
	fpi->parent_tentative = false;

	if (fpi->parent_scan)
		xrep_findparent_scan_found(fpi->parent_scan, I_INO(fpi->dp));

	return 0;
}

/*
 * If this is a directory, walk the dirents looking for any that point to the
 * scrub target inode.
 */
STATIC int
xrep_findparent_walk_directory(
	struct xrep_findparent_info	*fpi)
{
	struct xfs_scrub		*sc = fpi->sc;
	struct xfs_inode		*dp = fpi->dp;
	unsigned int			lock_mode;
	int				error = 0;

	/*
	 * The inode being scanned cannot be its own parent, nor can any
	 * temporary directory we created to stage this repair.
	 */
	if (dp == sc->ip || dp == sc->tempip)
		return 0;

	/*
	 * Similarly, temporary files created to stage a repair cannot be the
	 * parent of this inode.
	 */
	if (xrep_is_tempfile(dp))
		return 0;

	/*
	 * Scan the directory to see if there it contains an entry pointing to
	 * the directory that we are repairing.
	 */
	lock_mode = xfs_ilock_data_map_shared(dp);

	/* Don't mix metadata and regular directory trees. */
	if (xfs_is_metadir_inode(dp) != xfs_is_metadir_inode(sc->ip))
		goto out_unlock;

	/*
	 * If this directory is known to be sick, we cannot scan it reliably
	 * and must abort.
	 */
	if (xfs_inode_has_sickness(dp, XFS_SICK_INO_CORE |
				       XFS_SICK_INO_BMBTD |
				       XFS_SICK_INO_DIR)) {
		error = -EFSCORRUPTED;
		goto out_unlock;
	}

	/*
	 * We cannot complete our parent pointer scan if a directory looks as
	 * though it has been zapped by the inode record repair code.
	 */
	if (xchk_dir_looks_zapped(dp)) {
		error = -EBUSY;
		goto out_unlock;
	}

	error = xchk_dir_walk(sc, dp, xrep_findparent_dirent, fpi);
	if (error)
		goto out_unlock;

out_unlock:
	xfs_iunlock(dp, lock_mode);
	return error;
}

/*
 * Update this directory's dotdot pointer based on ongoing dirent updates.
 */
STATIC int
xrep_findparent_live_update(
	struct notifier_block		*nb,
	unsigned long			action,
	void				*data)
{
	struct xfs_dir_update_params	*p = data;
	struct xrep_parent_scan_info	*pscan;
	struct xfs_scrub		*sc;

	pscan = container_of(nb, struct xrep_parent_scan_info,
			dhook.dirent_hook.nb);
	sc = pscan->sc;

	/*
	 * If @p->ip is the subdirectory that we're interested in and we've
	 * already scanned @p->dp, update the dotdot target inumber to the
	 * parent inode.
	 */
	if (I_INO(p->ip) == I_INO(sc->ip) &&
	    xchk_iscan_want_live_update(&pscan->iscan, I_INO(p->dp))) {
		if (p->delta > 0)
			xrep_findparent_scan_found(pscan, I_INO(p->dp));
		else
			xrep_findparent_scan_found(pscan, NULLFSINO);
	}

	return NOTIFY_DONE;
}

/*
 * Set up a scan to find the parent of a directory.  The provided dirent hook
 * will be called when there is a dotdot update for the inode being repaired.
 */
int
__xrep_findparent_scan_start(
	struct xfs_scrub		*sc,
	struct xrep_parent_scan_info	*pscan,
	notifier_fn_t			custom_fn)
{
	int				error;

	if (!(sc->flags & XCHK_FSGATES_DIRENTS)) {
		ASSERT(sc->flags & XCHK_FSGATES_DIRENTS);
		return -EINVAL;
	}

	pscan->sc = sc;
	pscan->parent_ino = NULLFSINO;

	mutex_init(&pscan->lock);

	xchk_iscan_start(sc, 30000, 100, &pscan->iscan);

	/*
	 * Hook into the dirent update code.  The hook only operates on inodes
	 * that were already scanned, and the scanner thread takes each inode's
	 * ILOCK, which means that any in-progress inode updates will finish
	 * before we can scan the inode.
	 */
	if (custom_fn)
		xfs_dir_hook_setup(&pscan->dhook, custom_fn);
	else
		xfs_dir_hook_setup(&pscan->dhook, xrep_findparent_live_update);
	error = xfs_dir_hook_add(sc->mp, &pscan->dhook);
	if (error)
		goto out_iscan;

	return 0;
out_iscan:
	xchk_iscan_teardown(&pscan->iscan);
	mutex_destroy(&pscan->lock);
	return error;
}

/*
 * Scan the entire filesystem looking for a parent inode for the inode being
 * scrubbed.  @sc->ip must not be the root of a directory tree.  Callers must
 * not hold a dirty transaction or any lock that would interfere with taking
 * an ILOCK.
 *
 * Returns 0 with @pscan->parent_ino set to the parent that we found.
 * Returns 0 with @pscan->parent_ino set to NULLFSINO if we found no parents.
 * Returns the usual negative errno if something else happened.
 */
int
xrep_findparent_scan(
	struct xrep_parent_scan_info	*pscan)
{
	struct xrep_findparent_info	fpi = {
		.sc			= pscan->sc,
		.found_parent		= NULLFSINO,
		.parent_scan		= pscan,
	};
	struct xfs_scrub		*sc = pscan->sc;
	int				ret;

	ASSERT(S_ISDIR(VFS_IC(sc->ip)->i_mode));

	while ((ret = xchk_iscan_iter(&pscan->iscan, &fpi.dp)) == 1) {
		if (S_ISDIR(VFS_I(fpi.dp)->i_mode))
			ret = xrep_findparent_walk_directory(&fpi);
		else
			ret = 0;
		xchk_iscan_mark_visited(&pscan->iscan, fpi.dp);
		xchk_irele(sc, fpi.dp);
		if (ret)
			break;

		if (xchk_should_terminate(sc, &ret))
			break;
	}
	xchk_iscan_iter_finish(&pscan->iscan);

	return ret;
}

/* Tear down a parent scan. */
void
xrep_findparent_scan_teardown(
	struct xrep_parent_scan_info	*pscan)
{
	xfs_dir_hook_del(pscan->sc->mp, &pscan->dhook);
	xchk_iscan_teardown(&pscan->iscan);
	mutex_destroy(&pscan->lock);
}

/* Finish a parent scan early. */
void
xrep_findparent_scan_finish_early(
	struct xrep_parent_scan_info	*pscan,
	xfs_ino_t			ino)
{
	xrep_findparent_scan_found(pscan, ino);
	xchk_iscan_finish_early(&pscan->iscan);
}

/*
 * Confirm that the directory @parent_ino actually contains a directory entry
 * pointing to the child @sc->ip->ino.  This function returns one of several
 * ways:
 *
 * Returns 0 with @parent_ino unchanged if the parent was confirmed.
 * Returns 0 with @parent_ino set to NULLFSINO if the parent was not valid.
 * Returns the usual negative errno if something else happened.
 */
int
xrep_findparent_confirm(
	struct xfs_scrub	*sc,
	xfs_ino_t		*parent_ino)
{
	struct xrep_findparent_info fpi = {
		.sc		= sc,
		.found_parent	= NULLFSINO,
	};
	int			error;

	/* The root directory always points to itself. */
	if (sc->ip == sc->mp->m_rootip) {
		*parent_ino = sc->mp->m_sb.sb_rootino;
		return 0;
	}

	/* The metadata root directory always points to itself. */
	if (sc->ip == sc->mp->m_metadirip) {
		*parent_ino = sc->mp->m_sb.sb_metadirino;
		return 0;
	}

	/* Unlinked dirs can point anywhere; point them up to the root dir. */
	if (VFS_I(sc->ip)->i_nlink == 0) {
		*parent_ino = xchk_inode_rootdir_inum(sc->ip);
		return 0;
	}

	/* Reject garbage parent inode numbers and self-referential parents. */
	if (*parent_ino == NULLFSINO)
	       return 0;
	if (!xfs_verify_dir_ino(sc->mp, *parent_ino) ||
	    *parent_ino == I_INO(sc->ip)) {
		*parent_ino = NULLFSINO;
		return 0;
	}

	error = xchk_iget(sc, *parent_ino, &fpi.dp);
	if (error)
		return error;

	if (!S_ISDIR(VFS_I(fpi.dp)->i_mode)) {
		*parent_ino = NULLFSINO;
		goto out_rele;
	}

	error = xrep_findparent_walk_directory(&fpi);
	if (error)
		goto out_rele;

	*parent_ino = fpi.found_parent;
out_rele:
	xchk_irele(sc, fpi.dp);
	return error;
}

/*
 * If we're the root of a directory tree, we are our own parent.  If we're an
 * unlinked directory, the parent /won't/ have a link to us.  Set the parent
 * directory to the root for both cases.  Returns NULLFSINO if we don't know
 * what to do.
 */
xfs_ino_t
xrep_findparent_self_reference(
	struct xfs_scrub	*sc)
{
	if (I_INO(sc->ip) == sc->mp->m_sb.sb_rootino)
		return sc->mp->m_sb.sb_rootino;

	if (I_INO(sc->ip) == sc->mp->m_sb.sb_metadirino)
		return sc->mp->m_sb.sb_metadirino;

	if (VFS_I(sc->ip)->i_nlink == 0)
		return xchk_inode_rootdir_inum(sc->ip);

	return NULLFSINO;
}

/* Check the dentry cache to see if knows of a parent for the scrub target. */
xfs_ino_t
xrep_findparent_from_dcache(
	struct xfs_scrub	*sc)
{
	struct inode		*pip = NULL;
	struct dentry		*dentry, *parent;
	xfs_ino_t		ret = NULLFSINO;

	dentry = d_find_alias(VFS_I(sc->ip));
	if (!dentry)
		goto out;

	parent = dget_parent(dentry);
	if (!parent)
		goto out_dput;

	ASSERT(parent->d_sb == sc->ip->i_mount->m_super);

	pip = igrab(d_inode(parent));
	dput(parent);

	if (S_ISDIR(pip->i_mode)) {
		ret = pip->i_ino;
		trace_xrep_findparent_from_dcache(sc->ip, ret);
	}

	xchk_irele(sc, XFS_I(pip));

out_dput:
	dput(dentry);
out:
	return ret;
}
