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