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