fs/xfs/scrub/cow_repair.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/scrub/cow_repair.c
Extension
.c
Size
20605 bytes
Lines
751
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_cow {
	struct xfs_scrub	*sc;

	/* Bitmap of file offset ranges that need replacing. */
	struct xoff_bitmap	bad_fileoffs;

	/* Bitmap of fsblocks that were removed from the CoW fork. */
	union {
		struct xfsb_bitmap	old_cowfork_fsblocks;
		struct xrtb_bitmap	old_cowfork_rtblocks;
	};

	/* CoW fork mappings used to scan for bad CoW staging extents. */
	struct xfs_bmbt_irec	irec;

	/* refcount btree block number of irec.br_startblock */
	unsigned int		irec_startbno;

	/* refcount btree block number of the next refcount record we expect */
	unsigned int		next_bno;
};

/* CoW staging extent. */
struct xrep_cow_extent {
	xfs_fsblock_t		fsbno;
	xfs_extlen_t		len;
};

/*
 * Mark the part of the file range that corresponds to the given physical
 * space.  Caller must ensure that the physical range is within xc->irec.
 */
STATIC int
xrep_cow_mark_file_range(
	struct xrep_cow		*xc,
	xfs_fsblock_t		startblock,
	xfs_filblks_t		blockcount)
{
	xfs_fileoff_t		startoff;

	startoff = xc->irec.br_startoff +
				(startblock - xc->irec.br_startblock);

	trace_xrep_cow_mark_file_range(xc->sc->ip, startblock, startoff,
			blockcount);

	return xoff_bitmap_set(&xc->bad_fileoffs, startoff, blockcount);
}

/*
 * Trim @src to fit within the CoW fork mapping being examined, and put the
 * result in @dst.
 */
static inline void
xrep_cow_trim_refcount(
	struct xrep_cow			*xc,
	struct xfs_refcount_irec	*dst,
	const struct xfs_refcount_irec	*src)
{
	unsigned int			adj;

	memcpy(dst, src, sizeof(*dst));

	if (dst->rc_startblock < xc->irec_startbno) {
		adj = xc->irec_startbno - dst->rc_startblock;
		dst->rc_blockcount -= adj;
		dst->rc_startblock += adj;
	}

	if (dst->rc_startblock + dst->rc_blockcount >
	    xc->irec_startbno + xc->irec.br_blockcount) {
		adj = (dst->rc_startblock + dst->rc_blockcount) -
		      (xc->irec_startbno + xc->irec.br_blockcount);
		dst->rc_blockcount -= adj;
	}
}

/* Mark any shared CoW staging extents. */
STATIC int
xrep_cow_mark_shared_staging(
	struct xfs_btree_cur		*cur,
	const struct xfs_refcount_irec	*rec,
	void				*priv)
{
	struct xrep_cow			*xc = priv;
	struct xfs_refcount_irec	rrec;

	if (!xfs_refcount_check_domain(rec) ||
	    rec->rc_domain != XFS_REFC_DOMAIN_SHARED)
		return -EFSCORRUPTED;

Annotation

Implementation Notes