xref: /linux/fs/xfs/libxfs/xfs_rtbitmap.h (revision b477ff98d903618a1ab8247861f2ea6e70c0f0f8)
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 
11 struct 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 
23 static inline xfs_rtblock_t
xfs_rtx_to_rtb(struct xfs_rtgroup * rtg,xfs_rtxnum_t rtx)24 xfs_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. */
37 static inline xfs_rtxnum_t
xfs_rgbno_to_rtx(struct xfs_mount * mp,xfs_rgblock_t rgbno)38 xfs_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 
47 static inline uint64_t
xfs_rtbxlen_to_blen(struct xfs_mount * mp,xfs_rtbxlen_t rtbxlen)48 xfs_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 
58 static inline xfs_extlen_t
xfs_rtxlen_to_extlen(struct xfs_mount * mp,xfs_rtxlen_t rtxlen)59 xfs_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 .*/
70 static inline unsigned int
xfs_extlen_to_rtxmod(struct xfs_mount * mp,xfs_extlen_t len)71 xfs_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 
81 static inline xfs_rtxlen_t
xfs_extlen_to_rtxlen(struct xfs_mount * mp,xfs_extlen_t len)82 xfs_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. */
93 static inline xfs_rtbxlen_t
xfs_blen_to_rtbxlen(struct xfs_mount * mp,uint64_t blen)94 xfs_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. */
105 static inline xfs_extlen_t
xfs_blen_to_rtxoff(struct xfs_mount * mp,xfs_filblks_t blen)106 xfs_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. */
117 static inline xfs_filblks_t
xfs_blen_roundup_rtx(struct xfs_mount * mp,xfs_filblks_t blen)118 xfs_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. */
126 static inline xfs_rtxnum_t
xfs_rtb_to_rtx(struct xfs_mount * mp,xfs_rtblock_t rtbno)127 xfs_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. */
139 static inline xfs_extlen_t
xfs_rgbno_to_rtxoff(struct xfs_mount * mp,xfs_rgblock_t rgbno)140 xfs_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. */
148 static inline xfs_extlen_t
xfs_rtb_to_rtxoff(struct xfs_mount * mp,xfs_rtblock_t rtbno)149 xfs_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. */
161 static inline xfs_rtblock_t
xfs_fileoff_roundup_rtx(struct xfs_mount * mp,xfs_fileoff_t off)162 xfs_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. */
170 static inline xfs_rtblock_t
xfs_fileoff_rounddown_rtx(struct xfs_mount * mp,xfs_fileoff_t off)171 xfs_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. */
179 static inline xfs_fileoff_t
xfs_rtx_to_rbmblock(struct xfs_mount * mp,xfs_rtxnum_t rtx)180 xfs_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. */
191 static inline unsigned int
xfs_rtx_to_rbmword(struct xfs_mount * mp,xfs_rtxnum_t rtx)192 xfs_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. */
207 static inline xfs_rtxnum_t
xfs_rbmblock_to_rtx(struct xfs_mount * mp,xfs_fileoff_t rbmoff)208 xfs_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. */
219 static inline union xfs_rtword_raw *
xfs_rbmblock_wordptr(struct xfs_rtalloc_args * args,unsigned int index)220 xfs_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. */
237 static inline xfs_rtword_t
xfs_rtbitmap_getword(struct xfs_rtalloc_args * args,unsigned int index)238 xfs_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. */
250 static inline void
xfs_rtbitmap_setword(struct xfs_rtalloc_args * args,unsigned int index,xfs_rtword_t value)251 xfs_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  */
268 static inline xfs_rtsumoff_t
xfs_rtsumoffs(struct xfs_mount * mp,int log2_len,xfs_fileoff_t rbmoff)269 xfs_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  */
281 static inline xfs_fileoff_t
xfs_rtsumoffs_to_block(struct xfs_mount * mp,xfs_rtsumoff_t rsumoff)282 xfs_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  */
296 static inline unsigned int
xfs_rtsumoffs_to_infoword(struct xfs_mount * mp,xfs_rtsumoff_t rsumoff)297 xfs_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. */
310 static inline union xfs_suminfo_raw *
xfs_rsumblock_infoptr(struct xfs_rtalloc_args * args,unsigned int index)311 xfs_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. */
327 static inline xfs_suminfo_t
xfs_suminfo_get(struct xfs_rtalloc_args * args,unsigned int index)328 xfs_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. */
340 static inline xfs_suminfo_t
xfs_suminfo_add(struct xfs_rtalloc_args * args,unsigned int index,int delta)341 xfs_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 
357 static inline const struct xfs_buf_ops *
xfs_rtblock_ops(struct xfs_mount * mp,enum xfs_rtg_inodes type)358 xfs_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  */
373 struct xfs_rtalloc_rec {
374 	xfs_rtxnum_t		ar_startext;
375 	xfs_rtbxlen_t		ar_extcount;
376 };
377 
378 typedef 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
385 void xfs_rtbuf_cache_relse(struct xfs_rtalloc_args *args);
386 int xfs_rtbitmap_read_buf(struct xfs_rtalloc_args *args, xfs_fileoff_t block);
387 int xfs_rtsummary_read_buf(struct xfs_rtalloc_args *args, xfs_fileoff_t block);
388 int 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);
390 int xfs_rtfind_back(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
391 		xfs_rtxnum_t *rtblock);
392 int xfs_rtfind_forw(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
393 		xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
394 int xfs_rtmodify_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
395 		xfs_rtxlen_t len, int val);
396 int xfs_rtget_summary(struct xfs_rtalloc_args *args, int log,
397 		xfs_fileoff_t bbno, xfs_suminfo_t *sum);
398 int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log,
399 		xfs_fileoff_t bbno, int delta);
400 int xfs_rtfree_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
401 		xfs_rtxlen_t len);
402 int 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);
405 int xfs_rtalloc_query_all(struct xfs_rtgroup *rtg, struct xfs_trans *tp,
406 		xfs_rtalloc_query_range_fn fn, void *priv);
407 int 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);
409 int 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. */
412 int xfs_rtfree_blocks(struct xfs_trans *tp, struct xfs_rtgroup *rtg,
413 		xfs_fsblock_t rtbno, xfs_filblks_t rtlen);
414 
415 xfs_rtxnum_t xfs_rtbitmap_rtx_per_rbmblock(struct xfs_mount *mp);
416 xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp);
417 xfs_filblks_t xfs_rtbitmap_blockcount_len(struct xfs_mount *mp,
418 		xfs_rtbxlen_t rtextents);
419 xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
420 		unsigned int *rsumlevels);
421 
422 int 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);
425 int xfs_rtbitmap_create(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
426 		struct xfs_trans *tp, bool init);
427 int 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 
xfs_rtfree_blocks(struct xfs_trans * tp,struct xfs_rtgroup * rtg,xfs_fsblock_t rtbno,xfs_filblks_t rtlen)433 static 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)
445 static inline xfs_filblks_t
xfs_rtbitmap_blockcount_len(struct xfs_mount * mp,xfs_rtbxlen_t rtextents)446 xfs_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__ */
454