2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 File: VolumeAllocation.c
31 Contains: Routines for accessing and modifying the volume bitmap.
35 Copyright: © 1996-2001 by Apple Computer, Inc., all rights reserved.
42 Allocate space on a volume. Can allocate space contiguously.
43 If not contiguous, then allocation may be less than what was
44 asked for. Returns the starting block number, and number of
45 blocks. (Will only do a single extent???)
47 Deallocate a contiguous run of allocation blocks.
52 Mark a contiguous range of blocks as free. The corresponding
53 bits in the volume bitmap will be cleared.
55 Mark a contiguous range of blocks as allocated. The cor-
56 responding bits in the volume bitmap are set. Also tests to see
57 if any of the blocks were previously unallocated.
59 Find a contiguous range of blocks of a given size. The caller
60 specifies where to begin the search (by block number). The
61 block number of the first block in the range is returned.
63 Find and allocate a contiguous range of blocks up to a given size. The
64 first range of contiguous free blocks found are allocated, even if there
65 are fewer blocks than requested (and even if a contiguous range of blocks
66 of the given size exists elsewhere).
68 Find and allocate a contiguous range of blocks of a given size. If
69 a contiguous range of free blocks of the given size isn't found, then
70 the allocation fails (i.e. it is "all or nothing").
73 Try to allocate space from known free space in the volume's
77 Given an allocation block number, read the bitmap block that
78 contains that allocation block into a caller-supplied buffer.
81 Release a bitmap block back into the buffer cache.
84 #include "../../hfs_macos_defs.h"
86 #include <sys/types.h>
88 #include <sys/systm.h>
90 #include "../../hfs.h"
91 #include "../../hfs_dbg.h"
92 #include "../../hfs_format.h"
93 #include "../../hfs_endian.h"
95 #include "../headers/FileMgrInternal.h"
103 kBitsWithinWordMask
= kBitsPerWord
-1
106 #define kLowBitInWordMask 0x00000001ul
107 #define kHighBitInWordMask 0x80000000ul
108 #define kAllBitsSetInWord 0xFFFFFFFFul
111 static OSErr
ReadBitmapBlock(
117 static OSErr
ReleaseBitmapBlock(
122 static OSErr
BlockAllocateAny(
124 UInt32 startingBlock
,
128 UInt32
*actualStartBlock
,
129 UInt32
*actualNumBlocks
);
131 static OSErr
BlockAllocateContig(
133 UInt32 startingBlock
,
137 UInt32
*actualStartBlock
,
138 UInt32
*actualNumBlocks
);
140 static OSErr
BlockFindContiguous(
142 UInt32 startingBlock
,
147 UInt32
*actualStartBlock
,
148 UInt32
*actualNumBlocks
);
150 static OSErr
BlockAllocateKnown(
153 UInt32
*actualStartBlock
,
154 UInt32
*actualNumBlocks
);
158 ;________________________________________________________________________________
162 ; Function: Allocate space on a volume. If contiguous allocation is requested,
163 ; at least the requested number of bytes will be allocated or an
164 ; error will be returned. If contiguous allocation is not forced,
165 ; the space will be allocated at the first free fragment following
166 ; the requested starting allocation block. If there is not enough
167 ; room there, a block of less than the requested size will be
170 ; If the requested starting block is 0 (for new file allocations),
171 ; the volume's allocation block pointer will be used as a starting
175 ; vcb - Pointer to ExtendedVCB for the volume to allocate space on
176 ; fcb - Pointer to FCB for the file for which storage is being allocated
177 ; startingBlock - Preferred starting allocation block, 0 = no preference
178 ; forceContiguous - Force contiguous flag - if bit 0 set (NE), allocation is contiguous
179 ; or an error is returned
181 ; minBlocks - Number of blocks requested. If the allocation is non-contiguous,
182 ; less than this may actually be allocated
183 ; maxBlocks - The maximum number of blocks to allocate. If there is additional free
184 ; space after bytesRequested, then up to maxBlocks bytes should really
185 ; be allocated. (Used by ExtendFileC to round up allocations to a multiple
186 ; of the file's clump size.)
189 ; (result) - Error code, zero for successful allocation
190 ; *startBlock - Actual starting allocation block
191 ; *actualBlocks - Actual number of allocation blocks allocated
194 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
195 ;________________________________________________________________________________
199 OSErr
BlockAllocate (
200 ExtendedVCB
*vcb
, /* which volume to allocate space on */
201 UInt32 startingBlock
, /* preferred starting block, or 0 for no preference */
202 UInt32 minBlocks
, /* desired number of blocks to allocate */
203 UInt32 maxBlocks
, /* maximum number of blocks to allocate */
204 Boolean forceContiguous
, /* non-zero to force contiguous allocation and to force */
205 /* minBlocks bytes to actually be allocated */
208 UInt32
*actualStartBlock
, /* actual first block of allocation */
209 UInt32
*actualNumBlocks
) /* number of blocks actually allocated; if forceContiguous */
210 /* was zero, then this may represent fewer than minBlocks */
214 Boolean updateAllocPtr
= false; // true if nextAllocation needs to be updated
217 // Initialize outputs in case we get an error
219 *actualStartBlock
= 0;
220 *actualNumBlocks
= 0;
221 freeBlocks
= hfs_freeblks(VCBTOHFS(vcb
), 0);
224 // If the disk is already full, don't bother.
226 if (freeBlocks
== 0) {
230 if (forceContiguous
&& freeBlocks
< minBlocks
) {
235 * Clip if necessary so we don't over-subscribe the free blocks.
237 if (minBlocks
> freeBlocks
) {
238 minBlocks
= freeBlocks
;
240 if (maxBlocks
> freeBlocks
) {
241 maxBlocks
= freeBlocks
;
245 // If caller didn't specify a starting block number, then use the volume's
246 // next block to allocate from.
248 if (startingBlock
== 0) {
249 HFS_MOUNT_LOCK(vcb
, TRUE
);
250 startingBlock
= vcb
->nextAllocation
;
251 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
252 updateAllocPtr
= true;
254 if (startingBlock
>= vcb
->totalBlocks
) {
255 startingBlock
= 0; /* overflow so start at beginning */
259 // If the request must be contiguous, then find a sequence of free blocks
260 // that is long enough. Otherwise, find the first free block.
262 if (forceContiguous
) {
263 err
= BlockAllocateContig(vcb
, startingBlock
, minBlocks
, maxBlocks
,
264 useMetaZone
, actualStartBlock
, actualNumBlocks
);
266 * If we allocated from a new position then
267 * also update the roving allocatior.
269 if ((err
== noErr
) &&
270 (*actualStartBlock
> startingBlock
) &&
271 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
272 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
273 HFS_MOUNT_LOCK(vcb
, TRUE
);
274 vcb
->nextAllocation
= *actualStartBlock
;
275 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
279 * Scan the bitmap once, gather the N largest free extents, then
280 * allocate from these largest extents. Repeat as needed until
281 * we get all the space we needed. We could probably build up
282 * that list when the higher level caller tried (and failed) a
283 * contiguous allocation first.
285 err
= BlockAllocateKnown(vcb
, maxBlocks
, actualStartBlock
, actualNumBlocks
);
286 if (err
== dskFulErr
)
287 err
= BlockAllocateAny(vcb
, startingBlock
, vcb
->totalBlocks
,
288 maxBlocks
, useMetaZone
, actualStartBlock
,
290 if (err
== dskFulErr
)
291 err
= BlockAllocateAny(vcb
, 1, startingBlock
, maxBlocks
,
292 useMetaZone
, actualStartBlock
,
297 // if we actually allocated something then go update the
298 // various bits of state that we maintain regardless of
299 // whether there was an error (i.e. partial allocations
300 // still need to update things like the free block count).
302 if (*actualNumBlocks
!= 0) {
304 // If we used the volume's roving allocation pointer, then we need to update it.
305 // Adding in the length of the current allocation might reduce the next allocate
306 // call by avoiding a re-scan of the already allocated space. However, the clump
307 // just allocated can quite conceivably end up being truncated or released when
308 // the file is closed or its EOF changed. Leaving the allocation pointer at the
309 // start of the last allocation will avoid unnecessary fragmentation in this case.
311 HFS_MOUNT_LOCK(vcb
, TRUE
);
313 if (updateAllocPtr
&&
314 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
315 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
316 vcb
->nextAllocation
= *actualStartBlock
;
319 // Update the number of free blocks on the volume
321 vcb
->freeBlocks
-= *actualNumBlocks
;
323 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
325 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
333 ;________________________________________________________________________________
335 ; Routine: BlkDealloc
337 ; Function: Update the bitmap to deallocate a run of disk allocation blocks
340 ; vcb - Pointer to ExtendedVCB for the volume to free space on
341 ; firstBlock - First allocation block to be freed
342 ; numBlocks - Number of allocation blocks to free up (must be > 0!)
345 ; (result) - Result code
348 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
349 ;________________________________________________________________________________
353 OSErr
BlockDeallocate (
354 ExtendedVCB
*vcb
, // Which volume to deallocate space on
355 UInt32 firstBlock
, // First block in range to deallocate
356 UInt32 numBlocks
) // Number of contiguous blocks to deallocate
361 // If no blocks to deallocate, then exit early
363 if (numBlocks
== 0) {
369 // Call internal routine to free the sequence of blocks
371 err
= BlockMarkFree(vcb
, firstBlock
, numBlocks
);
376 // Update the volume's free block count, and mark the VCB as dirty.
378 HFS_MOUNT_LOCK(vcb
, TRUE
);
379 vcb
->freeBlocks
+= numBlocks
;
380 if (vcb
->nextAllocation
== (firstBlock
+ numBlocks
))
381 vcb
->nextAllocation
-= numBlocks
;
383 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
385 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
392 UInt8 freebitcount
[16] = {
393 4, 3, 3, 2, 3, 2, 2, 1, /* 0 1 2 3 4 5 6 7 */
394 3, 2, 2, 1, 2, 1, 1, 0, /* 8 9 A B C D E F */
399 MetaZoneFreeBlocks(ExtendedVCB
*vcb
)
412 bytesleft
= freeblocks
= 0;
414 bit
= VCBTOHFS(vcb
)->hfs_metazone_start
;
418 lastbit
= VCBTOHFS(vcb
)->hfs_metazone_end
;
419 bytesperblock
= vcb
->vcbVBMIOSize
;
422 * Count all the bits from bit to lastbit.
424 while (bit
< lastbit
) {
426 * Get next bitmap block.
428 if (bytesleft
== 0) {
430 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
433 if (ReadBitmapBlock(vcb
, bit
, &currCache
, &blockRef
) != 0) {
436 buffer
= (UInt8
*)currCache
;
437 bytesleft
= bytesperblock
;
440 freeblocks
+= freebitcount
[byte
& 0x0F];
441 freeblocks
+= freebitcount
[(byte
>> 4) & 0x0F];
446 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
453 * Obtain the next allocation block (bit) that's
454 * outside the metadata allocation zone.
456 static UInt32
NextBitmapBlock(
460 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
462 if ((hfsmp
->hfs_flags
& HFS_METADATA_ZONE
) == 0)
465 * Skip over metadata allocation zone.
467 if ((bit
>= hfsmp
->hfs_metazone_start
) &&
468 (bit
<= hfsmp
->hfs_metazone_end
)) {
469 bit
= hfsmp
->hfs_metazone_end
+ 1;
476 ;_______________________________________________________________________
478 ; Routine: ReadBitmapBlock
480 ; Function: Read in a bitmap block corresponding to a given allocation
481 ; block (bit). Return a pointer to the bitmap block.
484 ; vcb -- Pointer to ExtendedVCB
485 ; bit -- Allocation block whose bitmap block is desired
488 ; buffer -- Pointer to bitmap block corresonding to "block"
490 ;_______________________________________________________________________
492 static OSErr
ReadBitmapBlock(
499 struct buf
*bp
= NULL
;
500 struct vnode
*vp
= NULL
;
505 * volume bitmap blocks are protected by the allocation file lock
507 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
509 blockSize
= (UInt32
)vcb
->vcbVBMIOSize
;
510 block
= (daddr64_t
)(bit
/ (blockSize
* kBitsPerByte
));
512 if (vcb
->vcbSigWord
== kHFSPlusSigWord
) {
513 vp
= vcb
->hfs_allocation_vp
; /* use allocation file vnode */
516 vp
= VCBTOHFS(vcb
)->hfs_devvp
; /* use device I/O vnode */
517 block
+= vcb
->vcbVBMSt
; /* map to physical block */
520 err
= (int)buf_meta_bread(vp
, block
, blockSize
, NOCRED
, &bp
);
528 *blockRef
= (UInt32
)bp
;
529 *buffer
= (UInt32
*)buf_dataptr(bp
);
538 ;_______________________________________________________________________
540 ; Routine: ReleaseBitmapBlock
542 ; Function: Relase a bitmap block.
548 ;_______________________________________________________________________
550 static OSErr
ReleaseBitmapBlock(
555 struct buf
*bp
= (struct buf
*)blockRef
;
559 panic("ReleaseBitmapBlock: missing bp");
566 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
569 journal_modify_block_end(hfsmp
->jnl
, bp
);
583 _______________________________________________________________________
585 Routine: BlockAllocateContig
587 Function: Allocate a contiguous group of allocation blocks. The
588 allocation is all-or-nothing. The caller guarantees that
589 there are enough free blocks (though they may not be
590 contiguous, in which case this call will fail).
593 vcb Pointer to volume where space is to be allocated
594 startingBlock Preferred first block for allocation
595 minBlocks Minimum number of contiguous blocks to allocate
596 maxBlocks Maximum number of contiguous blocks to allocate
600 actualStartBlock First block of range allocated, or 0 if error
601 actualNumBlocks Number of blocks allocated, or 0 if error
602 _______________________________________________________________________
604 static OSErr
BlockAllocateContig(
606 UInt32 startingBlock
,
610 UInt32
*actualStartBlock
,
611 UInt32
*actualNumBlocks
)
616 // Find a contiguous group of blocks at least minBlocks long.
617 // Determine the number of contiguous blocks available (up
622 * NOTE: If the only contiguous free extent of at least minBlocks
623 * crosses startingBlock (i.e. starts before, ends after), then we
624 * won't find it. Earlier versions *did* find this case by letting
625 * the second search look past startingBlock by minBlocks. But
626 * with the free extent cache, this can lead to duplicate entries
627 * in the cache, causing the same blocks to be allocated twice.
629 err
= BlockFindContiguous(vcb
, startingBlock
, vcb
->totalBlocks
, minBlocks
,
630 maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
631 if (err
== dskFulErr
&& startingBlock
!= 0) {
633 * Constrain the endingBlock so we don't bother looking for ranges
634 * that would overlap those found in the previous call.
636 err
= BlockFindContiguous(vcb
, 1, startingBlock
, minBlocks
, maxBlocks
,
637 useMetaZone
, actualStartBlock
, actualNumBlocks
);
639 if (err
!= noErr
) goto Exit
;
642 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->totalBlocks
)
643 panic("BlockAllocateContig: allocation overflow on \"%s\"", vcb
->vcbVN
);
646 // Now mark those blocks allocated.
648 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
652 *actualStartBlock
= 0;
653 *actualNumBlocks
= 0;
660 _______________________________________________________________________
662 Routine: BlockAllocateAny
664 Function: Allocate one or more allocation blocks. If there are fewer
665 free blocks than requested, all free blocks will be
666 allocated. The caller guarantees that there is at least
670 vcb Pointer to volume where space is to be allocated
671 startingBlock Preferred first block for allocation
672 endingBlock Last block to check + 1
673 maxBlocks Maximum number of contiguous blocks to allocate
677 actualStartBlock First block of range allocated, or 0 if error
678 actualNumBlocks Number of blocks allocated, or 0 if error
679 _______________________________________________________________________
681 static OSErr
BlockAllocateAny(
683 UInt32 startingBlock
,
684 register UInt32 endingBlock
,
687 UInt32
*actualStartBlock
,
688 UInt32
*actualNumBlocks
)
691 register UInt32 block
; // current block number
692 register UInt32 currentWord
; // Pointer to current word within bitmap block
693 register UInt32 bitMask
; // Word with given bits already set (ready to OR in)
694 register UInt32 wordsLeft
; // Number of words left in this bitmap block
695 UInt32
*buffer
= NULL
;
696 UInt32
*currCache
= NULL
;
699 UInt32 wordsPerBlock
;
700 Boolean dirty
= false;
701 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
703 // Since this routine doesn't wrap around
704 if (maxBlocks
> (endingBlock
- startingBlock
)) {
705 maxBlocks
= endingBlock
- startingBlock
;
709 * Skip over metadata blocks.
712 startingBlock
= NextBitmapBlock(vcb
, startingBlock
);
715 // Pre-read the first bitmap block
717 err
= ReadBitmapBlock(vcb
, startingBlock
, &currCache
, &blockRef
);
718 if (err
!= noErr
) goto Exit
;
722 // Set up the current position within the block
725 UInt32 wordIndexInBlock
;
727 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
728 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
730 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
731 buffer
+= wordIndexInBlock
;
732 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
733 currentWord
= SWAP_BE32 (*buffer
);
734 bitMask
= kHighBitInWordMask
>> (startingBlock
& kBitsWithinWordMask
);
738 // Find the first unallocated block
741 while (block
< endingBlock
) {
742 if ((currentWord
& bitMask
) == 0)
750 bitMask
= kHighBitInWordMask
;
753 if (--wordsLeft
== 0) {
755 buffer
= currCache
= NULL
;
756 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
757 if (err
!= noErr
) goto Exit
;
760 * Skip over metadata blocks.
763 block
= NextBitmapBlock(vcb
, block
);
764 if (block
>= endingBlock
) {
769 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
770 if (err
!= noErr
) goto Exit
;
773 wordsLeft
= wordsPerBlock
;
775 currentWord
= SWAP_BE32 (*buffer
);
779 // Did we get to the end of the bitmap before finding a free block?
780 // If so, then couldn't allocate anything.
781 if (block
>= endingBlock
) {
786 // Return the first block in the allocated range
787 *actualStartBlock
= block
;
790 // If we could get the desired number of blocks before hitting endingBlock,
791 // then adjust endingBlock so we won't keep looking. Ideally, the comparison
792 // would be (block + maxBlocks) < endingBlock, but that could overflow. The
793 // comparison below yields identical results, but without overflow.
794 if (block
< (endingBlock
-maxBlocks
)) {
795 endingBlock
= block
+ maxBlocks
; // if we get this far, we've found enough
800 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
804 // Allocate all of the consecutive blocks
806 while ((currentWord
& bitMask
) == 0) {
807 // Allocate this block
808 currentWord
|= bitMask
;
810 // Move to the next block. If no more, then exit.
812 if (block
== endingBlock
)
818 *buffer
= SWAP_BE32 (currentWord
); // update value in bitmap
821 bitMask
= kHighBitInWordMask
;
824 if (--wordsLeft
== 0) {
826 buffer
= currCache
= NULL
;
827 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
828 if (err
!= noErr
) goto Exit
;
831 * Skip over metadata blocks.
836 nextBlock
= NextBitmapBlock(vcb
, block
);
837 if (nextBlock
!= block
) {
838 goto Exit
; /* allocation gap, so stop */
842 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
843 if (err
!= noErr
) goto Exit
;
848 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
851 wordsLeft
= wordsPerBlock
;
854 currentWord
= SWAP_BE32 (*buffer
);
857 *buffer
= SWAP_BE32 (currentWord
); // update the last change
861 *actualNumBlocks
= block
- *actualStartBlock
;
864 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->totalBlocks
)
865 panic("BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
868 *actualStartBlock
= 0;
869 *actualNumBlocks
= 0;
873 (void) ReleaseBitmapBlock(vcb
, blockRef
, dirty
);
880 _______________________________________________________________________
882 Routine: BlockAllocateKnown
884 Function: Try to allocate space from known free space in the free
888 vcb Pointer to volume where space is to be allocated
889 maxBlocks Maximum number of contiguous blocks to allocate
892 actualStartBlock First block of range allocated, or 0 if error
893 actualNumBlocks Number of blocks allocated, or 0 if error
896 dskFulErr Free extent cache is empty
897 _______________________________________________________________________
899 static OSErr
BlockAllocateKnown(
902 UInt32
*actualStartBlock
,
903 UInt32
*actualNumBlocks
)
907 UInt32 newStartBlock
, newBlockCount
;
909 if (vcb
->vcbFreeExtCnt
== 0)
912 // Just grab up to maxBlocks of the first (largest) free exent.
913 *actualStartBlock
= vcb
->vcbFreeExt
[0].startBlock
;
914 foundBlocks
= vcb
->vcbFreeExt
[0].blockCount
;
915 if (foundBlocks
> maxBlocks
)
916 foundBlocks
= maxBlocks
;
917 *actualNumBlocks
= foundBlocks
;
919 // Adjust the start and length of that extent.
920 newStartBlock
= vcb
->vcbFreeExt
[0].startBlock
+ foundBlocks
;
921 newBlockCount
= vcb
->vcbFreeExt
[0].blockCount
- foundBlocks
;
923 // The first extent might not be the largest anymore. Bubble up any
924 // (now larger) extents to the top of the list.
925 for (i
=1; i
<vcb
->vcbFreeExtCnt
; ++i
)
927 if (vcb
->vcbFreeExt
[i
].blockCount
> newBlockCount
)
929 vcb
->vcbFreeExt
[i
-1].startBlock
= vcb
->vcbFreeExt
[i
].startBlock
;
930 vcb
->vcbFreeExt
[i
-1].blockCount
= vcb
->vcbFreeExt
[i
].blockCount
;
938 // If this is now the smallest known free extent, then it might be smaller than
939 // other extents we didn't keep track of. So, just forget about this extent.
940 // After the previous loop, (i-1) is the index of the extent we just allocated from.
941 if (i
== vcb
->vcbFreeExtCnt
)
943 // It's now the smallest extent, so forget about it
944 --vcb
->vcbFreeExtCnt
;
948 // It's not the smallest, so store it in its proper place
949 vcb
->vcbFreeExt
[i
-1].startBlock
= newStartBlock
;
950 vcb
->vcbFreeExt
[i
-1].blockCount
= newBlockCount
;
954 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->totalBlocks
)
955 panic("BlockAllocateKnown: allocation overflow on \"%s\"", vcb
->vcbVN
);
958 // Now mark the found extent in the bitmap
960 return BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
966 _______________________________________________________________________
968 Routine: BlockMarkAllocated
970 Function: Mark a contiguous group of blocks as allocated (set in the
971 bitmap). It assumes those bits are currently marked
972 deallocated (clear in the bitmap).
975 vcb Pointer to volume where space is to be allocated
976 startingBlock First block number to mark as allocated
977 numBlocks Number of blocks to mark as allocated
978 _______________________________________________________________________
981 OSErr
BlockMarkAllocated(
983 UInt32 startingBlock
,
984 register UInt32 numBlocks
)
987 register UInt32
*currentWord
; // Pointer to current word within bitmap block
988 register UInt32 wordsLeft
; // Number of words left in this bitmap block
989 register UInt32 bitMask
; // Word with given bits already set (ready to OR in)
990 UInt32 firstBit
; // Bit index within word of first bit to allocate
991 UInt32 numBits
; // Number of bits in word to allocate
992 UInt32
*buffer
= NULL
;
995 UInt32 wordsPerBlock
;
997 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1001 // Pre-read the bitmap block containing the first word of allocation
1004 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1005 if (err
!= noErr
) goto Exit
;
1007 // Initialize currentWord, and wordsLeft.
1010 UInt32 wordIndexInBlock
;
1012 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1013 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1015 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1016 currentWord
= buffer
+ wordIndexInBlock
;
1017 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1022 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1026 // If the first block to allocate doesn't start on a word
1027 // boundary in the bitmap, then treat that first word
1031 firstBit
= startingBlock
% kBitsPerWord
;
1032 if (firstBit
!= 0) {
1033 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1034 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1035 if (numBits
> numBlocks
) {
1036 numBits
= numBlocks
; // entire allocation is inside this one word
1037 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1040 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1041 panic("BlockMarkAllocated: blocks already allocated!");
1044 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1045 numBlocks
-= numBits
; // adjust number of blocks left to allocate
1047 ++currentWord
; // move to next word
1048 --wordsLeft
; // one less word left in this block
1052 // Allocate whole words (32 blocks) at a time.
1055 bitMask
= kAllBitsSetInWord
; // put this in a register for 68K
1056 while (numBlocks
>= kBitsPerWord
) {
1057 if (wordsLeft
== 0) {
1058 // Read in the next bitmap block
1059 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1062 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1063 if (err
!= noErr
) goto Exit
;
1065 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1066 if (err
!= noErr
) goto Exit
;
1070 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1073 // Readjust currentWord and wordsLeft
1074 currentWord
= buffer
;
1075 wordsLeft
= wordsPerBlock
;
1078 if (*currentWord
!= 0) {
1079 panic("BlockMarkAllocated: blocks already allocated!");
1082 *currentWord
= SWAP_BE32 (bitMask
);
1083 numBlocks
-= kBitsPerWord
;
1085 ++currentWord
; // move to next word
1086 --wordsLeft
; // one less word left in this block
1090 // Allocate any remaining blocks.
1093 if (numBlocks
!= 0) {
1094 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1095 if (wordsLeft
== 0) {
1096 // Read in the next bitmap block
1097 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1100 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1101 if (err
!= noErr
) goto Exit
;
1103 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1104 if (err
!= noErr
) goto Exit
;
1108 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1111 // Readjust currentWord and wordsLeft
1112 currentWord
= buffer
;
1113 wordsLeft
= wordsPerBlock
;
1116 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1117 panic("BlockMarkAllocated: blocks already allocated!");
1120 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1122 // No need to update currentWord or wordsLeft
1128 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1135 _______________________________________________________________________
1137 Routine: BlockMarkFree
1139 Function: Mark a contiguous group of blocks as free (clear in the
1140 bitmap). It assumes those bits are currently marked
1141 allocated (set in the bitmap).
1144 vcb Pointer to volume where space is to be freed
1145 startingBlock First block number to mark as freed
1146 numBlocks Number of blocks to mark as freed
1147 _______________________________________________________________________
1150 OSErr
BlockMarkFree(
1152 UInt32 startingBlock
,
1153 register UInt32 numBlocks
)
1156 register UInt32
*currentWord
; // Pointer to current word within bitmap block
1157 register UInt32 wordsLeft
; // Number of words left in this bitmap block
1158 register UInt32 bitMask
; // Word with given bits already set (ready to OR in)
1159 UInt32 firstBit
; // Bit index within word of first bit to allocate
1160 UInt32 numBits
; // Number of bits in word to allocate
1161 UInt32
*buffer
= NULL
;
1163 UInt32 bitsPerBlock
;
1164 UInt32 wordsPerBlock
;
1166 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1168 if (startingBlock
+ numBlocks
> vcb
->totalBlocks
) {
1169 panic("hfs: block mark free: trying to free non-existent blocks (%d %d %d)\n",
1170 startingBlock
, numBlocks
, vcb
->totalBlocks
);
1175 // Pre-read the bitmap block containing the first word of allocation
1178 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1179 if (err
!= noErr
) goto Exit
;
1182 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1186 // Initialize currentWord, and wordsLeft.
1189 UInt32 wordIndexInBlock
;
1191 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1192 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1194 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1195 currentWord
= buffer
+ wordIndexInBlock
;
1196 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1200 // If the first block to free doesn't start on a word
1201 // boundary in the bitmap, then treat that first word
1205 firstBit
= startingBlock
% kBitsPerWord
;
1206 if (firstBit
!= 0) {
1207 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1208 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1209 if (numBits
> numBlocks
) {
1210 numBits
= numBlocks
; // entire allocation is inside this one word
1211 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1213 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1216 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1217 numBlocks
-= numBits
; // adjust number of blocks left to free
1219 ++currentWord
; // move to next word
1220 --wordsLeft
; // one less word left in this block
1224 // Free whole words (32 blocks) at a time.
1227 while (numBlocks
>= kBitsPerWord
) {
1228 if (wordsLeft
== 0) {
1229 // Read in the next bitmap block
1230 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1233 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1234 if (err
!= noErr
) goto Exit
;
1236 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1237 if (err
!= noErr
) goto Exit
;
1241 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1244 // Readjust currentWord and wordsLeft
1245 currentWord
= buffer
;
1246 wordsLeft
= wordsPerBlock
;
1248 if (*currentWord
!= SWAP_BE32 (kAllBitsSetInWord
)) {
1251 *currentWord
= 0; // clear the entire word
1252 numBlocks
-= kBitsPerWord
;
1254 ++currentWord
; // move to next word
1255 --wordsLeft
; // one less word left in this block
1259 // Free any remaining blocks.
1262 if (numBlocks
!= 0) {
1263 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1264 if (wordsLeft
== 0) {
1265 // Read in the next bitmap block
1266 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1269 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1270 if (err
!= noErr
) goto Exit
;
1272 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1273 if (err
!= noErr
) goto Exit
;
1277 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1280 // Readjust currentWord and wordsLeft
1281 currentWord
= buffer
;
1282 wordsLeft
= wordsPerBlock
;
1284 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1287 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1289 // No need to update currentWord or wordsLeft
1295 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1301 panic("BlockMarkFree: blocks not allocated!");
1303 printf("hfs: WARNING - blocks on volume %s not allocated!\n", vcb
->vcbVN
);
1304 vcb
->vcbAtrb
|= kHFSVolumeInconsistentMask
;
1313 _______________________________________________________________________
1315 Routine: BlockFindContiguous
1317 Function: Find a contiguous range of blocks that are free (bits
1318 clear in the bitmap). If a contiguous range of the
1319 minimum size can't be found, an error will be returned.
1322 vcb Pointer to volume where space is to be allocated
1323 startingBlock Preferred first block of range
1324 endingBlock Last possible block in range + 1
1325 minBlocks Minimum number of blocks needed. Must be > 0.
1326 maxBlocks Maximum (ideal) number of blocks desired
1327 useMetaZone OK to dip into metadata allocation zone
1330 actualStartBlock First block of range found, or 0 if error
1331 actualNumBlocks Number of blocks found, or 0 if error
1334 noErr Found at least minBlocks contiguous
1335 dskFulErr No contiguous space found, or all less than minBlocks
1336 _______________________________________________________________________
1339 static OSErr
BlockFindContiguous(
1341 UInt32 startingBlock
,
1345 Boolean useMetaZone
,
1346 UInt32
*actualStartBlock
,
1347 UInt32
*actualNumBlocks
)
1350 register UInt32 currentBlock
; // Block we're currently looking at.
1351 UInt32 firstBlock
; // First free block in current extent.
1352 UInt32 stopBlock
; // If we get to this block, stop searching for first free block.
1353 UInt32 foundBlocks
; // Number of contiguous free blocks in current extent.
1354 UInt32
*buffer
= NULL
;
1355 register UInt32
*currentWord
;
1356 register UInt32 bitMask
;
1357 register UInt32 wordsLeft
;
1358 register UInt32 tempWord
;
1360 UInt32 wordsPerBlock
;
1363 * When we're skipping the metadata zone and the start/end
1364 * range overlaps with the metadata zone then adjust the
1365 * start to be outside of the metadata zone. If the range
1366 * is entirely inside the metadata zone then we can deny the
1367 * request (dskFulErr).
1369 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
1370 if (startingBlock
<= vcb
->hfs_metazone_end
) {
1371 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
1372 startingBlock
= vcb
->hfs_metazone_end
+ 1;
1378 if ((endingBlock
- startingBlock
) < minBlocks
)
1380 // The set of blocks we're checking is smaller than the minimum number
1381 // of blocks, so we couldn't possibly find a good range.
1385 stopBlock
= endingBlock
- minBlocks
+ 1;
1386 currentBlock
= startingBlock
;
1390 * Skip over metadata blocks.
1393 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1396 // Pre-read the first bitmap block.
1398 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1399 if ( err
!= noErr
) goto ErrorExit
;
1402 // Figure out where currentBlock is within the buffer.
1404 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1406 wordsLeft
= (currentBlock
/ kBitsPerWord
) & (wordsPerBlock
-1); // Current index into buffer
1407 currentWord
= buffer
+ wordsLeft
;
1408 wordsLeft
= wordsPerBlock
- wordsLeft
;
1414 //============================================================
1415 // Look for a free block, skipping over allocated blocks.
1416 //============================================================
1419 // Check an initial partial word (if any)
1421 bitMask
= currentBlock
& kBitsWithinWordMask
;
1424 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1425 bitMask
= kHighBitInWordMask
>> bitMask
;
1426 while (tempWord
& bitMask
)
1432 // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)?
1436 // Didn't find any unused bits, so we're done with this word.
1442 // Check whole words
1444 while (currentBlock
< stopBlock
)
1446 // See if it's time to read another block.
1450 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1451 if (err
!= noErr
) goto ErrorExit
;
1454 * Skip over metadata blocks.
1457 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1458 if (currentBlock
>= stopBlock
) {
1463 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1464 if ( err
!= noErr
) goto ErrorExit
;
1466 currentWord
= buffer
;
1467 wordsLeft
= wordsPerBlock
;
1470 // See if any of the bits are clear
1471 if ((tempWord
= SWAP_BE32(*currentWord
)) + 1) // non-zero if any bits were clear
1473 // Figure out which bit is clear
1474 bitMask
= kHighBitInWordMask
;
1475 while (tempWord
& bitMask
)
1481 break; // Found the free bit; break out to FoundUnused.
1484 // Keep looking at the next word
1485 currentBlock
+= kBitsPerWord
;
1491 // Make sure the unused bit is early enough to use
1492 if (currentBlock
>= stopBlock
)
1497 // Remember the start of the extent
1498 firstBlock
= currentBlock
;
1500 //============================================================
1501 // Count the number of contiguous free blocks.
1502 //============================================================
1505 // Check an initial partial word (if any)
1507 bitMask
= currentBlock
& kBitsWithinWordMask
;
1510 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1511 bitMask
= kHighBitInWordMask
>> bitMask
;
1512 while (bitMask
&& !(tempWord
& bitMask
))
1518 // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)?
1522 // Didn't find any used bits, so we're done with this word.
1528 // Check whole words
1530 while (currentBlock
< endingBlock
)
1532 // See if it's time to read another block.
1536 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1537 if (err
!= noErr
) goto ErrorExit
;
1540 * Skip over metadata blocks.
1545 nextBlock
= NextBitmapBlock(vcb
, currentBlock
);
1546 if (nextBlock
!= currentBlock
) {
1547 goto LoopExit
; /* allocation gap, so stop */
1551 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1552 if ( err
!= noErr
) goto ErrorExit
;
1554 currentWord
= buffer
;
1555 wordsLeft
= wordsPerBlock
;
1558 // See if any of the bits are set
1559 if ((tempWord
= SWAP_BE32(*currentWord
)) != 0)
1561 // Figure out which bit is set
1562 bitMask
= kHighBitInWordMask
;
1563 while (!(tempWord
& bitMask
))
1569 break; // Found the used bit; break out to FoundUsed.
1572 // Keep looking at the next word
1573 currentBlock
+= kBitsPerWord
;
1577 // If we found at least maxBlocks, we can quit early.
1578 if ((currentBlock
- firstBlock
) >= maxBlocks
)
1583 // Make sure we didn't run out of bitmap looking for a used block.
1584 // If so, pin to the end of the bitmap.
1585 if (currentBlock
> endingBlock
)
1586 currentBlock
= endingBlock
;
1588 // Figure out how many contiguous free blocks there were.
1589 // Pin the answer to maxBlocks.
1590 foundBlocks
= currentBlock
- firstBlock
;
1591 if (foundBlocks
> maxBlocks
)
1592 foundBlocks
= maxBlocks
;
1593 if (foundBlocks
>= minBlocks
)
1594 break; // Found what we needed!
1596 // This free chunk wasn't big enough. Try inserting it into the free extent cache in case
1597 // the allocation wasn't forced contiguous.
1598 tempWord
= vcb
->vcbFreeExtCnt
;
1599 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< foundBlocks
)
1601 if (tempWord
< kMaxFreeExtents
)
1603 // We're going to add this extent. Bubble any smaller extents down in the list.
1604 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< foundBlocks
)
1606 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1609 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1610 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1612 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
)
1613 ++vcb
->vcbFreeExtCnt
;
1615 } while (currentBlock
< stopBlock
);
1618 // Return the outputs.
1619 if (foundBlocks
< minBlocks
)
1624 *actualStartBlock
= 0;
1625 *actualNumBlocks
= 0;
1630 *actualStartBlock
= firstBlock
;
1631 *actualNumBlocks
= foundBlocks
;
1635 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1641 * Test to see if any blocks in a range are allocated.
1643 * The journal or allocation file lock must be held.
1647 hfs_isallocated(struct hfsmount
*hfsmp
, u_long startingBlock
, u_long numBlocks
)
1649 UInt32
*currentWord
; // Pointer to current word within bitmap block
1650 UInt32 wordsLeft
; // Number of words left in this bitmap block
1651 UInt32 bitMask
; // Word with given bits already set (ready to test)
1652 UInt32 firstBit
; // Bit index within word of first bit to allocate
1653 UInt32 numBits
; // Number of bits in word to allocate
1654 UInt32
*buffer
= NULL
;
1656 UInt32 bitsPerBlock
;
1657 UInt32 wordsPerBlock
;
1662 * Pre-read the bitmap block containing the first word of allocation
1664 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1669 * Initialize currentWord, and wordsLeft.
1672 UInt32 wordIndexInBlock
;
1674 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
1675 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
1677 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1678 currentWord
= buffer
+ wordIndexInBlock
;
1679 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1683 * First test any non word aligned bits.
1685 firstBit
= startingBlock
% kBitsPerWord
;
1686 if (firstBit
!= 0) {
1687 bitMask
= kAllBitsSetInWord
>> firstBit
;
1688 numBits
= kBitsPerWord
- firstBit
;
1689 if (numBits
> numBlocks
) {
1690 numBits
= numBlocks
;
1691 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
1693 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1697 numBlocks
-= numBits
;
1703 * Test whole words (32 blocks) at a time.
1705 while (numBlocks
>= kBitsPerWord
) {
1706 if (wordsLeft
== 0) {
1707 /* Read in the next bitmap block. */
1708 startingBlock
+= bitsPerBlock
;
1711 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1712 if (error
) goto Exit
;
1714 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1715 if (error
) goto Exit
;
1717 /* Readjust currentWord and wordsLeft. */
1718 currentWord
= buffer
;
1719 wordsLeft
= wordsPerBlock
;
1721 if (*currentWord
!= 0) {
1725 numBlocks
-= kBitsPerWord
;
1731 * Test any remaining blocks.
1733 if (numBlocks
!= 0) {
1734 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
);
1735 if (wordsLeft
== 0) {
1736 /* Read in the next bitmap block */
1737 startingBlock
+= bitsPerBlock
;
1740 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1741 if (error
) goto Exit
;
1743 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1744 if (error
) goto Exit
;
1746 currentWord
= buffer
;
1747 wordsLeft
= wordsPerBlock
;
1749 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1756 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);