2 * Copyright (c) 2000-2007 Apple 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(
115 u_int32_t
*blockRef
);
117 static OSErr
ReleaseBitmapBlock(
122 static OSErr
BlockAllocateAny(
124 u_int32_t startingBlock
,
125 u_int32_t endingBlock
,
128 u_int32_t
*actualStartBlock
,
129 u_int32_t
*actualNumBlocks
);
131 static OSErr
BlockAllocateContig(
133 u_int32_t startingBlock
,
137 u_int32_t
*actualStartBlock
,
138 u_int32_t
*actualNumBlocks
);
140 static OSErr
BlockFindContiguous(
142 u_int32_t startingBlock
,
143 u_int32_t endingBlock
,
147 u_int32_t
*actualStartBlock
,
148 u_int32_t
*actualNumBlocks
);
150 static OSErr
BlockAllocateKnown(
153 u_int32_t
*actualStartBlock
,
154 u_int32_t
*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 u_int32_t startingBlock
, /* preferred starting block, or 0 for no preference */
202 u_int32_t minBlocks
, /* desired number of blocks to allocate */
203 u_int32_t 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 u_int32_t
*actualStartBlock
, /* actual first block of allocation */
209 u_int32_t
*actualNumBlocks
) /* number of blocks actually allocated; if forceContiguous */
210 /* was zero, then this may represent fewer than minBlocks */
212 u_int32_t freeBlocks
;
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
->allocLimit
) {
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 allocator.
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 HFS_UPDATE_NEXT_ALLOCATION(vcb
, *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
->allocLimit
,
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 HFS_UPDATE_NEXT_ALLOCATION(vcb
, *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 u_int32_t firstBlock
, // First block in range to deallocate
356 u_int32_t 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 HFS_UPDATE_NEXT_ALLOCATION(vcb
, (vcb
->nextAllocation
- numBlocks
));
383 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
385 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
392 u_int8_t 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
)
401 u_int32_t freeblocks
;
402 u_int32_t
*currCache
;
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
= (u_int8_t
*)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 u_int32_t
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
= (u_int32_t
)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
= (u_int32_t
)bp
;
529 *buffer
= (u_int32_t
*)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
, NULL
, NULL
);
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 u_int32_t startingBlock
,
610 u_int32_t
*actualStartBlock
,
611 u_int32_t
*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
->allocLimit
, 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
);
640 // Now mark those blocks allocated.
643 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
649 _______________________________________________________________________
651 Routine: BlockAllocateAny
653 Function: Allocate one or more allocation blocks. If there are fewer
654 free blocks than requested, all free blocks will be
655 allocated. The caller guarantees that there is at least
659 vcb Pointer to volume where space is to be allocated
660 startingBlock Preferred first block for allocation
661 endingBlock Last block to check + 1
662 maxBlocks Maximum number of contiguous blocks to allocate
666 actualStartBlock First block of range allocated, or 0 if error
667 actualNumBlocks Number of blocks allocated, or 0 if error
668 _______________________________________________________________________
670 static OSErr
BlockAllocateAny(
672 u_int32_t startingBlock
,
673 register u_int32_t endingBlock
,
676 u_int32_t
*actualStartBlock
,
677 u_int32_t
*actualNumBlocks
)
680 register u_int32_t block
; // current block number
681 register u_int32_t currentWord
; // Pointer to current word within bitmap block
682 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
683 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
684 u_int32_t
*buffer
= NULL
;
685 u_int32_t
*currCache
= NULL
;
687 u_int32_t bitsPerBlock
;
688 u_int32_t wordsPerBlock
;
689 Boolean dirty
= false;
690 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
693 * When we're skipping the metadata zone and the start/end
694 * range overlaps with the metadata zone then adjust the
695 * start to be outside of the metadata zone. If the range
696 * is entirely inside the metadata zone then we can deny the
697 * request (dskFulErr).
699 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
700 if (startingBlock
<= vcb
->hfs_metazone_end
) {
701 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
702 startingBlock
= vcb
->hfs_metazone_end
+ 1;
710 // Since this routine doesn't wrap around
711 if (maxBlocks
> (endingBlock
- startingBlock
)) {
712 maxBlocks
= endingBlock
- startingBlock
;
716 // Pre-read the first bitmap block
718 err
= ReadBitmapBlock(vcb
, startingBlock
, &currCache
, &blockRef
);
719 if (err
!= noErr
) goto Exit
;
723 // Set up the current position within the block
726 u_int32_t wordIndexInBlock
;
728 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
729 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
731 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
732 buffer
+= wordIndexInBlock
;
733 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
734 currentWord
= SWAP_BE32 (*buffer
);
735 bitMask
= kHighBitInWordMask
>> (startingBlock
& kBitsWithinWordMask
);
739 // Find the first unallocated block
742 while (block
< endingBlock
) {
743 if ((currentWord
& bitMask
) == 0)
751 bitMask
= kHighBitInWordMask
;
754 if (--wordsLeft
== 0) {
756 buffer
= currCache
= NULL
;
757 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
758 if (err
!= noErr
) goto Exit
;
761 * Skip over metadata blocks.
764 block
= NextBitmapBlock(vcb
, block
);
766 if (block
>= endingBlock
) {
771 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
772 if (err
!= noErr
) goto Exit
;
775 wordsLeft
= wordsPerBlock
;
777 currentWord
= SWAP_BE32 (*buffer
);
781 // Did we get to the end of the bitmap before finding a free block?
782 // If so, then couldn't allocate anything.
783 if (block
>= endingBlock
) {
788 // Return the first block in the allocated range
789 *actualStartBlock
= block
;
792 // If we could get the desired number of blocks before hitting endingBlock,
793 // then adjust endingBlock so we won't keep looking. Ideally, the comparison
794 // would be (block + maxBlocks) < endingBlock, but that could overflow. The
795 // comparison below yields identical results, but without overflow.
796 if (block
< (endingBlock
-maxBlocks
)) {
797 endingBlock
= block
+ maxBlocks
; // if we get this far, we've found enough
802 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
806 // Allocate all of the consecutive blocks
808 while ((currentWord
& bitMask
) == 0) {
809 // Allocate this block
810 currentWord
|= bitMask
;
812 // Move to the next block. If no more, then exit.
814 if (block
== endingBlock
)
820 *buffer
= SWAP_BE32 (currentWord
); // update value in bitmap
823 bitMask
= kHighBitInWordMask
;
826 if (--wordsLeft
== 0) {
828 buffer
= currCache
= NULL
;
829 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
830 if (err
!= noErr
) goto Exit
;
833 * Skip over metadata blocks.
838 nextBlock
= NextBitmapBlock(vcb
, block
);
839 if (nextBlock
!= block
) {
840 goto Exit
; /* allocation gap, so stop */
844 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
845 if (err
!= noErr
) goto Exit
;
850 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
853 wordsLeft
= wordsPerBlock
;
856 currentWord
= SWAP_BE32 (*buffer
);
859 *buffer
= SWAP_BE32 (currentWord
); // update the last change
863 *actualNumBlocks
= block
- *actualStartBlock
;
866 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
867 panic("BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
870 *actualStartBlock
= 0;
871 *actualNumBlocks
= 0;
875 (void) ReleaseBitmapBlock(vcb
, blockRef
, dirty
);
882 _______________________________________________________________________
884 Routine: BlockAllocateKnown
886 Function: Try to allocate space from known free space in the free
890 vcb Pointer to volume where space is to be allocated
891 maxBlocks Maximum number of contiguous blocks to allocate
894 actualStartBlock First block of range allocated, or 0 if error
895 actualNumBlocks Number of blocks allocated, or 0 if error
898 dskFulErr Free extent cache is empty
899 _______________________________________________________________________
901 static OSErr
BlockAllocateKnown(
904 u_int32_t
*actualStartBlock
,
905 u_int32_t
*actualNumBlocks
)
909 u_int32_t foundBlocks
;
910 u_int32_t newStartBlock
, newBlockCount
;
912 if (vcb
->vcbFreeExtCnt
== 0)
915 // Just grab up to maxBlocks of the first (largest) free exent.
916 *actualStartBlock
= vcb
->vcbFreeExt
[0].startBlock
;
917 foundBlocks
= vcb
->vcbFreeExt
[0].blockCount
;
918 if (foundBlocks
> maxBlocks
)
919 foundBlocks
= maxBlocks
;
920 *actualNumBlocks
= foundBlocks
;
922 // Adjust the start and length of that extent.
923 newStartBlock
= vcb
->vcbFreeExt
[0].startBlock
+ foundBlocks
;
924 newBlockCount
= vcb
->vcbFreeExt
[0].blockCount
- foundBlocks
;
926 // The first extent might not be the largest anymore. Bubble up any
927 // (now larger) extents to the top of the list.
928 for (i
=1; i
<vcb
->vcbFreeExtCnt
; ++i
)
930 if (vcb
->vcbFreeExt
[i
].blockCount
> newBlockCount
)
932 vcb
->vcbFreeExt
[i
-1].startBlock
= vcb
->vcbFreeExt
[i
].startBlock
;
933 vcb
->vcbFreeExt
[i
-1].blockCount
= vcb
->vcbFreeExt
[i
].blockCount
;
941 // If this is now the smallest known free extent, then it might be smaller than
942 // other extents we didn't keep track of. So, just forget about this extent.
943 // After the previous loop, (i-1) is the index of the extent we just allocated from.
944 if (i
== vcb
->vcbFreeExtCnt
)
946 // It's now the smallest extent, so forget about it
947 --vcb
->vcbFreeExtCnt
;
951 // It's not the smallest, so store it in its proper place
952 vcb
->vcbFreeExt
[i
-1].startBlock
= newStartBlock
;
953 vcb
->vcbFreeExt
[i
-1].blockCount
= newBlockCount
;
957 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
959 printf ("hfs: BlockAllocateKnown() found allocation overflow on \"%s\"", vcb
->vcbVN
);
960 hfs_mark_volume_inconsistent(vcb
);
961 *actualStartBlock
= 0;
962 *actualNumBlocks
= 0;
968 // Now mark the found extent in the bitmap
970 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
979 _______________________________________________________________________
981 Routine: BlockMarkAllocated
983 Function: Mark a contiguous group of blocks as allocated (set in the
984 bitmap). It assumes those bits are currently marked
985 deallocated (clear in the bitmap).
988 vcb Pointer to volume where space is to be allocated
989 startingBlock First block number to mark as allocated
990 numBlocks Number of blocks to mark as allocated
991 _______________________________________________________________________
994 OSErr
BlockMarkAllocated(
996 u_int32_t startingBlock
,
997 register u_int32_t numBlocks
)
1000 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1001 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1002 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1003 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1004 u_int32_t numBits
; // Number of bits in word to allocate
1005 u_int32_t
*buffer
= NULL
;
1007 u_int32_t bitsPerBlock
;
1008 u_int32_t wordsPerBlock
;
1010 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1014 // Pre-read the bitmap block containing the first word of allocation
1017 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1018 if (err
!= noErr
) goto Exit
;
1020 // Initialize currentWord, and wordsLeft.
1023 u_int32_t wordIndexInBlock
;
1025 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1026 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1028 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1029 currentWord
= buffer
+ wordIndexInBlock
;
1030 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1035 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1039 // If the first block to allocate doesn't start on a word
1040 // boundary in the bitmap, then treat that first word
1044 firstBit
= startingBlock
% kBitsPerWord
;
1045 if (firstBit
!= 0) {
1046 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1047 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1048 if (numBits
> numBlocks
) {
1049 numBits
= numBlocks
; // entire allocation is inside this one word
1050 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1053 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1054 panic("BlockMarkAllocated: blocks already allocated!");
1057 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1058 numBlocks
-= numBits
; // adjust number of blocks left to allocate
1060 ++currentWord
; // move to next word
1061 --wordsLeft
; // one less word left in this block
1065 // Allocate whole words (32 blocks) at a time.
1068 bitMask
= kAllBitsSetInWord
; // put this in a register for 68K
1069 while (numBlocks
>= kBitsPerWord
) {
1070 if (wordsLeft
== 0) {
1071 // Read in the next bitmap block
1072 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1075 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1076 if (err
!= noErr
) goto Exit
;
1078 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1079 if (err
!= noErr
) goto Exit
;
1083 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1086 // Readjust currentWord and wordsLeft
1087 currentWord
= buffer
;
1088 wordsLeft
= wordsPerBlock
;
1091 if (*currentWord
!= 0) {
1092 panic("BlockMarkAllocated: blocks already allocated!");
1095 *currentWord
= SWAP_BE32 (bitMask
);
1096 numBlocks
-= kBitsPerWord
;
1098 ++currentWord
; // move to next word
1099 --wordsLeft
; // one less word left in this block
1103 // Allocate any remaining blocks.
1106 if (numBlocks
!= 0) {
1107 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1108 if (wordsLeft
== 0) {
1109 // Read in the next bitmap block
1110 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1113 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1114 if (err
!= noErr
) goto Exit
;
1116 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1117 if (err
!= noErr
) goto Exit
;
1121 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1124 // Readjust currentWord and wordsLeft
1125 currentWord
= buffer
;
1126 wordsLeft
= wordsPerBlock
;
1129 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1130 panic("BlockMarkAllocated: blocks already allocated!");
1133 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1135 // No need to update currentWord or wordsLeft
1141 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1148 _______________________________________________________________________
1150 Routine: BlockMarkFree
1152 Function: Mark a contiguous group of blocks as free (clear in the
1153 bitmap). It assumes those bits are currently marked
1154 allocated (set in the bitmap).
1157 vcb Pointer to volume where space is to be freed
1158 startingBlock First block number to mark as freed
1159 numBlocks Number of blocks to mark as freed
1160 _______________________________________________________________________
1163 OSErr
BlockMarkFree(
1165 u_int32_t startingBlock
,
1166 register u_int32_t numBlocks
)
1169 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1170 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1171 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1172 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1173 u_int32_t numBits
; // Number of bits in word to allocate
1174 u_int32_t
*buffer
= NULL
;
1176 u_int32_t bitsPerBlock
;
1177 u_int32_t wordsPerBlock
;
1179 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1182 * NOTE: We use vcb->totalBlocks instead of vcb->allocLimit because we
1183 * need to be able to free blocks being relocated during hfs_truncatefs.
1185 if (startingBlock
+ numBlocks
> vcb
->totalBlocks
) {
1186 printf ("hfs: BlockMarkFree() trying to free non-existent blocks starting at %u (numBlock=%u) on volume %s\n", startingBlock
, numBlocks
, vcb
->vcbVN
);
1187 hfs_mark_volume_inconsistent(vcb
);
1194 // Pre-read the bitmap block containing the first word of allocation
1197 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1198 if (err
!= noErr
) goto Exit
;
1201 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1205 // Initialize currentWord, and wordsLeft.
1208 u_int32_t wordIndexInBlock
;
1210 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1211 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1213 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1214 currentWord
= buffer
+ wordIndexInBlock
;
1215 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1219 // If the first block to free doesn't start on a word
1220 // boundary in the bitmap, then treat that first word
1224 firstBit
= startingBlock
% kBitsPerWord
;
1225 if (firstBit
!= 0) {
1226 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1227 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1228 if (numBits
> numBlocks
) {
1229 numBits
= numBlocks
; // entire allocation is inside this one word
1230 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1232 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1235 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1236 numBlocks
-= numBits
; // adjust number of blocks left to free
1238 ++currentWord
; // move to next word
1239 --wordsLeft
; // one less word left in this block
1243 // Free whole words (32 blocks) at a time.
1246 while (numBlocks
>= kBitsPerWord
) {
1247 if (wordsLeft
== 0) {
1248 // Read in the next bitmap block
1249 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1252 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1253 if (err
!= noErr
) goto Exit
;
1255 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1256 if (err
!= noErr
) goto Exit
;
1260 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1263 // Readjust currentWord and wordsLeft
1264 currentWord
= buffer
;
1265 wordsLeft
= wordsPerBlock
;
1267 if (*currentWord
!= SWAP_BE32 (kAllBitsSetInWord
)) {
1270 *currentWord
= 0; // clear the entire word
1271 numBlocks
-= kBitsPerWord
;
1273 ++currentWord
; // move to next word
1274 --wordsLeft
; // one less word left in this block
1278 // Free any remaining blocks.
1281 if (numBlocks
!= 0) {
1282 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1283 if (wordsLeft
== 0) {
1284 // Read in the next bitmap block
1285 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1288 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1289 if (err
!= noErr
) goto Exit
;
1291 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1292 if (err
!= noErr
) goto Exit
;
1296 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1299 // Readjust currentWord and wordsLeft
1300 currentWord
= buffer
;
1301 wordsLeft
= wordsPerBlock
;
1303 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1306 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1308 // No need to update currentWord or wordsLeft
1314 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1320 panic("BlockMarkFree: blocks not allocated!");
1322 printf ("hfs: BlockMarkFree() trying to free unallocated blocks on volume %s\n", vcb
->vcbVN
);
1323 hfs_mark_volume_inconsistent(vcb
);
1331 _______________________________________________________________________
1333 Routine: BlockFindContiguous
1335 Function: Find a contiguous range of blocks that are free (bits
1336 clear in the bitmap). If a contiguous range of the
1337 minimum size can't be found, an error will be returned.
1340 vcb Pointer to volume where space is to be allocated
1341 startingBlock Preferred first block of range
1342 endingBlock Last possible block in range + 1
1343 minBlocks Minimum number of blocks needed. Must be > 0.
1344 maxBlocks Maximum (ideal) number of blocks desired
1345 useMetaZone OK to dip into metadata allocation zone
1348 actualStartBlock First block of range found, or 0 if error
1349 actualNumBlocks Number of blocks found, or 0 if error
1352 noErr Found at least minBlocks contiguous
1353 dskFulErr No contiguous space found, or all less than minBlocks
1354 _______________________________________________________________________
1357 static OSErr
BlockFindContiguous(
1359 u_int32_t startingBlock
,
1360 u_int32_t endingBlock
,
1361 u_int32_t minBlocks
,
1362 u_int32_t maxBlocks
,
1363 Boolean useMetaZone
,
1364 u_int32_t
*actualStartBlock
,
1365 u_int32_t
*actualNumBlocks
)
1368 register u_int32_t currentBlock
; // Block we're currently looking at.
1369 u_int32_t firstBlock
; // First free block in current extent.
1370 u_int32_t stopBlock
; // If we get to this block, stop searching for first free block.
1371 u_int32_t foundBlocks
; // Number of contiguous free blocks in current extent.
1372 u_int32_t
*buffer
= NULL
;
1373 register u_int32_t
*currentWord
;
1374 register u_int32_t bitMask
;
1375 register u_int32_t wordsLeft
;
1376 register u_int32_t tempWord
;
1378 u_int32_t wordsPerBlock
;
1381 * When we're skipping the metadata zone and the start/end
1382 * range overlaps with the metadata zone then adjust the
1383 * start to be outside of the metadata zone. If the range
1384 * is entirely inside the metadata zone then we can deny the
1385 * request (dskFulErr).
1387 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
1388 if (startingBlock
<= vcb
->hfs_metazone_end
) {
1389 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
1390 startingBlock
= vcb
->hfs_metazone_end
+ 1;
1396 if ((endingBlock
- startingBlock
) < minBlocks
)
1398 // The set of blocks we're checking is smaller than the minimum number
1399 // of blocks, so we couldn't possibly find a good range.
1403 stopBlock
= endingBlock
- minBlocks
+ 1;
1404 currentBlock
= startingBlock
;
1408 * Skip over metadata blocks.
1411 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1414 // Pre-read the first bitmap block.
1416 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1417 if ( err
!= noErr
) goto ErrorExit
;
1420 // Figure out where currentBlock is within the buffer.
1422 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1424 wordsLeft
= (currentBlock
/ kBitsPerWord
) & (wordsPerBlock
-1); // Current index into buffer
1425 currentWord
= buffer
+ wordsLeft
;
1426 wordsLeft
= wordsPerBlock
- wordsLeft
;
1432 //============================================================
1433 // Look for a free block, skipping over allocated blocks.
1434 //============================================================
1437 // Check an initial partial word (if any)
1439 bitMask
= currentBlock
& kBitsWithinWordMask
;
1442 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1443 bitMask
= kHighBitInWordMask
>> bitMask
;
1444 while (tempWord
& bitMask
)
1450 // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)?
1454 // Didn't find any unused bits, so we're done with this word.
1460 // Check whole words
1462 while (currentBlock
< stopBlock
)
1464 // See if it's time to read another block.
1468 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1469 if (err
!= noErr
) goto ErrorExit
;
1472 * Skip over metadata blocks.
1475 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1476 if (currentBlock
>= stopBlock
) {
1481 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1482 if ( err
!= noErr
) goto ErrorExit
;
1484 currentWord
= buffer
;
1485 wordsLeft
= wordsPerBlock
;
1488 // See if any of the bits are clear
1489 if ((tempWord
= SWAP_BE32(*currentWord
)) + 1) // non-zero if any bits were clear
1491 // Figure out which bit is clear
1492 bitMask
= kHighBitInWordMask
;
1493 while (tempWord
& bitMask
)
1499 break; // Found the free bit; break out to FoundUnused.
1502 // Keep looking at the next word
1503 currentBlock
+= kBitsPerWord
;
1509 // Make sure the unused bit is early enough to use
1510 if (currentBlock
>= stopBlock
)
1515 // Remember the start of the extent
1516 firstBlock
= currentBlock
;
1518 //============================================================
1519 // Count the number of contiguous free blocks.
1520 //============================================================
1523 // Check an initial partial word (if any)
1525 bitMask
= currentBlock
& kBitsWithinWordMask
;
1528 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1529 bitMask
= kHighBitInWordMask
>> bitMask
;
1530 while (bitMask
&& !(tempWord
& bitMask
))
1536 // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)?
1540 // Didn't find any used bits, so we're done with this word.
1546 // Check whole words
1548 while (currentBlock
< endingBlock
)
1550 // See if it's time to read another block.
1554 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1555 if (err
!= noErr
) goto ErrorExit
;
1558 * Skip over metadata blocks.
1561 u_int32_t nextBlock
;
1563 nextBlock
= NextBitmapBlock(vcb
, currentBlock
);
1564 if (nextBlock
!= currentBlock
) {
1565 goto LoopExit
; /* allocation gap, so stop */
1569 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1570 if ( err
!= noErr
) goto ErrorExit
;
1572 currentWord
= buffer
;
1573 wordsLeft
= wordsPerBlock
;
1576 // See if any of the bits are set
1577 if ((tempWord
= SWAP_BE32(*currentWord
)) != 0)
1579 // Figure out which bit is set
1580 bitMask
= kHighBitInWordMask
;
1581 while (!(tempWord
& bitMask
))
1587 break; // Found the used bit; break out to FoundUsed.
1590 // Keep looking at the next word
1591 currentBlock
+= kBitsPerWord
;
1595 // If we found at least maxBlocks, we can quit early.
1596 if ((currentBlock
- firstBlock
) >= maxBlocks
)
1601 // Make sure we didn't run out of bitmap looking for a used block.
1602 // If so, pin to the end of the bitmap.
1603 if (currentBlock
> endingBlock
)
1604 currentBlock
= endingBlock
;
1606 // Figure out how many contiguous free blocks there were.
1607 // Pin the answer to maxBlocks.
1608 foundBlocks
= currentBlock
- firstBlock
;
1609 if (foundBlocks
> maxBlocks
)
1610 foundBlocks
= maxBlocks
;
1611 if (foundBlocks
>= minBlocks
)
1612 break; // Found what we needed!
1614 // This free chunk wasn't big enough. Try inserting it into the free extent cache in case
1615 // the allocation wasn't forced contiguous.
1616 tempWord
= vcb
->vcbFreeExtCnt
;
1617 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< foundBlocks
)
1619 if (tempWord
< kMaxFreeExtents
)
1621 // We're going to add this extent. Bubble any smaller extents down in the list.
1622 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< foundBlocks
)
1624 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1627 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1628 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1630 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
)
1631 ++vcb
->vcbFreeExtCnt
;
1633 } while (currentBlock
< stopBlock
);
1636 // Return the outputs.
1637 if (foundBlocks
< minBlocks
)
1642 *actualStartBlock
= 0;
1643 *actualNumBlocks
= 0;
1648 *actualStartBlock
= firstBlock
;
1649 *actualNumBlocks
= foundBlocks
;
1651 * Sanity check for overflow
1653 if ((firstBlock
+ foundBlocks
) > vcb
->allocLimit
) {
1654 panic("blk allocation overflow on \"%s\" sb:0x%08x eb:0x%08x cb:0x%08x fb:0x%08x stop:0x%08x min:0x%08x found:0x%08x",
1655 vcb
->vcbVN
, startingBlock
, endingBlock
, currentBlock
,
1656 firstBlock
, stopBlock
, minBlocks
, foundBlocks
);
1661 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1667 * Test to see if any blocks in a range are allocated.
1669 * The journal or allocation file lock must be held.
1673 hfs_isallocated(struct hfsmount
*hfsmp
, u_long startingBlock
, u_long numBlocks
)
1675 u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1676 u_int32_t wordsLeft
; // Number of words left in this bitmap block
1677 u_int32_t bitMask
; // Word with given bits already set (ready to test)
1678 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1679 u_int32_t numBits
; // Number of bits in word to allocate
1680 u_int32_t
*buffer
= NULL
;
1682 u_int32_t bitsPerBlock
;
1683 u_int32_t wordsPerBlock
;
1688 * Pre-read the bitmap block containing the first word of allocation
1690 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1695 * Initialize currentWord, and wordsLeft.
1698 u_int32_t wordIndexInBlock
;
1700 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
1701 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
1703 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1704 currentWord
= buffer
+ wordIndexInBlock
;
1705 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1709 * First test any non word aligned bits.
1711 firstBit
= startingBlock
% kBitsPerWord
;
1712 if (firstBit
!= 0) {
1713 bitMask
= kAllBitsSetInWord
>> firstBit
;
1714 numBits
= kBitsPerWord
- firstBit
;
1715 if (numBits
> numBlocks
) {
1716 numBits
= numBlocks
;
1717 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
1719 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1723 numBlocks
-= numBits
;
1729 * Test whole words (32 blocks) at a time.
1731 while (numBlocks
>= kBitsPerWord
) {
1732 if (wordsLeft
== 0) {
1733 /* Read in the next bitmap block. */
1734 startingBlock
+= bitsPerBlock
;
1737 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1738 if (error
) goto Exit
;
1740 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1741 if (error
) goto Exit
;
1743 /* Readjust currentWord and wordsLeft. */
1744 currentWord
= buffer
;
1745 wordsLeft
= wordsPerBlock
;
1747 if (*currentWord
!= 0) {
1751 numBlocks
-= kBitsPerWord
;
1757 * Test any remaining blocks.
1759 if (numBlocks
!= 0) {
1760 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
);
1761 if (wordsLeft
== 0) {
1762 /* Read in the next bitmap block */
1763 startingBlock
+= bitsPerBlock
;
1766 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1767 if (error
) goto Exit
;
1769 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1770 if (error
) goto Exit
;
1772 currentWord
= buffer
;
1773 wordsLeft
= wordsPerBlock
;
1775 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1782 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);