Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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#include "xfs_rtgroup.h"
10
11struct xfs_rtalloc_args {
12 struct xfs_rtgroup *rtg;
13 struct xfs_mount *mp;
14 struct xfs_trans *tp;
15
16 struct xfs_buf *rbmbp; /* bitmap block buffer */
17 struct xfs_buf *sumbp; /* summary block buffer */
18
19 xfs_fileoff_t rbmoff; /* bitmap block number */
20 xfs_fileoff_t sumoff; /* summary block number */
21};
22
23static inline xfs_rtblock_t
24xfs_rtx_to_rtb(
25 struct xfs_rtgroup *rtg,
26 xfs_rtxnum_t rtx)
27{
28 struct xfs_mount *mp = rtg_mount(rtg);
29 xfs_rtblock_t start = xfs_group_start_fsb(rtg_group(rtg));
30
31 if (mp->m_rtxblklog >= 0)
32 return start + (rtx << mp->m_rtxblklog);
33 return start + (rtx * mp->m_sb.sb_rextsize);
34}
35
36/* Convert an rgbno into an rt extent number. */
37static inline xfs_rtxnum_t
38xfs_rgbno_to_rtx(
39 struct xfs_mount *mp,
40 xfs_rgblock_t rgbno)
41{
42 if (likely(mp->m_rtxblklog >= 0))
43 return rgbno >> mp->m_rtxblklog;
44 return rgbno / mp->m_sb.sb_rextsize;
45}
46
47static inline uint64_t
48xfs_rtbxlen_to_blen(
49 struct xfs_mount *mp,
50 xfs_rtbxlen_t rtbxlen)
51{
52 if (mp->m_rtxblklog >= 0)
53 return rtbxlen << mp->m_rtxblklog;
54
55 return rtbxlen * mp->m_sb.sb_rextsize;
56}
57
58static inline xfs_extlen_t
59xfs_rtxlen_to_extlen(
60 struct xfs_mount *mp,
61 xfs_rtxlen_t rtxlen)
62{
63 if (mp->m_rtxblklog >= 0)
64 return rtxlen << mp->m_rtxblklog;
65
66 return rtxlen * mp->m_sb.sb_rextsize;
67}
68
69/* Compute the misalignment between an extent length and a realtime extent .*/
70static inline unsigned int
71xfs_extlen_to_rtxmod(
72 struct xfs_mount *mp,
73 xfs_extlen_t len)
74{
75 if (mp->m_rtxblklog >= 0)
76 return len & mp->m_rtxblkmask;
77
78 return len % mp->m_sb.sb_rextsize;
79}
80
81static inline xfs_rtxlen_t
82xfs_extlen_to_rtxlen(
83 struct xfs_mount *mp,
84 xfs_extlen_t len)
85{
86 if (mp->m_rtxblklog >= 0)
87 return len >> mp->m_rtxblklog;
88
89 return len / mp->m_sb.sb_rextsize;
90}
91
92/* Convert an rt block count into an rt extent count. */
93static inline xfs_rtbxlen_t
94xfs_blen_to_rtbxlen(
95 struct xfs_mount *mp,
96 uint64_t blen)
97{
98 if (likely(mp->m_rtxblklog >= 0))
99 return blen >> mp->m_rtxblklog;
100
101 return div_u64(blen, mp->m_sb.sb_rextsize);
102}
103
104/* Return the offset of a file block length within an rt extent. */
105static inline xfs_extlen_t
106xfs_blen_to_rtxoff(
107 struct xfs_mount *mp,
108 xfs_filblks_t blen)
109{
110 if (likely(mp->m_rtxblklog >= 0))
111 return blen & mp->m_rtxblkmask;
112
113 return do_div(blen, mp->m_sb.sb_rextsize);
114}
115
116/* Round this block count up to the nearest rt extent size. */
117static inline xfs_filblks_t
118xfs_blen_roundup_rtx(
119 struct xfs_mount *mp,
120 xfs_filblks_t blen)
121{
122 return roundup_64(blen, mp->m_sb.sb_rextsize);
123}
124
125/* Convert an rt block number into an rt extent number. */
126static inline xfs_rtxnum_t
127xfs_rtb_to_rtx(
128 struct xfs_mount *mp,
129 xfs_rtblock_t rtbno)
130{
131 /* open-coded 64-bit masking operation */
132 rtbno &= mp->m_groups[XG_TYPE_RTG].blkmask;
133 if (likely(mp->m_rtxblklog >= 0))
134 return rtbno >> mp->m_rtxblklog;
135 return div_u64(rtbno, mp->m_sb.sb_rextsize);
136}
137
138/* Return the offset of a rtgroup block number within an rt extent. */
139static inline xfs_extlen_t
140xfs_rgbno_to_rtxoff(
141 struct xfs_mount *mp,
142 xfs_rgblock_t rgbno)
143{
144 return rgbno % mp->m_sb.sb_rextsize;
145}
146
147/* Return the offset of an rt block number within an rt extent. */
148static inline xfs_extlen_t
149xfs_rtb_to_rtxoff(
150 struct xfs_mount *mp,
151 xfs_rtblock_t rtbno)
152{
153 /* open-coded 64-bit masking operation */
154 rtbno &= mp->m_groups[XG_TYPE_RTG].blkmask;
155 if (likely(mp->m_rtxblklog >= 0))
156 return rtbno & mp->m_rtxblkmask;
157 return do_div(rtbno, mp->m_sb.sb_rextsize);
158}
159
160/* Round this file block offset up to the nearest rt extent size. */
161static inline xfs_rtblock_t
162xfs_fileoff_roundup_rtx(
163 struct xfs_mount *mp,
164 xfs_fileoff_t off)
165{
166 return roundup_64(off, mp->m_sb.sb_rextsize);
167}
168
169/* Round this file block offset down to the nearest rt extent size. */
170static inline xfs_rtblock_t
171xfs_fileoff_rounddown_rtx(
172 struct xfs_mount *mp,
173 xfs_fileoff_t off)
174{
175 return rounddown_64(off, mp->m_sb.sb_rextsize);
176}
177
178/* Convert an rt extent number to a file block offset in the rt bitmap file. */
179static inline xfs_fileoff_t
180xfs_rtx_to_rbmblock(
181 struct xfs_mount *mp,
182 xfs_rtxnum_t rtx)
183{
184 if (xfs_has_rtgroups(mp))
185 return div_u64(rtx, mp->m_rtx_per_rbmblock);
186
187 return rtx >> mp->m_blkbit_log;
188}
189
190/* Convert an rt extent number to a word offset within an rt bitmap block. */
191static inline unsigned int
192xfs_rtx_to_rbmword(
193 struct xfs_mount *mp,
194 xfs_rtxnum_t rtx)
195{
196 if (xfs_has_rtgroups(mp)) {
197 unsigned int mod;
198
199 div_u64_rem(rtx >> XFS_NBWORDLOG, mp->m_blockwsize, &mod);
200 return mod;
201 }
202
203 return (rtx >> XFS_NBWORDLOG) & (mp->m_blockwsize - 1);
204}
205
206/* Convert a file block offset in the rt bitmap file to an rt extent number. */
207static inline xfs_rtxnum_t
208xfs_rbmblock_to_rtx(
209 struct xfs_mount *mp,
210 xfs_fileoff_t rbmoff)
211{
212 if (xfs_has_rtgroups(mp))
213 return rbmoff * mp->m_rtx_per_rbmblock;
214
215 return rbmoff << mp->m_blkbit_log;
216}
217
218/* Return a pointer to a bitmap word within a rt bitmap block. */
219static inline union xfs_rtword_raw *
220xfs_rbmblock_wordptr(
221 struct xfs_rtalloc_args *args,
222 unsigned int index)
223{
224 struct xfs_mount *mp = args->mp;
225 union xfs_rtword_raw *words;
226 struct xfs_rtbuf_blkinfo *hdr = args->rbmbp->b_addr;
227
228 if (xfs_has_rtgroups(mp))
229 words = (union xfs_rtword_raw *)(hdr + 1);
230 else
231 words = args->rbmbp->b_addr;
232
233 return words + index;
234}
235
236/* Convert an ondisk bitmap word to its incore representation. */
237static inline xfs_rtword_t
238xfs_rtbitmap_getword(
239 struct xfs_rtalloc_args *args,
240 unsigned int index)
241{
242 union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
243
244 if (xfs_has_rtgroups(args->mp))
245 return be32_to_cpu(word->rtg);
246 return word->old;
247}
248
249/* Set an ondisk bitmap word from an incore representation. */
250static inline void
251xfs_rtbitmap_setword(
252 struct xfs_rtalloc_args *args,
253 unsigned int index,
254 xfs_rtword_t value)
255{
256 union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
257
258 if (xfs_has_rtgroups(args->mp))
259 word->rtg = cpu_to_be32(value);
260 else
261 word->old = value;
262}
263
264/*
265 * Convert a rt extent length and rt bitmap block number to a xfs_suminfo_t
266 * offset within the rt summary file.
267 */
268static inline xfs_rtsumoff_t
269xfs_rtsumoffs(
270 struct xfs_mount *mp,
271 int log2_len,
272 xfs_fileoff_t rbmoff)
273{
274 return log2_len * mp->m_sb.sb_rbmblocks + rbmoff;
275}
276
277/*
278 * Convert an xfs_suminfo_t offset to a file block offset within the rt summary
279 * file.
280 */
281static inline xfs_fileoff_t
282xfs_rtsumoffs_to_block(
283 struct xfs_mount *mp,
284 xfs_rtsumoff_t rsumoff)
285{
286 if (xfs_has_rtgroups(mp))
287 return rsumoff / mp->m_blockwsize;
288
289 return XFS_B_TO_FSBT(mp, rsumoff * sizeof(xfs_suminfo_t));
290}
291
292/*
293 * Convert an xfs_suminfo_t offset to an info word offset within an rt summary
294 * block.
295 */
296static inline unsigned int
297xfs_rtsumoffs_to_infoword(
298 struct xfs_mount *mp,
299 xfs_rtsumoff_t rsumoff)
300{
301 unsigned int mask = mp->m_blockmask >> XFS_SUMINFOLOG;
302
303 if (xfs_has_rtgroups(mp))
304 return rsumoff % mp->m_blockwsize;
305
306 return rsumoff & mask;
307}
308
309/* Return a pointer to a summary info word within a rt summary block. */
310static inline union xfs_suminfo_raw *
311xfs_rsumblock_infoptr(
312 struct xfs_rtalloc_args *args,
313 unsigned int index)
314{
315 union xfs_suminfo_raw *info;
316 struct xfs_rtbuf_blkinfo *hdr = args->sumbp->b_addr;
317
318 if (xfs_has_rtgroups(args->mp))
319 info = (union xfs_suminfo_raw *)(hdr + 1);
320 else
321 info = args->sumbp->b_addr;
322
323 return info + index;
324}
325
326/* Get the current value of a summary counter. */
327static inline xfs_suminfo_t
328xfs_suminfo_get(
329 struct xfs_rtalloc_args *args,
330 unsigned int index)
331{
332 union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
333
334 if (xfs_has_rtgroups(args->mp))
335 return be32_to_cpu(info->rtg);
336 return info->old;
337}
338
339/* Add to the current value of a summary counter and return the new value. */
340static inline xfs_suminfo_t
341xfs_suminfo_add(
342 struct xfs_rtalloc_args *args,
343 unsigned int index,
344 int delta)
345{
346 union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
347
348 if (xfs_has_rtgroups(args->mp)) {
349 be32_add_cpu(&info->rtg, delta);
350 return be32_to_cpu(info->rtg);
351 }
352
353 info->old += delta;
354 return info->old;
355}
356
357static inline const struct xfs_buf_ops *
358xfs_rtblock_ops(
359 struct xfs_mount *mp,
360 enum xfs_rtg_inodes type)
361{
362 if (xfs_has_rtgroups(mp)) {
363 if (type == XFS_RTGI_SUMMARY)
364 return &xfs_rtsummary_buf_ops;
365 return &xfs_rtbitmap_buf_ops;
366 }
367 return &xfs_rtbuf_ops;
368}
369
370/*
371 * Functions for walking free space rtextents in the realtime bitmap.
372 */
373struct xfs_rtalloc_rec {
374 xfs_rtxnum_t ar_startext;
375 xfs_rtbxlen_t ar_extcount;
376};
377
378typedef int (*xfs_rtalloc_query_range_fn)(
379 struct xfs_rtgroup *rtg,
380 struct xfs_trans *tp,
381 const struct xfs_rtalloc_rec *rec,
382 void *priv);
383
384#ifdef CONFIG_XFS_RT
385void xfs_rtbuf_cache_relse(struct xfs_rtalloc_args *args);
386int xfs_rtbitmap_read_buf(struct xfs_rtalloc_args *args, xfs_fileoff_t block);
387int xfs_rtsummary_read_buf(struct xfs_rtalloc_args *args, xfs_fileoff_t block);
388int xfs_rtcheck_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
389 xfs_rtxlen_t len, int val, xfs_rtxnum_t *new, int *stat);
390int xfs_rtfind_back(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
391 xfs_rtxnum_t *rtblock);
392int xfs_rtfind_forw(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
393 xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
394int xfs_rtmodify_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
395 xfs_rtxlen_t len, int val);
396int xfs_rtget_summary(struct xfs_rtalloc_args *args, int log,
397 xfs_fileoff_t bbno, xfs_suminfo_t *sum);
398int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log,
399 xfs_fileoff_t bbno, int delta);
400int xfs_rtfree_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
401 xfs_rtxlen_t len);
402int xfs_rtalloc_query_range(struct xfs_rtgroup *rtg, struct xfs_trans *tp,
403 xfs_rtxnum_t start, xfs_rtxnum_t end,
404 xfs_rtalloc_query_range_fn fn, void *priv);
405int xfs_rtalloc_query_all(struct xfs_rtgroup *rtg, struct xfs_trans *tp,
406 xfs_rtalloc_query_range_fn fn, void *priv);
407int xfs_rtalloc_extent_is_free(struct xfs_rtgroup *rtg, struct xfs_trans *tp,
408 xfs_rtxnum_t start, xfs_rtxlen_t len, bool *is_free);
409int xfs_rtfree_extent(struct xfs_trans *tp, struct xfs_rtgroup *rtg,
410 xfs_rtxnum_t start, xfs_rtxlen_t len);
411/* Same as above, but in units of rt blocks. */
412int xfs_rtfree_blocks(struct xfs_trans *tp, struct xfs_rtgroup *rtg,
413 xfs_fsblock_t rtbno, xfs_filblks_t rtlen);
414
415xfs_rtxnum_t xfs_rtbitmap_rtx_per_rbmblock(struct xfs_mount *mp);
416xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp);
417xfs_filblks_t xfs_rtbitmap_blockcount_len(struct xfs_mount *mp,
418 xfs_rtbxlen_t rtextents);
419xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
420 unsigned int *rsumlevels);
421
422int xfs_rtfile_initialize_blocks(struct xfs_rtgroup *rtg,
423 enum xfs_rtg_inodes type, xfs_fileoff_t offset_fsb,
424 xfs_fileoff_t end_fsb, void *data);
425int xfs_rtbitmap_create(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
426 struct xfs_trans *tp, bool init);
427int xfs_rtsummary_create(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
428 struct xfs_trans *tp, bool init);
429
430#else /* CONFIG_XFS_RT */
431# define xfs_rtfree_extent(t,b,l) (-ENOSYS)
432
433static inline int xfs_rtfree_blocks(struct xfs_trans *tp,
434 struct xfs_rtgroup *rtg, xfs_fsblock_t rtbno,
435 xfs_filblks_t rtlen)
436{
437 return -ENOSYS;
438}
439# define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS)
440# define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS)
441# define xfs_rtbitmap_read_buf(a,b) (-ENOSYS)
442# define xfs_rtsummary_read_buf(a,b) (-ENOSYS)
443# define xfs_rtbuf_cache_relse(a) (0)
444# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS)
445static inline xfs_filblks_t
446xfs_rtbitmap_blockcount_len(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
447{
448 /* shut up gcc */
449 return 0;
450}
451#endif /* CONFIG_XFS_RT */
452
453#endif /* __XFS_RTBITMAP_H__ */