162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
462306a36Sopenharmony_ci * All Rights Reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#ifndef	__XFS_INODE_FORK_H__
762306a36Sopenharmony_ci#define	__XFS_INODE_FORK_H__
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct xfs_inode_log_item;
1062306a36Sopenharmony_cistruct xfs_dinode;
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * File incore extent information, present for each of data & attr forks.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_cistruct xfs_ifork {
1662306a36Sopenharmony_ci	int64_t			if_bytes;	/* bytes in if_u1 */
1762306a36Sopenharmony_ci	struct xfs_btree_block	*if_broot;	/* file's incore btree root */
1862306a36Sopenharmony_ci	unsigned int		if_seq;		/* fork mod counter */
1962306a36Sopenharmony_ci	int			if_height;	/* height of the extent tree */
2062306a36Sopenharmony_ci	union {
2162306a36Sopenharmony_ci		void		*if_root;	/* extent tree root */
2262306a36Sopenharmony_ci		char		*if_data;	/* inline file data */
2362306a36Sopenharmony_ci	} if_u1;
2462306a36Sopenharmony_ci	xfs_extnum_t		if_nextents;	/* # of extents in this fork */
2562306a36Sopenharmony_ci	short			if_broot_bytes;	/* bytes allocated for root */
2662306a36Sopenharmony_ci	int8_t			if_format;	/* format of this fork */
2762306a36Sopenharmony_ci	uint8_t			if_needextents;	/* extents have not been read */
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * Worst-case increase in the fork extent count when we're adding a single
3262306a36Sopenharmony_ci * extent to a fork and there's no possibility of splitting an existing mapping.
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_ci#define XFS_IEXT_ADD_NOSPLIT_CNT	(1)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/*
3762306a36Sopenharmony_ci * Punching out an extent from the middle of an existing extent can cause the
3862306a36Sopenharmony_ci * extent count to increase by 1.
3962306a36Sopenharmony_ci * i.e. | Old extent | Hole | Old extent |
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci#define XFS_IEXT_PUNCH_HOLE_CNT		(1)
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/*
4462306a36Sopenharmony_ci * Adding/removing an xattr can cause XFS_DA_NODE_MAXDEPTH extents to
4562306a36Sopenharmony_ci * be added. One extra extent for dabtree in case a local attr is
4662306a36Sopenharmony_ci * large enough to cause a double split.  It can also cause extent
4762306a36Sopenharmony_ci * count to increase proportional to the size of a remote xattr's
4862306a36Sopenharmony_ci * value.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_ci#define XFS_IEXT_ATTR_MANIP_CNT(rmt_blks) \
5162306a36Sopenharmony_ci	(XFS_DA_NODE_MAXDEPTH + max(1, rmt_blks))
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/*
5462306a36Sopenharmony_ci * A write to a sub-interval of an existing unwritten extent causes the original
5562306a36Sopenharmony_ci * extent to be split into 3 extents
5662306a36Sopenharmony_ci * i.e. | Unwritten | Real | Unwritten |
5762306a36Sopenharmony_ci * Hence extent count can increase by 2.
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_ci#define XFS_IEXT_WRITE_UNWRITTEN_CNT	(2)
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/*
6362306a36Sopenharmony_ci * Moving an extent to data fork can cause a sub-interval of an existing extent
6462306a36Sopenharmony_ci * to be unmapped. This will increase extent count by 1. Mapping in the new
6562306a36Sopenharmony_ci * extent can increase the extent count by 1 again i.e.
6662306a36Sopenharmony_ci * | Old extent | New extent | Old extent |
6762306a36Sopenharmony_ci * Hence number of extents increases by 2.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_ci#define XFS_IEXT_REFLINK_END_COW_CNT	(2)
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * Removing an initial range of source/donor file's extent and adding a new
7362306a36Sopenharmony_ci * extent (from donor/source file) in its place will cause extent count to
7462306a36Sopenharmony_ci * increase by 1.
7562306a36Sopenharmony_ci */
7662306a36Sopenharmony_ci#define XFS_IEXT_SWAP_RMAP_CNT		(1)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/*
7962306a36Sopenharmony_ci * Fork handling.
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_ci#define XFS_IFORK_MAXEXT(ip, w) \
8262306a36Sopenharmony_ci	(xfs_inode_fork_size(ip, w) / sizeof(xfs_bmbt_rec_t))
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic inline bool xfs_ifork_has_extents(struct xfs_ifork *ifp)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	return ifp->if_format == XFS_DINODE_FMT_EXTENTS ||
8762306a36Sopenharmony_ci		ifp->if_format == XFS_DINODE_FMT_BTREE;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	if (!ifp)
9362306a36Sopenharmony_ci		return 0;
9462306a36Sopenharmony_ci	return ifp->if_nextents;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic inline int8_t xfs_ifork_format(struct xfs_ifork *ifp)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	if (!ifp)
10062306a36Sopenharmony_ci		return XFS_DINODE_FMT_EXTENTS;
10162306a36Sopenharmony_ci	return ifp->if_format;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic inline xfs_extnum_t xfs_iext_max_nextents(bool has_large_extent_counts,
10562306a36Sopenharmony_ci				int whichfork)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	switch (whichfork) {
10862306a36Sopenharmony_ci	case XFS_DATA_FORK:
10962306a36Sopenharmony_ci	case XFS_COW_FORK:
11062306a36Sopenharmony_ci		if (has_large_extent_counts)
11162306a36Sopenharmony_ci			return XFS_MAX_EXTCNT_DATA_FORK_LARGE;
11262306a36Sopenharmony_ci		return XFS_MAX_EXTCNT_DATA_FORK_SMALL;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	case XFS_ATTR_FORK:
11562306a36Sopenharmony_ci		if (has_large_extent_counts)
11662306a36Sopenharmony_ci			return XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
11762306a36Sopenharmony_ci		return XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	default:
12062306a36Sopenharmony_ci		ASSERT(0);
12162306a36Sopenharmony_ci		return 0;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic inline xfs_extnum_t
12662306a36Sopenharmony_cixfs_dfork_data_extents(
12762306a36Sopenharmony_ci	struct xfs_dinode	*dip)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	if (xfs_dinode_has_large_extent_counts(dip))
13062306a36Sopenharmony_ci		return be64_to_cpu(dip->di_big_nextents);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	return be32_to_cpu(dip->di_nextents);
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic inline xfs_extnum_t
13662306a36Sopenharmony_cixfs_dfork_attr_extents(
13762306a36Sopenharmony_ci	struct xfs_dinode	*dip)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	if (xfs_dinode_has_large_extent_counts(dip))
14062306a36Sopenharmony_ci		return be32_to_cpu(dip->di_big_anextents);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return be16_to_cpu(dip->di_anextents);
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic inline xfs_extnum_t
14662306a36Sopenharmony_cixfs_dfork_nextents(
14762306a36Sopenharmony_ci	struct xfs_dinode	*dip,
14862306a36Sopenharmony_ci	int			whichfork)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	switch (whichfork) {
15162306a36Sopenharmony_ci	case XFS_DATA_FORK:
15262306a36Sopenharmony_ci		return xfs_dfork_data_extents(dip);
15362306a36Sopenharmony_ci	case XFS_ATTR_FORK:
15462306a36Sopenharmony_ci		return xfs_dfork_attr_extents(dip);
15562306a36Sopenharmony_ci	default:
15662306a36Sopenharmony_ci		ASSERT(0);
15762306a36Sopenharmony_ci		break;
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	return 0;
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_civoid xfs_ifork_zap_attr(struct xfs_inode *ip);
16462306a36Sopenharmony_civoid xfs_ifork_init_attr(struct xfs_inode *ip, enum xfs_dinode_fmt format,
16562306a36Sopenharmony_ci		xfs_extnum_t nextents);
16662306a36Sopenharmony_cistruct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ciint		xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *);
16962306a36Sopenharmony_ciint		xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *);
17062306a36Sopenharmony_civoid		xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *,
17162306a36Sopenharmony_ci				struct xfs_inode_log_item *, int);
17262306a36Sopenharmony_civoid		xfs_idestroy_fork(struct xfs_ifork *ifp);
17362306a36Sopenharmony_civoid		xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff,
17462306a36Sopenharmony_ci				int whichfork);
17562306a36Sopenharmony_civoid		xfs_iroot_realloc(struct xfs_inode *, int, int);
17662306a36Sopenharmony_ciint		xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int);
17762306a36Sopenharmony_ciint		xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *,
17862306a36Sopenharmony_ci				  int);
17962306a36Sopenharmony_civoid		xfs_init_local_fork(struct xfs_inode *ip, int whichfork,
18062306a36Sopenharmony_ci				const void *data, int64_t size);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cixfs_extnum_t	xfs_iext_count(struct xfs_ifork *ifp);
18362306a36Sopenharmony_civoid		xfs_iext_insert(struct xfs_inode *, struct xfs_iext_cursor *cur,
18462306a36Sopenharmony_ci			struct xfs_bmbt_irec *, int);
18562306a36Sopenharmony_civoid		xfs_iext_remove(struct xfs_inode *, struct xfs_iext_cursor *,
18662306a36Sopenharmony_ci			int);
18762306a36Sopenharmony_civoid		xfs_iext_destroy(struct xfs_ifork *);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cibool		xfs_iext_lookup_extent(struct xfs_inode *ip,
19062306a36Sopenharmony_ci			struct xfs_ifork *ifp, xfs_fileoff_t bno,
19162306a36Sopenharmony_ci			struct xfs_iext_cursor *cur,
19262306a36Sopenharmony_ci			struct xfs_bmbt_irec *gotp);
19362306a36Sopenharmony_cibool		xfs_iext_lookup_extent_before(struct xfs_inode *ip,
19462306a36Sopenharmony_ci			struct xfs_ifork *ifp, xfs_fileoff_t *end,
19562306a36Sopenharmony_ci			struct xfs_iext_cursor *cur,
19662306a36Sopenharmony_ci			struct xfs_bmbt_irec *gotp);
19762306a36Sopenharmony_cibool		xfs_iext_get_extent(struct xfs_ifork *ifp,
19862306a36Sopenharmony_ci			struct xfs_iext_cursor *cur,
19962306a36Sopenharmony_ci			struct xfs_bmbt_irec *gotp);
20062306a36Sopenharmony_civoid		xfs_iext_update_extent(struct xfs_inode *ip, int state,
20162306a36Sopenharmony_ci			struct xfs_iext_cursor *cur,
20262306a36Sopenharmony_ci			struct xfs_bmbt_irec *gotp);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_civoid		xfs_iext_first(struct xfs_ifork *, struct xfs_iext_cursor *);
20562306a36Sopenharmony_civoid		xfs_iext_last(struct xfs_ifork *, struct xfs_iext_cursor *);
20662306a36Sopenharmony_civoid		xfs_iext_next(struct xfs_ifork *, struct xfs_iext_cursor *);
20762306a36Sopenharmony_civoid		xfs_iext_prev(struct xfs_ifork *, struct xfs_iext_cursor *);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic inline bool xfs_iext_next_extent(struct xfs_ifork *ifp,
21062306a36Sopenharmony_ci		struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	xfs_iext_next(ifp, cur);
21362306a36Sopenharmony_ci	return xfs_iext_get_extent(ifp, cur, gotp);
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic inline bool xfs_iext_prev_extent(struct xfs_ifork *ifp,
21762306a36Sopenharmony_ci		struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	xfs_iext_prev(ifp, cur);
22062306a36Sopenharmony_ci	return xfs_iext_get_extent(ifp, cur, gotp);
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci/*
22462306a36Sopenharmony_ci * Return the extent after cur in gotp without updating the cursor.
22562306a36Sopenharmony_ci */
22662306a36Sopenharmony_cistatic inline bool xfs_iext_peek_next_extent(struct xfs_ifork *ifp,
22762306a36Sopenharmony_ci		struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	struct xfs_iext_cursor ncur = *cur;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	xfs_iext_next(ifp, &ncur);
23262306a36Sopenharmony_ci	return xfs_iext_get_extent(ifp, &ncur, gotp);
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci/*
23662306a36Sopenharmony_ci * Return the extent before cur in gotp without updating the cursor.
23762306a36Sopenharmony_ci */
23862306a36Sopenharmony_cistatic inline bool xfs_iext_peek_prev_extent(struct xfs_ifork *ifp,
23962306a36Sopenharmony_ci		struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	struct xfs_iext_cursor ncur = *cur;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	xfs_iext_prev(ifp, &ncur);
24462306a36Sopenharmony_ci	return xfs_iext_get_extent(ifp, &ncur, gotp);
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci#define for_each_xfs_iext(ifp, ext, got)		\
24862306a36Sopenharmony_ci	for (xfs_iext_first((ifp), (ext));		\
24962306a36Sopenharmony_ci	     xfs_iext_get_extent((ifp), (ext), (got));	\
25062306a36Sopenharmony_ci	     xfs_iext_next((ifp), (ext)))
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ciextern struct kmem_cache	*xfs_ifork_cache;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ciextern void xfs_ifork_init_cow(struct xfs_inode *ip);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ciint xfs_ifork_verify_local_data(struct xfs_inode *ip);
25762306a36Sopenharmony_ciint xfs_ifork_verify_local_attr(struct xfs_inode *ip);
25862306a36Sopenharmony_ciint xfs_iext_count_may_overflow(struct xfs_inode *ip, int whichfork,
25962306a36Sopenharmony_ci		int nr_to_add);
26062306a36Sopenharmony_ciint xfs_iext_count_upgrade(struct xfs_trans *tp, struct xfs_inode *ip,
26162306a36Sopenharmony_ci		uint nr_to_add);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci/* returns true if the fork has extents but they are not read in yet. */
26462306a36Sopenharmony_cistatic inline bool xfs_need_iread_extents(const struct xfs_ifork *ifp)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	/* see xfs_iformat_{data,attr}_fork() for needextents semantics */
26762306a36Sopenharmony_ci	return smp_load_acquire(&ifp->if_needextents) != 0;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci#endif	/* __XFS_INODE_FORK_H__ */
271