fs/xfs/xfs_fsmap.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/xfs_fsmap.c
Extension
.c
Size
40070 bytes
Lines
1429
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_getfsmap_info {
	struct xfs_fsmap_head	*head;
	struct fsmap		*fsmap_recs;	/* mapping records */
	struct xfs_buf		*agf_bp;	/* AGF, for refcount queries */
	struct xfs_group	*group;		/* group info, if applicable */
	xfs_daddr_t		next_daddr;	/* next daddr we expect */
	/* daddr of low fsmap key when we're using the rtbitmap */
	xfs_daddr_t		low_daddr;
	/* daddr of high fsmap key, or the last daddr on the device */
	xfs_daddr_t		end_daddr;
	u64			missing_owner;	/* owner of holes */
	u32			dev;		/* device id */
	/*
	 * Low rmap key for the query.  If low.rm_blockcount is nonzero, this
	 * is the second (or later) call to retrieve the recordset in pieces.
	 * xfs_getfsmap_rec_before_start will compare all records retrieved
	 * by the rmapbt query to filter out any records that start before
	 * the last record.
	 */
	struct xfs_rmap_irec	low;
	struct xfs_rmap_irec	high;		/* high rmap key */
	bool			last;		/* last extent? */
};

/* Associate a device with a getfsmap handler. */
struct xfs_getfsmap_dev {
	u32			dev;
	int			(*fn)(struct xfs_trans *tp,
				      const struct xfs_fsmap *keys,
				      struct xfs_getfsmap_info *info);
	sector_t		nr_sectors;
};

/* Compare two getfsmap device handlers. */
static int
xfs_getfsmap_dev_compare(
	const void			*p1,
	const void			*p2)
{
	const struct xfs_getfsmap_dev	*d1 = p1;
	const struct xfs_getfsmap_dev	*d2 = p2;

	return d1->dev - d2->dev;
}

/* Decide if this mapping is shared. */
STATIC int
xfs_getfsmap_is_shared(
	struct xfs_trans		*tp,
	struct xfs_getfsmap_info	*info,
	const struct xfs_fsmap_irec	*frec,
	bool				*stat)
{
	struct xfs_mount		*mp = tp->t_mountp;
	struct xfs_btree_cur		*cur;
	xfs_agblock_t			fbno;
	xfs_extlen_t			flen = 0;
	int				error;

	*stat = false;
	if (!xfs_has_reflink(mp) || !info->group)
		return 0;

	if (info->group->xg_type == XG_TYPE_RTG)
		cur = xfs_rtrefcountbt_init_cursor(tp, to_rtg(info->group));
	else
		cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp,
				to_perag(info->group));

	/* Are there any shared blocks here? */
	error = xfs_refcount_find_shared(cur, frec->rec_key,
			XFS_BB_TO_FSBT(mp, frec->len_daddr), &fbno, &flen,
			false);

	xfs_btree_del_cursor(cur, error);
	if (error)
		return error;

	*stat = flen > 0;
	return 0;
}

static inline void
xfs_getfsmap_format(
	struct xfs_mount		*mp,
	struct xfs_fsmap		*xfm,
	struct xfs_getfsmap_info	*info)
{
	struct fsmap			*rec;

Annotation

Implementation Notes