]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_rtbitmap.c
xfsprogs: Release v6.15.0
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_rtbitmap.c
CommitLineData
37b3b4d6 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
5e656dbb 3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
da23017d 4 * All Rights Reserved.
2bd0ea18 5 */
9c799827 6#include "libxfs_priv.h"
b626fb59
DC
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_log_format.h"
11#include "xfs_trans_resv.h"
12#include "xfs_bit.h"
13#include "xfs_mount.h"
14#include "xfs_inode.h"
15#include "xfs_bmap.h"
f666752a
CH
16#include "xfs_bmap_btree.h"
17#include "xfs_trans_space.h"
b626fb59 18#include "xfs_trans.h"
a8616431 19#include "xfs_rtbitmap.h"
bb9be3f8 20#include "xfs_health.h"
3241cd2c 21#include "xfs_sb.h"
e200799d 22#include "xfs_errortag.h"
b626fb59 23
5e656dbb 24/*
2ceff9ce 25 * Realtime allocator bitmap functions shared with userspace.
5e656dbb 26 */
2bd0ea18 27
06fb4ab2
DW
28static xfs_failaddr_t
29xfs_rtbuf_verify(
30 struct xfs_buf *bp)
31{
32 struct xfs_mount *mp = bp->b_mount;
33 struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
34
35 if (!xfs_verify_magic(bp, hdr->rt_magic))
36 return __this_address;
37 if (!xfs_has_rtgroups(mp))
38 return __this_address;
39 if (!xfs_has_crc(mp))
40 return __this_address;
41 if (!uuid_equal(&hdr->rt_uuid, &mp->m_sb.sb_meta_uuid))
42 return __this_address;
43 if (hdr->rt_blkno != cpu_to_be64(xfs_buf_daddr(bp)))
44 return __this_address;
45 return NULL;
46}
47
a3d22941
DC
48static void
49xfs_rtbuf_verify_read(
06fb4ab2 50 struct xfs_buf *bp)
a3d22941 51{
06fb4ab2
DW
52 struct xfs_mount *mp = bp->b_mount;
53 struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
54 xfs_failaddr_t fa;
55
56 if (!xfs_has_rtgroups(mp))
57 return;
58
59 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr->rt_lsn))) {
60 fa = __this_address;
61 goto fail;
62 }
63
64 if (!xfs_buf_verify_cksum(bp, XFS_RTBUF_CRC_OFF)) {
65 fa = __this_address;
66 goto fail;
67 }
68
69 fa = xfs_rtbuf_verify(bp);
70 if (fa)
71 goto fail;
72
a3d22941 73 return;
06fb4ab2
DW
74fail:
75 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
a3d22941
DC
76}
77
78static void
79xfs_rtbuf_verify_write(
80 struct xfs_buf *bp)
81{
06fb4ab2
DW
82 struct xfs_mount *mp = bp->b_mount;
83 struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
84 struct xfs_buf_log_item *bip = bp->b_log_item;
85 xfs_failaddr_t fa;
86
87 if (!xfs_has_rtgroups(mp))
88 return;
89
90 fa = xfs_rtbuf_verify(bp);
91 if (fa) {
92 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
93 return;
94 }
95
96 if (bip)
97 hdr->rt_lsn = cpu_to_be64(bip->bli_item.li_lsn);
98 xfs_buf_update_cksum(bp, XFS_RTBUF_CRC_OFF);
a3d22941
DC
99}
100
101const struct xfs_buf_ops xfs_rtbuf_ops = {
102 .name = "rtbuf",
103 .verify_read = xfs_rtbuf_verify_read,
104 .verify_write = xfs_rtbuf_verify_write,
105};
106
06fb4ab2
DW
107const struct xfs_buf_ops xfs_rtbitmap_buf_ops = {
108 .name = "xfs_rtbitmap",
109 .magic = { 0, cpu_to_be32(XFS_RTBITMAP_MAGIC) },
110 .verify_read = xfs_rtbuf_verify_read,
111 .verify_write = xfs_rtbuf_verify_write,
112 .verify_struct = xfs_rtbuf_verify,
113};
114
115const struct xfs_buf_ops xfs_rtsummary_buf_ops = {
116 .name = "xfs_rtsummary",
117 .magic = { 0, cpu_to_be32(XFS_RTSUMMARY_MAGIC) },
118 .verify_read = xfs_rtbuf_verify_read,
119 .verify_write = xfs_rtbuf_verify_write,
120 .verify_struct = xfs_rtbuf_verify,
121};
122
52273f22
OS
123/* Release cached rt bitmap and summary buffers. */
124void
125xfs_rtbuf_cache_relse(
126 struct xfs_rtalloc_args *args)
127{
128 if (args->rbmbp) {
129 xfs_trans_brelse(args->tp, args->rbmbp);
130 args->rbmbp = NULL;
131 args->rbmoff = NULLFILEOFF;
132 }
133 if (args->sumbp) {
134 xfs_trans_brelse(args->tp, args->sumbp);
135 args->sumbp = NULL;
136 args->sumoff = NULLFILEOFF;
137 }
138}
139
2bd0ea18
NS
140/*
141 * Get a buffer for the bitmap or summary file block specified.
142 * The buffer is returned read and locked.
143 */
915ebe75 144static int
2bd0ea18 145xfs_rtbuf_get(
f827e51c
DC
146 struct xfs_rtalloc_args *args,
147 xfs_fileoff_t block, /* block number in bitmap or summary */
2342f2c0 148 enum xfs_rtg_inodes type)
2bd0ea18 149{
2342f2c0 150 struct xfs_inode *ip = args->rtg->rtg_inodes[type];
f827e51c 151 struct xfs_mount *mp = args->mp;
52273f22
OS
152 struct xfs_buf **cbpp; /* cached block buffer */
153 xfs_fileoff_t *coffp; /* cached block number */
f827e51c 154 struct xfs_buf *bp; /* block buffer, result */
f827e51c 155 struct xfs_bmbt_irec map;
2342f2c0 156 enum xfs_blft buf_type;
f827e51c
DC
157 int nmap = 1;
158 int error;
2bd0ea18 159
2342f2c0
DW
160 switch (type) {
161 case XFS_RTGI_SUMMARY:
52273f22
OS
162 cbpp = &args->sumbp;
163 coffp = &args->sumoff;
2342f2c0
DW
164 buf_type = XFS_BLFT_RTSUMMARY_BUF;
165 break;
166 case XFS_RTGI_BITMAP:
52273f22
OS
167 cbpp = &args->rbmbp;
168 coffp = &args->rbmoff;
2342f2c0
DW
169 buf_type = XFS_BLFT_RTBITMAP_BUF;
170 break;
171 default:
172 return -EINVAL;
52273f22
OS
173 }
174
175 /*
176 * If we have a cached buffer, and the block number matches, use that.
177 */
ae391218 178 if (*cbpp && *coffp == block)
52273f22 179 return 0;
ae391218 180
52273f22
OS
181 /*
182 * Otherwise we have to have to get the buffer. If there was an old
183 * one, get rid of it first.
184 */
185 if (*cbpp) {
186 xfs_trans_brelse(args->tp, *cbpp);
187 *cbpp = NULL;
188 }
a2ceac1f 189
f5d22700 190 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
a2ceac1f 191 if (error)
2bd0ea18 192 return error;
a2ceac1f 193
bb9be3f8 194 if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map))) {
2342f2c0 195 xfs_rtginode_mark_sick(args->rtg, type);
5e28c9c8 196 return -EFSCORRUPTED;
bb9be3f8 197 }
5e28c9c8 198
a2ceac1f 199 ASSERT(map.br_startblock != NULLFSBLOCK);
f827e51c 200 error = xfs_trans_read_buf(mp, args->tp, mp->m_ddev_targp,
a2ceac1f 201 XFS_FSB_TO_DADDR(mp, map.br_startblock),
06fb4ab2
DW
202 mp->m_bsize, 0, &bp,
203 xfs_rtblock_ops(mp, type));
bb9be3f8 204 if (xfs_metadata_is_sick(error))
2342f2c0 205 xfs_rtginode_mark_sick(args->rtg, type);
a2ceac1f 206 if (error)
2bd0ea18 207 return error;
f36349d8 208
06fb4ab2
DW
209 if (xfs_has_rtgroups(mp)) {
210 struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
211
212 if (hdr->rt_owner != cpu_to_be64(ip->i_ino)) {
213 xfs_buf_mark_corrupt(bp);
214 xfs_trans_brelse(args->tp, bp);
215 xfs_rtginode_mark_sick(args->rtg, type);
216 return -EFSCORRUPTED;
217 }
218 }
219
2342f2c0 220 xfs_trans_buf_set_type(args->tp, bp, buf_type);
ae391218 221 *cbpp = bp;
52273f22 222 *coffp = block;
2bd0ea18
NS
223 return 0;
224}
225
915ebe75
CH
226int
227xfs_rtbitmap_read_buf(
228 struct xfs_rtalloc_args *args,
229 xfs_fileoff_t block)
230{
231 struct xfs_mount *mp = args->mp;
232
233 if (XFS_IS_CORRUPT(mp, block >= mp->m_sb.sb_rbmblocks)) {
2342f2c0 234 xfs_rtginode_mark_sick(args->rtg, XFS_RTGI_BITMAP);
915ebe75
CH
235 return -EFSCORRUPTED;
236 }
237
2342f2c0 238 return xfs_rtbuf_get(args, block, XFS_RTGI_BITMAP);
915ebe75
CH
239}
240
241int
242xfs_rtsummary_read_buf(
243 struct xfs_rtalloc_args *args,
244 xfs_fileoff_t block)
245{
246 struct xfs_mount *mp = args->mp;
247
84704ebf 248 if (XFS_IS_CORRUPT(mp, block >= mp->m_rsumblocks)) {
2342f2c0 249 xfs_rtginode_mark_sick(args->rtg, XFS_RTGI_SUMMARY);
915ebe75
CH
250 return -EFSCORRUPTED;
251 }
2342f2c0 252 return xfs_rtbuf_get(args, block, XFS_RTGI_SUMMARY);
915ebe75
CH
253}
254
2bd0ea18 255/*
a9af23f7
CH
256 * Searching backward from start find the first block whose allocated/free state
257 * is different from start's.
2bd0ea18 258 */
2ceff9ce 259int
2bd0ea18 260xfs_rtfind_back(
f827e51c
DC
261 struct xfs_rtalloc_args *args,
262 xfs_rtxnum_t start, /* starting rtext to look at */
f827e51c 263 xfs_rtxnum_t *rtx) /* out: start rtext found */
2bd0ea18 264{
f827e51c
DC
265 struct xfs_mount *mp = args->mp;
266 int bit; /* bit number in the word */
267 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
268 int error; /* error value */
269 xfs_rtxnum_t firstbit; /* first useful bit in the word */
270 xfs_rtxnum_t i; /* current bit number rel. to start */
271 xfs_rtxnum_t len; /* length of inspected area */
272 xfs_rtword_t mask; /* mask of relevant bits for value */
273 xfs_rtword_t want; /* mask for "good" values */
274 xfs_rtword_t wdiff; /* difference from wanted value */
275 xfs_rtword_t incore;
276 unsigned int word; /* word number in the buffer */
2bd0ea18
NS
277
278 /*
279 * Compute and read in starting bitmap block for starting block.
280 */
75e15fbc 281 block = xfs_rtx_to_rbmblock(mp, start);
ae391218
DW
282 error = xfs_rtbitmap_read_buf(args, block);
283 if (error)
2bd0ea18 284 return error;
c1f9bc4b 285
2bd0ea18
NS
286 /*
287 * Get the first word's index & point to it.
288 */
75e15fbc 289 word = xfs_rtx_to_rbmword(mp, start);
2bd0ea18 290 bit = (int)(start & (XFS_NBWORD - 1));
a9af23f7 291 len = start + 1;
2bd0ea18
NS
292 /*
293 * Compute match value, based on the bit at start: if 1 (free)
294 * then all-ones, else all-zeroes.
295 */
93b4decb 296 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 297 want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
2bd0ea18
NS
298 /*
299 * If the starting position is not word-aligned, deal with the
300 * partial word.
301 */
302 if (bit < XFS_NBWORD - 1) {
303 /*
304 * Calculate first (leftmost) bit number to look at,
305 * and mask for all the relevant bits in this word.
306 */
50e6e3c2 307 firstbit = max_t(xfs_srtblock_t, bit - len + 1, 0);
2bd0ea18
NS
308 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
309 firstbit;
310 /*
311 * Calculate the difference between the value there
312 * and what we're looking for.
313 */
f4a0432b 314 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
315 /*
316 * Different. Mark where we are and return.
317 */
6742ada6 318 i = bit - xfs_highbit32(wdiff);
817e9237 319 *rtx = start - i + 1;
2bd0ea18
NS
320 return 0;
321 }
322 i = bit - firstbit + 1;
323 /*
324 * Go on to previous block if that's where the previous word is
325 * and we need the previous word.
326 */
327 if (--word == -1 && i < len) {
328 /*
329 * If done with this block, get the previous one.
330 */
ae391218
DW
331 error = xfs_rtbitmap_read_buf(args, --block);
332 if (error)
2bd0ea18 333 return error;
c1f9bc4b 334
18b4102a 335 word = mp->m_blockwsize - 1;
2bd0ea18
NS
336 }
337 } else {
338 /*
339 * Starting on a word boundary, no partial word.
340 */
341 i = 0;
342 }
343 /*
344 * Loop over whole words in buffers. When we use up one buffer
345 * we move on to the previous one.
346 */
347 while (len - i >= XFS_NBWORD) {
348 /*
349 * Compute difference between actual and desired value.
350 */
93b4decb 351 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 352 if ((wdiff = incore ^ want)) {
2bd0ea18
NS
353 /*
354 * Different, mark where we are and return.
355 */
6742ada6 356 i += XFS_NBWORD - 1 - xfs_highbit32(wdiff);
817e9237 357 *rtx = start - i + 1;
2bd0ea18
NS
358 return 0;
359 }
360 i += XFS_NBWORD;
361 /*
362 * Go on to previous block if that's where the previous word is
363 * and we need the previous word.
364 */
365 if (--word == -1 && i < len) {
366 /*
367 * If done with this block, get the previous one.
368 */
ae391218
DW
369 error = xfs_rtbitmap_read_buf(args, --block);
370 if (error)
2bd0ea18 371 return error;
c1f9bc4b 372
18b4102a 373 word = mp->m_blockwsize - 1;
2bd0ea18
NS
374 }
375 }
376 /*
377 * If not ending on a word boundary, deal with the last
378 * (partial) word.
379 */
380 if (len - i) {
381 /*
382 * Calculate first (leftmost) bit number to look at,
383 * and mask for all the relevant bits in this word.
384 */
385 firstbit = XFS_NBWORD - (len - i);
386 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
387 /*
388 * Compute difference between actual and desired value.
389 */
93b4decb 390 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 391 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
392 /*
393 * Different, mark where we are and return.
394 */
6742ada6 395 i += XFS_NBWORD - 1 - xfs_highbit32(wdiff);
817e9237 396 *rtx = start - i + 1;
2bd0ea18
NS
397 return 0;
398 } else
399 i = len;
400 }
401 /*
402 * No match, return that we scanned the whole area.
403 */
817e9237 404 *rtx = start - i + 1;
2bd0ea18
NS
405 return 0;
406}
407
408/*
409 * Searching forward from start to limit, find the first block whose
410 * allocated/free state is different from start's.
411 */
2ceff9ce 412int
2bd0ea18 413xfs_rtfind_forw(
f827e51c
DC
414 struct xfs_rtalloc_args *args,
415 xfs_rtxnum_t start, /* starting rtext to look at */
416 xfs_rtxnum_t limit, /* last rtext to look at */
417 xfs_rtxnum_t *rtx) /* out: start rtext found */
2bd0ea18 418{
f827e51c
DC
419 struct xfs_mount *mp = args->mp;
420 int bit; /* bit number in the word */
421 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
422 int error;
423 xfs_rtxnum_t i; /* current bit number rel. to start */
424 xfs_rtxnum_t lastbit;/* last useful bit in the word */
425 xfs_rtxnum_t len; /* length of inspected area */
426 xfs_rtword_t mask; /* mask of relevant bits for value */
427 xfs_rtword_t want; /* mask for "good" values */
428 xfs_rtword_t wdiff; /* difference from wanted value */
429 xfs_rtword_t incore;
430 unsigned int word; /* word number in the buffer */
2bd0ea18 431
39c5ade9
CH
432 ASSERT(start <= limit);
433
2bd0ea18
NS
434 /*
435 * Compute and read in starting bitmap block for starting block.
436 */
75e15fbc 437 block = xfs_rtx_to_rbmblock(mp, start);
ae391218
DW
438 error = xfs_rtbitmap_read_buf(args, block);
439 if (error)
2bd0ea18 440 return error;
c1f9bc4b 441
2bd0ea18
NS
442 /*
443 * Get the first word's index & point to it.
444 */
75e15fbc 445 word = xfs_rtx_to_rbmword(mp, start);
2bd0ea18
NS
446 bit = (int)(start & (XFS_NBWORD - 1));
447 len = limit - start + 1;
448 /*
449 * Compute match value, based on the bit at start: if 1 (free)
450 * then all-ones, else all-zeroes.
451 */
93b4decb 452 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 453 want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
2bd0ea18
NS
454 /*
455 * If the starting position is not word-aligned, deal with the
456 * partial word.
457 */
458 if (bit) {
459 /*
460 * Calculate last (rightmost) bit number to look at,
461 * and mask for all the relevant bits in this word.
462 */
50e6e3c2 463 lastbit = min(bit + len, XFS_NBWORD);
2bd0ea18
NS
464 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
465 /*
466 * Calculate the difference between the value there
467 * and what we're looking for.
468 */
f4a0432b 469 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
470 /*
471 * Different. Mark where we are and return.
472 */
6742ada6 473 i = xfs_lowbit32(wdiff) - bit;
817e9237 474 *rtx = start + i - 1;
2bd0ea18
NS
475 return 0;
476 }
477 i = lastbit - bit;
478 /*
479 * Go on to next block if that's where the next word is
480 * and we need the next word.
481 */
18b4102a 482 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
483 /*
484 * If done with this block, get the previous one.
485 */
ae391218
DW
486 error = xfs_rtbitmap_read_buf(args, ++block);
487 if (error)
2bd0ea18 488 return error;
c1f9bc4b 489
2bd0ea18 490 word = 0;
2bd0ea18
NS
491 }
492 } else {
493 /*
494 * Starting on a word boundary, no partial word.
495 */
496 i = 0;
497 }
498 /*
499 * Loop over whole words in buffers. When we use up one buffer
500 * we move on to the next one.
501 */
502 while (len - i >= XFS_NBWORD) {
503 /*
504 * Compute difference between actual and desired value.
505 */
93b4decb 506 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 507 if ((wdiff = incore ^ want)) {
2bd0ea18
NS
508 /*
509 * Different, mark where we are and return.
510 */
6742ada6 511 i += xfs_lowbit32(wdiff);
817e9237 512 *rtx = start + i - 1;
2bd0ea18
NS
513 return 0;
514 }
515 i += XFS_NBWORD;
516 /*
517 * Go on to next block if that's where the next word is
518 * and we need the next word.
519 */
18b4102a 520 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
521 /*
522 * If done with this block, get the next one.
523 */
ae391218
DW
524 error = xfs_rtbitmap_read_buf(args, ++block);
525 if (error)
2bd0ea18 526 return error;
c1f9bc4b 527
2bd0ea18 528 word = 0;
2bd0ea18
NS
529 }
530 }
531 /*
532 * If not ending on a word boundary, deal with the last
533 * (partial) word.
534 */
0e266570 535 if ((lastbit = len - i)) {
2bd0ea18
NS
536 /*
537 * Calculate mask for all the relevant bits in this word.
538 */
539 mask = ((xfs_rtword_t)1 << lastbit) - 1;
540 /*
541 * Compute difference between actual and desired value.
542 */
93b4decb 543 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 544 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
545 /*
546 * Different, mark where we are and return.
547 */
6742ada6 548 i += xfs_lowbit32(wdiff);
817e9237 549 *rtx = start + i - 1;
2bd0ea18
NS
550 return 0;
551 } else
552 i = len;
553 }
554 /*
555 * No match, return that we scanned the whole area.
556 */
817e9237 557 *rtx = start + i - 1;
2bd0ea18
NS
558 return 0;
559}
560
3d763f98
DW
561/* Log rtsummary counter at @infoword. */
562static inline void
563xfs_trans_log_rtsummary(
93b4decb 564 struct xfs_rtalloc_args *args,
3d763f98
DW
565 unsigned int infoword)
566{
93b4decb 567 struct xfs_buf *bp = args->sumbp;
3d763f98
DW
568 size_t first, last;
569
93b4decb 570 first = (void *)xfs_rsumblock_infoptr(args, infoword) - bp->b_addr;
3d763f98
DW
571 last = first + sizeof(xfs_suminfo_t) - 1;
572
93b4decb 573 xfs_trans_log_buf(args->tp, bp, first, last);
3d763f98
DW
574}
575
2bd0ea18 576/*
5dded934
CH
577 * Modify the summary information for a given extent size, bitmap block
578 * combination.
2bd0ea18 579 */
2ceff9ce 580int
5dded934 581xfs_rtmodify_summary(
f827e51c
DC
582 struct xfs_rtalloc_args *args,
583 int log, /* log2 of extent size */
584 xfs_fileoff_t bbno, /* bitmap block number */
5dded934 585 int delta) /* in/out: summary block number */
2bd0ea18 586{
f827e51c 587 struct xfs_mount *mp = args->mp;
5dded934 588 xfs_rtsumoff_t so = xfs_rtsumoffs(mp, log, bbno);
55ed4049 589 uint8_t *rsum_cache = args->rtg->rtg_rsum_cache;
f827e51c 590 unsigned int infoword;
5dded934
CH
591 xfs_suminfo_t val;
592 int error;
2bd0ea18 593
5dded934 594 error = xfs_rtsummary_read_buf(args, xfs_rtsumoffs_to_block(mp, so));
52273f22
OS
595 if (error)
596 return error;
597
ccffd2f9 598 infoword = xfs_rtsumoffs_to_infoword(mp, so);
5dded934
CH
599 val = xfs_suminfo_add(args, infoword, delta);
600
55ed4049
CH
601 if (rsum_cache) {
602 if (val == 0 && log + 1 == rsum_cache[bbno])
603 rsum_cache[bbno] = log;
604 if (val != 0 && log >= rsum_cache[bbno])
605 rsum_cache[bbno] = log + 1;
5a35bf2c 606 }
2bd0ea18 607
5dded934
CH
608 xfs_trans_log_rtsummary(args, infoword);
609 return 0;
5a35bf2c
DC
610}
611
fbaaa7b3
CH
612/*
613 * Read and return the summary information for a given extent size, bitmap block
614 * combination.
615 */
616int
617xfs_rtget_summary(
618 struct xfs_rtalloc_args *args,
619 int log, /* log2 of extent size */
620 xfs_fileoff_t bbno, /* bitmap block number */
621 xfs_suminfo_t *sum) /* out: summary info for this block */
622{
5dded934
CH
623 struct xfs_mount *mp = args->mp;
624 xfs_rtsumoff_t so = xfs_rtsumoffs(mp, log, bbno);
625 int error;
626
627 error = xfs_rtsummary_read_buf(args, xfs_rtsumoffs_to_block(mp, so));
628 if (!error)
629 *sum = xfs_suminfo_get(args, xfs_rtsumoffs_to_infoword(mp, so));
630 return error;
fbaaa7b3
CH
631}
632
3d763f98
DW
633/* Log rtbitmap block from the word @from to the byte before @next. */
634static inline void
635xfs_trans_log_rtbitmap(
93b4decb 636 struct xfs_rtalloc_args *args,
3d763f98
DW
637 unsigned int from,
638 unsigned int next)
639{
93b4decb 640 struct xfs_buf *bp = args->rbmbp;
3d763f98
DW
641 size_t first, last;
642
93b4decb
DW
643 first = (void *)xfs_rbmblock_wordptr(args, from) - bp->b_addr;
644 last = ((void *)xfs_rbmblock_wordptr(args, next) - 1) - bp->b_addr;
3d763f98 645
93b4decb 646 xfs_trans_log_buf(args->tp, bp, first, last);
3d763f98
DW
647}
648
2bd0ea18
NS
649/*
650 * Set the given range of bitmap bits to the given value.
651 * Do whatever I/O and logging is required.
652 */
2ceff9ce 653int
2bd0ea18 654xfs_rtmodify_range(
f827e51c
DC
655 struct xfs_rtalloc_args *args,
656 xfs_rtxnum_t start, /* starting rtext to modify */
657 xfs_rtxlen_t len, /* length of extent to modify */
658 int val) /* 1 for free, 0 for allocated */
2bd0ea18 659{
f827e51c
DC
660 struct xfs_mount *mp = args->mp;
661 int bit; /* bit number in the word */
662 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
663 int error;
664 int i; /* current bit number rel. to start */
665 int lastbit; /* last useful bit in word */
666 xfs_rtword_t mask; /* mask of relevant bits for value */
667 xfs_rtword_t incore;
668 unsigned int firstword; /* first word used in the buffer */
669 unsigned int word; /* word number in the buffer */
2bd0ea18
NS
670
671 /*
672 * Compute starting bitmap block number.
673 */
75e15fbc 674 block = xfs_rtx_to_rbmblock(mp, start);
2bd0ea18
NS
675 /*
676 * Read the bitmap block, and point to its data.
677 */
ae391218
DW
678 error = xfs_rtbitmap_read_buf(args, block);
679 if (error)
2bd0ea18 680 return error;
c1f9bc4b 681
2bd0ea18
NS
682 /*
683 * Compute the starting word's address, and starting bit.
684 */
3d763f98 685 firstword = word = xfs_rtx_to_rbmword(mp, start);
2bd0ea18
NS
686 bit = (int)(start & (XFS_NBWORD - 1));
687 /*
688 * 0 (allocated) => all zeroes; 1 (free) => all ones.
689 */
690 val = -val;
691 /*
692 * If not starting on a word boundary, deal with the first
693 * (partial) word.
694 */
695 if (bit) {
696 /*
697 * Compute first bit not changed and mask of relevant bits.
698 */
50e6e3c2 699 lastbit = min(bit + len, XFS_NBWORD);
2bd0ea18
NS
700 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
701 /*
702 * Set/clear the active bits.
703 */
93b4decb 704 incore = xfs_rtbitmap_getword(args, word);
2bd0ea18 705 if (val)
f4a0432b 706 incore |= mask;
2bd0ea18 707 else
f4a0432b 708 incore &= ~mask;
93b4decb 709 xfs_rtbitmap_setword(args, word, incore);
2bd0ea18
NS
710 i = lastbit - bit;
711 /*
712 * Go on to the next block if that's where the next word is
713 * and we need the next word.
714 */
18b4102a 715 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
716 /*
717 * Log the changed part of this block.
718 * Get the next one.
719 */
93b4decb 720 xfs_trans_log_rtbitmap(args, firstword, word);
ae391218
DW
721 error = xfs_rtbitmap_read_buf(args, ++block);
722 if (error)
2bd0ea18 723 return error;
c1f9bc4b 724
3d763f98 725 firstword = word = 0;
2bd0ea18
NS
726 }
727 } else {
728 /*
729 * Starting on a word boundary, no partial word.
730 */
731 i = 0;
732 }
733 /*
734 * Loop over whole words in buffers. When we use up one buffer
735 * we move on to the next one.
736 */
737 while (len - i >= XFS_NBWORD) {
738 /*
739 * Set the word value correctly.
740 */
93b4decb 741 xfs_rtbitmap_setword(args, word, val);
2bd0ea18
NS
742 i += XFS_NBWORD;
743 /*
744 * Go on to the next block if that's where the next word is
745 * and we need the next word.
746 */
18b4102a 747 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
748 /*
749 * Log the changed part of this block.
750 * Get the next one.
751 */
93b4decb 752 xfs_trans_log_rtbitmap(args, firstword, word);
ae391218 753 error = xfs_rtbitmap_read_buf(args, ++block);
f827e51c 754 if (error)
2bd0ea18 755 return error;
c1f9bc4b 756
3d763f98 757 firstword = word = 0;
2bd0ea18
NS
758 }
759 }
760 /*
761 * If not ending on a word boundary, deal with the last
762 * (partial) word.
763 */
0e266570 764 if ((lastbit = len - i)) {
2bd0ea18
NS
765 /*
766 * Compute a mask of relevant bits.
767 */
2bd0ea18
NS
768 mask = ((xfs_rtword_t)1 << lastbit) - 1;
769 /*
770 * Set/clear the active bits.
771 */
93b4decb 772 incore = xfs_rtbitmap_getword(args, word);
2bd0ea18 773 if (val)
f4a0432b 774 incore |= mask;
2bd0ea18 775 else
f4a0432b 776 incore &= ~mask;
93b4decb 777 xfs_rtbitmap_setword(args, word, incore);
3d763f98 778 word++;
2bd0ea18
NS
779 }
780 /*
781 * Log any remaining changed bytes.
782 */
f4a0432b 783 if (word > firstword)
93b4decb 784 xfs_trans_log_rtbitmap(args, firstword, word);
2bd0ea18
NS
785 return 0;
786}
787
788/*
2ceff9ce
DC
789 * Mark an extent specified by start and len freed.
790 * Updates all the summary information as well as the bitmap.
2bd0ea18 791 */
2ceff9ce
DC
792int
793xfs_rtfree_range(
f827e51c
DC
794 struct xfs_rtalloc_args *args,
795 xfs_rtxnum_t start, /* starting rtext to free */
52273f22 796 xfs_rtxlen_t len) /* in/out: summary block number */
2bd0ea18 797{
f827e51c
DC
798 struct xfs_mount *mp = args->mp;
799 xfs_rtxnum_t end; /* end of the freed extent */
800 int error; /* error value */
801 xfs_rtxnum_t postblock; /* first rtext freed > end */
802 xfs_rtxnum_t preblock; /* first rtext freed < start */
2bd0ea18 803
2ceff9ce 804 end = start + len - 1;
2bd0ea18 805 /*
2ceff9ce 806 * Modify the bitmap to mark this extent freed.
2bd0ea18 807 */
f827e51c 808 error = xfs_rtmodify_range(args, start, len, 1);
2ceff9ce
DC
809 if (error) {
810 return error;
811 }
2bd0ea18 812 /*
2ceff9ce
DC
813 * Assume we're freeing out of the middle of an allocated extent.
814 * We need to find the beginning and end of the extent so we can
815 * properly update the summary.
2bd0ea18 816 */
a9af23f7 817 error = xfs_rtfind_back(args, start, &preblock);
2ceff9ce
DC
818 if (error) {
819 return error;
820 }
2bd0ea18 821 /*
2ceff9ce 822 * Find the next allocated block (end of allocated extent).
2bd0ea18 823 */
55ed4049 824 error = xfs_rtfind_forw(args, end, args->rtg->rtg_extents - 1,
52273f22 825 &postblock);
2ceff9ce
DC
826 if (error)
827 return error;
2bd0ea18 828 /*
2ceff9ce
DC
829 * If there are blocks not being freed at the front of the
830 * old extent, add summary data for them to be allocated.
2bd0ea18 831 */
2ceff9ce 832 if (preblock < start) {
f827e51c 833 error = xfs_rtmodify_summary(args,
6742ada6 834 xfs_highbit64(start - preblock),
52273f22 835 xfs_rtx_to_rbmblock(mp, preblock), -1);
2bd0ea18
NS
836 if (error) {
837 return error;
838 }
2ceff9ce
DC
839 }
840 /*
841 * If there are blocks not being freed at the end of the
842 * old extent, add summary data for them to be allocated.
843 */
844 if (postblock > end) {
f827e51c 845 error = xfs_rtmodify_summary(args,
6742ada6 846 xfs_highbit64(postblock - end),
52273f22 847 xfs_rtx_to_rbmblock(mp, end + 1), -1);
2ceff9ce
DC
848 if (error) {
849 return error;
850 }
851 }
852 /*
853 * Increment the summary information corresponding to the entire
854 * (new) free extent.
855 */
52273f22 856 return xfs_rtmodify_summary(args,
6742ada6 857 xfs_highbit64(postblock + 1 - preblock),
52273f22 858 xfs_rtx_to_rbmblock(mp, preblock), 1);
2ceff9ce
DC
859}
860
861/*
862 * Check that the given range is either all allocated (val = 0) or
863 * all free (val = 1).
864 */
865int
866xfs_rtcheck_range(
f827e51c
DC
867 struct xfs_rtalloc_args *args,
868 xfs_rtxnum_t start, /* starting rtext number of extent */
869 xfs_rtxlen_t len, /* length of extent */
870 int val, /* 1 for free, 0 for allocated */
871 xfs_rtxnum_t *new, /* out: first rtext not matching */
872 int *stat) /* out: 1 for matches, 0 for not */
2ceff9ce 873{
f827e51c
DC
874 struct xfs_mount *mp = args->mp;
875 int bit; /* bit number in the word */
876 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
877 int error;
878 xfs_rtxnum_t i; /* current bit number rel. to start */
879 xfs_rtxnum_t lastbit; /* last useful bit in word */
880 xfs_rtword_t mask; /* mask of relevant bits for value */
881 xfs_rtword_t wdiff; /* difference from wanted value */
882 xfs_rtword_t incore;
883 unsigned int word; /* word number in the buffer */
2ceff9ce
DC
884
885 /*
886 * Compute starting bitmap block number
887 */
75e15fbc 888 block = xfs_rtx_to_rbmblock(mp, start);
2ceff9ce
DC
889 /*
890 * Read the bitmap block.
891 */
ae391218
DW
892 error = xfs_rtbitmap_read_buf(args, block);
893 if (error)
2ceff9ce 894 return error;
c1f9bc4b 895
2ceff9ce
DC
896 /*
897 * Compute the starting word's address, and starting bit.
898 */
75e15fbc 899 word = xfs_rtx_to_rbmword(mp, start);
2ceff9ce
DC
900 bit = (int)(start & (XFS_NBWORD - 1));
901 /*
902 * 0 (allocated) => all zero's; 1 (free) => all one's.
903 */
904 val = -val;
905 /*
906 * If not starting on a word boundary, deal with the first
907 * (partial) word.
908 */
909 if (bit) {
910 /*
911 * Compute first bit not examined.
912 */
50e6e3c2 913 lastbit = min(bit + len, XFS_NBWORD);
2ceff9ce
DC
914 /*
915 * Mask of relevant bits.
916 */
917 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
918 /*
919 * Compute difference between actual and desired value.
920 */
93b4decb 921 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 922 if ((wdiff = (incore ^ val) & mask)) {
2ceff9ce
DC
923 /*
924 * Different, compute first wrong bit and return.
925 */
6742ada6 926 i = xfs_lowbit32(wdiff) - bit;
2ceff9ce
DC
927 *new = start + i;
928 *stat = 0;
929 return 0;
930 }
931 i = lastbit - bit;
2bd0ea18 932 /*
2ceff9ce
DC
933 * Go on to next block if that's where the next word is
934 * and we need the next word.
2bd0ea18 935 */
18b4102a 936 if (++word == mp->m_blockwsize && i < len) {
2ceff9ce
DC
937 /*
938 * If done with this block, get the next one.
939 */
ae391218
DW
940 error = xfs_rtbitmap_read_buf(args, ++block);
941 if (error)
2ceff9ce 942 return error;
c1f9bc4b 943
2ceff9ce 944 word = 0;
2ceff9ce
DC
945 }
946 } else {
947 /*
948 * Starting on a word boundary, no partial word.
949 */
950 i = 0;
951 }
952 /*
953 * Loop over whole words in buffers. When we use up one buffer
954 * we move on to the next one.
955 */
956 while (len - i >= XFS_NBWORD) {
957 /*
958 * Compute difference between actual and desired value.
959 */
93b4decb 960 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 961 if ((wdiff = incore ^ val)) {
2ceff9ce
DC
962 /*
963 * Different, compute first wrong bit and return.
964 */
6742ada6 965 i += xfs_lowbit32(wdiff);
2ceff9ce
DC
966 *new = start + i;
967 *stat = 0;
968 return 0;
969 }
970 i += XFS_NBWORD;
971 /*
972 * Go on to next block if that's where the next word is
973 * and we need the next word.
974 */
18b4102a 975 if (++word == mp->m_blockwsize && i < len) {
2ceff9ce
DC
976 /*
977 * If done with this block, get the next one.
978 */
ae391218
DW
979 error = xfs_rtbitmap_read_buf(args, ++block);
980 if (error)
2ceff9ce 981 return error;
c1f9bc4b 982
2ceff9ce 983 word = 0;
2bd0ea18
NS
984 }
985 }
986 /*
2ceff9ce
DC
987 * If not ending on a word boundary, deal with the last
988 * (partial) word.
2bd0ea18 989 */
2ceff9ce
DC
990 if ((lastbit = len - i)) {
991 /*
992 * Mask of relevant bits.
993 */
994 mask = ((xfs_rtword_t)1 << lastbit) - 1;
995 /*
996 * Compute difference between actual and desired value.
997 */
93b4decb 998 incore = xfs_rtbitmap_getword(args, word);
f4a0432b 999 if ((wdiff = (incore ^ val) & mask)) {
2ceff9ce
DC
1000 /*
1001 * Different, compute first wrong bit and return.
1002 */
6742ada6 1003 i += xfs_lowbit32(wdiff);
2ceff9ce
DC
1004 *new = start + i;
1005 *stat = 0;
1006 return 0;
1007 } else
1008 i = len;
1009 }
1010 /*
1011 * Successful, return.
1012 */
2ceff9ce
DC
1013 *new = start + i;
1014 *stat = 1;
2bd0ea18
NS
1015 return 0;
1016}
1017
2ceff9ce
DC
1018#ifdef DEBUG
1019/*
1020 * Check that the given extent (block range) is allocated already.
1021 */
f827e51c 1022STATIC int
2ceff9ce 1023xfs_rtcheck_alloc_range(
f827e51c
DC
1024 struct xfs_rtalloc_args *args,
1025 xfs_rtxnum_t start, /* starting rtext number of extent */
1026 xfs_rtxlen_t len) /* length of extent */
2ceff9ce 1027{
f827e51c
DC
1028 xfs_rtxnum_t new; /* dummy for xfs_rtcheck_range */
1029 int stat;
1030 int error;
2ceff9ce 1031
f827e51c 1032 error = xfs_rtcheck_range(args, start, len, 0, &new, &stat);
2ceff9ce
DC
1033 if (error)
1034 return error;
1035 ASSERT(stat);
1036 return 0;
1037}
1038#else
f827e51c 1039#define xfs_rtcheck_alloc_range(a,b,l) (0)
2ceff9ce 1040#endif
2bd0ea18 1041/*
5000d01d 1042 * Free an extent in the realtime subvolume. Length is expressed in
2bd0ea18
NS
1043 * realtime extents, as is the block number.
1044 */
f827e51c 1045int
2bd0ea18 1046xfs_rtfree_extent(
d27e715c 1047 struct xfs_trans *tp, /* transaction pointer */
55ed4049 1048 struct xfs_rtgroup *rtg,
f827e51c
DC
1049 xfs_rtxnum_t start, /* starting rtext number to free */
1050 xfs_rtxlen_t len) /* length of extent freed */
2bd0ea18 1051{
f827e51c 1052 struct xfs_mount *mp = tp->t_mountp;
41f06ede 1053 struct xfs_inode *rbmip = rtg_bitmap(rtg);
f827e51c
DC
1054 struct xfs_rtalloc_args args = {
1055 .mp = mp,
1056 .tp = tp,
55ed4049 1057 .rtg = rtg,
f827e51c
DC
1058 };
1059 int error;
f827e51c 1060 struct timespec64 atime;
a2ceac1f 1061
55ed4049
CH
1062 ASSERT(rbmip->i_itemp != NULL);
1063 xfs_assert_ilocked(rbmip, XFS_ILOCK_EXCL);
a2ceac1f 1064
e200799d
DW
1065 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_FREE_EXTENT))
1066 return -EIO;
1067
f827e51c 1068 error = xfs_rtcheck_alloc_range(&args, start, len);
2ceff9ce
DC
1069 if (error)
1070 return error;
2bd0ea18 1071
2bd0ea18
NS
1072 /*
1073 * Free the range of realtime blocks.
1074 */
52273f22
OS
1075 error = xfs_rtfree_range(&args, start, len);
1076 if (error)
1077 goto out;
1078
2bd0ea18
NS
1079 /*
1080 * Mark more blocks free in the superblock.
1081 */
1082 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
9f09e4e0 1083
2bd0ea18
NS
1084 /*
1085 * If we've now freed all the blocks, reset the file sequence
9f09e4e0 1086 * number to 0 for pre-RTG file systems.
2bd0ea18 1087 */
9f09e4e0
CH
1088 if (!xfs_has_rtgroups(mp) &&
1089 tp->t_frextents_delta + mp->m_sb.sb_frextents ==
2bd0ea18 1090 mp->m_sb.sb_rextents) {
55ed4049
CH
1091 if (!(rbmip->i_diflags & XFS_DIFLAG_NEWRTBM))
1092 rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;
bb16db6a 1093
55ed4049 1094 atime = inode_get_atime(VFS_I(rbmip));
bb16db6a 1095 atime.tv_sec = 0;
55ed4049
CH
1096 inode_set_atime_to_ts(VFS_I(rbmip), atime);
1097 xfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE);
2bd0ea18 1098 }
52273f22
OS
1099 error = 0;
1100out:
1101 xfs_rtbuf_cache_relse(&args);
1102 return error;
2bd0ea18 1103}
0b10a7f4 1104
4dbd5762
DW
1105/*
1106 * Free some blocks in the realtime subvolume. rtbno and rtlen are in units of
1107 * rt blocks, not rt extents; must be aligned to the rt extent size; and rtlen
1108 * cannot exceed XFS_MAX_BMBT_EXTLEN.
1109 */
1110int
1111xfs_rtfree_blocks(
1112 struct xfs_trans *tp,
55ed4049 1113 struct xfs_rtgroup *rtg,
4dbd5762
DW
1114 xfs_fsblock_t rtbno,
1115 xfs_filblks_t rtlen)
1116{
1117 struct xfs_mount *mp = tp->t_mountp;
4dbd5762 1118 xfs_extlen_t mod;
84daa9bd 1119 int error;
4dbd5762 1120
611ad47e 1121 ASSERT(!xfs_has_zoned(mp));
4dbd5762
DW
1122 ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN);
1123
7901a592 1124 mod = xfs_blen_to_rtxoff(mp, rtlen);
4dbd5762
DW
1125 if (mod) {
1126 ASSERT(mod == 0);
1127 return -EIO;
1128 }
1129
325a7bbf 1130 mod = xfs_rtb_to_rtxoff(mp, rtbno);
4dbd5762
DW
1131 if (mod) {
1132 ASSERT(mod == 0);
1133 return -EIO;
1134 }
1135
84daa9bd 1136 error = xfs_rtfree_extent(tp, rtg, xfs_rtb_to_rtx(mp, rtbno),
55ed4049 1137 xfs_extlen_to_rtxlen(mp, rtlen));
84daa9bd
DW
1138 if (error)
1139 return error;
1140
1141 if (xfs_has_rtgroups(mp))
1142 xfs_extent_busy_insert(tp, rtg_group(rtg),
1143 xfs_rtb_to_rgbno(mp, rtbno), rtlen, 0);
1144
1145 return 0;
4dbd5762
DW
1146}
1147
0b10a7f4
DW
1148/* Find all the free records within a given range. */
1149int
1150xfs_rtalloc_query_range(
55ed4049 1151 struct xfs_rtgroup *rtg,
0b10a7f4 1152 struct xfs_trans *tp,
f7d5200c
CH
1153 xfs_rtxnum_t start,
1154 xfs_rtxnum_t end,
0b10a7f4
DW
1155 xfs_rtalloc_query_range_fn fn,
1156 void *priv)
1157{
55ed4049 1158 struct xfs_mount *mp = rtg_mount(rtg);
f827e51c 1159 struct xfs_rtalloc_args args = {
55ed4049 1160 .rtg = rtg,
f827e51c
DC
1161 .mp = mp,
1162 .tp = tp,
1163 };
0b10a7f4
DW
1164 int error = 0;
1165
f7d5200c 1166 if (start > end)
0b10a7f4 1167 return -EINVAL;
55ed4049 1168 if (start == end || start >= rtg->rtg_extents)
0b10a7f4 1169 return 0;
9eb4f400 1170
55ed4049 1171 end = min(end, rtg->rtg_extents - 1);
0b10a7f4 1172
611ad47e
CH
1173 if (xfs_has_zoned(mp))
1174 return -EINVAL;
1175
0b10a7f4 1176 /* Iterate the bitmap, looking for discrepancies. */
f7d5200c
CH
1177 while (start <= end) {
1178 struct xfs_rtalloc_rec rec;
1179 int is_free;
1180 xfs_rtxnum_t rtend;
1181
0b10a7f4 1182 /* Is the first block free? */
f7d5200c 1183 error = xfs_rtcheck_range(&args, start, 1, 1, &rtend,
0b10a7f4
DW
1184 &is_free);
1185 if (error)
1186 break;
1187
1188 /* How long does the extent go for? */
f7d5200c 1189 error = xfs_rtfind_forw(&args, start, end, &rtend);
0b10a7f4
DW
1190 if (error)
1191 break;
1192
1193 if (is_free) {
f7d5200c
CH
1194 rec.ar_startext = start;
1195 rec.ar_extcount = rtend - start + 1;
0b10a7f4 1196
55ed4049 1197 error = fn(rtg, tp, &rec, priv);
0b10a7f4
DW
1198 if (error)
1199 break;
1200 }
1201
f7d5200c 1202 start = rtend + 1;
0b10a7f4
DW
1203 }
1204
52273f22 1205 xfs_rtbuf_cache_relse(&args);
0b10a7f4
DW
1206 return error;
1207}
1208
1209/* Find all the free records. */
1210int
1211xfs_rtalloc_query_all(
55ed4049 1212 struct xfs_rtgroup *rtg,
0b10a7f4
DW
1213 struct xfs_trans *tp,
1214 xfs_rtalloc_query_range_fn fn,
1215 void *priv)
1216{
55ed4049 1217 return xfs_rtalloc_query_range(rtg, tp, 0, rtg->rtg_extents - 1, fn,
f7d5200c 1218 priv);
0b10a7f4 1219}
9bef6258 1220
221b1ddc
DW
1221/* Is the given extent all free? */
1222int
1223xfs_rtalloc_extent_is_free(
55ed4049 1224 struct xfs_rtgroup *rtg,
221b1ddc 1225 struct xfs_trans *tp,
817e9237 1226 xfs_rtxnum_t start,
73b5e770 1227 xfs_rtxlen_t len,
221b1ddc
DW
1228 bool *is_free)
1229{
f827e51c 1230 struct xfs_rtalloc_args args = {
55ed4049
CH
1231 .mp = rtg_mount(rtg),
1232 .rtg = rtg,
f827e51c
DC
1233 .tp = tp,
1234 };
817e9237 1235 xfs_rtxnum_t end;
221b1ddc
DW
1236 int matches;
1237 int error;
1238
f827e51c 1239 error = xfs_rtcheck_range(&args, start, len, 1, &end, &matches);
52273f22 1240 xfs_rtbuf_cache_relse(&args);
221b1ddc
DW
1241 if (error)
1242 return error;
1243
1244 *is_free = matches;
1245 return 0;
1246}
3789ac00 1247
06fb4ab2
DW
1248/* Compute the number of rt extents tracked by a single bitmap block. */
1249xfs_rtxnum_t
1250xfs_rtbitmap_rtx_per_rbmblock(
1251 struct xfs_mount *mp)
1252{
1253 unsigned int rbmblock_bytes = mp->m_sb.sb_blocksize;
1254
1255 if (xfs_has_rtgroups(mp))
1256 rbmblock_bytes -= sizeof(struct xfs_rtbuf_blkinfo);
1257
1258 return rbmblock_bytes * NBBY;
1259}
1260
3789ac00
DW
1261/*
1262 * Compute the number of rtbitmap blocks needed to track the given number of rt
1263 * extents.
1264 */
1265xfs_filblks_t
b3d80952 1266xfs_rtbitmap_blockcount_len(
3789ac00
DW
1267 struct xfs_mount *mp,
1268 xfs_rtbxlen_t rtextents)
1269{
611ad47e
CH
1270 if (xfs_has_zoned(mp))
1271 return 0;
06fb4ab2 1272 return howmany_64(rtextents, xfs_rtbitmap_rtx_per_rbmblock(mp));
3789ac00
DW
1273}
1274
1278e817
DW
1275/* How many rt extents does each rtbitmap file track? */
1276static inline xfs_rtbxlen_t
1277xfs_rtbitmap_bitcount(
1278 struct xfs_mount *mp)
1279{
1280 if (!mp->m_sb.sb_rextents)
1281 return 0;
1282
1283 /* rtgroup size can be nonzero even if rextents is zero */
1284 if (xfs_has_rtgroups(mp))
1285 return mp->m_sb.sb_rgextents;
1286
1287 return mp->m_sb.sb_rextents;
1288}
1289
b3d80952
CH
1290/*
1291 * Compute the number of rtbitmap blocks used for a given file system.
1292 */
1293xfs_filblks_t
1294xfs_rtbitmap_blockcount(
1295 struct xfs_mount *mp)
1296{
1278e817 1297 return xfs_rtbitmap_blockcount_len(mp, xfs_rtbitmap_bitcount(mp));
b3d80952
CH
1298}
1299
3241cd2c
CH
1300/*
1301 * Compute the geometry of the rtsummary file needed to track the given rt
1302 * space.
1303 */
75805b29
DW
1304xfs_filblks_t
1305xfs_rtsummary_blockcount(
1306 struct xfs_mount *mp,
3241cd2c 1307 unsigned int *rsumlevels)
75805b29 1308{
06fb4ab2 1309 xfs_rtbxlen_t rextents = xfs_rtbitmap_bitcount(mp);
75805b29
DW
1310 unsigned long long rsumwords;
1311
611ad47e
CH
1312 if (xfs_has_zoned(mp)) {
1313 *rsumlevels = 0;
1314 return 0;
1315 }
1316
06fb4ab2
DW
1317 *rsumlevels = xfs_compute_rextslog(rextents) + 1;
1318 rsumwords = xfs_rtbitmap_blockcount_len(mp, rextents) * (*rsumlevels);
1319 return howmany_64(rsumwords, mp->m_blockwsize);
75805b29
DW
1320}
1321
f666752a
CH
1322static int
1323xfs_rtfile_alloc_blocks(
1324 struct xfs_inode *ip,
1325 xfs_fileoff_t offset_fsb,
1326 xfs_filblks_t count_fsb,
1327 struct xfs_bmbt_irec *map)
1328{
1329 struct xfs_mount *mp = ip->i_mount;
1330 struct xfs_trans *tp;
1331 int nmap = 1;
1332 int error;
1333
1334 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc,
1335 XFS_GROWFSRT_SPACE_RES(mp, count_fsb), 0, 0, &tp);
1336 if (error)
1337 return error;
1338
1339 xfs_ilock(ip, XFS_ILOCK_EXCL);
1340 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1341
1342 error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK,
1343 XFS_IEXT_ADD_NOSPLIT_CNT);
1344 if (error)
1345 goto out_trans_cancel;
1346
1347 error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
1348 XFS_BMAPI_METADATA, 0, map, &nmap);
1349 if (error)
1350 goto out_trans_cancel;
1351
1352 return xfs_trans_commit(tp);
1353
1354out_trans_cancel:
1355 xfs_trans_cancel(tp);
1356 return error;
1357}
1358
1359/* Get a buffer for the block. */
1360static int
1361xfs_rtfile_initialize_block(
55ed4049
CH
1362 struct xfs_rtgroup *rtg,
1363 enum xfs_rtg_inodes type,
f666752a
CH
1364 xfs_fsblock_t fsbno,
1365 void *data)
1366{
55ed4049
CH
1367 struct xfs_mount *mp = rtg_mount(rtg);
1368 struct xfs_inode *ip = rtg->rtg_inodes[type];
f666752a
CH
1369 struct xfs_trans *tp;
1370 struct xfs_buf *bp;
06fb4ab2 1371 void *bufdata;
f666752a
CH
1372 const size_t copylen = mp->m_blockwsize << XFS_WORDLOG;
1373 enum xfs_blft buf_type;
1374 int error;
1375
55ed4049
CH
1376 if (type == XFS_RTGI_BITMAP)
1377 buf_type = XFS_BLFT_RTBITMAP_BUF;
1378 else if (type == XFS_RTGI_SUMMARY)
f666752a
CH
1379 buf_type = XFS_BLFT_RTSUMMARY_BUF;
1380 else
55ed4049 1381 return -EINVAL;
f666752a
CH
1382
1383 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero, 0, 0, 0, &tp);
1384 if (error)
1385 return error;
1386 xfs_ilock(ip, XFS_ILOCK_EXCL);
1387 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1388
1389 error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
1390 XFS_FSB_TO_DADDR(mp, fsbno), mp->m_bsize, 0, &bp);
1391 if (error) {
1392 xfs_trans_cancel(tp);
1393 return error;
1394 }
06fb4ab2 1395 bufdata = bp->b_addr;
f666752a
CH
1396
1397 xfs_trans_buf_set_type(tp, bp, buf_type);
06fb4ab2
DW
1398 bp->b_ops = xfs_rtblock_ops(mp, type);
1399
1400 if (xfs_has_rtgroups(mp)) {
1401 struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
1402
1403 if (type == XFS_RTGI_BITMAP)
1404 hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC);
1405 else
1406 hdr->rt_magic = cpu_to_be32(XFS_RTSUMMARY_MAGIC);
1407 hdr->rt_owner = cpu_to_be64(ip->i_ino);
1408 hdr->rt_blkno = cpu_to_be64(XFS_FSB_TO_DADDR(mp, fsbno));
1409 hdr->rt_lsn = 0;
1410 uuid_copy(&hdr->rt_uuid, &mp->m_sb.sb_meta_uuid);
1411
1412 bufdata += sizeof(*hdr);
1413 }
1414
f666752a 1415 if (data)
06fb4ab2 1416 memcpy(bufdata, data, copylen);
f666752a 1417 else
06fb4ab2 1418 memset(bufdata, 0, copylen);
f666752a
CH
1419 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
1420 return xfs_trans_commit(tp);
1421}
1422
1423/*
1424 * Allocate space to the bitmap or summary file, and zero it, for growfs.
1425 * @data must be a contiguous buffer large enough to fill all blocks in the
1426 * file; or NULL to initialize the contents to zeroes.
1427 */
1428int
1429xfs_rtfile_initialize_blocks(
55ed4049
CH
1430 struct xfs_rtgroup *rtg,
1431 enum xfs_rtg_inodes type,
f666752a
CH
1432 xfs_fileoff_t offset_fsb, /* offset to start from */
1433 xfs_fileoff_t end_fsb, /* offset to allocate to */
1434 void *data) /* data to fill the blocks */
1435{
55ed4049 1436 struct xfs_mount *mp = rtg_mount(rtg);
f666752a
CH
1437 const size_t copylen = mp->m_blockwsize << XFS_WORDLOG;
1438
1439 while (offset_fsb < end_fsb) {
1440 struct xfs_bmbt_irec map;
1441 xfs_filblks_t i;
1442 int error;
1443
55ed4049
CH
1444 error = xfs_rtfile_alloc_blocks(rtg->rtg_inodes[type],
1445 offset_fsb, end_fsb - offset_fsb, &map);
f666752a
CH
1446 if (error)
1447 return error;
1448
1449 /*
1450 * Now we need to clear the allocated blocks.
1451 *
1452 * Do this one block per transaction, to keep it simple.
1453 */
1454 for (i = 0; i < map.br_blockcount; i++) {
55ed4049 1455 error = xfs_rtfile_initialize_block(rtg, type,
f666752a
CH
1456 map.br_startblock + i, data);
1457 if (error)
1458 return error;
1459 if (data)
1460 data += copylen;
1461 }
1462
1463 offset_fsb = map.br_startoff + map.br_blockcount;
1464 }
1465
1466 return 0;
1467}
884acdc4
CH
1468
1469int
1470xfs_rtbitmap_create(
1471 struct xfs_rtgroup *rtg,
1472 struct xfs_inode *ip,
1473 struct xfs_trans *tp,
1474 bool init)
1475{
1476 struct xfs_mount *mp = rtg_mount(rtg);
1477
1478 ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
1479 if (init && !xfs_has_rtgroups(mp)) {
1480 ip->i_diflags |= XFS_DIFLAG_NEWRTBM;
1481 inode_set_atime(VFS_I(ip), 0, 0);
1482 }
1483 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1484 return 0;
1485}
1486
1487int
1488xfs_rtsummary_create(
1489 struct xfs_rtgroup *rtg,
1490 struct xfs_inode *ip,
1491 struct xfs_trans *tp,
1492 bool init)
1493{
1494 struct xfs_mount *mp = rtg_mount(rtg);
1495
1496 ip->i_disk_size = mp->m_rsumblocks * mp->m_sb.sb_blocksize;
1497 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1498 return 0;
1499}