]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/xfs_rtalloc.c
2 * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
34 * Free realtime space allocation for XFS.
40 * Get a buffer for the bitmap or summary file block specified.
41 * The buffer is returned read and locked.
43 STATIC
int /* error */
45 xfs_mount_t
*mp
, /* file system mount structure */
46 xfs_trans_t
*tp
, /* transaction pointer */
47 xfs_rtblock_t block
, /* block number in bitmap or summary */
48 int issum
, /* is summary not bitmap */
49 xfs_buf_t
**bpp
) /* output: buffer for the block */
51 xfs_buf_t
*bp
; /* block buffer, result */
52 xfs_daddr_t d
; /* disk addr of block */
53 int error
; /* error value */
54 xfs_fsblock_t fsb
; /* fs block number for block */
55 xfs_inode_t
*ip
; /* bitmap or summary inode */
57 ip
= issum
? mp
->m_rsumip
: mp
->m_rbmip
;
59 * Map from the file offset (block) and inode number to the
62 error
= xfs_bmapi_single(tp
, ip
, XFS_DATA_FORK
, &fsb
, block
);
66 ASSERT(fsb
!= NULLFSBLOCK
);
68 * Convert to disk address for buffer cache.
70 d
= XFS_FSB_TO_DADDR(mp
, fsb
);
74 error
= xfs_trans_read_buf(mp
, tp
, mp
->m_ddev_targp
, d
,
79 ASSERT(bp
&& !XFS_BUF_GETERROR(bp
));
85 * Searching backward from start to limit, find the first block whose
86 * allocated/free state is different from start's.
88 STATIC
int /* error */
90 xfs_mount_t
*mp
, /* file system mount point */
91 xfs_trans_t
*tp
, /* transaction pointer */
92 xfs_rtblock_t start
, /* starting block to look at */
93 xfs_rtblock_t limit
, /* last block to look at */
94 xfs_rtblock_t
*rtblock
) /* out: start block found */
96 xfs_rtword_t
*b
; /* current word in buffer */
97 int bit
; /* bit number in the word */
98 xfs_rtblock_t block
; /* bitmap block number */
99 xfs_buf_t
*bp
; /* buf for the block */
100 xfs_rtword_t
*bufp
; /* starting word in buffer */
101 int error
; /* error value */
102 xfs_rtblock_t firstbit
; /* first useful bit in the word */
103 xfs_rtblock_t i
; /* current bit number rel. to start */
104 xfs_rtblock_t len
; /* length of inspected area */
105 xfs_rtword_t mask
; /* mask of relevant bits for value */
106 xfs_rtword_t want
; /* mask for "good" values */
107 xfs_rtword_t wdiff
; /* difference from wanted value */
108 int word
; /* word number in the buffer */
111 * Compute and read in starting bitmap block for starting block.
113 block
= XFS_BITTOBLOCK(mp
, start
);
114 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
118 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
120 * Get the first word's index & point to it.
122 word
= XFS_BITTOWORD(mp
, start
);
124 bit
= (int)(start
& (XFS_NBWORD
- 1));
125 len
= start
- limit
+ 1;
127 * Compute match value, based on the bit at start: if 1 (free)
128 * then all-ones, else all-zeroes.
130 want
= (*b
& ((xfs_rtword_t
)1 << bit
)) ? -1 : 0;
132 * If the starting position is not word-aligned, deal with the
135 if (bit
< XFS_NBWORD
- 1) {
137 * Calculate first (leftmost) bit number to look at,
138 * and mask for all the relevant bits in this word.
140 firstbit
= XFS_RTMAX((xfs_srtblock_t
)(bit
- len
+ 1), 0);
141 mask
= (((xfs_rtword_t
)1 << (bit
- firstbit
+ 1)) - 1) <<
144 * Calculate the difference between the value there
145 * and what we're looking for.
147 if ((wdiff
= (*b
^ want
) & mask
)) {
149 * Different. Mark where we are and return.
151 xfs_trans_brelse(tp
, bp
);
152 i
= bit
- XFS_RTHIBIT(wdiff
);
153 *rtblock
= start
- i
+ 1;
156 i
= bit
- firstbit
+ 1;
158 * Go on to previous block if that's where the previous word is
159 * and we need the previous word.
161 if (--word
== -1 && i
< len
) {
163 * If done with this block, get the previous one.
165 xfs_trans_brelse(tp
, bp
);
166 error
= xfs_rtbuf_get(mp
, tp
, --block
, 0, &bp
);
170 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
171 word
= XFS_BLOCKWMASK(mp
);
175 * Go on to the previous word in the buffer.
181 * Starting on a word boundary, no partial word.
186 * Loop over whole words in buffers. When we use up one buffer
187 * we move on to the previous one.
189 while (len
- i
>= XFS_NBWORD
) {
191 * Compute difference between actual and desired value.
193 if ((wdiff
= *b
^ want
)) {
195 * Different, mark where we are and return.
197 xfs_trans_brelse(tp
, bp
);
198 i
+= XFS_NBWORD
- 1 - XFS_RTHIBIT(wdiff
);
199 *rtblock
= start
- i
+ 1;
204 * Go on to previous block if that's where the previous word is
205 * and we need the previous word.
207 if (--word
== -1 && i
< len
) {
209 * If done with this block, get the previous one.
211 xfs_trans_brelse(tp
, bp
);
212 error
= xfs_rtbuf_get(mp
, tp
, --block
, 0, &bp
);
216 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
217 word
= XFS_BLOCKWMASK(mp
);
221 * Go on to the previous word in the buffer.
227 * If not ending on a word boundary, deal with the last
232 * Calculate first (leftmost) bit number to look at,
233 * and mask for all the relevant bits in this word.
235 firstbit
= XFS_NBWORD
- (len
- i
);
236 mask
= (((xfs_rtword_t
)1 << (len
- i
)) - 1) << firstbit
;
238 * Compute difference between actual and desired value.
240 if ((wdiff
= (*b
^ want
) & mask
)) {
242 * Different, mark where we are and return.
244 xfs_trans_brelse(tp
, bp
);
245 i
+= XFS_NBWORD
- 1 - XFS_RTHIBIT(wdiff
);
246 *rtblock
= start
- i
+ 1;
252 * No match, return that we scanned the whole area.
254 xfs_trans_brelse(tp
, bp
);
255 *rtblock
= start
- i
+ 1;
260 * Searching forward from start to limit, find the first block whose
261 * allocated/free state is different from start's.
263 STATIC
int /* error */
265 xfs_mount_t
*mp
, /* file system mount point */
266 xfs_trans_t
*tp
, /* transaction pointer */
267 xfs_rtblock_t start
, /* starting block to look at */
268 xfs_rtblock_t limit
, /* last block to look at */
269 xfs_rtblock_t
*rtblock
) /* out: start block found */
271 xfs_rtword_t
*b
; /* current word in buffer */
272 int bit
; /* bit number in the word */
273 xfs_rtblock_t block
; /* bitmap block number */
274 xfs_buf_t
*bp
; /* buf for the block */
275 xfs_rtword_t
*bufp
; /* starting word in buffer */
276 int error
; /* error value */
277 xfs_rtblock_t i
; /* current bit number rel. to start */
278 xfs_rtblock_t lastbit
; /* last useful bit in the word */
279 xfs_rtblock_t len
; /* length of inspected area */
280 xfs_rtword_t mask
; /* mask of relevant bits for value */
281 xfs_rtword_t want
; /* mask for "good" values */
282 xfs_rtword_t wdiff
; /* difference from wanted value */
283 int word
; /* word number in the buffer */
286 * Compute and read in starting bitmap block for starting block.
288 block
= XFS_BITTOBLOCK(mp
, start
);
289 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
293 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
295 * Get the first word's index & point to it.
297 word
= XFS_BITTOWORD(mp
, start
);
299 bit
= (int)(start
& (XFS_NBWORD
- 1));
300 len
= limit
- start
+ 1;
302 * Compute match value, based on the bit at start: if 1 (free)
303 * then all-ones, else all-zeroes.
305 want
= (*b
& ((xfs_rtword_t
)1 << bit
)) ? -1 : 0;
307 * If the starting position is not word-aligned, deal with the
312 * Calculate last (rightmost) bit number to look at,
313 * and mask for all the relevant bits in this word.
315 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
316 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
318 * Calculate the difference between the value there
319 * and what we're looking for.
321 if ((wdiff
= (*b
^ want
) & mask
)) {
323 * Different. Mark where we are and return.
325 xfs_trans_brelse(tp
, bp
);
326 i
= XFS_RTLOBIT(wdiff
) - bit
;
327 *rtblock
= start
+ i
- 1;
332 * Go on to next block if that's where the next word is
333 * and we need the next word.
335 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
337 * If done with this block, get the previous one.
339 xfs_trans_brelse(tp
, bp
);
340 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
344 b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
348 * Go on to the previous word in the buffer.
354 * Starting on a word boundary, no partial word.
359 * Loop over whole words in buffers. When we use up one buffer
360 * we move on to the next one.
362 while (len
- i
>= XFS_NBWORD
) {
364 * Compute difference between actual and desired value.
366 if ((wdiff
= *b
^ want
)) {
368 * Different, mark where we are and return.
370 xfs_trans_brelse(tp
, bp
);
371 i
+= XFS_RTLOBIT(wdiff
);
372 *rtblock
= start
+ i
- 1;
377 * Go on to next block if that's where the next word is
378 * and we need the next word.
380 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
382 * If done with this block, get the next one.
384 xfs_trans_brelse(tp
, bp
);
385 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
389 b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
393 * Go on to the next word in the buffer.
399 * If not ending on a word boundary, deal with the last
402 if ((lastbit
= len
- i
)) {
404 * Calculate mask for all the relevant bits in this word.
406 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
408 * Compute difference between actual and desired value.
410 if ((wdiff
= (*b
^ want
) & mask
)) {
412 * Different, mark where we are and return.
414 xfs_trans_brelse(tp
, bp
);
415 i
+= XFS_RTLOBIT(wdiff
);
416 *rtblock
= start
+ i
- 1;
422 * No match, return that we scanned the whole area.
424 xfs_trans_brelse(tp
, bp
);
425 *rtblock
= start
+ i
- 1;
430 * Mark an extent specified by start and len freed.
431 * Updates all the summary information as well as the bitmap.
433 STATIC
int /* error */
435 xfs_mount_t
*mp
, /* file system mount point */
436 xfs_trans_t
*tp
, /* transaction pointer */
437 xfs_rtblock_t start
, /* starting block to free */
438 xfs_extlen_t len
, /* length to free */
439 xfs_buf_t
**rbpp
, /* in/out: summary block buffer */
440 xfs_fsblock_t
*rsb
) /* in/out: summary block number */
442 xfs_rtblock_t end
; /* end of the freed extent */
443 int error
; /* error value */
444 xfs_rtblock_t postblock
; /* first block freed > end */
445 xfs_rtblock_t preblock
; /* first block freed < start */
447 end
= start
+ len
- 1;
449 * Modify the bitmap to mark this extent freed.
451 error
= xfs_rtmodify_range(mp
, tp
, start
, len
, 1);
456 * Assume we're freeing out of the middle of an allocated extent.
457 * We need to find the beginning and end of the extent so we can
458 * properly update the summary.
460 error
= xfs_rtfind_back(mp
, tp
, start
, 0, &preblock
);
465 * Find the next allocated block (end of allocated extent).
467 error
= xfs_rtfind_forw(mp
, tp
, end
, mp
->m_sb
.sb_rextents
- 1,
470 * If there are blocks not being freed at the front of the
471 * old extent, add summary data for them to be allocated.
473 if (preblock
< start
) {
474 error
= xfs_rtmodify_summary(mp
, tp
,
475 XFS_RTBLOCKLOG(start
- preblock
),
476 XFS_BITTOBLOCK(mp
, preblock
), -1, rbpp
, rsb
);
482 * If there are blocks not being freed at the end of the
483 * old extent, add summary data for them to be allocated.
485 if (postblock
> end
) {
486 error
= xfs_rtmodify_summary(mp
, tp
,
487 XFS_RTBLOCKLOG(postblock
- end
),
488 XFS_BITTOBLOCK(mp
, end
+ 1), -1, rbpp
, rsb
);
494 * Increment the summary information corresponding to the entire
497 error
= xfs_rtmodify_summary(mp
, tp
,
498 XFS_RTBLOCKLOG(postblock
+ 1 - preblock
),
499 XFS_BITTOBLOCK(mp
, preblock
), 1, rbpp
, rsb
);
504 * Set the given range of bitmap bits to the given value.
505 * Do whatever I/O and logging is required.
507 STATIC
int /* error */
509 xfs_mount_t
*mp
, /* file system mount point */
510 xfs_trans_t
*tp
, /* transaction pointer */
511 xfs_rtblock_t start
, /* starting block to modify */
512 xfs_extlen_t len
, /* length of extent to modify */
513 int val
) /* 1 for free, 0 for allocated */
515 xfs_rtword_t
*b
; /* current word in buffer */
516 int bit
; /* bit number in the word */
517 xfs_rtblock_t block
; /* bitmap block number */
518 xfs_buf_t
*bp
; /* buf for the block */
519 xfs_rtword_t
*bufp
; /* starting word in buffer */
520 int error
; /* error value */
521 xfs_rtword_t
*first
; /* first used word in the buffer */
522 int i
; /* current bit number rel. to start */
523 int lastbit
; /* last useful bit in word */
524 xfs_rtword_t mask
; /* mask o frelevant bits for value */
525 int word
; /* word number in the buffer */
528 * Compute starting bitmap block number.
530 block
= XFS_BITTOBLOCK(mp
, start
);
532 * Read the bitmap block, and point to its data.
534 error
= xfs_rtbuf_get(mp
, tp
, block
, 0, &bp
);
538 bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
540 * Compute the starting word's address, and starting bit.
542 word
= XFS_BITTOWORD(mp
, start
);
543 first
= b
= &bufp
[word
];
544 bit
= (int)(start
& (XFS_NBWORD
- 1));
546 * 0 (allocated) => all zeroes; 1 (free) => all ones.
550 * If not starting on a word boundary, deal with the first
555 * Compute first bit not changed and mask of relevant bits.
557 lastbit
= XFS_RTMIN(bit
+ len
, XFS_NBWORD
);
558 mask
= (((xfs_rtword_t
)1 << (lastbit
- bit
)) - 1) << bit
;
560 * Set/clear the active bits.
568 * Go on to the next block if that's where the next word is
569 * and we need the next word.
571 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
573 * Log the changed part of this block.
576 xfs_trans_log_buf(tp
, bp
,
577 (uint
)((char *)first
- (char *)bufp
),
578 (uint
)((char *)b
- (char *)bufp
));
579 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
583 first
= b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
587 * Go on to the next word in the buffer
593 * Starting on a word boundary, no partial word.
598 * Loop over whole words in buffers. When we use up one buffer
599 * we move on to the next one.
601 while (len
- i
>= XFS_NBWORD
) {
603 * Set the word value correctly.
608 * Go on to the next block if that's where the next word is
609 * and we need the next word.
611 if (++word
== XFS_BLOCKWSIZE(mp
) && i
< len
) {
613 * Log the changed part of this block.
616 xfs_trans_log_buf(tp
, bp
,
617 (uint
)((char *)first
- (char *)bufp
),
618 (uint
)((char *)b
- (char *)bufp
));
619 error
= xfs_rtbuf_get(mp
, tp
, ++block
, 0, &bp
);
623 first
= b
= bufp
= (xfs_rtword_t
*)XFS_BUF_PTR(bp
);
627 * Go on to the next word in the buffer
633 * If not ending on a word boundary, deal with the last
636 if ((lastbit
= len
- i
)) {
638 * Compute a mask of relevant bits.
641 mask
= ((xfs_rtword_t
)1 << lastbit
) - 1;
643 * Set/clear the active bits.
652 * Log any remaining changed bytes.
655 xfs_trans_log_buf(tp
, bp
, (uint
)((char *)first
- (char *)bufp
),
656 (uint
)((char *)b
- (char *)bufp
- 1));
661 * Read and modify the summary information for a given extent size,
662 * bitmap block combination.
663 * Keeps track of a current summary block, so we don't keep reading
664 * it from the buffer cache.
666 STATIC
int /* error */
667 xfs_rtmodify_summary(
668 xfs_mount_t
*mp
, /* file system mount point */
669 xfs_trans_t
*tp
, /* transaction pointer */
670 int log
, /* log2 of extent size */
671 xfs_rtblock_t bbno
, /* bitmap block number */
672 int delta
, /* change to make to summary info */
673 xfs_buf_t
**rbpp
, /* in/out: summary block buffer */
674 xfs_fsblock_t
*rsb
) /* in/out: summary block number */
676 xfs_buf_t
*bp
; /* buffer for the summary block */
677 int error
; /* error value */
678 xfs_fsblock_t sb
; /* summary fsblock */
679 int so
; /* index into the summary file */
680 xfs_suminfo_t
*sp
; /* pointer to returned data */
683 * Compute entry number in the summary file.
685 so
= XFS_SUMOFFS(mp
, log
, bbno
);
687 * Compute the block number in the summary file.
689 sb
= XFS_SUMOFFSTOBLOCK(mp
, so
);
691 * If we have an old buffer, and the block number matches, use that.
693 if (rbpp
&& *rbpp
&& *rsb
== sb
)
696 * Otherwise we have to get the buffer.
700 * If there was an old one, get rid of it first.
703 xfs_trans_brelse(tp
, *rbpp
);
704 error
= xfs_rtbuf_get(mp
, tp
, sb
, 1, &bp
);
709 * Remember this buffer and block for the next call.
717 * Point to the summary information, modify and log it.
719 sp
= XFS_SUMPTR(mp
, bp
, so
);
721 xfs_trans_log_buf(tp
, bp
, (uint
)((char *)sp
- (char *)XFS_BUF_PTR(bp
)),
722 (uint
)((char *)sp
- (char *)XFS_BUF_PTR(bp
) + sizeof(*sp
) - 1));
727 * Free an extent in the realtime subvolume. Length is expressed in
728 * realtime extents, as is the block number.
732 xfs_trans_t
*tp
, /* transaction pointer */
733 xfs_rtblock_t bno
, /* starting block number to free */
734 xfs_extlen_t len
) /* length of extent freed */
736 int error
; /* error value */
737 xfs_inode_t
*ip
; /* bitmap file inode */
738 xfs_mount_t
*mp
; /* file system mount structure */
739 xfs_fsblock_t sb
; /* summary file block number */
740 xfs_buf_t
*sumbp
; /* summary file block buffer */
744 * Synchronize by locking the bitmap inode.
746 error
= xfs_trans_iget(mp
, tp
, mp
->m_sb
.sb_rbmino
, XFS_ILOCK_EXCL
, &ip
);
750 #if defined(__KERNEL__) && defined(DEBUG)
752 * Check to see that this whole range is currently allocated.
755 int stat
; /* result from checking range */
757 error
= xfs_rtcheck_alloc_range(mp
, tp
, bno
, len
, &stat
);
766 * Free the range of realtime blocks.
768 error
= xfs_rtfree_range(mp
, tp
, bno
, len
, &sumbp
, &sb
);
773 * Mark more blocks free in the superblock.
775 xfs_trans_mod_sb(tp
, XFS_TRANS_SB_FREXTENTS
, (long)len
);
777 * If we've now freed all the blocks, reset the file sequence
780 if (tp
->t_frextents_delta
+ mp
->m_sb
.sb_frextents
==
781 mp
->m_sb
.sb_rextents
) {
782 if (!(ip
->i_d
.di_flags
& XFS_DIFLAG_NEWRTBM
))
783 ip
->i_d
.di_flags
|= XFS_DIFLAG_NEWRTBM
;
784 *(__uint64_t
*)&ip
->i_d
.di_atime
= 0;
785 xfs_trans_log_inode(tp
, ip
, XFS_ILOG_CORE
);
791 * Initialize realtime fields in the mount structure.
795 xfs_mount_t
*mp
) /* file system mount structure */
797 xfs_buf_t
*bp
; /* buffer for last block of subvolume */
798 xfs_daddr_t d
; /* address of last block of subvolume */
799 int error
; /* error return value */
800 xfs_sb_t
*sbp
; /* filesystem superblock copy in mount */
803 if (sbp
->sb_rblocks
== 0)
805 if (kdev_none(mp
->m_rtdev
)) {
807 "XFS: This FS has an RT subvol - specify -o rtdev on mount\n");
808 return XFS_ERROR(ENODEV
);
810 mp
->m_rsumlevels
= sbp
->sb_rextslog
+ 1;
812 (uint
)sizeof(xfs_suminfo_t
) * mp
->m_rsumlevels
*
814 mp
->m_rsumsize
= roundup(mp
->m_rsumsize
, sbp
->sb_blocksize
);
815 mp
->m_rbmip
= mp
->m_rsumip
= NULL
;
817 * Check that the realtime section is an ok size.
819 d
= (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_rblocks
);
820 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_rblocks
) {
821 printk(KERN_WARNING
"XFS: RT mount - %llu != %llu\n",
822 (unsigned long long) XFS_BB_TO_FSB(mp
, d
),
823 (unsigned long long) mp
->m_sb
.sb_rblocks
);
824 return XFS_ERROR(E2BIG
);
826 error
= xfs_read_buf(mp
, m_rtdev_targp(mp
), d
- 1, 1, 0, &bp
);
829 "XFS: RT mount - xfs_read_buf returned %d\n", error
);
831 return XFS_ERROR(E2BIG
);