fs/xfs/libxfs/xfs_rmap.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/libxfs/xfs_rmap.c
Extension
.c
Size
83489 bytes
Lines
3143
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_find_left_neighbor_info {
	struct xfs_rmap_irec	high;
	struct xfs_rmap_irec	*irec;
};

/* For each rmap given, figure out if it matches the key we want. */
STATIC int
xfs_rmap_find_left_neighbor_helper(
	struct xfs_btree_cur		*cur,
	const struct xfs_rmap_irec	*rec,
	void				*priv)
{
	struct xfs_find_left_neighbor_info	*info = priv;

	trace_xfs_rmap_find_left_neighbor_candidate(cur, rec->rm_startblock,
			rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
			rec->rm_flags);

	if (rec->rm_owner != info->high.rm_owner)
		return 0;
	if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
	    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
	    rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
		return 0;

	*info->irec = *rec;
	return -ECANCELED;
}

/*
 * Find the record to the left of the given extent, being careful only to
 * return a match with the same owner and adjacent physical and logical
 * block ranges.
 */
STATIC int
xfs_rmap_find_left_neighbor(
	struct xfs_btree_cur	*cur,
	xfs_agblock_t		bno,
	uint64_t		owner,
	uint64_t		offset,
	unsigned int		flags,
	struct xfs_rmap_irec	*irec,
	int			*stat)
{
	struct xfs_find_left_neighbor_info	info;
	int			found = 0;
	int			error;

	*stat = 0;
	if (bno == 0)
		return 0;
	info.high.rm_startblock = bno - 1;
	info.high.rm_owner = owner;
	if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
	    !(flags & XFS_RMAP_BMBT_BLOCK)) {
		if (offset == 0)
			return 0;
		info.high.rm_offset = offset - 1;
	} else
		info.high.rm_offset = 0;
	info.high.rm_flags = flags;
	info.high.rm_blockcount = 0;
	info.irec = irec;

	trace_xfs_rmap_find_left_neighbor_query(cur, bno, 0, owner, offset,
			flags);

	/*
	 * Historically, we always used the range query to walk every reverse
	 * mapping that could possibly overlap the key that the caller asked
	 * for, and filter out the ones that don't.  That is very slow when
	 * there are a lot of records.
	 *
	 * However, there are two scenarios where the classic btree search can
	 * produce correct results -- if the index contains a record that is an
	 * exact match for the lookup key; and if there are no other records
	 * between the record we want and the key we supplied.
	 *
	 * As an optimization, try a non-overlapped lookup first.  This makes
	 * extent conversion and remap operations run a bit faster if the
	 * physical extents aren't being shared.  If we don't find what we
	 * want, we fall back to the overlapped query.
	 */
	error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
			&found);
	if (error)
		return error;
	if (found)
		error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
	if (!error)

Annotation

Implementation Notes