fs/xfs/scrub/nlinks_repair.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/nlinks_repair.c
Extension
.c
Size
9077 bytes
Lines
350
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

if (error) {
			xchk_iunlock(sc, XFS_IOLOCK_EXCL);
			xrep_orphanage_iunlock(sc, XFS_IOLOCK_EXCL);
		} else {
			orphanage_available = true;
		}
	}

	/*
	 * Either there is no orphanage or we couldn't allocate resources for
	 * that kind of update.  Let's try again with only the resources we
	 * need for a simple link count update, since that's much more common.
	 */
	if (!orphanage_available) {
		xchk_ilock(sc, XFS_IOLOCK_EXCL);

		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_link, 0, 0, 0,
				&sc->tp);
		if (error) {
			xchk_iunlock(sc, XFS_IOLOCK_EXCL);
			return error;
		}

		xchk_ilock(sc, XFS_ILOCK_EXCL);
		xfs_trans_ijoin(sc->tp, ip, 0);
	}

	mutex_lock(&xnc->lock);

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

	error = xfarray_load_sparse(xnc->nlinks, I_INO(ip), &obs);
	if (error)
		goto out_scanlock;

	/*
	 * We're done accessing the shared scan data, so we can drop the lock.
	 * We still hold @ip's ILOCK, so its link count cannot change.
	 */
	mutex_unlock(&xnc->lock);

	total_links = xchk_nlink_total(ip, &obs);
	actual_nlink = VFS_I(ip)->i_nlink;

	/*
	 * Non-directories cannot have directories pointing up to them.
	 *
	 * We previously set error to zero, but set it again because one static
	 * checker author fears that programmers will fail to maintain this
	 * invariant and built their tool to flag this as a security risk.  A
	 * different tool author made their bot complain about the redundant
	 * store.  This is a never-ending and stupid battle; both tools missed
	 * *actual bugs* elsewhere; and I no longer care.
	 */
	if (!S_ISDIR(VFS_I(ip)->i_mode) && obs.children != 0) {
		trace_xrep_nlinks_unfixable_inode(mp, ip, &obs);
		error = 0;
		goto out_trans;
	}

	/*
	 * Decide if we're going to move this file to the orphanage, and fix
	 * up the incore link counts if we are.
	 */
	if (orphanage_available &&
	    xrep_nlinks_is_orphaned(sc, ip, actual_nlink, &obs)) {
		/* Figure out what name we're going to use here. */
		error = xrep_adoption_compute_name(&xnc->adoption, &xnc->xname);
		if (error)
			goto out_trans;

		/*
		 * Reattach this file to the directory tree by moving it to
		 * the orphanage per the adoption parameters that we already
		 * computed.
		 */
		error = xrep_adoption_move(&xnc->adoption);
		if (error)
			goto out_trans;

		/*
		 * Re-read the link counts since the reparenting will have
		 * updated our scan info.
		 */
		mutex_lock(&xnc->lock);
		error = xfarray_load_sparse(xnc->nlinks, I_INO(ip), &obs);
		mutex_unlock(&xnc->lock);

Annotation

Implementation Notes