]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/xfs_rtalloc.c
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Free realtime space allocation for XFS.
25 extern int xfs_lowbit32(__uint32_t
);
28 * Get a buffer for the bitmap or summary file block specified.
29 * The buffer is returned read and locked.
31 STATIC
int /* error */
33 xfs_mount_t
*mp
, /* file system mount structure */
34 xfs_trans_t
*tp
, /* transaction pointer */
35 xfs_rtblock_t block
, /* block number in bitmap or summary */
36 int issum
, /* is summary not bitmap */
37 xfs_buf_t
**bpp
) /* output: buffer for the block */
39 xfs_buf_t
*bp
; /* block buffer, result */
40 xfs_daddr_t d
; /* disk addr of block */
41 int error
; /* error value */
42 xfs_fsblock_t fsb
; /* fs block number for block */
43 xfs_inode_t
*ip
; /* bitmap or summary inode */
45 ip
= issum
? mp
->m_rsumip
: mp
->m_rbmip
;
47 * Map from the file offset (block) and inode number to the
50 error
= xfs_bmapi_single(tp
, ip
, XFS_DATA_FORK
, &fsb
, block
);
54 ASSERT(fsb
!= NULLFSBLOCK
);
56 * Convert to disk address for buffer cache.
58 d
= XFS_FSB_TO_DADDR(mp
, fsb
);
62 error
= xfs_trans_read_buf(mp
, tp
, mp
->m_ddev_targp
, d
,
67 ASSERT(bp
&& !XFS_BUF_GETERROR(bp
));
73 * Searching backward from start to limit, find the first block whose
74 * allocated/free state is different from start's.
76 STATIC
int /* error */
78 xfs_mount_t
*mp
, /* file system mount point */
79 xfs_trans_t
*tp
, /* transaction pointer */
80 xfs_rtblock_t start
, /* starting block to look at */
81 xfs_rtblock_t limit
, /* last block to look at */
82 xfs_rtblock_t
*rtblock
) /* out: start block found */
84 xfs_rtword_t
*b
; /* current word in buffer */
85 int bit
; /* bit number in the word */
86 xfs_rtblock_t block
; /* bitmap block number */
87 xfs_buf_t
*bp
; /* buf for the block */
88 xfs_rtword_t
*bufp
; /* starting word in buffer */
89 int error
; /* error value */
90 xfs_rtblock_t firstbit
; /* first useful bit in the word */
91 xfs_rtblock_t i
; /* current bit number rel. to start */
92 xfs_rtblock_t len
; /* length of inspected area */
93 xfs_rtword_t mask
; /* mask of relevant bits for value */
94 xfs_rtword_t want
; /* mask for "good" values */
95 xfs_rtword_t wdiff
; /* difference from wanted value */
96 int word
; /* word number in the buffer */
99 * Compute and read in starting bitmap block for starting block.
101 block
= XFS_BITTOBLOCK(mp
, start
);
102 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
106 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
108 * Get the first word's index & point to it.
110 word
= XFS_BITTOWORD(mp
, start
);
112 bit
= (int)(start
& (XFS_NBWORD
- 1));
113 len
= start
- limit
+ 1;
115 * Compute match value, based on the bit at start: if 1 (free)
116 * then all-ones, else all-zeroes.
118 want
= (*b
& ((xfs_rtword_t
)1 << bit
)) ? -1 : 0;
120 * If the starting position is not word-aligned, deal with the
123 if (bit
< XFS_NBWORD
- 1) {
125 * Calculate first (leftmost) bit number to look at,
126 * and mask for all the relevant bits in this word.
128 firstbit
= XFS_RTMAX((xfs_srtblock_t
)(bit
- len
+ 1), 0);
129 mask
= (((xfs_rtword_t
)1 << (bit
- firstbit
+ 1)) - 1) <<
132 * Calculate the difference between the value there
133 * and what we're looking for.
135 if ((wdiff
= (*b
^ want
) & mask
)) {
137 * Different. Mark where we are and return.
139 xfs_trans_brelse(tp
, bp
);
140 i
= bit
- XFS_RTHIBIT(wdiff
);
141 *rtblock
= start
- i
+ 1;
144 i
= bit
- firstbit
+ 1;
146 * Go on to previous block if that's where the previous word is
147 * and we need the previous word.
149 if (--word
== -1 && i
< len
) {
151 * If done with this block, get the previous one.
153 xfs_trans_brelse(tp
, bp
);
154 error
= xfs_rtbuf_get(mp
, tp
, --block
, 0, &bp
);
158 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
159 word
= XFS_BLOCKWMASK(mp
);
163 * Go on to the previous word in the buffer.
169 * Starting on a word boundary, no partial word.
174 * Loop over whole words in buffers. When we use up one buffer
175 * we move on to the previous one.
177 while (len
- i
>= XFS_NBWORD
) {
179 * Compute difference between actual and desired value.
181 if ((wdiff
= *b
^ want
)) {
183 * Different, mark where we are and return.
185 xfs_trans_brelse(tp
, bp
);
186 i
+= XFS_NBWORD
- 1 - XFS_RTHIBIT(wdiff
);
187 *rtblock
= start
- i
+ 1;
192 * Go on to previous block if that's where the previous word is
193 * and we need the previous word.
195 if (--word
== -1 && i
< len
) {
197 * If done with this block, get the previous one.
199 xfs_trans_brelse(tp
, bp
);
200 error
= xfs_rtbuf_get(mp
, tp
, --block
, 0, &bp
);
204 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
205 word
= XFS_BLOCKWMASK(mp
);
209 * Go on to the previous word in the buffer.
215 * If not ending on a word boundary, deal with the last
220 * Calculate first (leftmost) bit number to look at,
221 * and mask for all the relevant bits in this word.
223 firstbit
= XFS_NBWORD
- (len
- i
);
224 mask
= (((xfs_rtword_t
)1 << (len
- i
)) - 1) << firstbit
;
226 * Compute difference between actual and desired value.
228 if ((wdiff
= (*b
^ want
) & mask
)) {
230 * Different, mark where we are and return.
232 xfs_trans_brelse(tp
, bp
);
233 i
+= XFS_NBWORD
- 1 - XFS_RTHIBIT(wdiff
);
234 *rtblock
= start
- i
+ 1;
240 * No match, return that we scanned the whole area.
242 xfs_trans_brelse(tp
, bp
);
243 *rtblock
= start
- i
+ 1;
248 * Searching forward from start to limit, find the first block whose
249 * allocated/free state is different from start's.
251 STATIC
int /* error */
253 xfs_mount_t
*mp
, /* file system mount point */
254 xfs_trans_t
*tp
, /* transaction pointer */
255 xfs_rtblock_t start
, /* starting block to look at */
256 xfs_rtblock_t limit
, /* last block to look at */
257 xfs_rtblock_t
*rtblock
) /* out: start block found */
259 xfs_rtword_t
*b
; /* current word in buffer */
260 int bit
; /* bit number in the word */
261 xfs_rtblock_t block
; /* bitmap block number */
262 xfs_buf_t
*bp
; /* buf for the block */
263 xfs_rtword_t
*bufp
; /* starting word in buffer */
264 int error
; /* error value */
265 xfs_rtblock_t i
; /* current bit number rel. to start */
266 xfs_rtblock_t lastbit
; /* last useful bit in the word */
267 xfs_rtblock_t len
; /* length of inspected area */
268 xfs_rtword_t mask
; /* mask of relevant bits for value */
269 xfs_rtword_t want
; /* mask for "good" values */
270 xfs_rtword_t wdiff
; /* difference from wanted value */
271 int word
; /* word number in the buffer */
274 * Compute and read in starting bitmap block for starting block.
276 block
= XFS_BITTOBLOCK(mp
, start
);
277 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
281 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
283 * Get the first word's index & point to it.
285 word
= XFS_BITTOWORD(mp
, start
);
287 bit
= (int)(start
& (XFS_NBWORD
- 1));
288 len
= limit
- start
+ 1;
290 * Compute match value, based on the bit at start: if 1 (free)
291 * then all-ones, else all-zeroes.
293 want
= (*b
& ((xfs_rtword_t
)1 << bit
)) ? -1 : 0;
295 * If the starting position is not word-aligned, deal with the
300 * Calculate last (rightmost) bit number to look at,
301 * and mask for all the relevant bits in this word.
303 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
304 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
306 * Calculate the difference between the value there
307 * and what we're looking for.
309 if ((wdiff
= (*b
^ want
) & mask
)) {
311 * Different. Mark where we are and return.
313 xfs_trans_brelse(tp
, bp
);
314 i
= XFS_RTLOBIT(wdiff
) - bit
;
315 *rtblock
= start
+ i
- 1;
320 * Go on to next block if that's where the next word is
321 * and we need the next word.
323 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
325 * If done with this block, get the previous one.
327 xfs_trans_brelse(tp
, bp
);
328 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
332 b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
336 * Go on to the previous word in the buffer.
342 * Starting on a word boundary, no partial word.
347 * Loop over whole words in buffers. When we use up one buffer
348 * we move on to the next one.
350 while (len
- i
>= XFS_NBWORD
) {
352 * Compute difference between actual and desired value.
354 if ((wdiff
= *b
^ want
)) {
356 * Different, mark where we are and return.
358 xfs_trans_brelse(tp
, bp
);
359 i
+= XFS_RTLOBIT(wdiff
);
360 *rtblock
= start
+ i
- 1;
365 * Go on to next block if that's where the next word is
366 * and we need the next word.
368 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
370 * If done with this block, get the next one.
372 xfs_trans_brelse(tp
, bp
);
373 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
377 b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
381 * Go on to the next word in the buffer.
387 * If not ending on a word boundary, deal with the last
390 if ((lastbit
= len
- i
)) {
392 * Calculate mask for all the relevant bits in this word.
394 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
396 * Compute difference between actual and desired value.
398 if ((wdiff
= (*b
^ want
) & mask
)) {
400 * Different, mark where we are and return.
402 xfs_trans_brelse(tp
, bp
);
403 i
+= XFS_RTLOBIT(wdiff
);
404 *rtblock
= start
+ i
- 1;
410 * No match, return that we scanned the whole area.
412 xfs_trans_brelse(tp
, bp
);
413 *rtblock
= start
+ i
- 1;
418 * Mark an extent specified by start and len freed.
419 * Updates all the summary information as well as the bitmap.
421 STATIC
int /* error */
423 xfs_mount_t
*mp
, /* file system mount point */
424 xfs_trans_t
*tp
, /* transaction pointer */
425 xfs_rtblock_t start
, /* starting block to free */
426 xfs_extlen_t len
, /* length to free */
427 xfs_buf_t
**rbpp
, /* in/out: summary block buffer */
428 xfs_fsblock_t
*rsb
) /* in/out: summary block number */
430 xfs_rtblock_t end
; /* end of the freed extent */
431 int error
; /* error value */
432 xfs_rtblock_t postblock
; /* first block freed > end */
433 xfs_rtblock_t preblock
; /* first block freed < start */
435 end
= start
+ len
- 1;
437 * Modify the bitmap to mark this extent freed.
439 error
= xfs_rtmodify_range(mp
, tp
, start
, len
, 1);
444 * Assume we're freeing out of the middle of an allocated extent.
445 * We need to find the beginning and end of the extent so we can
446 * properly update the summary.
448 error
= xfs_rtfind_back(mp
, tp
, start
, 0, &preblock
);
453 * Find the next allocated block (end of allocated extent).
455 error
= xfs_rtfind_forw(mp
, tp
, end
, mp
->m_sb
.sb_rextents
- 1,
458 * If there are blocks not being freed at the front of the
459 * old extent, add summary data for them to be allocated.
461 if (preblock
< start
) {
462 error
= xfs_rtmodify_summary(mp
, tp
,
463 XFS_RTBLOCKLOG(start
- preblock
),
464 XFS_BITTOBLOCK(mp
, preblock
), -1, rbpp
, rsb
);
470 * If there are blocks not being freed at the end of the
471 * old extent, add summary data for them to be allocated.
473 if (postblock
> end
) {
474 error
= xfs_rtmodify_summary(mp
, tp
,
475 XFS_RTBLOCKLOG(postblock
- end
),
476 XFS_BITTOBLOCK(mp
, end
+ 1), -1, rbpp
, rsb
);
482 * Increment the summary information corresponding to the entire
485 error
= xfs_rtmodify_summary(mp
, tp
,
486 XFS_RTBLOCKLOG(postblock
+ 1 - preblock
),
487 XFS_BITTOBLOCK(mp
, preblock
), 1, rbpp
, rsb
);
492 * Set the given range of bitmap bits to the given value.
493 * Do whatever I/O and logging is required.
495 STATIC
int /* error */
497 xfs_mount_t
*mp
, /* file system mount point */
498 xfs_trans_t
*tp
, /* transaction pointer */
499 xfs_rtblock_t start
, /* starting block to modify */
500 xfs_extlen_t len
, /* length of extent to modify */
501 int val
) /* 1 for free, 0 for allocated */
503 xfs_rtword_t
*b
; /* current word in buffer */
504 int bit
; /* bit number in the word */
505 xfs_rtblock_t block
; /* bitmap block number */
506 xfs_buf_t
*bp
; /* buf for the block */
507 xfs_rtword_t
*bufp
; /* starting word in buffer */
508 int error
; /* error value */
509 xfs_rtword_t
*first
; /* first used word in the buffer */
510 int i
; /* current bit number rel. to start */
511 int lastbit
; /* last useful bit in word */
512 xfs_rtword_t mask
; /* mask o frelevant bits for value */
513 int word
; /* word number in the buffer */
516 * Compute starting bitmap block number.
518 block
= XFS_BITTOBLOCK(mp
, start
);
520 * Read the bitmap block, and point to its data.
522 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
526 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
528 * Compute the starting word's address, and starting bit.
530 word
= XFS_BITTOWORD(mp
, start
);
531 first
= b
= &bufp
[word
];
532 bit
= (int)(start
& (XFS_NBWORD
- 1));
534 * 0 (allocated) => all zeroes; 1 (free) => all ones.
538 * If not starting on a word boundary, deal with the first
543 * Compute first bit not changed and mask of relevant bits.
545 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
546 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
548 * Set/clear the active bits.
556 * Go on to the next block if that's where the next word is
557 * and we need the next word.
559 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
561 * Log the changed part of this block.
564 xfs_trans_log_buf(tp
, bp
,
565 (uint
)((char *)first
- (char *)bufp
),
566 (uint
)((char *)b
- (char *)bufp
));
567 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
571 first
= b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
575 * Go on to the next word in the buffer
581 * Starting on a word boundary, no partial word.
586 * Loop over whole words in buffers. When we use up one buffer
587 * we move on to the next one.
589 while (len
- i
>= XFS_NBWORD
) {
591 * Set the word value correctly.
596 * Go on to the next block if that's where the next word is
597 * and we need the next word.
599 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
601 * Log the changed part of this block.
604 xfs_trans_log_buf(tp
, bp
,
605 (uint
)((char *)first
- (char *)bufp
),
606 (uint
)((char *)b
- (char *)bufp
));
607 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
611 first
= b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
615 * Go on to the next word in the buffer
621 * If not ending on a word boundary, deal with the last
624 if ((lastbit
= len
- i
)) {
626 * Compute a mask of relevant bits.
629 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
631 * Set/clear the active bits.
640 * Log any remaining changed bytes.
643 xfs_trans_log_buf(tp
, bp
, (uint
)((char *)first
- (char *)bufp
),
644 (uint
)((char *)b
- (char *)bufp
- 1));
649 * Read and modify the summary information for a given extent size,
650 * bitmap block combination.
651 * Keeps track of a current summary block, so we don't keep reading
652 * it from the buffer cache.
654 STATIC
int /* error */
655 xfs_rtmodify_summary(
656 xfs_mount_t
*mp
, /* file system mount point */
657 xfs_trans_t
*tp
, /* transaction pointer */
658 int log
, /* log2 of extent size */
659 xfs_rtblock_t bbno
, /* bitmap block number */
660 int delta
, /* change to make to summary info */
661 xfs_buf_t
**rbpp
, /* in/out: summary block buffer */
662 xfs_fsblock_t
*rsb
) /* in/out: summary block number */
664 xfs_buf_t
*bp
; /* buffer for the summary block */
665 int error
; /* error value */
666 xfs_fsblock_t sb
; /* summary fsblock */
667 int so
; /* index into the summary file */
668 xfs_suminfo_t
*sp
; /* pointer to returned data */
671 * Compute entry number in the summary file.
673 so
= XFS_SUMOFFS(mp
, log
, bbno
);
675 * Compute the block number in the summary file.
677 sb
= XFS_SUMOFFSTOBLOCK(mp
, so
);
679 * If we have an old buffer, and the block number matches, use that.
681 if (rbpp
&& *rbpp
&& *rsb
== sb
)
684 * Otherwise we have to get the buffer.
688 * If there was an old one, get rid of it first.
691 xfs_trans_brelse(tp
, *rbpp
);
692 error
= xfs_rtbuf_get(mp
, tp
, sb
, 1, &bp
);
697 * Remember this buffer and block for the next call.
705 * Point to the summary information, modify and log it.
707 sp
= XFS_SUMPTR(mp
, bp
, so
);
709 xfs_trans_log_buf(tp
, bp
, (uint
)((char *)sp
- (char *)XFS_BUF_PTR(bp
)),
710 (uint
)((char *)sp
- (char *)XFS_BUF_PTR(bp
) + sizeof(*sp
) - 1));
715 * Free an extent in the realtime subvolume. Length is expressed in
716 * realtime extents, as is the block number.
720 xfs_trans_t
*tp
, /* transaction pointer */
721 xfs_rtblock_t bno
, /* starting block number to free */
722 xfs_extlen_t len
) /* length of extent freed */
724 int error
; /* error value */
725 xfs_inode_t
*ip
; /* bitmap file inode */
726 xfs_mount_t
*mp
; /* file system mount structure */
727 xfs_fsblock_t sb
; /* summary file block number */
728 xfs_buf_t
*sumbp
; /* summary file block buffer */
732 * Synchronize by locking the bitmap inode.
734 error
= xfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, 0, XFS_ILOCK_EXCL
, &ip
);
738 #if defined(__KERNEL__) && defined(DEBUG)
740 * Check to see that this whole range is currently allocated.
743 int stat
; /* result from checking range */
745 error
= xfs_rtcheck_alloc_range(mp
, tp
, bno
, len
, &stat
);
754 * Free the range of realtime blocks.
756 error
= xfs_rtfree_range(mp
, tp
, bno
, len
, &sumbp
, &sb
);
761 * Mark more blocks free in the superblock.
763 xfs_trans_mod_sb(tp
, XFS_TRANS_SB_FREXTENTS
, (long)len
);
765 * If we've now freed all the blocks, reset the file sequence
768 if (tp
->t_frextents_delta
+ mp
->m_sb
.sb_frextents
==
769 mp
->m_sb
.sb_rextents
) {
770 if (!(ip
->i_d
.di_flags
& XFS_DIFLAG_NEWRTBM
))
771 ip
->i_d
.di_flags
|= XFS_DIFLAG_NEWRTBM
;
772 *(__uint64_t
*)&ip
->i_d
.di_atime
= 0;
773 xfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
779 * Pick an extent for allocation at the start of a new realtime file.
780 * Use the sequence number stored in the atime field of the bitmap inode.
781 * Translate this to a fraction of the rtextents, and return the product
782 * of rtextents and the fraction.
783 * The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
787 xfs_mount_t
*mp
, /* file system mount point */
788 xfs_trans_t
*tp
, /* transaction pointer */
789 xfs_extlen_t len
, /* allocation length (rtextents) */
790 xfs_rtblock_t
*pick
) /* result rt extent */
792 xfs_rtblock_t b
; /* result block */
793 int error
; /* error return value */
794 xfs_inode_t
*ip
; /* bitmap incore inode */
795 int log2
; /* log of sequence number */
796 __uint64_t resid
; /* residual after log removed */
797 __uint64_t seq
; /* sequence number of file creation */
798 __uint64_t
*seqp
; /* pointer to seqno in inode */
800 error
= xfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, 0, XFS_ILOCK_EXCL
, &ip
);
803 ASSERT(ip
== mp
->m_rbmip
);
804 seqp
= (__uint64_t
*)&ip
->i_d
.di_atime
;
805 if (!(ip
->i_d
.di_flags
& XFS_DIFLAG_NEWRTBM
)) {
806 ip
->i_d
.di_flags
|= XFS_DIFLAG_NEWRTBM
;
810 if ((log2
= xfs_highbit64(seq
)) == -1)
813 resid
= seq
- (1ULL << log2
);
814 b
= (mp
->m_sb
.sb_rextents
* ((resid
<< 1) + 1ULL)) >>
816 if (b
>= mp
->m_sb
.sb_rextents
)
817 b
= do_mod(b
, mp
->m_sb
.sb_rextents
);
818 if (b
+ len
> mp
->m_sb
.sb_rextents
)
819 b
= mp
->m_sb
.sb_rextents
- len
;
822 xfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);