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