]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_rtbitmap.c
xfs: simplify xfs_rtbuf_get calling conventions
[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"
b626fb59 16#include "xfs_trans.h"
a8616431 17#include "xfs_rtbitmap.h"
b626fb59 18
5e656dbb 19/*
2ceff9ce 20 * Realtime allocator bitmap functions shared with userspace.
5e656dbb 21 */
2bd0ea18 22
a3d22941
DC
23/*
24 * Real time buffers need verifiers to avoid runtime warnings during IO.
25 * We don't have anything to verify, however, so these are just dummy
26 * operations.
27 */
28static void
29xfs_rtbuf_verify_read(
30 struct xfs_buf *bp)
31{
32 return;
33}
34
35static void
36xfs_rtbuf_verify_write(
37 struct xfs_buf *bp)
38{
39 return;
40}
41
42const struct xfs_buf_ops xfs_rtbuf_ops = {
43 .name = "rtbuf",
44 .verify_read = xfs_rtbuf_verify_read,
45 .verify_write = xfs_rtbuf_verify_write,
46};
47
52273f22
OS
48/* Release cached rt bitmap and summary buffers. */
49void
50xfs_rtbuf_cache_relse(
51 struct xfs_rtalloc_args *args)
52{
53 if (args->rbmbp) {
54 xfs_trans_brelse(args->tp, args->rbmbp);
55 args->rbmbp = NULL;
56 args->rbmoff = NULLFILEOFF;
57 }
58 if (args->sumbp) {
59 xfs_trans_brelse(args->tp, args->sumbp);
60 args->sumbp = NULL;
61 args->sumoff = NULLFILEOFF;
62 }
63}
64
2bd0ea18
NS
65/*
66 * Get a buffer for the bitmap or summary file block specified.
67 * The buffer is returned read and locked.
68 */
50bb67d6 69int
2bd0ea18 70xfs_rtbuf_get(
f827e51c
DC
71 struct xfs_rtalloc_args *args,
72 xfs_fileoff_t block, /* block number in bitmap or summary */
ae391218 73 int issum) /* is summary not bitmap */
2bd0ea18 74{
f827e51c 75 struct xfs_mount *mp = args->mp;
52273f22
OS
76 struct xfs_buf **cbpp; /* cached block buffer */
77 xfs_fileoff_t *coffp; /* cached block number */
f827e51c
DC
78 struct xfs_buf *bp; /* block buffer, result */
79 struct xfs_inode *ip; /* bitmap or summary inode */
80 struct xfs_bmbt_irec map;
52273f22 81 enum xfs_blft type;
f827e51c
DC
82 int nmap = 1;
83 int error;
2bd0ea18 84
52273f22
OS
85 if (issum) {
86 cbpp = &args->sumbp;
87 coffp = &args->sumoff;
88 ip = mp->m_rsumip;
89 type = XFS_BLFT_RTSUMMARY_BUF;
90 } else {
91 cbpp = &args->rbmbp;
92 coffp = &args->rbmoff;
93 ip = mp->m_rbmip;
94 type = XFS_BLFT_RTBITMAP_BUF;
95 }
96
97 /*
98 * If we have a cached buffer, and the block number matches, use that.
99 */
ae391218 100 if (*cbpp && *coffp == block)
52273f22 101 return 0;
ae391218 102
52273f22
OS
103 /*
104 * Otherwise we have to have to get the buffer. If there was an old
105 * one, get rid of it first.
106 */
107 if (*cbpp) {
108 xfs_trans_brelse(args->tp, *cbpp);
109 *cbpp = NULL;
110 }
a2ceac1f 111
f5d22700 112 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
a2ceac1f 113 if (error)
2bd0ea18 114 return error;
a2ceac1f 115
23571db9 116 if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map)))
5e28c9c8
DW
117 return -EFSCORRUPTED;
118
a2ceac1f 119 ASSERT(map.br_startblock != NULLFSBLOCK);
f827e51c 120 error = xfs_trans_read_buf(mp, args->tp, mp->m_ddev_targp,
a2ceac1f 121 XFS_FSB_TO_DADDR(mp, map.br_startblock),
a3d22941 122 mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
a2ceac1f 123 if (error)
2bd0ea18 124 return error;
f36349d8 125
52273f22 126 xfs_trans_buf_set_type(args->tp, bp, type);
ae391218 127 *cbpp = bp;
52273f22 128 *coffp = block;
2bd0ea18
NS
129 return 0;
130}
131
132/*
133 * Searching backward from start to limit, find the first block whose
134 * allocated/free state is different from start's.
135 */
2ceff9ce 136int
2bd0ea18 137xfs_rtfind_back(
f827e51c
DC
138 struct xfs_rtalloc_args *args,
139 xfs_rtxnum_t start, /* starting rtext to look at */
140 xfs_rtxnum_t limit, /* last rtext to look at */
141 xfs_rtxnum_t *rtx) /* out: start rtext found */
2bd0ea18 142{
f827e51c
DC
143 struct xfs_mount *mp = args->mp;
144 int bit; /* bit number in the word */
145 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
146 int error; /* error value */
147 xfs_rtxnum_t firstbit; /* first useful bit in the word */
148 xfs_rtxnum_t i; /* current bit number rel. to start */
149 xfs_rtxnum_t len; /* length of inspected area */
150 xfs_rtword_t mask; /* mask of relevant bits for value */
151 xfs_rtword_t want; /* mask for "good" values */
152 xfs_rtword_t wdiff; /* difference from wanted value */
153 xfs_rtword_t incore;
154 unsigned int word; /* word number in the buffer */
2bd0ea18
NS
155
156 /*
157 * Compute and read in starting bitmap block for starting block.
158 */
75e15fbc 159 block = xfs_rtx_to_rbmblock(mp, start);
ae391218
DW
160 error = xfs_rtbitmap_read_buf(args, block);
161 if (error)
2bd0ea18 162 return error;
c1f9bc4b 163
2bd0ea18
NS
164 /*
165 * Get the first word's index & point to it.
166 */
75e15fbc 167 word = xfs_rtx_to_rbmword(mp, start);
2bd0ea18
NS
168 bit = (int)(start & (XFS_NBWORD - 1));
169 len = start - limit + 1;
170 /*
171 * Compute match value, based on the bit at start: if 1 (free)
172 * then all-ones, else all-zeroes.
173 */
ae391218 174 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 175 want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
2bd0ea18
NS
176 /*
177 * If the starting position is not word-aligned, deal with the
178 * partial word.
179 */
180 if (bit < XFS_NBWORD - 1) {
181 /*
182 * Calculate first (leftmost) bit number to look at,
183 * and mask for all the relevant bits in this word.
184 */
185 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
186 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
187 firstbit;
188 /*
189 * Calculate the difference between the value there
190 * and what we're looking for.
191 */
f4a0432b 192 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
193 /*
194 * Different. Mark where we are and return.
195 */
2bd0ea18 196 i = bit - XFS_RTHIBIT(wdiff);
817e9237 197 *rtx = start - i + 1;
2bd0ea18
NS
198 return 0;
199 }
200 i = bit - firstbit + 1;
201 /*
202 * Go on to previous block if that's where the previous word is
203 * and we need the previous word.
204 */
205 if (--word == -1 && i < len) {
206 /*
207 * If done with this block, get the previous one.
208 */
ae391218
DW
209 error = xfs_rtbitmap_read_buf(args, --block);
210 if (error)
2bd0ea18 211 return error;
c1f9bc4b 212
18b4102a 213 word = mp->m_blockwsize - 1;
2bd0ea18
NS
214 }
215 } else {
216 /*
217 * Starting on a word boundary, no partial word.
218 */
219 i = 0;
220 }
221 /*
222 * Loop over whole words in buffers. When we use up one buffer
223 * we move on to the previous one.
224 */
225 while (len - i >= XFS_NBWORD) {
226 /*
227 * Compute difference between actual and desired value.
228 */
ae391218 229 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 230 if ((wdiff = incore ^ want)) {
2bd0ea18
NS
231 /*
232 * Different, mark where we are and return.
233 */
2bd0ea18 234 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
817e9237 235 *rtx = start - i + 1;
2bd0ea18
NS
236 return 0;
237 }
238 i += XFS_NBWORD;
239 /*
240 * Go on to previous block if that's where the previous word is
241 * and we need the previous word.
242 */
243 if (--word == -1 && i < len) {
244 /*
245 * If done with this block, get the previous one.
246 */
ae391218
DW
247 error = xfs_rtbitmap_read_buf(args, --block);
248 if (error)
2bd0ea18 249 return error;
c1f9bc4b 250
18b4102a 251 word = mp->m_blockwsize - 1;
2bd0ea18
NS
252 }
253 }
254 /*
255 * If not ending on a word boundary, deal with the last
256 * (partial) word.
257 */
258 if (len - i) {
259 /*
260 * Calculate first (leftmost) bit number to look at,
261 * and mask for all the relevant bits in this word.
262 */
263 firstbit = XFS_NBWORD - (len - i);
264 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
265 /*
266 * Compute difference between actual and desired value.
267 */
ae391218 268 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 269 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
270 /*
271 * Different, mark where we are and return.
272 */
2bd0ea18 273 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
817e9237 274 *rtx = start - i + 1;
2bd0ea18
NS
275 return 0;
276 } else
277 i = len;
278 }
279 /*
280 * No match, return that we scanned the whole area.
281 */
817e9237 282 *rtx = start - i + 1;
2bd0ea18
NS
283 return 0;
284}
285
286/*
287 * Searching forward from start to limit, find the first block whose
288 * allocated/free state is different from start's.
289 */
2ceff9ce 290int
2bd0ea18 291xfs_rtfind_forw(
f827e51c
DC
292 struct xfs_rtalloc_args *args,
293 xfs_rtxnum_t start, /* starting rtext to look at */
294 xfs_rtxnum_t limit, /* last rtext to look at */
295 xfs_rtxnum_t *rtx) /* out: start rtext found */
2bd0ea18 296{
f827e51c
DC
297 struct xfs_mount *mp = args->mp;
298 int bit; /* bit number in the word */
299 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
300 int error;
301 xfs_rtxnum_t i; /* current bit number rel. to start */
302 xfs_rtxnum_t lastbit;/* last useful bit in the word */
303 xfs_rtxnum_t len; /* length of inspected area */
304 xfs_rtword_t mask; /* mask of relevant bits for value */
305 xfs_rtword_t want; /* mask for "good" values */
306 xfs_rtword_t wdiff; /* difference from wanted value */
307 xfs_rtword_t incore;
308 unsigned int word; /* word number in the buffer */
2bd0ea18
NS
309
310 /*
311 * Compute and read in starting bitmap block for starting block.
312 */
75e15fbc 313 block = xfs_rtx_to_rbmblock(mp, start);
ae391218
DW
314 error = xfs_rtbitmap_read_buf(args, block);
315 if (error)
2bd0ea18 316 return error;
c1f9bc4b 317
2bd0ea18
NS
318 /*
319 * Get the first word's index & point to it.
320 */
75e15fbc 321 word = xfs_rtx_to_rbmword(mp, start);
2bd0ea18
NS
322 bit = (int)(start & (XFS_NBWORD - 1));
323 len = limit - start + 1;
324 /*
325 * Compute match value, based on the bit at start: if 1 (free)
326 * then all-ones, else all-zeroes.
327 */
ae391218 328 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 329 want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
2bd0ea18
NS
330 /*
331 * If the starting position is not word-aligned, deal with the
332 * partial word.
333 */
334 if (bit) {
335 /*
336 * Calculate last (rightmost) bit number to look at,
337 * and mask for all the relevant bits in this word.
338 */
339 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
340 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
341 /*
342 * Calculate the difference between the value there
343 * and what we're looking for.
344 */
f4a0432b 345 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
346 /*
347 * Different. Mark where we are and return.
348 */
2bd0ea18 349 i = XFS_RTLOBIT(wdiff) - bit;
817e9237 350 *rtx = start + i - 1;
2bd0ea18
NS
351 return 0;
352 }
353 i = lastbit - bit;
354 /*
355 * Go on to next block if that's where the next word is
356 * and we need the next word.
357 */
18b4102a 358 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
359 /*
360 * If done with this block, get the previous one.
361 */
ae391218
DW
362 error = xfs_rtbitmap_read_buf(args, ++block);
363 if (error)
2bd0ea18 364 return error;
c1f9bc4b 365
2bd0ea18 366 word = 0;
2bd0ea18
NS
367 }
368 } else {
369 /*
370 * Starting on a word boundary, no partial word.
371 */
372 i = 0;
373 }
374 /*
375 * Loop over whole words in buffers. When we use up one buffer
376 * we move on to the next one.
377 */
378 while (len - i >= XFS_NBWORD) {
379 /*
380 * Compute difference between actual and desired value.
381 */
ae391218 382 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 383 if ((wdiff = incore ^ want)) {
2bd0ea18
NS
384 /*
385 * Different, mark where we are and return.
386 */
2bd0ea18 387 i += XFS_RTLOBIT(wdiff);
817e9237 388 *rtx = start + i - 1;
2bd0ea18
NS
389 return 0;
390 }
391 i += XFS_NBWORD;
392 /*
393 * Go on to next block if that's where the next word is
394 * and we need the next word.
395 */
18b4102a 396 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
397 /*
398 * If done with this block, get the next one.
399 */
ae391218
DW
400 error = xfs_rtbitmap_read_buf(args, ++block);
401 if (error)
2bd0ea18 402 return error;
c1f9bc4b 403
2bd0ea18 404 word = 0;
2bd0ea18
NS
405 }
406 }
407 /*
408 * If not ending on a word boundary, deal with the last
409 * (partial) word.
410 */
0e266570 411 if ((lastbit = len - i)) {
2bd0ea18
NS
412 /*
413 * Calculate mask for all the relevant bits in this word.
414 */
415 mask = ((xfs_rtword_t)1 << lastbit) - 1;
416 /*
417 * Compute difference between actual and desired value.
418 */
ae391218 419 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 420 if ((wdiff = (incore ^ want) & mask)) {
2bd0ea18
NS
421 /*
422 * Different, mark where we are and return.
423 */
2bd0ea18 424 i += XFS_RTLOBIT(wdiff);
817e9237 425 *rtx = start + i - 1;
2bd0ea18
NS
426 return 0;
427 } else
428 i = len;
429 }
430 /*
431 * No match, return that we scanned the whole area.
432 */
817e9237 433 *rtx = start + i - 1;
2bd0ea18
NS
434 return 0;
435}
436
3d763f98
DW
437/* Log rtsummary counter at @infoword. */
438static inline void
439xfs_trans_log_rtsummary(
440 struct xfs_trans *tp,
441 struct xfs_buf *bp,
442 unsigned int infoword)
443{
444 size_t first, last;
445
446 first = (void *)xfs_rsumblock_infoptr(bp, infoword) - bp->b_addr;
447 last = first + sizeof(xfs_suminfo_t) - 1;
448
449 xfs_trans_log_buf(tp, bp, first, last);
450}
451
2bd0ea18 452/*
5a35bf2c 453 * Read and/or modify the summary information for a given extent size,
2ceff9ce
DC
454 * bitmap block combination.
455 * Keeps track of a current summary block, so we don't keep reading
456 * it from the buffer cache.
5a35bf2c
DC
457 *
458 * Summary information is returned in *sum if specified.
459 * If no delta is specified, returns summary only.
2bd0ea18 460 */
2ceff9ce 461int
5a35bf2c 462xfs_rtmodify_summary_int(
f827e51c
DC
463 struct xfs_rtalloc_args *args,
464 int log, /* log2 of extent size */
465 xfs_fileoff_t bbno, /* bitmap block number */
466 int delta, /* change to make to summary info */
f827e51c 467 xfs_suminfo_t *sum) /* out: summary info for this block */
2bd0ea18 468{
f827e51c 469 struct xfs_mount *mp = args->mp;
f827e51c
DC
470 int error;
471 xfs_fileoff_t sb; /* summary fsblock */
472 xfs_rtsumoff_t so; /* index into the summary file */
473 unsigned int infoword;
2bd0ea18 474
2bd0ea18 475 /*
2ceff9ce 476 * Compute entry number in the summary file.
2bd0ea18 477 */
ccffd2f9 478 so = xfs_rtsumoffs(mp, log, bbno);
2bd0ea18 479 /*
2ceff9ce 480 * Compute the block number in the summary file.
2bd0ea18 481 */
ccffd2f9 482 sb = xfs_rtsumoffs_to_block(mp, so);
52273f22 483
ae391218 484 error = xfs_rtsummary_read_buf(args, sb);
52273f22
OS
485 if (error)
486 return error;
487
2bd0ea18 488 /*
5a35bf2c 489 * Point to the summary information, modify/log it, and/or copy it out.
2bd0ea18 490 */
ccffd2f9 491 infoword = xfs_rtsumoffs_to_infoword(mp, so);
5a35bf2c 492 if (delta) {
ae391218
DW
493 xfs_suminfo_t val = xfs_suminfo_add(args->sumbp, infoword,
494 delta);
b16c5a81 495
463b0a60 496 if (mp->m_rsum_cache) {
b16c5a81 497 if (val == 0 && log == mp->m_rsum_cache[bbno])
463b0a60 498 mp->m_rsum_cache[bbno]++;
b16c5a81 499 if (val != 0 && log < mp->m_rsum_cache[bbno])
463b0a60
OS
500 mp->m_rsum_cache[bbno] = log;
501 }
ae391218 502 xfs_trans_log_rtsummary(args->tp, args->sumbp, infoword);
b16c5a81
DW
503 if (sum)
504 *sum = val;
505 } else if (sum) {
ae391218 506 *sum = xfs_suminfo_get(args->sumbp, infoword);
5a35bf2c 507 }
2ceff9ce 508 return 0;
2bd0ea18
NS
509}
510
5a35bf2c
DC
511int
512xfs_rtmodify_summary(
f827e51c
DC
513 struct xfs_rtalloc_args *args,
514 int log, /* log2 of extent size */
515 xfs_fileoff_t bbno, /* bitmap block number */
52273f22 516 int delta) /* in/out: summary block number */
5a35bf2c 517{
52273f22 518 return xfs_rtmodify_summary_int(args, log, bbno, delta, NULL);
5a35bf2c
DC
519}
520
3d763f98
DW
521/* Log rtbitmap block from the word @from to the byte before @next. */
522static inline void
523xfs_trans_log_rtbitmap(
524 struct xfs_trans *tp,
525 struct xfs_buf *bp,
526 unsigned int from,
527 unsigned int next)
528{
529 size_t first, last;
530
531 first = (void *)xfs_rbmblock_wordptr(bp, from) - bp->b_addr;
532 last = ((void *)xfs_rbmblock_wordptr(bp, next) - 1) - bp->b_addr;
533
534 xfs_trans_log_buf(tp, bp, first, last);
535}
536
2bd0ea18
NS
537/*
538 * Set the given range of bitmap bits to the given value.
539 * Do whatever I/O and logging is required.
540 */
2ceff9ce 541int
2bd0ea18 542xfs_rtmodify_range(
f827e51c
DC
543 struct xfs_rtalloc_args *args,
544 xfs_rtxnum_t start, /* starting rtext to modify */
545 xfs_rtxlen_t len, /* length of extent to modify */
546 int val) /* 1 for free, 0 for allocated */
2bd0ea18 547{
f827e51c
DC
548 struct xfs_mount *mp = args->mp;
549 int bit; /* bit number in the word */
550 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
551 int error;
552 int i; /* current bit number rel. to start */
553 int lastbit; /* last useful bit in word */
554 xfs_rtword_t mask; /* mask of relevant bits for value */
555 xfs_rtword_t incore;
556 unsigned int firstword; /* first word used in the buffer */
557 unsigned int word; /* word number in the buffer */
2bd0ea18
NS
558
559 /*
560 * Compute starting bitmap block number.
561 */
75e15fbc 562 block = xfs_rtx_to_rbmblock(mp, start);
2bd0ea18
NS
563 /*
564 * Read the bitmap block, and point to its data.
565 */
ae391218
DW
566 error = xfs_rtbitmap_read_buf(args, block);
567 if (error)
2bd0ea18 568 return error;
c1f9bc4b 569
2bd0ea18
NS
570 /*
571 * Compute the starting word's address, and starting bit.
572 */
3d763f98 573 firstword = word = xfs_rtx_to_rbmword(mp, start);
2bd0ea18
NS
574 bit = (int)(start & (XFS_NBWORD - 1));
575 /*
576 * 0 (allocated) => all zeroes; 1 (free) => all ones.
577 */
578 val = -val;
579 /*
580 * If not starting on a word boundary, deal with the first
581 * (partial) word.
582 */
583 if (bit) {
584 /*
585 * Compute first bit not changed and mask of relevant bits.
586 */
587 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
588 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
589 /*
590 * Set/clear the active bits.
591 */
ae391218 592 incore = xfs_rtbitmap_getword(args->rbmbp, word);
2bd0ea18 593 if (val)
f4a0432b 594 incore |= mask;
2bd0ea18 595 else
f4a0432b 596 incore &= ~mask;
ae391218 597 xfs_rtbitmap_setword(args->rbmbp, word, incore);
2bd0ea18
NS
598 i = lastbit - bit;
599 /*
600 * Go on to the next block if that's where the next word is
601 * and we need the next word.
602 */
18b4102a 603 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
604 /*
605 * Log the changed part of this block.
606 * Get the next one.
607 */
ae391218 608 xfs_trans_log_rtbitmap(args->tp, args->rbmbp, firstword,
f827e51c 609 word);
ae391218
DW
610 error = xfs_rtbitmap_read_buf(args, ++block);
611 if (error)
2bd0ea18 612 return error;
c1f9bc4b 613
3d763f98 614 firstword = word = 0;
2bd0ea18
NS
615 }
616 } else {
617 /*
618 * Starting on a word boundary, no partial word.
619 */
620 i = 0;
621 }
622 /*
623 * Loop over whole words in buffers. When we use up one buffer
624 * we move on to the next one.
625 */
626 while (len - i >= XFS_NBWORD) {
627 /*
628 * Set the word value correctly.
629 */
ae391218 630 xfs_rtbitmap_setword(args->rbmbp, word, val);
2bd0ea18
NS
631 i += XFS_NBWORD;
632 /*
633 * Go on to the next block if that's where the next word is
634 * and we need the next word.
635 */
18b4102a 636 if (++word == mp->m_blockwsize && i < len) {
2bd0ea18
NS
637 /*
638 * Log the changed part of this block.
639 * Get the next one.
640 */
ae391218 641 xfs_trans_log_rtbitmap(args->tp, args->rbmbp, firstword,
f827e51c 642 word);
ae391218 643 error = xfs_rtbitmap_read_buf(args, ++block);
f827e51c 644 if (error)
2bd0ea18 645 return error;
c1f9bc4b 646
3d763f98 647 firstword = word = 0;
2bd0ea18
NS
648 }
649 }
650 /*
651 * If not ending on a word boundary, deal with the last
652 * (partial) word.
653 */
0e266570 654 if ((lastbit = len - i)) {
2bd0ea18
NS
655 /*
656 * Compute a mask of relevant bits.
657 */
2bd0ea18
NS
658 mask = ((xfs_rtword_t)1 << lastbit) - 1;
659 /*
660 * Set/clear the active bits.
661 */
ae391218 662 incore = xfs_rtbitmap_getword(args->rbmbp, word);
2bd0ea18 663 if (val)
f4a0432b 664 incore |= mask;
2bd0ea18 665 else
f4a0432b 666 incore &= ~mask;
ae391218 667 xfs_rtbitmap_setword(args->rbmbp, word, incore);
3d763f98 668 word++;
2bd0ea18
NS
669 }
670 /*
671 * Log any remaining changed bytes.
672 */
f4a0432b 673 if (word > firstword)
ae391218 674 xfs_trans_log_rtbitmap(args->tp, args->rbmbp, firstword, word);
2bd0ea18
NS
675 return 0;
676}
677
678/*
2ceff9ce
DC
679 * Mark an extent specified by start and len freed.
680 * Updates all the summary information as well as the bitmap.
2bd0ea18 681 */
2ceff9ce
DC
682int
683xfs_rtfree_range(
f827e51c
DC
684 struct xfs_rtalloc_args *args,
685 xfs_rtxnum_t start, /* starting rtext to free */
52273f22 686 xfs_rtxlen_t len) /* in/out: summary block number */
2bd0ea18 687{
f827e51c
DC
688 struct xfs_mount *mp = args->mp;
689 xfs_rtxnum_t end; /* end of the freed extent */
690 int error; /* error value */
691 xfs_rtxnum_t postblock; /* first rtext freed > end */
692 xfs_rtxnum_t preblock; /* first rtext freed < start */
2bd0ea18 693
2ceff9ce 694 end = start + len - 1;
2bd0ea18 695 /*
2ceff9ce 696 * Modify the bitmap to mark this extent freed.
2bd0ea18 697 */
f827e51c 698 error = xfs_rtmodify_range(args, start, len, 1);
2ceff9ce
DC
699 if (error) {
700 return error;
701 }
2bd0ea18 702 /*
2ceff9ce
DC
703 * Assume we're freeing out of the middle of an allocated extent.
704 * We need to find the beginning and end of the extent so we can
705 * properly update the summary.
2bd0ea18 706 */
f827e51c 707 error = xfs_rtfind_back(args, start, 0, &preblock);
2ceff9ce
DC
708 if (error) {
709 return error;
710 }
2bd0ea18 711 /*
2ceff9ce 712 * Find the next allocated block (end of allocated extent).
2bd0ea18 713 */
f827e51c 714 error = xfs_rtfind_forw(args, end, mp->m_sb.sb_rextents - 1,
52273f22 715 &postblock);
2ceff9ce
DC
716 if (error)
717 return error;
2bd0ea18 718 /*
2ceff9ce
DC
719 * If there are blocks not being freed at the front of the
720 * old extent, add summary data for them to be allocated.
2bd0ea18 721 */
2ceff9ce 722 if (preblock < start) {
f827e51c 723 error = xfs_rtmodify_summary(args,
52273f22
OS
724 XFS_RTBLOCKLOG(start - preblock),
725 xfs_rtx_to_rbmblock(mp, preblock), -1);
2bd0ea18
NS
726 if (error) {
727 return error;
728 }
2ceff9ce
DC
729 }
730 /*
731 * If there are blocks not being freed at the end of the
732 * old extent, add summary data for them to be allocated.
733 */
734 if (postblock > end) {
f827e51c 735 error = xfs_rtmodify_summary(args,
52273f22
OS
736 XFS_RTBLOCKLOG(postblock - end),
737 xfs_rtx_to_rbmblock(mp, end + 1), -1);
2ceff9ce
DC
738 if (error) {
739 return error;
740 }
741 }
742 /*
743 * Increment the summary information corresponding to the entire
744 * (new) free extent.
745 */
52273f22
OS
746 return xfs_rtmodify_summary(args,
747 XFS_RTBLOCKLOG(postblock + 1 - preblock),
748 xfs_rtx_to_rbmblock(mp, preblock), 1);
2ceff9ce
DC
749}
750
751/*
752 * Check that the given range is either all allocated (val = 0) or
753 * all free (val = 1).
754 */
755int
756xfs_rtcheck_range(
f827e51c
DC
757 struct xfs_rtalloc_args *args,
758 xfs_rtxnum_t start, /* starting rtext number of extent */
759 xfs_rtxlen_t len, /* length of extent */
760 int val, /* 1 for free, 0 for allocated */
761 xfs_rtxnum_t *new, /* out: first rtext not matching */
762 int *stat) /* out: 1 for matches, 0 for not */
2ceff9ce 763{
f827e51c
DC
764 struct xfs_mount *mp = args->mp;
765 int bit; /* bit number in the word */
766 xfs_fileoff_t block; /* bitmap block number */
f827e51c
DC
767 int error;
768 xfs_rtxnum_t i; /* current bit number rel. to start */
769 xfs_rtxnum_t lastbit; /* last useful bit in word */
770 xfs_rtword_t mask; /* mask of relevant bits for value */
771 xfs_rtword_t wdiff; /* difference from wanted value */
772 xfs_rtword_t incore;
773 unsigned int word; /* word number in the buffer */
2ceff9ce
DC
774
775 /*
776 * Compute starting bitmap block number
777 */
75e15fbc 778 block = xfs_rtx_to_rbmblock(mp, start);
2ceff9ce
DC
779 /*
780 * Read the bitmap block.
781 */
ae391218
DW
782 error = xfs_rtbitmap_read_buf(args, block);
783 if (error)
2ceff9ce 784 return error;
c1f9bc4b 785
2ceff9ce
DC
786 /*
787 * Compute the starting word's address, and starting bit.
788 */
75e15fbc 789 word = xfs_rtx_to_rbmword(mp, start);
2ceff9ce
DC
790 bit = (int)(start & (XFS_NBWORD - 1));
791 /*
792 * 0 (allocated) => all zero's; 1 (free) => all one's.
793 */
794 val = -val;
795 /*
796 * If not starting on a word boundary, deal with the first
797 * (partial) word.
798 */
799 if (bit) {
800 /*
801 * Compute first bit not examined.
802 */
803 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
804 /*
805 * Mask of relevant bits.
806 */
807 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
808 /*
809 * Compute difference between actual and desired value.
810 */
ae391218 811 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 812 if ((wdiff = (incore ^ val) & mask)) {
2ceff9ce
DC
813 /*
814 * Different, compute first wrong bit and return.
815 */
2ceff9ce
DC
816 i = XFS_RTLOBIT(wdiff) - bit;
817 *new = start + i;
818 *stat = 0;
819 return 0;
820 }
821 i = lastbit - bit;
2bd0ea18 822 /*
2ceff9ce
DC
823 * Go on to next block if that's where the next word is
824 * and we need the next word.
2bd0ea18 825 */
18b4102a 826 if (++word == mp->m_blockwsize && i < len) {
2ceff9ce
DC
827 /*
828 * If done with this block, get the next one.
829 */
ae391218
DW
830 error = xfs_rtbitmap_read_buf(args, ++block);
831 if (error)
2ceff9ce 832 return error;
c1f9bc4b 833
2ceff9ce 834 word = 0;
2ceff9ce
DC
835 }
836 } else {
837 /*
838 * Starting on a word boundary, no partial word.
839 */
840 i = 0;
841 }
842 /*
843 * Loop over whole words in buffers. When we use up one buffer
844 * we move on to the next one.
845 */
846 while (len - i >= XFS_NBWORD) {
847 /*
848 * Compute difference between actual and desired value.
849 */
ae391218 850 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 851 if ((wdiff = incore ^ val)) {
2ceff9ce
DC
852 /*
853 * Different, compute first wrong bit and return.
854 */
2ceff9ce
DC
855 i += XFS_RTLOBIT(wdiff);
856 *new = start + i;
857 *stat = 0;
858 return 0;
859 }
860 i += XFS_NBWORD;
861 /*
862 * Go on to next block if that's where the next word is
863 * and we need the next word.
864 */
18b4102a 865 if (++word == mp->m_blockwsize && i < len) {
2ceff9ce
DC
866 /*
867 * If done with this block, get the next one.
868 */
ae391218
DW
869 error = xfs_rtbitmap_read_buf(args, ++block);
870 if (error)
2ceff9ce 871 return error;
c1f9bc4b 872
2ceff9ce 873 word = 0;
2bd0ea18
NS
874 }
875 }
876 /*
2ceff9ce
DC
877 * If not ending on a word boundary, deal with the last
878 * (partial) word.
2bd0ea18 879 */
2ceff9ce
DC
880 if ((lastbit = len - i)) {
881 /*
882 * Mask of relevant bits.
883 */
884 mask = ((xfs_rtword_t)1 << lastbit) - 1;
885 /*
886 * Compute difference between actual and desired value.
887 */
ae391218 888 incore = xfs_rtbitmap_getword(args->rbmbp, word);
f4a0432b 889 if ((wdiff = (incore ^ val) & mask)) {
2ceff9ce
DC
890 /*
891 * Different, compute first wrong bit and return.
892 */
2ceff9ce
DC
893 i += XFS_RTLOBIT(wdiff);
894 *new = start + i;
895 *stat = 0;
896 return 0;
897 } else
898 i = len;
899 }
900 /*
901 * Successful, return.
902 */
2ceff9ce
DC
903 *new = start + i;
904 *stat = 1;
2bd0ea18
NS
905 return 0;
906}
907
2ceff9ce
DC
908#ifdef DEBUG
909/*
910 * Check that the given extent (block range) is allocated already.
911 */
f827e51c 912STATIC int
2ceff9ce 913xfs_rtcheck_alloc_range(
f827e51c
DC
914 struct xfs_rtalloc_args *args,
915 xfs_rtxnum_t start, /* starting rtext number of extent */
916 xfs_rtxlen_t len) /* length of extent */
2ceff9ce 917{
f827e51c
DC
918 xfs_rtxnum_t new; /* dummy for xfs_rtcheck_range */
919 int stat;
920 int error;
2ceff9ce 921
f827e51c 922 error = xfs_rtcheck_range(args, start, len, 0, &new, &stat);
2ceff9ce
DC
923 if (error)
924 return error;
925 ASSERT(stat);
926 return 0;
927}
928#else
f827e51c 929#define xfs_rtcheck_alloc_range(a,b,l) (0)
2ceff9ce 930#endif
2bd0ea18 931/*
5000d01d 932 * Free an extent in the realtime subvolume. Length is expressed in
2bd0ea18
NS
933 * realtime extents, as is the block number.
934 */
f827e51c 935int
2bd0ea18 936xfs_rtfree_extent(
f827e51c
DC
937 xfs_trans_t *tp, /* transaction pointer */
938 xfs_rtxnum_t start, /* starting rtext number to free */
939 xfs_rtxlen_t len) /* length of extent freed */
2bd0ea18 940{
f827e51c
DC
941 struct xfs_mount *mp = tp->t_mountp;
942 struct xfs_rtalloc_args args = {
943 .mp = mp,
944 .tp = tp,
945 };
946 int error;
f827e51c 947 struct timespec64 atime;
a2ceac1f
DC
948
949 ASSERT(mp->m_rbmip->i_itemp != NULL);
950 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
951
f827e51c 952 error = xfs_rtcheck_alloc_range(&args, start, len);
2ceff9ce
DC
953 if (error)
954 return error;
2bd0ea18 955
2bd0ea18
NS
956 /*
957 * Free the range of realtime blocks.
958 */
52273f22
OS
959 error = xfs_rtfree_range(&args, start, len);
960 if (error)
961 goto out;
962
2bd0ea18
NS
963 /*
964 * Mark more blocks free in the superblock.
965 */
966 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
967 /*
968 * If we've now freed all the blocks, reset the file sequence
969 * number to 0.
970 */
971 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
972 mp->m_sb.sb_rextents) {
4350eee7
CH
973 if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM))
974 mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;
bb16db6a
JL
975
976 atime = inode_get_atime(VFS_I(mp->m_rbmip));
977 atime.tv_sec = 0;
978 inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime);
a2ceac1f 979 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
2bd0ea18 980 }
52273f22
OS
981 error = 0;
982out:
983 xfs_rtbuf_cache_relse(&args);
984 return error;
2bd0ea18 985}
0b10a7f4 986
4dbd5762
DW
987/*
988 * Free some blocks in the realtime subvolume. rtbno and rtlen are in units of
989 * rt blocks, not rt extents; must be aligned to the rt extent size; and rtlen
990 * cannot exceed XFS_MAX_BMBT_EXTLEN.
991 */
992int
993xfs_rtfree_blocks(
994 struct xfs_trans *tp,
995 xfs_fsblock_t rtbno,
996 xfs_filblks_t rtlen)
997{
998 struct xfs_mount *mp = tp->t_mountp;
817e9237 999 xfs_rtxnum_t start;
4dbd5762
DW
1000 xfs_filblks_t len;
1001 xfs_extlen_t mod;
1002
1003 ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN);
1004
1dac259c 1005 len = xfs_rtb_to_rtxrem(mp, rtlen, &mod);
4dbd5762
DW
1006 if (mod) {
1007 ASSERT(mod == 0);
1008 return -EIO;
1009 }
1010
1dac259c 1011 start = xfs_rtb_to_rtxrem(mp, rtbno, &mod);
4dbd5762
DW
1012 if (mod) {
1013 ASSERT(mod == 0);
1014 return -EIO;
1015 }
1016
817e9237 1017 return xfs_rtfree_extent(tp, start, len);
4dbd5762
DW
1018}
1019
0b10a7f4
DW
1020/* Find all the free records within a given range. */
1021int
1022xfs_rtalloc_query_range(
90880f92 1023 struct xfs_mount *mp,
0b10a7f4 1024 struct xfs_trans *tp,
9eb4f400
DW
1025 const struct xfs_rtalloc_rec *low_rec,
1026 const struct xfs_rtalloc_rec *high_rec,
0b10a7f4
DW
1027 xfs_rtalloc_query_range_fn fn,
1028 void *priv)
1029{
f827e51c
DC
1030 struct xfs_rtalloc_args args = {
1031 .mp = mp,
1032 .tp = tp,
1033 };
0b10a7f4 1034 struct xfs_rtalloc_rec rec;
817e9237
DW
1035 xfs_rtxnum_t rtstart;
1036 xfs_rtxnum_t rtend;
1037 xfs_rtxnum_t high_key;
0b10a7f4
DW
1038 int is_free;
1039 int error = 0;
1040
858ae338 1041 if (low_rec->ar_startext > high_rec->ar_startext)
0b10a7f4 1042 return -EINVAL;
858ae338
DW
1043 if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1044 low_rec->ar_startext == high_rec->ar_startext)
0b10a7f4 1045 return 0;
9eb4f400
DW
1046
1047 high_key = min(high_rec->ar_startext, mp->m_sb.sb_rextents - 1);
0b10a7f4
DW
1048
1049 /* Iterate the bitmap, looking for discrepancies. */
858ae338 1050 rtstart = low_rec->ar_startext;
9eb4f400 1051 while (rtstart <= high_key) {
0b10a7f4 1052 /* Is the first block free? */
f827e51c 1053 error = xfs_rtcheck_range(&args, rtstart, 1, 1, &rtend,
0b10a7f4
DW
1054 &is_free);
1055 if (error)
1056 break;
1057
1058 /* How long does the extent go for? */
f827e51c 1059 error = xfs_rtfind_forw(&args, rtstart, high_key, &rtend);
0b10a7f4
DW
1060 if (error)
1061 break;
1062
1063 if (is_free) {
858ae338
DW
1064 rec.ar_startext = rtstart;
1065 rec.ar_extcount = rtend - rtstart + 1;
0b10a7f4 1066
90880f92 1067 error = fn(mp, tp, &rec, priv);
0b10a7f4
DW
1068 if (error)
1069 break;
1070 }
1071
0b10a7f4
DW
1072 rtstart = rtend + 1;
1073 }
1074
52273f22 1075 xfs_rtbuf_cache_relse(&args);
0b10a7f4
DW
1076 return error;
1077}
1078
1079/* Find all the free records. */
1080int
1081xfs_rtalloc_query_all(
90880f92 1082 struct xfs_mount *mp,
0b10a7f4
DW
1083 struct xfs_trans *tp,
1084 xfs_rtalloc_query_range_fn fn,
1085 void *priv)
1086{
1087 struct xfs_rtalloc_rec keys[2];
1088
858ae338 1089 keys[0].ar_startext = 0;
90880f92 1090 keys[1].ar_startext = mp->m_sb.sb_rextents - 1;
858ae338 1091 keys[0].ar_extcount = keys[1].ar_extcount = 0;
0b10a7f4 1092
90880f92 1093 return xfs_rtalloc_query_range(mp, tp, &keys[0], &keys[1], fn, priv);
0b10a7f4 1094}
9bef6258 1095
221b1ddc
DW
1096/* Is the given extent all free? */
1097int
1098xfs_rtalloc_extent_is_free(
1099 struct xfs_mount *mp,
1100 struct xfs_trans *tp,
817e9237 1101 xfs_rtxnum_t start,
73b5e770 1102 xfs_rtxlen_t len,
221b1ddc
DW
1103 bool *is_free)
1104{
f827e51c
DC
1105 struct xfs_rtalloc_args args = {
1106 .mp = mp,
1107 .tp = tp,
1108 };
817e9237 1109 xfs_rtxnum_t end;
221b1ddc
DW
1110 int matches;
1111 int error;
1112
f827e51c 1113 error = xfs_rtcheck_range(&args, start, len, 1, &end, &matches);
52273f22 1114 xfs_rtbuf_cache_relse(&args);
221b1ddc
DW
1115 if (error)
1116 return error;
1117
1118 *is_free = matches;
1119 return 0;
1120}
3789ac00
DW
1121
1122/*
1123 * Compute the number of rtbitmap blocks needed to track the given number of rt
1124 * extents.
1125 */
1126xfs_filblks_t
1127xfs_rtbitmap_blockcount(
1128 struct xfs_mount *mp,
1129 xfs_rtbxlen_t rtextents)
1130{
1131 return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize);
1132}
1133
1134/*
1135 * Compute the number of rtbitmap words needed to populate every block of a
1136 * bitmap that is large enough to track the given number of rt extents.
1137 */
1138unsigned long long
1139xfs_rtbitmap_wordcount(
1140 struct xfs_mount *mp,
1141 xfs_rtbxlen_t rtextents)
1142{
1143 xfs_filblks_t blocks;
1144
1145 blocks = xfs_rtbitmap_blockcount(mp, rtextents);
1146 return XFS_FSB_TO_B(mp, blocks) >> XFS_WORDLOG;
1147}
75805b29
DW
1148
1149/* Compute the number of rtsummary blocks needed to track the given rt space. */
1150xfs_filblks_t
1151xfs_rtsummary_blockcount(
1152 struct xfs_mount *mp,
1153 unsigned int rsumlevels,
1154 xfs_extlen_t rbmblocks)
1155{
1156 unsigned long long rsumwords;
1157
1158 rsumwords = (unsigned long long)rsumlevels * rbmblocks;
1159 return XFS_B_TO_FSB(mp, rsumwords << XFS_WORDLOG);
1160}
1161
1162/*
1163 * Compute the number of rtsummary info words needed to populate every block of
1164 * a summary file that is large enough to track the given rt space.
1165 */
1166unsigned long long
1167xfs_rtsummary_wordcount(
1168 struct xfs_mount *mp,
1169 unsigned int rsumlevels,
1170 xfs_extlen_t rbmblocks)
1171{
1172 xfs_filblks_t blocks;
1173
1174 blocks = xfs_rtsummary_blockcount(mp, rsumlevels, rbmblocks);
1175 return XFS_FSB_TO_B(mp, blocks) >> XFS_WORDLOG;
1176}