fs/xfs/scrub/ialloc_repair.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/ialloc_repair.c
Extension
.c
Size
24673 bytes
Lines
886
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_ibt {
	/* Record under construction. */
	struct xfs_inobt_rec_incore	rie;

	/* new inobt information */
	struct xrep_newbt	new_inobt;

	/* new finobt information */
	struct xrep_newbt	new_finobt;

	/* Old inode btree blocks we found in the rmap. */
	struct xagb_bitmap	old_iallocbt_blocks;

	/* Reconstructed inode records. */
	struct xfarray		*inode_records;

	struct xfs_scrub	*sc;

	/* Number of inodes assigned disk space. */
	unsigned int		icount;

	/* Number of inodes in use. */
	unsigned int		iused;

	/* Number of finobt records needed. */
	unsigned int		finobt_recs;

	/* get_records()'s position in the inode record array. */
	xfarray_idx_t		array_cur;
};

/*
 * Is this inode in use?  If the inode is in memory we can tell from i_mode,
 * otherwise we have to check di_mode in the on-disk buffer.  We only care
 * that the high (i.e. non-permission) bits of _mode are zero.  This should be
 * safe because repair keeps all AG headers locked until the end, and process
 * trying to perform an inode allocation/free must lock the AGI.
 *
 * @cluster_ag_base is the inode offset of the cluster within the AG.
 * @cluster_bp is the cluster buffer.
 * @cluster_index is the inode offset within the inode cluster.
 */
STATIC int
xrep_ibt_check_ifree(
	struct xrep_ibt		*ri,
	xfs_agino_t		cluster_ag_base,
	struct xfs_buf		*cluster_bp,
	unsigned int		cluster_index,
	bool			*inuse)
{
	struct xfs_scrub	*sc = ri->sc;
	struct xfs_mount	*mp = sc->mp;
	struct xfs_dinode	*dip;
	xfs_agino_t		agino;
	unsigned int		cluster_buf_base;
	unsigned int		offset;
	int			error;

	agino = cluster_ag_base + cluster_index;

	/* Inode uncached or half assembled, read disk buffer */
	cluster_buf_base = XFS_INO_TO_OFFSET(mp, cluster_ag_base);
	offset = (cluster_buf_base + cluster_index) * mp->m_sb.sb_inodesize;
	if (offset >= BBTOB(cluster_bp->b_length))
		return -EFSCORRUPTED;
	dip = xfs_buf_offset(cluster_bp, offset);
	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)
		return -EFSCORRUPTED;

	if (dip->di_version >= 3 &&
	    be64_to_cpu(dip->di_ino) != xfs_agino_to_ino(ri->sc->sa.pag, agino))
		return -EFSCORRUPTED;

	/* Will the in-core inode tell us if it's in use? */
	error = xchk_inode_is_allocated(sc, agino, inuse);
	if (!error)
		return 0;

	*inuse = dip->di_mode != 0;
	return 0;
}

/* Stash the accumulated inobt record for rebuilding. */
STATIC int
xrep_ibt_stash(
	struct xrep_ibt		*ri)
{
	int			error = 0;

	if (xchk_should_terminate(ri->sc, &error))

Annotation

Implementation Notes