fs/xfs/scrub/ialloc.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/ialloc.c
Extension
.c
Size
22042 bytes
Lines
797
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 xchk_iallocbt {
	/* Number of inodes we see while scanning inobt. */
	unsigned long long	inodes;

	/* Expected next startino, for big block filesystems. */
	xfs_agino_t		next_startino;

	/* Expected end of the current inode cluster. */
	xfs_agino_t		next_cluster_ino;
};

/*
 * Does the finobt have a record for this inode with the same hole/free state?
 * This is a bit complicated because of the following:
 *
 * - The finobt need not have a record if all inodes in the inobt record are
 *   allocated.
 * - The finobt need not have a record if all inodes in the inobt record are
 *   free.
 * - The finobt need not have a record if the inobt record says this is a hole.
 *   This likely doesn't happen in practice.
 */
STATIC int
xchk_inobt_xref_finobt(
	struct xfs_scrub	*sc,
	struct xfs_inobt_rec_incore *irec,
	xfs_agino_t		agino,
	bool			free,
	bool			hole)
{
	struct xfs_inobt_rec_incore frec;
	struct xfs_btree_cur	*cur = sc->sa.fino_cur;
	bool			ffree, fhole;
	unsigned int		frec_idx, fhole_idx;
	int			has_record;
	int			error;

	ASSERT(xfs_btree_is_fino(cur->bc_ops));

	error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &has_record);
	if (error)
		return error;
	if (!has_record)
		goto no_record;

	error = xfs_inobt_get_rec(cur, &frec, &has_record);
	if (!has_record)
		return -EFSCORRUPTED;

	if (frec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
		goto no_record;

	/* There's a finobt record; free and hole status must match. */
	frec_idx = agino - frec.ir_startino;
	ffree = frec.ir_free & (1ULL << frec_idx);
	fhole_idx = frec_idx / XFS_INODES_PER_HOLEMASK_BIT;
	fhole = frec.ir_holemask & (1U << fhole_idx);

	if (ffree != free)
		xchk_btree_xref_set_corrupt(sc, cur, 0);
	if (fhole != hole)
		xchk_btree_xref_set_corrupt(sc, cur, 0);
	return 0;

no_record:
	/* inobt record is fully allocated */
	if (irec->ir_free == 0)
		return 0;

	/* inobt record is totally unallocated */
	if (irec->ir_free == XFS_INOBT_ALL_FREE)
		return 0;

	/* inobt record says this is a hole */
	if (hole)
		return 0;

	/* finobt doesn't care about allocated inodes */
	if (!free)
		return 0;

	xchk_btree_xref_set_corrupt(sc, cur, 0);
	return 0;
}

/*
 * Make sure that each inode of this part of an inobt record has the same
 * sparse and free status as the finobt.
 */
STATIC void

Annotation

Implementation Notes