fs/xfs/scrub/nlinks.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/nlinks.c
Extension
.c
Size
28164 bytes
Lines
1073
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

xchk_iscan_want_live_update(&xnc->collect_iscan, I_INO(p->ip))) {
		mutex_lock(&xnc->lock);
		error = xchk_nlinks_update_incore(xnc, I_INO(p->dp), 0,
				p->delta, 0);
		mutex_unlock(&xnc->lock);
		if (error)
			goto out_abort;
	}

	return NOTIFY_DONE;

out_abort:
	xchk_iscan_abort(&xnc->collect_iscan);
	return NOTIFY_DONE;
}

/* Bump the observed link count for the inode referenced by this entry. */
STATIC int
xchk_nlinks_collect_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 xchk_nlink_ctrs	*xnc = priv;
	bool			dot = false, dotdot = false;
	int			error;

	/* Does this name make sense? */
	if (name->len == 0 || !xfs_dir2_namecheck(name->name, name->len)) {
		error = -ECANCELED;
		goto out_abort;
	}

	if (name->len == 1 && name->name[0] == '.')
		dot = true;
	else if (name->len == 2 && name->name[0] == '.' &&
				   name->name[1] == '.')
		dotdot = true;

	/* Don't accept a '.' entry that points somewhere else. */
	if (dot && ino != I_INO(dp)) {
		error = -ECANCELED;
		goto out_abort;
	}

	/* Don't accept an invalid inode number. */
	if (!xfs_verify_dir_ino(sc->mp, ino)) {
		error = -ECANCELED;
		goto out_abort;
	}

	/* Update the shadow link counts if we haven't already failed. */

	if (xchk_iscan_aborted(&xnc->collect_iscan)) {
		error = -ECANCELED;
		goto out_incomplete;
	}

	trace_xchk_nlinks_collect_dirent(sc->mp, dp, ino, name);

	mutex_lock(&xnc->lock);

	/*
	 * If this is a dotdot entry, it is a back link from dp to ino.  How
	 * we handle this depends on whether or not dp is the root directory.
	 *
	 * The root directory is its own parent, so we pretend the dotdot entry
	 * establishes the "parent" of the root directory.  Increment the
	 * number of parents of the root directory.
	 *
	 * Otherwise, increment the number of backrefs pointing back to ino.
	 *
	 * If the filesystem has parent pointers, we walk the pptrs to
	 * determine the backref count.
	 */
	if (dotdot) {
		if (xchk_inode_is_dirtree_root(dp))
			error = xchk_nlinks_update_incore(xnc, ino, 1, 0, 0);
		else if (!xfs_has_parent(sc->mp))
			error = xchk_nlinks_update_incore(xnc, ino, 0, 1, 0);
		else
			error = 0;
		if (error)
			goto out_unlock;
	}

	/*

Annotation

Implementation Notes