2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 File: VolumeAllocation.c
25 Contains: Routines for accessing and modifying the volume bitmap.
29 Copyright: © 1996-2001 by Apple Computer, Inc., all rights reserved.
36 Allocate space on a volume. Can allocate space contiguously.
37 If not contiguous, then allocation may be less than what was
38 asked for. Returns the starting block number, and number of
39 blocks. (Will only do a single extent???)
41 Deallocate a contiguous run of allocation blocks.
46 Mark a contiguous range of blocks as free. The corresponding
47 bits in the volume bitmap will be cleared.
49 Mark a contiguous range of blocks as allocated. The cor-
50 responding bits in the volume bitmap are set. Also tests to see
51 if any of the blocks were previously unallocated.
53 Find a contiguous range of blocks of a given size. The caller
54 specifies where to begin the search (by block number). The
55 block number of the first block in the range is returned.
57 Find and allocate a contiguous range of blocks up to a given size. The
58 first range of contiguous free blocks found are allocated, even if there
59 are fewer blocks than requested (and even if a contiguous range of blocks
60 of the given size exists elsewhere).
62 Find and allocate a contiguous range of blocks of a given size. If
63 a contiguous range of free blocks of the given size isn't found, then
64 the allocation fails (i.e. it is "all or nothing").
67 Try to allocate space from known free space in the volume's
71 Given an allocation block number, read the bitmap block that
72 contains that allocation block into a caller-supplied buffer.
75 Release a bitmap block back into the buffer cache.
78 #include "../../hfs_macos_defs.h"
80 #include <sys/types.h>
82 #include <sys/systm.h>
84 #include "../../hfs.h"
85 #include "../../hfs_dbg.h"
86 #include "../../hfs_format.h"
87 #include "../../hfs_endian.h"
89 #include "../headers/FileMgrInternal.h"
97 kBitsWithinWordMask
= kBitsPerWord
-1
100 #define kLowBitInWordMask 0x00000001ul
101 #define kHighBitInWordMask 0x80000000ul
102 #define kAllBitsSetInWord 0xFFFFFFFFul
105 static OSErr
ReadBitmapBlock(
111 static OSErr
ReleaseBitmapBlock(
116 static OSErr
BlockAllocateAny(
118 UInt32 startingBlock
,
122 UInt32
*actualStartBlock
,
123 UInt32
*actualNumBlocks
);
125 static OSErr
BlockAllocateContig(
127 UInt32 startingBlock
,
131 UInt32
*actualStartBlock
,
132 UInt32
*actualNumBlocks
);
134 static OSErr
BlockFindContiguous(
136 UInt32 startingBlock
,
141 UInt32
*actualStartBlock
,
142 UInt32
*actualNumBlocks
);
144 static OSErr
BlockAllocateKnown(
147 UInt32
*actualStartBlock
,
148 UInt32
*actualNumBlocks
);
152 ;________________________________________________________________________________
156 ; Function: Allocate space on a volume. If contiguous allocation is requested,
157 ; at least the requested number of bytes will be allocated or an
158 ; error will be returned. If contiguous allocation is not forced,
159 ; the space will be allocated at the first free fragment following
160 ; the requested starting allocation block. If there is not enough
161 ; room there, a block of less than the requested size will be
164 ; If the requested starting block is 0 (for new file allocations),
165 ; the volume's allocation block pointer will be used as a starting
169 ; vcb - Pointer to ExtendedVCB for the volume to allocate space on
170 ; fcb - Pointer to FCB for the file for which storage is being allocated
171 ; startingBlock - Preferred starting allocation block, 0 = no preference
172 ; forceContiguous - Force contiguous flag - if bit 0 set (NE), allocation is contiguous
173 ; or an error is returned
175 ; minBlocks - Number of blocks requested. If the allocation is non-contiguous,
176 ; less than this may actually be allocated
177 ; maxBlocks - The maximum number of blocks to allocate. If there is additional free
178 ; space after bytesRequested, then up to maxBlocks bytes should really
179 ; be allocated. (Used by ExtendFileC to round up allocations to a multiple
180 ; of the file's clump size.)
183 ; (result) - Error code, zero for successful allocation
184 ; *startBlock - Actual starting allocation block
185 ; *actualBlocks - Actual number of allocation blocks allocated
188 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
189 ;________________________________________________________________________________
193 OSErr
BlockAllocate (
194 ExtendedVCB
*vcb
, /* which volume to allocate space on */
195 UInt32 startingBlock
, /* preferred starting block, or 0 for no preference */
196 UInt32 minBlocks
, /* desired number of blocks to allocate */
197 UInt32 maxBlocks
, /* maximum number of blocks to allocate */
198 Boolean forceContiguous
, /* non-zero to force contiguous allocation and to force */
199 /* minBlocks bytes to actually be allocated */
202 UInt32
*actualStartBlock
, /* actual first block of allocation */
203 UInt32
*actualNumBlocks
) /* number of blocks actually allocated; if forceContiguous */
204 /* was zero, then this may represent fewer than minBlocks */
208 Boolean updateAllocPtr
= false; // true if nextAllocation needs to be updated
211 // Initialize outputs in case we get an error
213 *actualStartBlock
= 0;
214 *actualNumBlocks
= 0;
215 freeBlocks
= hfs_freeblks(VCBTOHFS(vcb
), 0);
218 // If the disk is already full, don't bother.
220 if (freeBlocks
== 0) {
224 if (forceContiguous
&& freeBlocks
< minBlocks
) {
229 * Clip if necessary so we don't over-subscribe the free blocks.
231 if (minBlocks
> freeBlocks
) {
232 minBlocks
= freeBlocks
;
234 if (maxBlocks
> freeBlocks
) {
235 maxBlocks
= freeBlocks
;
239 // If caller didn't specify a starting block number, then use the volume's
240 // next block to allocate from.
242 if (startingBlock
== 0) {
243 HFS_MOUNT_LOCK(vcb
, TRUE
);
244 startingBlock
= vcb
->nextAllocation
;
245 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
246 updateAllocPtr
= true;
248 if (startingBlock
>= vcb
->totalBlocks
) {
249 startingBlock
= 0; /* overflow so start at beginning */
253 // If the request must be contiguous, then find a sequence of free blocks
254 // that is long enough. Otherwise, find the first free block.
256 if (forceContiguous
) {
257 err
= BlockAllocateContig(vcb
, startingBlock
, minBlocks
, maxBlocks
,
258 useMetaZone
, actualStartBlock
, actualNumBlocks
);
260 * If we allocated from a new position then
261 * also update the roving allocatior.
263 if ((err
== noErr
) &&
264 (*actualStartBlock
> startingBlock
) &&
265 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
266 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
267 HFS_MOUNT_LOCK(vcb
, TRUE
);
268 vcb
->nextAllocation
= *actualStartBlock
;
269 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
273 * Scan the bitmap once, gather the N largest free extents, then
274 * allocate from these largest extents. Repeat as needed until
275 * we get all the space we needed. We could probably build up
276 * that list when the higher level caller tried (and failed) a
277 * contiguous allocation first.
279 err
= BlockAllocateKnown(vcb
, maxBlocks
, actualStartBlock
, actualNumBlocks
);
280 if (err
== dskFulErr
)
281 err
= BlockAllocateAny(vcb
, startingBlock
, vcb
->totalBlocks
,
282 maxBlocks
, useMetaZone
, actualStartBlock
,
284 if (err
== dskFulErr
)
285 err
= BlockAllocateAny(vcb
, 1, startingBlock
, maxBlocks
,
286 useMetaZone
, actualStartBlock
,
291 // if we actually allocated something then go update the
292 // various bits of state that we maintain regardless of
293 // whether there was an error (i.e. partial allocations
294 // still need to update things like the free block count).
296 if (*actualNumBlocks
!= 0) {
298 // If we used the volume's roving allocation pointer, then we need to update it.
299 // Adding in the length of the current allocation might reduce the next allocate
300 // call by avoiding a re-scan of the already allocated space. However, the clump
301 // just allocated can quite conceivably end up being truncated or released when
302 // the file is closed or its EOF changed. Leaving the allocation pointer at the
303 // start of the last allocation will avoid unnecessary fragmentation in this case.
305 HFS_MOUNT_LOCK(vcb
, TRUE
);
307 if (updateAllocPtr
&&
308 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
309 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
310 vcb
->nextAllocation
= *actualStartBlock
;
313 // Update the number of free blocks on the volume
315 vcb
->freeBlocks
-= *actualNumBlocks
;
317 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
319 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
327 ;________________________________________________________________________________
329 ; Routine: BlkDealloc
331 ; Function: Update the bitmap to deallocate a run of disk allocation blocks
334 ; vcb - Pointer to ExtendedVCB for the volume to free space on
335 ; firstBlock - First allocation block to be freed
336 ; numBlocks - Number of allocation blocks to free up (must be > 0!)
339 ; (result) - Result code
342 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
343 ;________________________________________________________________________________
347 OSErr
BlockDeallocate (
348 ExtendedVCB
*vcb
, // Which volume to deallocate space on
349 UInt32 firstBlock
, // First block in range to deallocate
350 UInt32 numBlocks
) // Number of contiguous blocks to deallocate
355 // If no blocks to deallocate, then exit early
357 if (numBlocks
== 0) {
363 // Call internal routine to free the sequence of blocks
365 err
= BlockMarkFree(vcb
, firstBlock
, numBlocks
);
370 // Update the volume's free block count, and mark the VCB as dirty.
372 HFS_MOUNT_LOCK(vcb
, TRUE
);
373 vcb
->freeBlocks
+= numBlocks
;
374 if (vcb
->nextAllocation
== (firstBlock
+ numBlocks
))
375 vcb
->nextAllocation
-= numBlocks
;
377 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
379 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
386 UInt8 freebitcount
[16] = {
387 4, 3, 3, 2, 3, 2, 2, 1, /* 0 1 2 3 4 5 6 7 */
388 3, 2, 2, 1, 2, 1, 1, 0, /* 8 9 A B C D E F */
393 MetaZoneFreeBlocks(ExtendedVCB
*vcb
)
406 bytesleft
= freeblocks
= 0;
408 bit
= VCBTOHFS(vcb
)->hfs_metazone_start
;
412 lastbit
= VCBTOHFS(vcb
)->hfs_metazone_end
;
413 bytesperblock
= vcb
->vcbVBMIOSize
;
416 * Count all the bits from bit to lastbit.
418 while (bit
< lastbit
) {
420 * Get next bitmap block.
422 if (bytesleft
== 0) {
424 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
427 if (ReadBitmapBlock(vcb
, bit
, &currCache
, &blockRef
) != 0) {
430 buffer
= (UInt8
*)currCache
;
431 bytesleft
= bytesperblock
;
434 freeblocks
+= freebitcount
[byte
& 0x0F];
435 freeblocks
+= freebitcount
[(byte
>> 4) & 0x0F];
440 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
447 * Obtain the next allocation block (bit) that's
448 * outside the metadata allocation zone.
450 static UInt32
NextBitmapBlock(
454 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
456 if ((hfsmp
->hfs_flags
& HFS_METADATA_ZONE
) == 0)
459 * Skip over metadata allocation zone.
461 if ((bit
>= hfsmp
->hfs_metazone_start
) &&
462 (bit
<= hfsmp
->hfs_metazone_end
)) {
463 bit
= hfsmp
->hfs_metazone_end
+ 1;
470 ;_______________________________________________________________________
472 ; Routine: ReadBitmapBlock
474 ; Function: Read in a bitmap block corresponding to a given allocation
475 ; block (bit). Return a pointer to the bitmap block.
478 ; vcb -- Pointer to ExtendedVCB
479 ; bit -- Allocation block whose bitmap block is desired
482 ; buffer -- Pointer to bitmap block corresonding to "block"
484 ;_______________________________________________________________________
486 static OSErr
ReadBitmapBlock(
493 struct buf
*bp
= NULL
;
494 struct vnode
*vp
= NULL
;
499 * volume bitmap blocks are protected by the allocation file lock
501 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
503 blockSize
= (UInt32
)vcb
->vcbVBMIOSize
;
504 block
= (daddr64_t
)(bit
/ (blockSize
* kBitsPerByte
));
506 if (vcb
->vcbSigWord
== kHFSPlusSigWord
) {
507 vp
= vcb
->hfs_allocation_vp
; /* use allocation file vnode */
510 vp
= VCBTOHFS(vcb
)->hfs_devvp
; /* use device I/O vnode */
511 block
+= vcb
->vcbVBMSt
; /* map to physical block */
514 err
= (int)buf_meta_bread(vp
, block
, blockSize
, NOCRED
, &bp
);
522 *blockRef
= (UInt32
)bp
;
523 *buffer
= (UInt32
*)buf_dataptr(bp
);
532 ;_______________________________________________________________________
534 ; Routine: ReleaseBitmapBlock
536 ; Function: Relase a bitmap block.
542 ;_______________________________________________________________________
544 static OSErr
ReleaseBitmapBlock(
549 struct buf
*bp
= (struct buf
*)blockRef
;
553 panic("ReleaseBitmapBlock: missing bp");
560 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
563 journal_modify_block_end(hfsmp
->jnl
, bp
);
577 _______________________________________________________________________
579 Routine: BlockAllocateContig
581 Function: Allocate a contiguous group of allocation blocks. The
582 allocation is all-or-nothing. The caller guarantees that
583 there are enough free blocks (though they may not be
584 contiguous, in which case this call will fail).
587 vcb Pointer to volume where space is to be allocated
588 startingBlock Preferred first block for allocation
589 minBlocks Minimum number of contiguous blocks to allocate
590 maxBlocks Maximum number of contiguous blocks to allocate
594 actualStartBlock First block of range allocated, or 0 if error
595 actualNumBlocks Number of blocks allocated, or 0 if error
596 _______________________________________________________________________
598 static OSErr
BlockAllocateContig(
600 UInt32 startingBlock
,
604 UInt32
*actualStartBlock
,
605 UInt32
*actualNumBlocks
)
610 // Find a contiguous group of blocks at least minBlocks long.
611 // Determine the number of contiguous blocks available (up
616 * NOTE: If the only contiguous free extent of at least minBlocks
617 * crosses startingBlock (i.e. starts before, ends after), then we
618 * won't find it. Earlier versions *did* find this case by letting
619 * the second search look past startingBlock by minBlocks. But
620 * with the free extent cache, this can lead to duplicate entries
621 * in the cache, causing the same blocks to be allocated twice.
623 err
= BlockFindContiguous(vcb
, startingBlock
, vcb
->totalBlocks
, minBlocks
,
624 maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
625 if (err
== dskFulErr
&& startingBlock
!= 0) {
627 * Constrain the endingBlock so we don't bother looking for ranges
628 * that would overlap those found in the previous call.
630 err
= BlockFindContiguous(vcb
, 1, startingBlock
, minBlocks
, maxBlocks
,
631 useMetaZone
, actualStartBlock
, actualNumBlocks
);
633 if (err
!= noErr
) goto Exit
;
636 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->totalBlocks
)
637 panic("BlockAllocateContig: allocation overflow on \"%s\"", vcb
->vcbVN
);
640 // Now mark those blocks allocated.
642 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
646 *actualStartBlock
= 0;
647 *actualNumBlocks
= 0;
654 _______________________________________________________________________
656 Routine: BlockAllocateAny
658 Function: Allocate one or more allocation blocks. If there are fewer
659 free blocks than requested, all free blocks will be
660 allocated. The caller guarantees that there is at least
664 vcb Pointer to volume where space is to be allocated
665 startingBlock Preferred first block for allocation
666 endingBlock Last block to check + 1
667 maxBlocks Maximum number of contiguous blocks to allocate
671 actualStartBlock First block of range allocated, or 0 if error
672 actualNumBlocks Number of blocks allocated, or 0 if error
673 _______________________________________________________________________
675 static OSErr
BlockAllocateAny(
677 UInt32 startingBlock
,
678 register UInt32 endingBlock
,
681 UInt32
*actualStartBlock
,
682 UInt32
*actualNumBlocks
)
685 register UInt32 block
; // current block number
686 register UInt32 currentWord
; // Pointer to current word within bitmap block
687 register UInt32 bitMask
; // Word with given bits already set (ready to OR in)
688 register UInt32 wordsLeft
; // Number of words left in this bitmap block
689 UInt32
*buffer
= NULL
;
690 UInt32
*currCache
= NULL
;
693 UInt32 wordsPerBlock
;
694 Boolean dirty
= false;
695 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
697 // Since this routine doesn't wrap around
698 if (maxBlocks
> (endingBlock
- startingBlock
)) {
699 maxBlocks
= endingBlock
- startingBlock
;
703 * Skip over metadata blocks.
706 startingBlock
= NextBitmapBlock(vcb
, startingBlock
);
709 // Pre-read the first bitmap block
711 err
= ReadBitmapBlock(vcb
, startingBlock
, &currCache
, &blockRef
);
712 if (err
!= noErr
) goto Exit
;
716 // Set up the current position within the block
719 UInt32 wordIndexInBlock
;
721 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
722 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
724 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
725 buffer
+= wordIndexInBlock
;
726 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
727 currentWord
= SWAP_BE32 (*buffer
);
728 bitMask
= kHighBitInWordMask
>> (startingBlock
& kBitsWithinWordMask
);
732 // Find the first unallocated block
735 while (block
< endingBlock
) {
736 if ((currentWord
& bitMask
) == 0)
744 bitMask
= kHighBitInWordMask
;
747 if (--wordsLeft
== 0) {
749 buffer
= currCache
= NULL
;
750 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
751 if (err
!= noErr
) goto Exit
;
754 * Skip over metadata blocks.
757 block
= NextBitmapBlock(vcb
, block
);
758 if (block
>= endingBlock
) {
763 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
764 if (err
!= noErr
) goto Exit
;
767 wordsLeft
= wordsPerBlock
;
769 currentWord
= SWAP_BE32 (*buffer
);
773 // Did we get to the end of the bitmap before finding a free block?
774 // If so, then couldn't allocate anything.
775 if (block
>= endingBlock
) {
780 // Return the first block in the allocated range
781 *actualStartBlock
= block
;
784 // If we could get the desired number of blocks before hitting endingBlock,
785 // then adjust endingBlock so we won't keep looking. Ideally, the comparison
786 // would be (block + maxBlocks) < endingBlock, but that could overflow. The
787 // comparison below yields identical results, but without overflow.
788 if (block
< (endingBlock
-maxBlocks
)) {
789 endingBlock
= block
+ maxBlocks
; // if we get this far, we've found enough
794 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
798 // Allocate all of the consecutive blocks
800 while ((currentWord
& bitMask
) == 0) {
801 // Allocate this block
802 currentWord
|= bitMask
;
804 // Move to the next block. If no more, then exit.
806 if (block
== endingBlock
)
812 *buffer
= SWAP_BE32 (currentWord
); // update value in bitmap
815 bitMask
= kHighBitInWordMask
;
818 if (--wordsLeft
== 0) {
820 buffer
= currCache
= NULL
;
821 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
822 if (err
!= noErr
) goto Exit
;
825 * Skip over metadata blocks.
830 nextBlock
= NextBitmapBlock(vcb
, block
);
831 if (nextBlock
!= block
) {
832 goto Exit
; /* allocation gap, so stop */
836 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
837 if (err
!= noErr
) goto Exit
;
842 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
845 wordsLeft
= wordsPerBlock
;
848 currentWord
= SWAP_BE32 (*buffer
);
851 *buffer
= SWAP_BE32 (currentWord
); // update the last change
855 *actualNumBlocks
= block
- *actualStartBlock
;
858 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->totalBlocks
)
859 panic("BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
862 *actualStartBlock
= 0;
863 *actualNumBlocks
= 0;
867 (void) ReleaseBitmapBlock(vcb
, blockRef
, dirty
);
874 _______________________________________________________________________
876 Routine: BlockAllocateKnown
878 Function: Try to allocate space from known free space in the free
882 vcb Pointer to volume where space is to be allocated
883 maxBlocks Maximum number of contiguous blocks to allocate
886 actualStartBlock First block of range allocated, or 0 if error
887 actualNumBlocks Number of blocks allocated, or 0 if error
890 dskFulErr Free extent cache is empty
891 _______________________________________________________________________
893 static OSErr
BlockAllocateKnown(
896 UInt32
*actualStartBlock
,
897 UInt32
*actualNumBlocks
)
901 UInt32 newStartBlock
, newBlockCount
;
903 if (vcb
->vcbFreeExtCnt
== 0)
906 // Just grab up to maxBlocks of the first (largest) free exent.
907 *actualStartBlock
= vcb
->vcbFreeExt
[0].startBlock
;
908 foundBlocks
= vcb
->vcbFreeExt
[0].blockCount
;
909 if (foundBlocks
> maxBlocks
)
910 foundBlocks
= maxBlocks
;
911 *actualNumBlocks
= foundBlocks
;
913 // Adjust the start and length of that extent.
914 newStartBlock
= vcb
->vcbFreeExt
[0].startBlock
+ foundBlocks
;
915 newBlockCount
= vcb
->vcbFreeExt
[0].blockCount
- foundBlocks
;
917 // The first extent might not be the largest anymore. Bubble up any
918 // (now larger) extents to the top of the list.
919 for (i
=1; i
<vcb
->vcbFreeExtCnt
; ++i
)
921 if (vcb
->vcbFreeExt
[i
].blockCount
> newBlockCount
)
923 vcb
->vcbFreeExt
[i
-1].startBlock
= vcb
->vcbFreeExt
[i
].startBlock
;
924 vcb
->vcbFreeExt
[i
-1].blockCount
= vcb
->vcbFreeExt
[i
].blockCount
;
932 // If this is now the smallest known free extent, then it might be smaller than
933 // other extents we didn't keep track of. So, just forget about this extent.
934 // After the previous loop, (i-1) is the index of the extent we just allocated from.
935 if (i
== vcb
->vcbFreeExtCnt
)
937 // It's now the smallest extent, so forget about it
938 --vcb
->vcbFreeExtCnt
;
942 // It's not the smallest, so store it in its proper place
943 vcb
->vcbFreeExt
[i
-1].startBlock
= newStartBlock
;
944 vcb
->vcbFreeExt
[i
-1].blockCount
= newBlockCount
;
948 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->totalBlocks
)
949 panic("BlockAllocateKnown: allocation overflow on \"%s\"", vcb
->vcbVN
);
952 // Now mark the found extent in the bitmap
954 return BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
960 _______________________________________________________________________
962 Routine: BlockMarkAllocated
964 Function: Mark a contiguous group of blocks as allocated (set in the
965 bitmap). It assumes those bits are currently marked
966 deallocated (clear in the bitmap).
969 vcb Pointer to volume where space is to be allocated
970 startingBlock First block number to mark as allocated
971 numBlocks Number of blocks to mark as allocated
972 _______________________________________________________________________
975 OSErr
BlockMarkAllocated(
977 UInt32 startingBlock
,
978 register UInt32 numBlocks
)
981 register UInt32
*currentWord
; // Pointer to current word within bitmap block
982 register UInt32 wordsLeft
; // Number of words left in this bitmap block
983 register UInt32 bitMask
; // Word with given bits already set (ready to OR in)
984 UInt32 firstBit
; // Bit index within word of first bit to allocate
985 UInt32 numBits
; // Number of bits in word to allocate
986 UInt32
*buffer
= NULL
;
989 UInt32 wordsPerBlock
;
991 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
995 // Pre-read the bitmap block containing the first word of allocation
998 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
999 if (err
!= noErr
) goto Exit
;
1001 // Initialize currentWord, and wordsLeft.
1004 UInt32 wordIndexInBlock
;
1006 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1007 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1009 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1010 currentWord
= buffer
+ wordIndexInBlock
;
1011 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1016 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1020 // If the first block to allocate doesn't start on a word
1021 // boundary in the bitmap, then treat that first word
1025 firstBit
= startingBlock
% kBitsPerWord
;
1026 if (firstBit
!= 0) {
1027 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1028 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1029 if (numBits
> numBlocks
) {
1030 numBits
= numBlocks
; // entire allocation is inside this one word
1031 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1034 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1035 panic("BlockMarkAllocated: blocks already allocated!");
1038 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1039 numBlocks
-= numBits
; // adjust number of blocks left to allocate
1041 ++currentWord
; // move to next word
1042 --wordsLeft
; // one less word left in this block
1046 // Allocate whole words (32 blocks) at a time.
1049 bitMask
= kAllBitsSetInWord
; // put this in a register for 68K
1050 while (numBlocks
>= kBitsPerWord
) {
1051 if (wordsLeft
== 0) {
1052 // Read in the next bitmap block
1053 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1056 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1057 if (err
!= noErr
) goto Exit
;
1059 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1060 if (err
!= noErr
) goto Exit
;
1064 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1067 // Readjust currentWord and wordsLeft
1068 currentWord
= buffer
;
1069 wordsLeft
= wordsPerBlock
;
1072 if (*currentWord
!= 0) {
1073 panic("BlockMarkAllocated: blocks already allocated!");
1076 *currentWord
= SWAP_BE32 (bitMask
);
1077 numBlocks
-= kBitsPerWord
;
1079 ++currentWord
; // move to next word
1080 --wordsLeft
; // one less word left in this block
1084 // Allocate any remaining blocks.
1087 if (numBlocks
!= 0) {
1088 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1089 if (wordsLeft
== 0) {
1090 // Read in the next bitmap block
1091 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1094 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1095 if (err
!= noErr
) goto Exit
;
1097 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1098 if (err
!= noErr
) goto Exit
;
1102 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1105 // Readjust currentWord and wordsLeft
1106 currentWord
= buffer
;
1107 wordsLeft
= wordsPerBlock
;
1110 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1111 panic("BlockMarkAllocated: blocks already allocated!");
1114 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1116 // No need to update currentWord or wordsLeft
1122 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1129 _______________________________________________________________________
1131 Routine: BlockMarkFree
1133 Function: Mark a contiguous group of blocks as free (clear in the
1134 bitmap). It assumes those bits are currently marked
1135 allocated (set in the bitmap).
1138 vcb Pointer to volume where space is to be freed
1139 startingBlock First block number to mark as freed
1140 numBlocks Number of blocks to mark as freed
1141 _______________________________________________________________________
1144 OSErr
BlockMarkFree(
1146 UInt32 startingBlock
,
1147 register UInt32 numBlocks
)
1150 register UInt32
*currentWord
; // Pointer to current word within bitmap block
1151 register UInt32 wordsLeft
; // Number of words left in this bitmap block
1152 register UInt32 bitMask
; // Word with given bits already set (ready to OR in)
1153 UInt32 firstBit
; // Bit index within word of first bit to allocate
1154 UInt32 numBits
; // Number of bits in word to allocate
1155 UInt32
*buffer
= NULL
;
1157 UInt32 bitsPerBlock
;
1158 UInt32 wordsPerBlock
;
1160 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1162 if (startingBlock
+ numBlocks
> vcb
->totalBlocks
) {
1163 panic("hfs: block mark free: trying to free non-existent blocks (%d %d %d)\n",
1164 startingBlock
, numBlocks
, vcb
->totalBlocks
);
1169 // Pre-read the bitmap block containing the first word of allocation
1172 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1173 if (err
!= noErr
) goto Exit
;
1176 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1180 // Initialize currentWord, and wordsLeft.
1183 UInt32 wordIndexInBlock
;
1185 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1186 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1188 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1189 currentWord
= buffer
+ wordIndexInBlock
;
1190 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1194 // If the first block to free doesn't start on a word
1195 // boundary in the bitmap, then treat that first word
1199 firstBit
= startingBlock
% kBitsPerWord
;
1200 if (firstBit
!= 0) {
1201 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1202 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1203 if (numBits
> numBlocks
) {
1204 numBits
= numBlocks
; // entire allocation is inside this one word
1205 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1207 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1210 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1211 numBlocks
-= numBits
; // adjust number of blocks left to free
1213 ++currentWord
; // move to next word
1214 --wordsLeft
; // one less word left in this block
1218 // Free whole words (32 blocks) at a time.
1221 while (numBlocks
>= kBitsPerWord
) {
1222 if (wordsLeft
== 0) {
1223 // Read in the next bitmap block
1224 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1227 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1228 if (err
!= noErr
) goto Exit
;
1230 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1231 if (err
!= noErr
) goto Exit
;
1235 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1238 // Readjust currentWord and wordsLeft
1239 currentWord
= buffer
;
1240 wordsLeft
= wordsPerBlock
;
1242 if (*currentWord
!= SWAP_BE32 (kAllBitsSetInWord
)) {
1245 *currentWord
= 0; // clear the entire word
1246 numBlocks
-= kBitsPerWord
;
1248 ++currentWord
; // move to next word
1249 --wordsLeft
; // one less word left in this block
1253 // Free any remaining blocks.
1256 if (numBlocks
!= 0) {
1257 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1258 if (wordsLeft
== 0) {
1259 // Read in the next bitmap block
1260 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1263 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1264 if (err
!= noErr
) goto Exit
;
1266 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1267 if (err
!= noErr
) goto Exit
;
1271 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1274 // Readjust currentWord and wordsLeft
1275 currentWord
= buffer
;
1276 wordsLeft
= wordsPerBlock
;
1278 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1281 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1283 // No need to update currentWord or wordsLeft
1289 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1295 panic("BlockMarkFree: blocks not allocated!");
1297 printf("hfs: WARNING - blocks on volume %s not allocated!\n", vcb
->vcbVN
);
1298 vcb
->vcbAtrb
|= kHFSVolumeInconsistentMask
;
1307 _______________________________________________________________________
1309 Routine: BlockFindContiguous
1311 Function: Find a contiguous range of blocks that are free (bits
1312 clear in the bitmap). If a contiguous range of the
1313 minimum size can't be found, an error will be returned.
1316 vcb Pointer to volume where space is to be allocated
1317 startingBlock Preferred first block of range
1318 endingBlock Last possible block in range + 1
1319 minBlocks Minimum number of blocks needed. Must be > 0.
1320 maxBlocks Maximum (ideal) number of blocks desired
1321 useMetaZone OK to dip into metadata allocation zone
1324 actualStartBlock First block of range found, or 0 if error
1325 actualNumBlocks Number of blocks found, or 0 if error
1328 noErr Found at least minBlocks contiguous
1329 dskFulErr No contiguous space found, or all less than minBlocks
1330 _______________________________________________________________________
1333 static OSErr
BlockFindContiguous(
1335 UInt32 startingBlock
,
1339 Boolean useMetaZone
,
1340 UInt32
*actualStartBlock
,
1341 UInt32
*actualNumBlocks
)
1344 register UInt32 currentBlock
; // Block we're currently looking at.
1345 UInt32 firstBlock
; // First free block in current extent.
1346 UInt32 stopBlock
; // If we get to this block, stop searching for first free block.
1347 UInt32 foundBlocks
; // Number of contiguous free blocks in current extent.
1348 UInt32
*buffer
= NULL
;
1349 register UInt32
*currentWord
;
1350 register UInt32 bitMask
;
1351 register UInt32 wordsLeft
;
1352 register UInt32 tempWord
;
1354 UInt32 wordsPerBlock
;
1357 * When we're skipping the metadata zone and the start/end
1358 * range overlaps with the metadata zone then adjust the
1359 * start to be outside of the metadata zone. If the range
1360 * is entirely inside the metadata zone then we can deny the
1361 * request (dskFulErr).
1363 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
1364 if (startingBlock
<= vcb
->hfs_metazone_end
) {
1365 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
1366 startingBlock
= vcb
->hfs_metazone_end
+ 1;
1372 if ((endingBlock
- startingBlock
) < minBlocks
)
1374 // The set of blocks we're checking is smaller than the minimum number
1375 // of blocks, so we couldn't possibly find a good range.
1379 stopBlock
= endingBlock
- minBlocks
+ 1;
1380 currentBlock
= startingBlock
;
1384 * Skip over metadata blocks.
1387 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1390 // Pre-read the first bitmap block.
1392 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1393 if ( err
!= noErr
) goto ErrorExit
;
1396 // Figure out where currentBlock is within the buffer.
1398 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1400 wordsLeft
= (currentBlock
/ kBitsPerWord
) & (wordsPerBlock
-1); // Current index into buffer
1401 currentWord
= buffer
+ wordsLeft
;
1402 wordsLeft
= wordsPerBlock
- wordsLeft
;
1408 //============================================================
1409 // Look for a free block, skipping over allocated blocks.
1410 //============================================================
1413 // Check an initial partial word (if any)
1415 bitMask
= currentBlock
& kBitsWithinWordMask
;
1418 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1419 bitMask
= kHighBitInWordMask
>> bitMask
;
1420 while (tempWord
& bitMask
)
1426 // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)?
1430 // Didn't find any unused bits, so we're done with this word.
1436 // Check whole words
1438 while (currentBlock
< stopBlock
)
1440 // See if it's time to read another block.
1444 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1445 if (err
!= noErr
) goto ErrorExit
;
1448 * Skip over metadata blocks.
1451 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1452 if (currentBlock
>= stopBlock
) {
1457 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1458 if ( err
!= noErr
) goto ErrorExit
;
1460 currentWord
= buffer
;
1461 wordsLeft
= wordsPerBlock
;
1464 // See if any of the bits are clear
1465 if ((tempWord
= SWAP_BE32(*currentWord
)) + 1) // non-zero if any bits were clear
1467 // Figure out which bit is clear
1468 bitMask
= kHighBitInWordMask
;
1469 while (tempWord
& bitMask
)
1475 break; // Found the free bit; break out to FoundUnused.
1478 // Keep looking at the next word
1479 currentBlock
+= kBitsPerWord
;
1485 // Make sure the unused bit is early enough to use
1486 if (currentBlock
>= stopBlock
)
1491 // Remember the start of the extent
1492 firstBlock
= currentBlock
;
1494 //============================================================
1495 // Count the number of contiguous free blocks.
1496 //============================================================
1499 // Check an initial partial word (if any)
1501 bitMask
= currentBlock
& kBitsWithinWordMask
;
1504 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1505 bitMask
= kHighBitInWordMask
>> bitMask
;
1506 while (bitMask
&& !(tempWord
& bitMask
))
1512 // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)?
1516 // Didn't find any used bits, so we're done with this word.
1522 // Check whole words
1524 while (currentBlock
< endingBlock
)
1526 // See if it's time to read another block.
1530 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1531 if (err
!= noErr
) goto ErrorExit
;
1534 * Skip over metadata blocks.
1539 nextBlock
= NextBitmapBlock(vcb
, currentBlock
);
1540 if (nextBlock
!= currentBlock
) {
1541 goto LoopExit
; /* allocation gap, so stop */
1545 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1546 if ( err
!= noErr
) goto ErrorExit
;
1548 currentWord
= buffer
;
1549 wordsLeft
= wordsPerBlock
;
1552 // See if any of the bits are set
1553 if ((tempWord
= SWAP_BE32(*currentWord
)) != 0)
1555 // Figure out which bit is set
1556 bitMask
= kHighBitInWordMask
;
1557 while (!(tempWord
& bitMask
))
1563 break; // Found the used bit; break out to FoundUsed.
1566 // Keep looking at the next word
1567 currentBlock
+= kBitsPerWord
;
1571 // If we found at least maxBlocks, we can quit early.
1572 if ((currentBlock
- firstBlock
) >= maxBlocks
)
1577 // Make sure we didn't run out of bitmap looking for a used block.
1578 // If so, pin to the end of the bitmap.
1579 if (currentBlock
> endingBlock
)
1580 currentBlock
= endingBlock
;
1582 // Figure out how many contiguous free blocks there were.
1583 // Pin the answer to maxBlocks.
1584 foundBlocks
= currentBlock
- firstBlock
;
1585 if (foundBlocks
> maxBlocks
)
1586 foundBlocks
= maxBlocks
;
1587 if (foundBlocks
>= minBlocks
)
1588 break; // Found what we needed!
1590 // This free chunk wasn't big enough. Try inserting it into the free extent cache in case
1591 // the allocation wasn't forced contiguous.
1592 tempWord
= vcb
->vcbFreeExtCnt
;
1593 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< foundBlocks
)
1595 if (tempWord
< kMaxFreeExtents
)
1597 // We're going to add this extent. Bubble any smaller extents down in the list.
1598 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< foundBlocks
)
1600 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1603 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1604 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1606 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
)
1607 ++vcb
->vcbFreeExtCnt
;
1609 } while (currentBlock
< stopBlock
);
1612 // Return the outputs.
1613 if (foundBlocks
< minBlocks
)
1618 *actualStartBlock
= 0;
1619 *actualNumBlocks
= 0;
1624 *actualStartBlock
= firstBlock
;
1625 *actualNumBlocks
= foundBlocks
;
1629 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1635 * Test to see if any blocks in a range are allocated.
1637 * The journal or allocation file lock must be held.
1641 hfs_isallocated(struct hfsmount
*hfsmp
, u_long startingBlock
, u_long numBlocks
)
1643 UInt32
*currentWord
; // Pointer to current word within bitmap block
1644 UInt32 wordsLeft
; // Number of words left in this bitmap block
1645 UInt32 bitMask
; // Word with given bits already set (ready to test)
1646 UInt32 firstBit
; // Bit index within word of first bit to allocate
1647 UInt32 numBits
; // Number of bits in word to allocate
1648 UInt32
*buffer
= NULL
;
1650 UInt32 bitsPerBlock
;
1651 UInt32 wordsPerBlock
;
1656 * Pre-read the bitmap block containing the first word of allocation
1658 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1663 * Initialize currentWord, and wordsLeft.
1666 UInt32 wordIndexInBlock
;
1668 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
1669 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
1671 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1672 currentWord
= buffer
+ wordIndexInBlock
;
1673 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1677 * First test any non word aligned bits.
1679 firstBit
= startingBlock
% kBitsPerWord
;
1680 if (firstBit
!= 0) {
1681 bitMask
= kAllBitsSetInWord
>> firstBit
;
1682 numBits
= kBitsPerWord
- firstBit
;
1683 if (numBits
> numBlocks
) {
1684 numBits
= numBlocks
;
1685 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
1687 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1691 numBlocks
-= numBits
;
1697 * Test whole words (32 blocks) at a time.
1699 while (numBlocks
>= kBitsPerWord
) {
1700 if (wordsLeft
== 0) {
1701 /* Read in the next bitmap block. */
1702 startingBlock
+= bitsPerBlock
;
1705 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1706 if (error
) goto Exit
;
1708 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1709 if (error
) goto Exit
;
1711 /* Readjust currentWord and wordsLeft. */
1712 currentWord
= buffer
;
1713 wordsLeft
= wordsPerBlock
;
1715 if (*currentWord
!= 0) {
1719 numBlocks
-= kBitsPerWord
;
1725 * Test any remaining blocks.
1727 if (numBlocks
!= 0) {
1728 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
);
1729 if (wordsLeft
== 0) {
1730 /* Read in the next bitmap block */
1731 startingBlock
+= bitsPerBlock
;
1734 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1735 if (error
) goto Exit
;
1737 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1738 if (error
) goto Exit
;
1740 currentWord
= buffer
;
1741 wordsLeft
= wordsPerBlock
;
1743 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1750 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);