xref: /linux/fs/xfs/libxfs/xfs_group.h (revision c148bc7535650fbfa95a1f571b9ffa2ab478ea33)
1e9c4d8bfSChristoph Hellwig /* SPDX-License-Identifier: GPL-2.0 */
2e9c4d8bfSChristoph Hellwig /*
3e9c4d8bfSChristoph Hellwig  * Copyright (c) 2018 Red Hat, Inc.
4e9c4d8bfSChristoph Hellwig  */
5e9c4d8bfSChristoph Hellwig #ifndef __LIBXFS_GROUP_H
6e9c4d8bfSChristoph Hellwig #define __LIBXFS_GROUP_H 1
7e9c4d8bfSChristoph Hellwig 
8e9c4d8bfSChristoph Hellwig struct xfs_group {
9e9c4d8bfSChristoph Hellwig 	struct xfs_mount	*xg_mount;
10e9c4d8bfSChristoph Hellwig 	uint32_t		xg_gno;
11e9c4d8bfSChristoph Hellwig 	enum xfs_group_type	xg_type;
12e9c4d8bfSChristoph Hellwig 	atomic_t		xg_ref;		/* passive reference count */
13e9c4d8bfSChristoph Hellwig 	atomic_t		xg_active_ref;	/* active reference count */
145c8483ceSChristoph Hellwig 
15e0b5b97dSDarrick J. Wong 	/* Precalculated geometry info */
16e0b5b97dSDarrick J. Wong 	uint32_t		xg_block_count;	/* max usable gbno */
17e0b5b97dSDarrick J. Wong 	uint32_t		xg_min_gbno;	/* min usable gbno */
18e0b5b97dSDarrick J. Wong 
195c8483ceSChristoph Hellwig #ifdef __KERNEL__
205c8483ceSChristoph Hellwig 	/* -- kernel only structures below this line -- */
215c8483ceSChristoph Hellwig 
22080d01c4SChristoph Hellwig 	union {
235c8483ceSChristoph Hellwig 		/*
24080d01c4SChristoph Hellwig 		 * For perags and non-zoned RT groups:
25adbc76aaSChristoph Hellwig 		 * Track freed but not yet committed extents.
26adbc76aaSChristoph Hellwig 		 */
27adbc76aaSChristoph Hellwig 		struct xfs_extent_busy_tree	*xg_busy_extents;
28adbc76aaSChristoph Hellwig 
29adbc76aaSChristoph Hellwig 		/*
30080d01c4SChristoph Hellwig 		 * For zoned RT groups:
31080d01c4SChristoph Hellwig 		 * List of groups that need a zone reset.
32080d01c4SChristoph Hellwig 		 *
33080d01c4SChristoph Hellwig 		 * The zonegc code forces a log flush of the rtrmap inode before
34080d01c4SChristoph Hellwig 		 * resetting the write pointer, so there is no need for
35080d01c4SChristoph Hellwig 		 * individual busy extent tracking.
36080d01c4SChristoph Hellwig 		 */
37080d01c4SChristoph Hellwig 		struct xfs_group		*xg_next_reset;
38080d01c4SChristoph Hellwig 	};
39080d01c4SChristoph Hellwig 
40080d01c4SChristoph Hellwig 	/*
415c8483ceSChristoph Hellwig 	 * Bitsets of per-ag metadata that have been checked and/or are sick.
425c8483ceSChristoph Hellwig 	 * Callers should hold xg_state_lock before accessing this field.
435c8483ceSChristoph Hellwig 	 */
445c8483ceSChristoph Hellwig 	uint16_t		xg_checked;
455c8483ceSChristoph Hellwig 	uint16_t		xg_sick;
465c8483ceSChristoph Hellwig 	spinlock_t		xg_state_lock;
4734cf3a6fSChristoph Hellwig 
4834cf3a6fSChristoph Hellwig 	/*
4934cf3a6fSChristoph Hellwig 	 * We use xfs_drain to track the number of deferred log intent items
5034cf3a6fSChristoph Hellwig 	 * that have been queued (but not yet processed) so that waiters (e.g.
5134cf3a6fSChristoph Hellwig 	 * scrub) will not lock resources when other threads are in the middle
5234cf3a6fSChristoph Hellwig 	 * of processing a chain of intent items only to find momentary
5334cf3a6fSChristoph Hellwig 	 * inconsistencies.
5434cf3a6fSChristoph Hellwig 	 */
5534cf3a6fSChristoph Hellwig 	struct xfs_defer_drain	xg_intents_drain;
56eb4a84a3SChristoph Hellwig 
57eb4a84a3SChristoph Hellwig 	/*
58eb4a84a3SChristoph Hellwig 	 * Hook to feed rmapbt updates to an active online repair.
59eb4a84a3SChristoph Hellwig 	 */
60eb4a84a3SChristoph Hellwig 	struct xfs_hooks	xg_rmap_update_hooks;
615c8483ceSChristoph Hellwig #endif /* __KERNEL__ */
62e9c4d8bfSChristoph Hellwig };
63e9c4d8bfSChristoph Hellwig 
64e9c4d8bfSChristoph Hellwig struct xfs_group *xfs_group_get(struct xfs_mount *mp, uint32_t index,
65e9c4d8bfSChristoph Hellwig 		enum xfs_group_type type);
66759cc198SChristoph Hellwig struct xfs_group *xfs_group_get_by_fsb(struct xfs_mount *mp,
67759cc198SChristoph Hellwig 		xfs_fsblock_t fsbno, enum xfs_group_type type);
68e9c4d8bfSChristoph Hellwig struct xfs_group *xfs_group_hold(struct xfs_group *xg);
69e9c4d8bfSChristoph Hellwig void xfs_group_put(struct xfs_group *xg);
70e9c4d8bfSChristoph Hellwig 
71e9c4d8bfSChristoph Hellwig struct xfs_group *xfs_group_grab(struct xfs_mount *mp, uint32_t index,
72e9c4d8bfSChristoph Hellwig 		enum xfs_group_type type);
7381992877SChristoph Hellwig struct xfs_group *xfs_group_next_range(struct xfs_mount *mp,
7481992877SChristoph Hellwig 		struct xfs_group *xg, uint32_t start_index, uint32_t end_index,
7581992877SChristoph Hellwig 		enum xfs_group_type type);
76e9c4d8bfSChristoph Hellwig struct xfs_group *xfs_group_grab_next_mark(struct xfs_mount *mp,
77e9c4d8bfSChristoph Hellwig 		struct xfs_group *xg, xa_mark_t mark, enum xfs_group_type type);
78e9c4d8bfSChristoph Hellwig void xfs_group_rele(struct xfs_group *xg);
79e9c4d8bfSChristoph Hellwig 
80e9c4d8bfSChristoph Hellwig void xfs_group_free(struct xfs_mount *mp, uint32_t index,
81e9c4d8bfSChristoph Hellwig 		enum xfs_group_type type, void (*uninit)(struct xfs_group *xg));
82e9c4d8bfSChristoph Hellwig int xfs_group_insert(struct xfs_mount *mp, struct xfs_group *xg,
83e9c4d8bfSChristoph Hellwig 		uint32_t index, enum xfs_group_type);
84e9c4d8bfSChristoph Hellwig 
85e9c4d8bfSChristoph Hellwig #define xfs_group_set_mark(_xg, _mark) \
86e9c4d8bfSChristoph Hellwig 	xa_set_mark(&(_xg)->xg_mount->m_groups[(_xg)->xg_type].xa, \
87e9c4d8bfSChristoph Hellwig 			(_xg)->xg_gno, (_mark))
88e9c4d8bfSChristoph Hellwig #define xfs_group_clear_mark(_xg, _mark) \
89e9c4d8bfSChristoph Hellwig 	xa_clear_mark(&(_xg)->xg_mount->m_groups[(_xg)->xg_type].xa, \
90e9c4d8bfSChristoph Hellwig 			(_xg)->xg_gno, (_mark))
91e9c4d8bfSChristoph Hellwig #define xfs_group_marked(_mp, _type, _mark) \
92e9c4d8bfSChristoph Hellwig 	xa_marked(&(_mp)->m_groups[(_type)].xa, (_mark))
93e9c4d8bfSChristoph Hellwig 
94759cc198SChristoph Hellwig static inline xfs_agblock_t
xfs_group_max_blocks(struct xfs_group * xg)95759cc198SChristoph Hellwig xfs_group_max_blocks(
96759cc198SChristoph Hellwig 	struct xfs_group	*xg)
97759cc198SChristoph Hellwig {
98759cc198SChristoph Hellwig 	return xg->xg_mount->m_groups[xg->xg_type].blocks;
99759cc198SChristoph Hellwig }
100759cc198SChristoph Hellwig 
101759cc198SChristoph Hellwig static inline xfs_fsblock_t
xfs_group_start_fsb(struct xfs_group * xg)102759cc198SChristoph Hellwig xfs_group_start_fsb(
103759cc198SChristoph Hellwig 	struct xfs_group	*xg)
104759cc198SChristoph Hellwig {
105759cc198SChristoph Hellwig 	return ((xfs_fsblock_t)xg->xg_gno) <<
106759cc198SChristoph Hellwig 		xg->xg_mount->m_groups[xg->xg_type].blklog;
107759cc198SChristoph Hellwig }
108759cc198SChristoph Hellwig 
109759cc198SChristoph Hellwig static inline xfs_fsblock_t
xfs_gbno_to_fsb(struct xfs_group * xg,xfs_agblock_t gbno)110759cc198SChristoph Hellwig xfs_gbno_to_fsb(
111759cc198SChristoph Hellwig 	struct xfs_group	*xg,
112759cc198SChristoph Hellwig 	xfs_agblock_t		gbno)
113759cc198SChristoph Hellwig {
114759cc198SChristoph Hellwig 	return xfs_group_start_fsb(xg) | gbno;
115759cc198SChristoph Hellwig }
116759cc198SChristoph Hellwig 
117759cc198SChristoph Hellwig static inline xfs_daddr_t
xfs_gbno_to_daddr(struct xfs_group * xg,xfs_agblock_t gbno)118759cc198SChristoph Hellwig xfs_gbno_to_daddr(
119759cc198SChristoph Hellwig 	struct xfs_group	*xg,
120759cc198SChristoph Hellwig 	xfs_agblock_t		gbno)
121759cc198SChristoph Hellwig {
122759cc198SChristoph Hellwig 	struct xfs_mount	*mp = xg->xg_mount;
123bdc03eb5SChristoph Hellwig 	struct xfs_groups	*g = &mp->m_groups[xg->xg_type];
124bdc03eb5SChristoph Hellwig 	xfs_fsblock_t		fsbno;
125759cc198SChristoph Hellwig 
126*97c69ba1SChristoph Hellwig 	if (g->has_daddr_gaps)
127*97c69ba1SChristoph Hellwig 		fsbno = xfs_gbno_to_fsb(xg, gbno);
128*97c69ba1SChristoph Hellwig 	else
129bdc03eb5SChristoph Hellwig 		fsbno = (xfs_fsblock_t)xg->xg_gno * g->blocks + gbno;
130*97c69ba1SChristoph Hellwig 
131bdc03eb5SChristoph Hellwig 	return XFS_FSB_TO_BB(mp, g->start_fsb + fsbno);
132759cc198SChristoph Hellwig }
133759cc198SChristoph Hellwig 
134759cc198SChristoph Hellwig static inline uint32_t
xfs_fsb_to_gno(struct xfs_mount * mp,xfs_fsblock_t fsbno,enum xfs_group_type type)135759cc198SChristoph Hellwig xfs_fsb_to_gno(
136759cc198SChristoph Hellwig 	struct xfs_mount	*mp,
137759cc198SChristoph Hellwig 	xfs_fsblock_t		fsbno,
138759cc198SChristoph Hellwig 	enum xfs_group_type	type)
139759cc198SChristoph Hellwig {
140759cc198SChristoph Hellwig 	if (!mp->m_groups[type].blklog)
141759cc198SChristoph Hellwig 		return 0;
142759cc198SChristoph Hellwig 	return fsbno >> mp->m_groups[type].blklog;
143759cc198SChristoph Hellwig }
144759cc198SChristoph Hellwig 
145759cc198SChristoph Hellwig static inline xfs_agblock_t
xfs_fsb_to_gbno(struct xfs_mount * mp,xfs_fsblock_t fsbno,enum xfs_group_type type)146759cc198SChristoph Hellwig xfs_fsb_to_gbno(
147759cc198SChristoph Hellwig 	struct xfs_mount	*mp,
148759cc198SChristoph Hellwig 	xfs_fsblock_t		fsbno,
149759cc198SChristoph Hellwig 	enum xfs_group_type	type)
150759cc198SChristoph Hellwig {
151759cc198SChristoph Hellwig 	return fsbno & mp->m_groups[type].blkmask;
152759cc198SChristoph Hellwig }
153759cc198SChristoph Hellwig 
154e0b5b97dSDarrick J. Wong static inline bool
xfs_verify_gbno(struct xfs_group * xg,uint32_t gbno)155e0b5b97dSDarrick J. Wong xfs_verify_gbno(
156e0b5b97dSDarrick J. Wong 	struct xfs_group	*xg,
157e0b5b97dSDarrick J. Wong 	uint32_t		gbno)
158e0b5b97dSDarrick J. Wong {
159e0b5b97dSDarrick J. Wong 	if (gbno >= xg->xg_block_count)
160e0b5b97dSDarrick J. Wong 		return false;
161e0b5b97dSDarrick J. Wong 	if (gbno < xg->xg_min_gbno)
162e0b5b97dSDarrick J. Wong 		return false;
163e0b5b97dSDarrick J. Wong 	return true;
164e0b5b97dSDarrick J. Wong }
165e0b5b97dSDarrick J. Wong 
166e0b5b97dSDarrick J. Wong static inline bool
xfs_verify_gbext(struct xfs_group * xg,uint32_t gbno,uint32_t glen)167e0b5b97dSDarrick J. Wong xfs_verify_gbext(
168e0b5b97dSDarrick J. Wong 	struct xfs_group	*xg,
169e0b5b97dSDarrick J. Wong 	uint32_t		gbno,
170e0b5b97dSDarrick J. Wong 	uint32_t		glen)
171e0b5b97dSDarrick J. Wong {
172e0b5b97dSDarrick J. Wong 	uint32_t		end;
173e0b5b97dSDarrick J. Wong 
174e0b5b97dSDarrick J. Wong 	if (!xfs_verify_gbno(xg, gbno))
175e0b5b97dSDarrick J. Wong 		return false;
176e0b5b97dSDarrick J. Wong 	if (glen == 0 || check_add_overflow(gbno, glen - 1, &end))
177e0b5b97dSDarrick J. Wong 		return false;
178e0b5b97dSDarrick J. Wong 	if (!xfs_verify_gbno(xg, end))
179e0b5b97dSDarrick J. Wong 		return false;
180e0b5b97dSDarrick J. Wong 	return true;
181e0b5b97dSDarrick J. Wong }
182e0b5b97dSDarrick J. Wong 
183e9c4d8bfSChristoph Hellwig #endif /* __LIBXFS_GROUP_H */
184