fs/xfs/scrub/rtrefcount_repair.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/rtrefcount_repair.c
Extension
.c
Size
19811 bytes
Lines
753
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_rtrefc {
	/* refcount extents */
	struct xfarray		*refcount_records;

	/* new refcountbt information */
	struct xrep_newbt	new_btree;

	/* old refcountbt blocks */
	struct xfsb_bitmap	old_rtrefcountbt_blocks;

	struct xfs_scrub	*sc;

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

	/* # of refcountbt blocks */
	xfs_filblks_t		btblocks;
};

/* Set us up to repair refcount btrees. */
int
xrep_setup_rtrefcountbt(
	struct xfs_scrub	*sc)
{
	return xrep_setup_xfbtree(sc, "realtime rmap record bag");
}

/* Check for any obvious conflicts with this shared/CoW staging extent. */
STATIC int
xrep_rtrefc_check_ext(
	struct xfs_scrub		*sc,
	const struct xfs_refcount_irec	*rec)
{
	xfs_rgblock_t			last;

	if (xfs_rtrefcount_check_irec(sc->sr.rtg, rec) != NULL)
		return -EFSCORRUPTED;

	if (xfs_rgbno_to_rtxoff(sc->mp, rec->rc_startblock) != 0)
		return -EFSCORRUPTED;

	last = rec->rc_startblock + rec->rc_blockcount - 1;
	if (xfs_rgbno_to_rtxoff(sc->mp, last) != sc->mp->m_sb.sb_rextsize - 1)
		return -EFSCORRUPTED;

	/* Make sure this isn't free space or misaligned. */
	return xrep_require_rtext_inuse(sc, rec->rc_startblock,
			rec->rc_blockcount);
}

/* Record a reference count extent. */
STATIC int
xrep_rtrefc_stash(
	struct xrep_rtrefc		*rr,
	enum xfs_refc_domain		domain,
	xfs_rgblock_t			bno,
	xfs_extlen_t			len,
	uint64_t			refcount)
{
	struct xfs_refcount_irec	irec = {
		.rc_startblock		= bno,
		.rc_blockcount		= len,
		.rc_refcount		= refcount,
		.rc_domain		= domain,
	};
	int				error = 0;

	if (xchk_should_terminate(rr->sc, &error))
		return error;

	irec.rc_refcount = min_t(uint64_t, XFS_REFC_REFCOUNT_MAX, refcount);

	error = xrep_rtrefc_check_ext(rr->sc, &irec);
	if (error)
		return error;

	trace_xrep_refc_found(rtg_group(rr->sc->sr.rtg), &irec);

	return xfarray_append(rr->refcount_records, &irec);
}

/* Record a CoW staging extent. */
STATIC int
xrep_rtrefc_stash_cow(
	struct xrep_rtrefc		*rr,
	xfs_rgblock_t			bno,
	xfs_extlen_t			len)
{
	return xrep_rtrefc_stash(rr, XFS_REFC_DOMAIN_COW, bno, len, 1);
}

Annotation

Implementation Notes