Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0-or-later */
2 : /*
3 : * Copyright (C) 2022-2023 Oracle. All Rights Reserved.
4 : * Author: Darrick J. Wong <djwong@kernel.org>
5 : */
6 : #ifndef __LIBXFS_RTGROUP_H
7 : #define __LIBXFS_RTGROUP_H 1
8 :
9 : struct xfs_mount;
10 : struct xfs_trans;
11 :
12 : /*
13 : * Realtime group incore structure, similar to the per-AG structure.
14 : */
15 : struct xfs_rtgroup {
16 : struct xfs_mount *rtg_mount;
17 : xfs_rgnumber_t rtg_rgno;
18 : atomic_t rtg_ref; /* passive reference count */
19 : atomic_t rtg_active_ref; /* active reference count */
20 : wait_queue_head_t rtg_active_wq;/* woken active_ref falls to zero */
21 :
22 : /* for rcu-safe freeing */
23 : struct rcu_head rcu_head;
24 :
25 : /* reverse mapping btree inode */
26 : struct xfs_inode *rtg_rmapip;
27 :
28 : /* refcount btree inode */
29 : struct xfs_inode *rtg_refcountip;
30 :
31 : /* Number of blocks in this group */
32 : xfs_rgblock_t rtg_blockcount;
33 :
34 : /*
35 : * Bitsets of per-rtgroup metadata that have been checked and/or are
36 : * sick. Callers should hold rtg_state_lock before accessing this
37 : * field.
38 : */
39 : uint16_t rtg_checked;
40 : uint16_t rtg_sick;
41 :
42 : #ifdef __KERNEL__
43 : /* -- kernel only structures below this line -- */
44 : spinlock_t rtg_state_lock;
45 :
46 : /*
47 : * We use xfs_drain to track the number of deferred log intent items
48 : * that have been queued (but not yet processed) so that waiters (e.g.
49 : * scrub) will not lock resources when other threads are in the middle
50 : * of processing a chain of intent items only to find momentary
51 : * inconsistencies.
52 : */
53 : struct xfs_defer_drain rtg_intents_drain;
54 :
55 : /* Hook to feed rt rmapbt updates to an active online repair. */
56 : struct xfs_hooks rtg_rmap_update_hooks;
57 : #endif /* __KERNEL__ */
58 : };
59 :
60 : #ifdef CONFIG_XFS_RT
61 : /* Passive rtgroup references */
62 : struct xfs_rtgroup *xfs_rtgroup_get(struct xfs_mount *mp, xfs_rgnumber_t rgno);
63 : struct xfs_rtgroup *xfs_rtgroup_hold(struct xfs_rtgroup *rtg);
64 : void xfs_rtgroup_put(struct xfs_rtgroup *rtg);
65 :
66 : /* Active rtgroup references */
67 : struct xfs_rtgroup *xfs_rtgroup_grab(struct xfs_mount *mp, xfs_rgnumber_t rgno);
68 : void xfs_rtgroup_rele(struct xfs_rtgroup *rtg);
69 :
70 : int xfs_initialize_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t rgcount);
71 : void xfs_free_rtgroups(struct xfs_mount *mp);
72 : #else
73 : static inline struct xfs_rtgroup *
74 : xfs_rtgroup_get(
75 : struct xfs_mount *mp,
76 : xfs_rgnumber_t rgno)
77 : {
78 : return NULL;
79 : }
80 : static inline struct xfs_rtgroup *
81 : xfs_rtgroup_hold(struct xfs_rtgroup *rtg)
82 : {
83 : ASSERT(rtg == NULL);
84 : return NULL;
85 : }
86 : # define xfs_rtgroup_grab xfs_rtgroup_get
87 : # define xfs_rtgroup_put(rtg) ((void)0)
88 : # define xfs_rtgroup_rele(rtg) ((void)0)
89 : # define xfs_initialize_rtgroups(mp, rgcount) (0)
90 : # define xfs_free_rtgroups(mp) ((void)0)
91 : #endif /* CONFIG_XFS_RT */
92 :
93 : /*
94 : * rt group iteration APIs
95 : */
96 : static inline struct xfs_rtgroup *
97 486744494 : xfs_rtgroup_next(
98 : struct xfs_rtgroup *rtg,
99 : xfs_rgnumber_t *rgno,
100 : xfs_rgnumber_t end_rgno)
101 : {
102 486744494 : struct xfs_mount *mp = rtg->rtg_mount;
103 :
104 486744494 : *rgno = rtg->rtg_rgno + 1;
105 486744494 : xfs_rtgroup_rele(rtg);
106 497411795 : if (*rgno > end_rgno)
107 : return NULL;
108 495248272 : return xfs_rtgroup_grab(mp, *rgno);
109 : }
110 :
111 : #define for_each_rtgroup_range(mp, rgno, end_rgno, rtg) \
112 : for ((rtg) = xfs_rtgroup_grab((mp), (rgno)); \
113 : (rtg) != NULL; \
114 : (rtg) = xfs_rtgroup_next((rtg), &(rgno), (end_rgno)))
115 :
116 : #define for_each_rtgroup_from(mp, rgno, rtg) \
117 : for_each_rtgroup_range((mp), (rgno), (mp)->m_sb.sb_rgcount - 1, (rtg))
118 :
119 :
120 : #define for_each_rtgroup(mp, rgno, rtg) \
121 : (rgno) = 0; \
122 : for_each_rtgroup_from((mp), (rgno), (rtg))
123 :
124 : static inline bool
125 : xfs_verify_rgbno(
126 : struct xfs_rtgroup *rtg,
127 : xfs_rgblock_t rgbno)
128 : {
129 >25597*10^7 : if (rgbno >= rtg->rtg_blockcount)
130 : return false;
131 >25597*10^7 : if (rgbno < rtg->rtg_mount->m_sb.sb_rextsize)
132 0 : return false;
133 : return true;
134 : }
135 :
136 : static inline bool
137 >12798*10^7 : xfs_verify_rgbext(
138 : struct xfs_rtgroup *rtg,
139 : xfs_rgblock_t rgbno,
140 : xfs_rgblock_t len)
141 : {
142 >12798*10^7 : if (rgbno + len <= rgbno)
143 : return false;
144 :
145 >12798*10^7 : if (!xfs_verify_rgbno(rtg, rgbno))
146 : return false;
147 :
148 >12798*10^7 : return xfs_verify_rgbno(rtg, rgbno + len - 1);
149 : }
150 :
151 : static inline xfs_rtblock_t
152 3275487551 : xfs_rgbno_to_rtb(
153 : struct xfs_mount *mp,
154 : xfs_rgnumber_t rgno,
155 : xfs_rgblock_t rgbno)
156 : {
157 3275487551 : ASSERT(xfs_has_rtgroups(mp));
158 :
159 3275487551 : if (mp->m_rgblklog >= 0)
160 2130782571 : return ((xfs_rtblock_t)rgno << mp->m_rgblklog) | rgbno;
161 :
162 1144704980 : return ((xfs_rtblock_t)rgno * mp->m_sb.sb_rgblocks) + rgbno;
163 : }
164 :
165 : static inline xfs_rgnumber_t
166 3575465594 : xfs_rtb_to_rgno(
167 : struct xfs_mount *mp,
168 : xfs_rtblock_t rtbno)
169 : {
170 3575465594 : ASSERT(xfs_has_rtgroups(mp));
171 :
172 3575465594 : if (mp->m_rgblklog >= 0)
173 3146406697 : return rtbno >> mp->m_rgblklog;
174 :
175 429058897 : return div_u64(rtbno, mp->m_sb.sb_rgblocks);
176 : }
177 :
178 : static inline xfs_rgblock_t
179 3938778279 : xfs_rtb_to_rgbno(
180 : struct xfs_mount *mp,
181 : xfs_rtblock_t rtbno,
182 : xfs_rgnumber_t *rgno)
183 : {
184 3938778279 : uint32_t rem;
185 :
186 3938778279 : ASSERT(xfs_has_rtgroups(mp));
187 :
188 3938778279 : if (mp->m_rgblklog >= 0) {
189 3510814201 : *rgno = rtbno >> mp->m_rgblklog;
190 3510814201 : return rtbno & mp->m_rgblkmask;
191 : }
192 :
193 427964078 : *rgno = div_u64_rem(rtbno, mp->m_sb.sb_rgblocks, &rem);
194 427956510 : return rem;
195 : }
196 :
197 : static inline xfs_daddr_t
198 2327968249 : xfs_rtb_to_daddr(
199 : struct xfs_mount *mp,
200 : xfs_rtblock_t rtbno)
201 : {
202 2327968249 : return rtbno << mp->m_blkbb_log;
203 : }
204 :
205 : static inline xfs_rtblock_t
206 : xfs_daddr_to_rtb(
207 : struct xfs_mount *mp,
208 : xfs_daddr_t daddr)
209 : {
210 : return daddr >> mp->m_blkbb_log;
211 : }
212 :
213 : static inline xfs_rgnumber_t
214 : xfs_daddr_to_rgno(
215 : struct xfs_mount *mp,
216 : xfs_daddr_t daddr)
217 : {
218 : xfs_rtblock_t rtb = daddr >> mp->m_blkbb_log;
219 :
220 : return xfs_rtb_to_rgno(mp, rtb);
221 : }
222 :
223 : static inline xfs_rgblock_t
224 : xfs_daddr_to_rgbno(
225 : struct xfs_mount *mp,
226 : xfs_daddr_t daddr)
227 : {
228 : xfs_rtblock_t rtb = daddr >> mp->m_blkbb_log;
229 : xfs_rgnumber_t rgno;
230 :
231 : return xfs_rtb_to_rgbno(mp, rtb, &rgno);
232 : }
233 :
234 : #ifdef CONFIG_XFS_RT
235 : xfs_rgblock_t xfs_rtgroup_block_count(struct xfs_mount *mp,
236 : xfs_rgnumber_t rgno);
237 :
238 : void xfs_rtgroup_update_super(struct xfs_buf *rtsb_bp,
239 : const struct xfs_buf *sb_bp);
240 : void xfs_rtgroup_log_super(struct xfs_trans *tp, const struct xfs_buf *sb_bp);
241 : int xfs_rtgroup_update_secondary_sbs(struct xfs_mount *mp);
242 : int xfs_rtgroup_init_secondary_super(struct xfs_mount *mp, xfs_rgnumber_t rgno,
243 : struct xfs_buf **bpp);
244 :
245 : /* Lock the rt bitmap inode in exclusive mode */
246 : #define XFS_RTGLOCK_BITMAP (1U << 0)
247 : /* Lock the rt bitmap inode in shared mode */
248 : #define XFS_RTGLOCK_BITMAP_SHARED (1U << 1)
249 : /* Lock the rt rmap inode in exclusive mode */
250 : #define XFS_RTGLOCK_RMAP (1U << 2)
251 : /* Lock the rt refcount inode in exclusive mode */
252 : #define XFS_RTGLOCK_REFCOUNT (1U << 3)
253 :
254 : #define XFS_RTGLOCK_ALL_FLAGS (XFS_RTGLOCK_BITMAP | \
255 : XFS_RTGLOCK_BITMAP_SHARED | \
256 : XFS_RTGLOCK_RMAP | \
257 : XFS_RTGLOCK_REFCOUNT)
258 :
259 : void xfs_rtgroup_lock(struct xfs_trans *tp, struct xfs_rtgroup *rtg,
260 : unsigned int rtglock_flags);
261 : void xfs_rtgroup_unlock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags);
262 :
263 : int xfs_rtgroup_get_geometry(struct xfs_rtgroup *rtg,
264 : struct xfs_rtgroup_geometry *rgeo);
265 : #else
266 : # define xfs_rtgroup_block_count(mp, rgno) (0)
267 : # define xfs_rtgroup_update_super(bp, sb_bp) ((void)0)
268 : # define xfs_rtgroup_log_super(tp, sb_bp) ((void)0)
269 : # define xfs_rtgroup_update_secondary_sbs(mp) (0)
270 : # define xfs_rtgroup_init_secondary_super(mp, rgno, bpp) (-EOPNOTSUPP)
271 : # define xfs_rtgroup_lock(tp, rtg, gf) ((void)0)
272 : # define xfs_rtgroup_unlock(rtg, gf) ((void)0)
273 : # define xfs_rtgroup_get_geometry(rtg, rgeo) (-EOPNOTSUPP)
274 : #endif /* CONFIG_XFS_RT */
275 :
276 : #endif /* __LIBXFS_RTGROUP_H */
|