1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
6 #include "libxfs_priv.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_inode.h"
16 #include "xfs_trans.h"
17 #include "xfs_rtbitmap.h"
20 * Realtime allocator bitmap functions shared with userspace.
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
29 xfs_rtbuf_verify_read(
36 xfs_rtbuf_verify_write(
42 const struct xfs_buf_ops xfs_rtbuf_ops
= {
44 .verify_read
= xfs_rtbuf_verify_read
,
45 .verify_write
= xfs_rtbuf_verify_write
,
49 * Get a buffer for the bitmap or summary file block specified.
50 * The buffer is returned read and locked.
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 */
60 struct xfs_buf
*bp
; /* block buffer, result */
61 xfs_inode_t
*ip
; /* bitmap or summary inode */
64 int error
; /* error value */
66 ip
= issum
? mp
->m_rsumip
: mp
->m_rbmip
;
68 error
= xfs_bmapi_read(ip
, block
, 1, &map
, &nmap
, 0);
72 if (XFS_IS_CORRUPT(mp
, nmap
== 0 || !xfs_bmap_is_written_extent(&map
)))
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
);
82 xfs_trans_buf_set_type(tp
, bp
, issum
? XFS_BLFT_RTSUMMARY_BUF
83 : XFS_BLFT_RTBITMAP_BUF
);
89 * Searching backward from start to limit, find the first block whose
90 * allocated/free state is different from start's.
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 */
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 */
115 * Compute and read in starting bitmap block for starting block.
117 block
= XFS_BITTOBLOCK(mp
, start
);
118 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
124 * Get the first word's index & point to it.
126 word
= XFS_BITTOWORD(mp
, start
);
128 bit
= (int)(start
& (XFS_NBWORD
- 1));
129 len
= start
- limit
+ 1;
131 * Compute match value, based on the bit at start: if 1 (free)
132 * then all-ones, else all-zeroes.
134 want
= (*b
& ((xfs_rtword_t
)1 << bit
)) ? -1 : 0;
136 * If the starting position is not word-aligned, deal with the
139 if (bit
< XFS_NBWORD
- 1) {
141 * Calculate first (leftmost) bit number to look at,
142 * and mask for all the relevant bits in this word.
144 firstbit
= XFS_RTMAX((xfs_srtblock_t
)(bit
- len
+ 1), 0);
145 mask
= (((xfs_rtword_t
)1 << (bit
- firstbit
+ 1)) - 1) <<
148 * Calculate the difference between the value there
149 * and what we're looking for.
151 if ((wdiff
= (*b
^ want
) & mask
)) {
153 * Different. Mark where we are and return.
155 xfs_trans_brelse(tp
, bp
);
156 i
= bit
- XFS_RTHIBIT(wdiff
);
157 *rtblock
= start
- i
+ 1;
160 i
= bit
- firstbit
+ 1;
162 * Go on to previous block if that's where the previous word is
163 * and we need the previous word.
165 if (--word
== -1 && i
< len
) {
167 * If done with this block, get the previous one.
169 xfs_trans_brelse(tp
, bp
);
170 error
= xfs_rtbuf_get(mp
, tp
, --block
, 0, &bp
);
175 word
= XFS_BLOCKWMASK(mp
);
179 * Go on to the previous word in the buffer.
185 * Starting on a word boundary, no partial word.
190 * Loop over whole words in buffers. When we use up one buffer
191 * we move on to the previous one.
193 while (len
- i
>= XFS_NBWORD
) {
195 * Compute difference between actual and desired value.
197 if ((wdiff
= *b
^ want
)) {
199 * Different, mark where we are and return.
201 xfs_trans_brelse(tp
, bp
);
202 i
+= XFS_NBWORD
- 1 - XFS_RTHIBIT(wdiff
);
203 *rtblock
= start
- i
+ 1;
208 * Go on to previous block if that's where the previous word is
209 * and we need the previous word.
211 if (--word
== -1 && i
< len
) {
213 * If done with this block, get the previous one.
215 xfs_trans_brelse(tp
, bp
);
216 error
= xfs_rtbuf_get(mp
, tp
, --block
, 0, &bp
);
221 word
= XFS_BLOCKWMASK(mp
);
225 * Go on to the previous word in the buffer.
231 * If not ending on a word boundary, deal with the last
236 * Calculate first (leftmost) bit number to look at,
237 * and mask for all the relevant bits in this word.
239 firstbit
= XFS_NBWORD
- (len
- i
);
240 mask
= (((xfs_rtword_t
)1 << (len
- i
)) - 1) << firstbit
;
242 * Compute difference between actual and desired value.
244 if ((wdiff
= (*b
^ want
) & mask
)) {
246 * Different, mark where we are and return.
248 xfs_trans_brelse(tp
, bp
);
249 i
+= XFS_NBWORD
- 1 - XFS_RTHIBIT(wdiff
);
250 *rtblock
= start
- i
+ 1;
256 * No match, return that we scanned the whole area.
258 xfs_trans_brelse(tp
, bp
);
259 *rtblock
= start
- i
+ 1;
264 * Searching forward from start to limit, find the first block whose
265 * allocated/free state is different from start's.
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 */
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 */
290 * Compute and read in starting bitmap block for starting block.
292 block
= XFS_BITTOBLOCK(mp
, start
);
293 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
299 * Get the first word's index & point to it.
301 word
= XFS_BITTOWORD(mp
, start
);
303 bit
= (int)(start
& (XFS_NBWORD
- 1));
304 len
= limit
- start
+ 1;
306 * Compute match value, based on the bit at start: if 1 (free)
307 * then all-ones, else all-zeroes.
309 want
= (*b
& ((xfs_rtword_t
)1 << bit
)) ? -1 : 0;
311 * If the starting position is not word-aligned, deal with the
316 * Calculate last (rightmost) bit number to look at,
317 * and mask for all the relevant bits in this word.
319 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
320 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
322 * Calculate the difference between the value there
323 * and what we're looking for.
325 if ((wdiff
= (*b
^ want
) & mask
)) {
327 * Different. Mark where we are and return.
329 xfs_trans_brelse(tp
, bp
);
330 i
= XFS_RTLOBIT(wdiff
) - bit
;
331 *rtblock
= start
+ i
- 1;
336 * Go on to next block if that's where the next word is
337 * and we need the next word.
339 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
341 * If done with this block, get the previous one.
343 xfs_trans_brelse(tp
, bp
);
344 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
348 b
= bufp
= bp
->b_addr
;
352 * Go on to the previous word in the buffer.
358 * Starting on a word boundary, no partial word.
363 * Loop over whole words in buffers. When we use up one buffer
364 * we move on to the next one.
366 while (len
- i
>= XFS_NBWORD
) {
368 * Compute difference between actual and desired value.
370 if ((wdiff
= *b
^ want
)) {
372 * Different, mark where we are and return.
374 xfs_trans_brelse(tp
, bp
);
375 i
+= XFS_RTLOBIT(wdiff
);
376 *rtblock
= start
+ i
- 1;
381 * Go on to next block if that's where the next word is
382 * and we need the next word.
384 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
386 * If done with this block, get the next one.
388 xfs_trans_brelse(tp
, bp
);
389 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
393 b
= bufp
= bp
->b_addr
;
397 * Go on to the next word in the buffer.
403 * If not ending on a word boundary, deal with the last
406 if ((lastbit
= len
- i
)) {
408 * Calculate mask for all the relevant bits in this word.
410 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
412 * Compute difference between actual and desired value.
414 if ((wdiff
= (*b
^ want
) & mask
)) {
416 * Different, mark where we are and return.
418 xfs_trans_brelse(tp
, bp
);
419 i
+= XFS_RTLOBIT(wdiff
);
420 *rtblock
= start
+ i
- 1;
426 * No match, return that we scanned the whole area.
428 xfs_trans_brelse(tp
, bp
);
429 *rtblock
= start
+ i
- 1;
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.
439 * Summary information is returned in *sum if specified.
440 * If no delta is specified, returns summary only.
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 */
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 */
460 * Compute entry number in the summary file.
462 so
= XFS_SUMOFFS(mp
, log
, bbno
);
464 * Compute the block number in the summary file.
466 sb
= XFS_SUMOFFSTOBLOCK(mp
, so
);
468 * If we have an old buffer, and the block number matches, use that.
470 if (*rbpp
&& *rsb
== sb
)
473 * Otherwise we have to get the buffer.
477 * If there was an old one, get rid of it first.
480 xfs_trans_brelse(tp
, *rbpp
);
481 error
= xfs_rtbuf_get(mp
, tp
, sb
, 1, &bp
);
486 * Remember this buffer and block for the next call.
492 * Point to the summary information, modify/log it, and/or copy it out.
494 sp
= XFS_SUMPTR(mp
, bp
, so
);
496 uint first
= (uint
)((char *)sp
- (char *)bp
->b_addr
);
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
;
505 xfs_trans_log_buf(tp
, bp
, first
, first
+ sizeof(*sp
) - 1);
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 */
522 return xfs_rtmodify_summary_int(mp
, tp
, log
, bbno
,
523 delta
, rbpp
, rsb
, NULL
);
527 * Set the given range of bitmap bits to the given value.
528 * Do whatever I/O and logging is required.
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 */
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 */
551 * Compute starting bitmap block number.
553 block
= XFS_BITTOBLOCK(mp
, start
);
555 * Read the bitmap block, and point to its data.
557 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
563 * Compute the starting word's address, and starting bit.
565 word
= XFS_BITTOWORD(mp
, start
);
566 first
= b
= &bufp
[word
];
567 bit
= (int)(start
& (XFS_NBWORD
- 1));
569 * 0 (allocated) => all zeroes; 1 (free) => all ones.
573 * If not starting on a word boundary, deal with the first
578 * Compute first bit not changed and mask of relevant bits.
580 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
581 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
583 * Set/clear the active bits.
591 * Go on to the next block if that's where the next word is
592 * and we need the next word.
594 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
596 * Log the changed part of this block.
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
);
606 first
= b
= bufp
= bp
->b_addr
;
610 * Go on to the next word in the buffer
616 * Starting on a word boundary, no partial word.
621 * Loop over whole words in buffers. When we use up one buffer
622 * we move on to the next one.
624 while (len
- i
>= XFS_NBWORD
) {
626 * Set the word value correctly.
631 * Go on to the next block if that's where the next word is
632 * and we need the next word.
634 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
636 * Log the changed part of this block.
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
);
646 first
= b
= bufp
= bp
->b_addr
;
650 * Go on to the next word in the buffer
656 * If not ending on a word boundary, deal with the last
659 if ((lastbit
= len
- i
)) {
661 * Compute a mask of relevant bits.
663 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
665 * Set/clear the active bits.
674 * Log any remaining changed bytes.
677 xfs_trans_log_buf(tp
, bp
, (uint
)((char *)first
- (char *)bufp
),
678 (uint
)((char *)b
- (char *)bufp
- 1));
683 * Mark an extent specified by start and len freed.
684 * Updates all the summary information as well as the bitmap.
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 */
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 */
700 end
= start
+ len
- 1;
702 * Modify the bitmap to mark this extent freed.
704 error
= xfs_rtmodify_range(mp
, tp
, start
, len
, 1);
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.
713 error
= xfs_rtfind_back(mp
, tp
, start
, 0, &preblock
);
718 * Find the next allocated block (end of allocated extent).
720 error
= xfs_rtfind_forw(mp
, tp
, end
, mp
->m_sb
.sb_rextents
- 1,
725 * If there are blocks not being freed at the front of the
726 * old extent, add summary data for them to be allocated.
728 if (preblock
< start
) {
729 error
= xfs_rtmodify_summary(mp
, tp
,
730 XFS_RTBLOCKLOG(start
- preblock
),
731 XFS_BITTOBLOCK(mp
, preblock
), -1, rbpp
, rsb
);
737 * If there are blocks not being freed at the end of the
738 * old extent, add summary data for them to be allocated.
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
);
749 * Increment the summary information corresponding to the entire
752 error
= xfs_rtmodify_summary(mp
, tp
,
753 XFS_RTBLOCKLOG(postblock
+ 1 - preblock
),
754 XFS_BITTOBLOCK(mp
, preblock
), 1, rbpp
, rsb
);
759 * Check that the given range is either all allocated (val = 0) or
760 * all free (val = 1).
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 */
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 */
785 * Compute starting bitmap block number
787 block
= XFS_BITTOBLOCK(mp
, start
);
789 * Read the bitmap block.
791 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
797 * Compute the starting word's address, and starting bit.
799 word
= XFS_BITTOWORD(mp
, start
);
801 bit
= (int)(start
& (XFS_NBWORD
- 1));
803 * 0 (allocated) => all zero's; 1 (free) => all one's.
807 * If not starting on a word boundary, deal with the first
812 * Compute first bit not examined.
814 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
816 * Mask of relevant bits.
818 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
820 * Compute difference between actual and desired value.
822 if ((wdiff
= (*b
^ val
) & mask
)) {
824 * Different, compute first wrong bit and return.
826 xfs_trans_brelse(tp
, bp
);
827 i
= XFS_RTLOBIT(wdiff
) - bit
;
834 * Go on to next block if that's where the next word is
835 * and we need the next word.
837 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
839 * If done with this block, get the next one.
841 xfs_trans_brelse(tp
, bp
);
842 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
846 b
= bufp
= bp
->b_addr
;
850 * Go on to the next word in the buffer.
856 * Starting on a word boundary, no partial word.
861 * Loop over whole words in buffers. When we use up one buffer
862 * we move on to the next one.
864 while (len
- i
>= XFS_NBWORD
) {
866 * Compute difference between actual and desired value.
868 if ((wdiff
= *b
^ val
)) {
870 * Different, compute first wrong bit and return.
872 xfs_trans_brelse(tp
, bp
);
873 i
+= XFS_RTLOBIT(wdiff
);
880 * Go on to next block if that's where the next word is
881 * and we need the next word.
883 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
885 * If done with this block, get the next one.
887 xfs_trans_brelse(tp
, bp
);
888 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
892 b
= bufp
= bp
->b_addr
;
896 * Go on to the next word in the buffer.
902 * If not ending on a word boundary, deal with the last
905 if ((lastbit
= len
- i
)) {
907 * Mask of relevant bits.
909 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
911 * Compute difference between actual and desired value.
913 if ((wdiff
= (*b
^ val
) & mask
)) {
915 * Different, compute first wrong bit and return.
917 xfs_trans_brelse(tp
, bp
);
918 i
+= XFS_RTLOBIT(wdiff
);
926 * Successful, return.
928 xfs_trans_brelse(tp
, bp
);
936 * Check that the given extent (block range) is allocated already.
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 */
945 xfs_rtblock_t
new; /* dummy for xfs_rtcheck_range */
949 error
= xfs_rtcheck_range(mp
, tp
, bno
, len
, 0, &new, &stat
);
956 #define xfs_rtcheck_alloc_range(m,t,b,l) (0)
959 * Free an extent in the realtime subvolume. Length is expressed in
960 * realtime extents, as is the block number.
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 */
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 */
975 ASSERT(mp
->m_rbmip
->i_itemp
!= NULL
);
976 ASSERT(xfs_isilocked(mp
->m_rbmip
, XFS_ILOCK_EXCL
));
978 error
= xfs_rtcheck_alloc_range(mp
, tp
, bno
, len
);
983 * Free the range of realtime blocks.
985 error
= xfs_rtfree_range(mp
, tp
, bno
, len
, &sumbp
, &sb
);
990 * Mark more blocks free in the superblock.
992 xfs_trans_mod_sb(tp
, XFS_TRANS_SB_FREXTENTS
, (long)len
);
994 * If we've now freed all the blocks, reset the file sequence
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
);
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.
1014 struct xfs_trans
*tp
,
1015 xfs_fsblock_t rtbno
,
1016 xfs_filblks_t rtlen
)
1018 struct xfs_mount
*mp
= tp
->t_mountp
;
1023 ASSERT(rtlen
<= XFS_MAX_BMBT_EXTLEN
);
1025 len
= div_u64_rem(rtlen
, mp
->m_sb
.sb_rextsize
, &mod
);
1031 bno
= div_u64_rem(rtbno
, mp
->m_sb
.sb_rextsize
, &mod
);
1037 return xfs_rtfree_extent(tp
, bno
, len
);
1040 /* Find all the free records within a given range. */
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
,
1050 struct xfs_rtalloc_rec rec
;
1051 xfs_rtblock_t rtstart
;
1052 xfs_rtblock_t rtend
;
1053 xfs_rtblock_t high_key
;
1057 if (low_rec
->ar_startext
> high_rec
->ar_startext
)
1059 if (low_rec
->ar_startext
>= mp
->m_sb
.sb_rextents
||
1060 low_rec
->ar_startext
== high_rec
->ar_startext
)
1063 high_key
= min(high_rec
->ar_startext
, mp
->m_sb
.sb_rextents
- 1);
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
,
1074 /* How long does the extent go for? */
1075 error
= xfs_rtfind_forw(mp
, tp
, rtstart
, high_key
, &rtend
);
1080 rec
.ar_startext
= rtstart
;
1081 rec
.ar_extcount
= rtend
- rtstart
+ 1;
1083 error
= fn(mp
, tp
, &rec
, priv
);
1088 rtstart
= rtend
+ 1;
1094 /* Find all the free records. */
1096 xfs_rtalloc_query_all(
1097 struct xfs_mount
*mp
,
1098 struct xfs_trans
*tp
,
1099 xfs_rtalloc_query_range_fn fn
,
1102 struct xfs_rtalloc_rec keys
[2];
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;
1108 return xfs_rtalloc_query_range(mp
, tp
, &keys
[0], &keys
[1], fn
, priv
);
1111 /* Is the given extent all free? */
1113 xfs_rtalloc_extent_is_free(
1114 struct xfs_mount
*mp
,
1115 struct xfs_trans
*tp
,
1116 xfs_rtblock_t start
,
1124 error
= xfs_rtcheck_range(mp
, tp
, start
, len
, 1, &end
, &matches
);