fs/xfs/scrub/findparent.c

Source file repositories/reference/linux-study-clean/fs/xfs/scrub/findparent.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/findparent.c
Extension
.c
Size
12087 bytes
Lines
470
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

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;

Annotation

Implementation Notes