fs/xfs/libxfs/xfs_bmap.c

Source file repositories/reference/linux-study-clean/fs/xfs/libxfs/xfs_bmap.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/libxfs/xfs_bmap.c
Extension
.c
Size
170167 bytes
Lines
6265
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 xfs_iread_state {
	struct xfs_iext_cursor	icur;
	xfs_extnum_t		loaded;
};

int
xfs_bmap_complain_bad_rec(
	struct xfs_inode		*ip,
	int				whichfork,
	xfs_failaddr_t			fa,
	const struct xfs_bmbt_irec	*irec)
{
	struct xfs_mount		*mp = ip->i_mount;
	const char			*forkname;

	switch (whichfork) {
	case XFS_DATA_FORK:	forkname = "data"; break;
	case XFS_ATTR_FORK:	forkname = "attr"; break;
	case XFS_COW_FORK:	forkname = "CoW"; break;
	default:		forkname = "???"; break;
	}

	xfs_warn(mp,
 "Bmap BTree record corruption in inode 0x%llx %s fork detected at %pS!",
				I_INO(ip), forkname, fa);
	xfs_warn(mp,
		"Offset 0x%llx, start block 0x%llx, block count 0x%llx state 0x%x",
		irec->br_startoff, irec->br_startblock, irec->br_blockcount,
		irec->br_state);

	return -EFSCORRUPTED;
}

/* Stuff every bmbt record from this block into the incore extent map. */
static int
xfs_iread_bmbt_block(
	struct xfs_btree_cur	*cur,
	int			level,
	void			*priv)
{
	struct xfs_iread_state	*ir = priv;
	struct xfs_mount	*mp = cur->bc_mp;
	struct xfs_inode	*ip = cur->bc_ino.ip;
	struct xfs_btree_block	*block;
	struct xfs_buf		*bp;
	struct xfs_bmbt_rec	*frp;
	xfs_extnum_t		num_recs;
	xfs_extnum_t		j;
	int			whichfork = cur->bc_ino.whichfork;
	struct xfs_ifork	*ifp = xfs_ifork_ptr(ip, whichfork);

	block = xfs_btree_get_block(cur, level, &bp);

	/* Abort if we find more records than nextents. */
	num_recs = xfs_btree_get_numrecs(block);
	if (unlikely(ir->loaded + num_recs > ifp->if_nextents)) {
		xfs_warn(ip->i_mount, "corrupt dinode %llu, (btree extents).",
				(unsigned long long)I_INO(ip));
		xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, block,
				sizeof(*block), __this_address);
		xfs_bmap_mark_sick(ip, whichfork);
		return -EFSCORRUPTED;
	}

	/* Copy records into the incore cache. */
	frp = xfs_bmbt_rec_addr(mp, block, 1);
	for (j = 0; j < num_recs; j++, frp++, ir->loaded++) {
		struct xfs_bmbt_irec	new;
		xfs_failaddr_t		fa;

		xfs_bmbt_disk_get_all(frp, &new);
		fa = xfs_bmap_validate_extent(ip, whichfork, &new);
		if (fa) {
			xfs_inode_verifier_error(ip, -EFSCORRUPTED,
					"xfs_iread_extents(2)", frp,
					sizeof(*frp), fa);
			xfs_bmap_mark_sick(ip, whichfork);
			return xfs_bmap_complain_bad_rec(ip, whichfork, fa,
					&new);
		}
		xfs_iext_insert(ip, &ir->icur, &new,
				xfs_bmap_fork_to_state(whichfork));
		trace_xfs_read_extent(ip, &ir->icur,
				xfs_bmap_fork_to_state(whichfork), _THIS_IP_);
		xfs_iext_next(ifp, &ir->icur);
	}

	return 0;
}

Annotation

Implementation Notes