linux/fs/xfs/scrub/findparent.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2020-2024 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <[email protected]>
 */
#include "xfs.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 {};

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/* Tear down a parent scan. */
void
xrep_findparent_scan_teardown(
	struct xrep_parent_scan_info	*pscan)
{}

/* Finish a parent scan early. */
void
xrep_findparent_scan_finish_early(
	struct xrep_parent_scan_info	*pscan,
	xfs_ino_t			ino)
{}

/*
 * 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)
{}

/*
 * 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)
{}

/* 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)
{}