1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. |
5 | */ |
6 | #ifndef __XFS_RTBITMAP_H__ |
7 | #define __XFS_RTBITMAP_H__ |
8 | |
9 | struct xfs_rtalloc_args { |
10 | struct xfs_mount *mp; |
11 | struct xfs_trans *tp; |
12 | |
13 | struct xfs_buf *rbmbp; /* bitmap block buffer */ |
14 | struct xfs_buf *sumbp; /* summary block buffer */ |
15 | |
16 | xfs_fileoff_t rbmoff; /* bitmap block number */ |
17 | xfs_fileoff_t sumoff; /* summary block number */ |
18 | }; |
19 | |
20 | static inline xfs_rtblock_t |
21 | xfs_rtx_to_rtb( |
22 | struct xfs_mount *mp, |
23 | xfs_rtxnum_t rtx) |
24 | { |
25 | if (mp->m_rtxblklog >= 0) |
26 | return rtx << mp->m_rtxblklog; |
27 | |
28 | return rtx * mp->m_sb.sb_rextsize; |
29 | } |
30 | |
31 | static inline xfs_extlen_t |
32 | xfs_rtxlen_to_extlen( |
33 | struct xfs_mount *mp, |
34 | xfs_rtxlen_t rtxlen) |
35 | { |
36 | if (mp->m_rtxblklog >= 0) |
37 | return rtxlen << mp->m_rtxblklog; |
38 | |
39 | return rtxlen * mp->m_sb.sb_rextsize; |
40 | } |
41 | |
42 | /* Compute the misalignment between an extent length and a realtime extent .*/ |
43 | static inline unsigned int |
44 | xfs_extlen_to_rtxmod( |
45 | struct xfs_mount *mp, |
46 | xfs_extlen_t len) |
47 | { |
48 | if (mp->m_rtxblklog >= 0) |
49 | return len & mp->m_rtxblkmask; |
50 | |
51 | return len % mp->m_sb.sb_rextsize; |
52 | } |
53 | |
54 | static inline xfs_rtxlen_t |
55 | xfs_extlen_to_rtxlen( |
56 | struct xfs_mount *mp, |
57 | xfs_extlen_t len) |
58 | { |
59 | if (mp->m_rtxblklog >= 0) |
60 | return len >> mp->m_rtxblklog; |
61 | |
62 | return len / mp->m_sb.sb_rextsize; |
63 | } |
64 | |
65 | /* Convert an rt block number into an rt extent number. */ |
66 | static inline xfs_rtxnum_t |
67 | xfs_rtb_to_rtx( |
68 | struct xfs_mount *mp, |
69 | xfs_rtblock_t rtbno) |
70 | { |
71 | if (likely(mp->m_rtxblklog >= 0)) |
72 | return rtbno >> mp->m_rtxblklog; |
73 | |
74 | return div_u64(rtbno, mp->m_sb.sb_rextsize); |
75 | } |
76 | |
77 | /* Return the offset of an rt block number within an rt extent. */ |
78 | static inline xfs_extlen_t |
79 | xfs_rtb_to_rtxoff( |
80 | struct xfs_mount *mp, |
81 | xfs_rtblock_t rtbno) |
82 | { |
83 | if (likely(mp->m_rtxblklog >= 0)) |
84 | return rtbno & mp->m_rtxblkmask; |
85 | |
86 | return do_div(rtbno, mp->m_sb.sb_rextsize); |
87 | } |
88 | |
89 | /* |
90 | * Crack an rt block number into an rt extent number and an offset within that |
91 | * rt extent. Returns the rt extent number directly and the offset in @off. |
92 | */ |
93 | static inline xfs_rtxnum_t |
94 | xfs_rtb_to_rtxrem( |
95 | struct xfs_mount *mp, |
96 | xfs_rtblock_t rtbno, |
97 | xfs_extlen_t *off) |
98 | { |
99 | if (likely(mp->m_rtxblklog >= 0)) { |
100 | *off = rtbno & mp->m_rtxblkmask; |
101 | return rtbno >> mp->m_rtxblklog; |
102 | } |
103 | |
104 | return div_u64_rem(rtbno, mp->m_sb.sb_rextsize, off); |
105 | } |
106 | |
107 | /* |
108 | * Convert an rt block number into an rt extent number, rounding up to the next |
109 | * rt extent if the rt block is not aligned to an rt extent boundary. |
110 | */ |
111 | static inline xfs_rtxnum_t |
112 | xfs_rtb_to_rtxup( |
113 | struct xfs_mount *mp, |
114 | xfs_rtblock_t rtbno) |
115 | { |
116 | if (likely(mp->m_rtxblklog >= 0)) { |
117 | if (rtbno & mp->m_rtxblkmask) |
118 | return (rtbno >> mp->m_rtxblklog) + 1; |
119 | return rtbno >> mp->m_rtxblklog; |
120 | } |
121 | |
122 | if (do_div(rtbno, mp->m_sb.sb_rextsize)) |
123 | rtbno++; |
124 | return rtbno; |
125 | } |
126 | |
127 | /* Round this rtblock up to the nearest rt extent size. */ |
128 | static inline xfs_rtblock_t |
129 | xfs_rtb_roundup_rtx( |
130 | struct xfs_mount *mp, |
131 | xfs_rtblock_t rtbno) |
132 | { |
133 | return roundup_64(rtbno, mp->m_sb.sb_rextsize); |
134 | } |
135 | |
136 | /* Round this rtblock down to the nearest rt extent size. */ |
137 | static inline xfs_rtblock_t |
138 | xfs_rtb_rounddown_rtx( |
139 | struct xfs_mount *mp, |
140 | xfs_rtblock_t rtbno) |
141 | { |
142 | return rounddown_64(rtbno, mp->m_sb.sb_rextsize); |
143 | } |
144 | |
145 | /* Convert an rt extent number to a file block offset in the rt bitmap file. */ |
146 | static inline xfs_fileoff_t |
147 | xfs_rtx_to_rbmblock( |
148 | struct xfs_mount *mp, |
149 | xfs_rtxnum_t rtx) |
150 | { |
151 | return rtx >> mp->m_blkbit_log; |
152 | } |
153 | |
154 | /* Convert an rt extent number to a word offset within an rt bitmap block. */ |
155 | static inline unsigned int |
156 | xfs_rtx_to_rbmword( |
157 | struct xfs_mount *mp, |
158 | xfs_rtxnum_t rtx) |
159 | { |
160 | return (rtx >> XFS_NBWORDLOG) & (mp->m_blockwsize - 1); |
161 | } |
162 | |
163 | /* Convert a file block offset in the rt bitmap file to an rt extent number. */ |
164 | static inline xfs_rtxnum_t |
165 | xfs_rbmblock_to_rtx( |
166 | struct xfs_mount *mp, |
167 | xfs_fileoff_t rbmoff) |
168 | { |
169 | return rbmoff << mp->m_blkbit_log; |
170 | } |
171 | |
172 | /* Return a pointer to a bitmap word within a rt bitmap block. */ |
173 | static inline union xfs_rtword_raw * |
174 | xfs_rbmblock_wordptr( |
175 | struct xfs_rtalloc_args *args, |
176 | unsigned int index) |
177 | { |
178 | union xfs_rtword_raw *words = args->rbmbp->b_addr; |
179 | |
180 | return words + index; |
181 | } |
182 | |
183 | /* Convert an ondisk bitmap word to its incore representation. */ |
184 | static inline xfs_rtword_t |
185 | xfs_rtbitmap_getword( |
186 | struct xfs_rtalloc_args *args, |
187 | unsigned int index) |
188 | { |
189 | union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index); |
190 | |
191 | return word->old; |
192 | } |
193 | |
194 | /* Set an ondisk bitmap word from an incore representation. */ |
195 | static inline void |
196 | xfs_rtbitmap_setword( |
197 | struct xfs_rtalloc_args *args, |
198 | unsigned int index, |
199 | xfs_rtword_t value) |
200 | { |
201 | union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index); |
202 | |
203 | word->old = value; |
204 | } |
205 | |
206 | /* |
207 | * Convert a rt extent length and rt bitmap block number to a xfs_suminfo_t |
208 | * offset within the rt summary file. |
209 | */ |
210 | static inline xfs_rtsumoff_t |
211 | xfs_rtsumoffs( |
212 | struct xfs_mount *mp, |
213 | int log2_len, |
214 | xfs_fileoff_t rbmoff) |
215 | { |
216 | return log2_len * mp->m_sb.sb_rbmblocks + rbmoff; |
217 | } |
218 | |
219 | /* |
220 | * Convert an xfs_suminfo_t offset to a file block offset within the rt summary |
221 | * file. |
222 | */ |
223 | static inline xfs_fileoff_t |
224 | xfs_rtsumoffs_to_block( |
225 | struct xfs_mount *mp, |
226 | xfs_rtsumoff_t rsumoff) |
227 | { |
228 | return XFS_B_TO_FSBT(mp, rsumoff * sizeof(xfs_suminfo_t)); |
229 | } |
230 | |
231 | /* |
232 | * Convert an xfs_suminfo_t offset to an info word offset within an rt summary |
233 | * block. |
234 | */ |
235 | static inline unsigned int |
236 | xfs_rtsumoffs_to_infoword( |
237 | struct xfs_mount *mp, |
238 | xfs_rtsumoff_t rsumoff) |
239 | { |
240 | unsigned int mask = mp->m_blockmask >> XFS_SUMINFOLOG; |
241 | |
242 | return rsumoff & mask; |
243 | } |
244 | |
245 | /* Return a pointer to a summary info word within a rt summary block. */ |
246 | static inline union xfs_suminfo_raw * |
247 | xfs_rsumblock_infoptr( |
248 | struct xfs_rtalloc_args *args, |
249 | unsigned int index) |
250 | { |
251 | union xfs_suminfo_raw *info = args->sumbp->b_addr; |
252 | |
253 | return info + index; |
254 | } |
255 | |
256 | /* Get the current value of a summary counter. */ |
257 | static inline xfs_suminfo_t |
258 | xfs_suminfo_get( |
259 | struct xfs_rtalloc_args *args, |
260 | unsigned int index) |
261 | { |
262 | union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index); |
263 | |
264 | return info->old; |
265 | } |
266 | |
267 | /* Add to the current value of a summary counter and return the new value. */ |
268 | static inline xfs_suminfo_t |
269 | xfs_suminfo_add( |
270 | struct xfs_rtalloc_args *args, |
271 | unsigned int index, |
272 | int delta) |
273 | { |
274 | union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index); |
275 | |
276 | info->old += delta; |
277 | return info->old; |
278 | } |
279 | |
280 | /* |
281 | * Functions for walking free space rtextents in the realtime bitmap. |
282 | */ |
283 | struct xfs_rtalloc_rec { |
284 | xfs_rtxnum_t ar_startext; |
285 | xfs_rtbxlen_t ar_extcount; |
286 | }; |
287 | |
288 | typedef int (*xfs_rtalloc_query_range_fn)( |
289 | struct xfs_mount *mp, |
290 | struct xfs_trans *tp, |
291 | const struct xfs_rtalloc_rec *rec, |
292 | void *priv); |
293 | |
294 | #ifdef CONFIG_XFS_RT |
295 | void xfs_rtbuf_cache_relse(struct xfs_rtalloc_args *args); |
296 | |
297 | int xfs_rtbuf_get(struct xfs_rtalloc_args *args, xfs_fileoff_t block, |
298 | int issum); |
299 | |
300 | static inline int |
301 | xfs_rtbitmap_read_buf( |
302 | struct xfs_rtalloc_args *args, |
303 | xfs_fileoff_t block) |
304 | { |
305 | return xfs_rtbuf_get(args, block, 0); |
306 | } |
307 | |
308 | static inline int |
309 | xfs_rtsummary_read_buf( |
310 | struct xfs_rtalloc_args *args, |
311 | xfs_fileoff_t block) |
312 | { |
313 | return xfs_rtbuf_get(args, block, 1); |
314 | } |
315 | |
316 | int xfs_rtcheck_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start, |
317 | xfs_rtxlen_t len, int val, xfs_rtxnum_t *new, int *stat); |
318 | int xfs_rtfind_back(struct xfs_rtalloc_args *args, xfs_rtxnum_t start, |
319 | xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock); |
320 | int xfs_rtfind_forw(struct xfs_rtalloc_args *args, xfs_rtxnum_t start, |
321 | xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock); |
322 | int xfs_rtmodify_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start, |
323 | xfs_rtxlen_t len, int val); |
324 | int xfs_rtget_summary(struct xfs_rtalloc_args *args, int log, |
325 | xfs_fileoff_t bbno, xfs_suminfo_t *sum); |
326 | int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log, |
327 | xfs_fileoff_t bbno, int delta); |
328 | int xfs_rtfree_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start, |
329 | xfs_rtxlen_t len); |
330 | int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp, |
331 | const struct xfs_rtalloc_rec *low_rec, |
332 | const struct xfs_rtalloc_rec *high_rec, |
333 | xfs_rtalloc_query_range_fn fn, void *priv); |
334 | int xfs_rtalloc_query_all(struct xfs_mount *mp, struct xfs_trans *tp, |
335 | xfs_rtalloc_query_range_fn fn, |
336 | void *priv); |
337 | int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp, |
338 | xfs_rtxnum_t start, xfs_rtxlen_t len, |
339 | bool *is_free); |
340 | /* |
341 | * Free an extent in the realtime subvolume. Length is expressed in |
342 | * realtime extents, as is the block number. |
343 | */ |
344 | int /* error */ |
345 | xfs_rtfree_extent( |
346 | struct xfs_trans *tp, /* transaction pointer */ |
347 | xfs_rtxnum_t start, /* starting rtext number to free */ |
348 | xfs_rtxlen_t len); /* length of extent freed */ |
349 | |
350 | /* Same as above, but in units of rt blocks. */ |
351 | int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno, |
352 | xfs_filblks_t rtlen); |
353 | |
354 | xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t |
355 | rtextents); |
356 | unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp, |
357 | xfs_rtbxlen_t rtextents); |
358 | |
359 | xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp, |
360 | unsigned int rsumlevels, xfs_extlen_t rbmblocks); |
361 | unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp, |
362 | unsigned int rsumlevels, xfs_extlen_t rbmblocks); |
363 | #else /* CONFIG_XFS_RT */ |
364 | # define xfs_rtfree_extent(t,b,l) (-ENOSYS) |
365 | # define xfs_rtfree_blocks(t,rb,rl) (-ENOSYS) |
366 | # define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS) |
367 | # define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS) |
368 | # define xfs_rtbitmap_read_buf(a,b) (-ENOSYS) |
369 | # define xfs_rtsummary_read_buf(a,b) (-ENOSYS) |
370 | # define xfs_rtbuf_cache_relse(a) (0) |
371 | # define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS) |
372 | static inline xfs_filblks_t |
373 | xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents) |
374 | { |
375 | /* shut up gcc */ |
376 | return 0; |
377 | } |
378 | # define xfs_rtbitmap_wordcount(mp, r) (0) |
379 | # define xfs_rtsummary_blockcount(mp, l, b) (0) |
380 | # define xfs_rtsummary_wordcount(mp, l, b) (0) |
381 | #endif /* CONFIG_XFS_RT */ |
382 | |
383 | #endif /* __XFS_RTBITMAP_H__ */ |
384 | |