fs/xfs/scrub/iscan.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/iscan.c
Extension
.c
Size
22334 bytes
Lines
827
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 (!has_rec) {
			*cursor = NULLAGINO;
			break;
		}

		error = xfs_inobt_get_rec(cur, &rec, &has_rec);
		if (error)
			break;
		if (!has_rec) {
			error = -EFSCORRUPTED;
			break;
		}

		/* Make sure that we always move forward. */
		if (lastino != NULLAGINO &&
		    XFS_IS_CORRUPT(mp, lastino >= rec.ir_startino)) {
			error = -EFSCORRUPTED;
			break;
		}
		lastino = rec.ir_startino + XFS_INODES_PER_CHUNK - 1;

		/*
		 * If this record only covers inodes that come before the
		 * cursor, advance to the next record.
		 */
		if (rec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
			continue;

		if (iscan->skip_ino)
			xchk_iscan_mask_skipino(iscan, pag, &rec, lastino);

		/*
		 * If the incoming lookup put us in the middle of an inobt
		 * record, mark it and the previous inodes "free" so that the
		 * search for allocated inodes will start at the cursor.
		 * We don't care about ir_freecount here.
		 */
		if (agino >= rec.ir_startino)
			rec.ir_free |= xfs_inobt_maskn(0,
						agino + 1 - rec.ir_startino);

		/*
		 * If there are allocated inodes in this chunk, find them
		 * and update the scan cursor.
		 */
		allocmask = ~rec.ir_free;
		if (hweight64(allocmask) > 0) {
			int	next = xfs_lowbit64(allocmask);

			ASSERT(next >= 0);
			*cursor = rec.ir_startino + next;
			*allocmaskp = allocmask >> next;
			*nr_inodesp = XFS_INODES_PER_CHUNK - next;
			break;
		}
	}

	xfs_btree_del_cursor(cur, error);
	return error;
}

/*
 * Advance both the scan and the visited cursors.
 *
 * The inumber address space for a given filesystem is sparse, which means that
 * the scan cursor can jump a long ways in a single iter() call.  There are no
 * inodes in these sparse areas, so we must move the visited cursor forward at
 * the same time so that the scan user can receive live updates for inodes that
 * may get created once we release the AGI buffer.
 */
static inline void
xchk_iscan_move_cursor(
	struct xchk_iscan	*iscan,
	xfs_agnumber_t		agno,
	xfs_agino_t		agino)
{
	struct xfs_scrub	*sc = iscan->sc;
	struct xfs_mount	*mp = sc->mp;
	xfs_ino_t		cursor, visited;

	BUILD_BUG_ON(XFS_MAXINUMBER == NULLFSINO);

	/*
	 * Special-case ino == 0 here so that we never set visited_ino to
	 * NULLFSINO when wrapping around EOFS, for that will let through all
	 * live updates.
	 */
	cursor = XFS_AGINO_TO_INO(mp, agno, agino);
	if (cursor == 0)
		visited = XFS_MAXINUMBER;

Annotation

Implementation Notes