2 * Copyright (c) 2000-2008 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>
91 #include "../../hfs.h"
92 #include "../../hfs_dbg.h"
93 #include "../../hfs_format.h"
94 #include "../../hfs_endian.h"
96 #include "../headers/FileMgrInternal.h"
104 kBitsWithinWordMask
= kBitsPerWord
-1
107 #define kLowBitInWordMask 0x00000001ul
108 #define kHighBitInWordMask 0x80000000ul
109 #define kAllBitsSetInWord 0xFFFFFFFFul
112 static OSErr
ReadBitmapBlock(
116 uintptr_t *blockRef
);
118 static OSErr
ReleaseBitmapBlock(
123 static OSErr
BlockAllocateAny(
125 u_int32_t startingBlock
,
126 u_int32_t endingBlock
,
129 u_int32_t
*actualStartBlock
,
130 u_int32_t
*actualNumBlocks
);
132 static OSErr
BlockAllocateContig(
134 u_int32_t startingBlock
,
138 u_int32_t
*actualStartBlock
,
139 u_int32_t
*actualNumBlocks
);
141 static OSErr
BlockFindContiguous(
143 u_int32_t startingBlock
,
144 u_int32_t endingBlock
,
148 u_int32_t
*actualStartBlock
,
149 u_int32_t
*actualNumBlocks
);
151 static OSErr
BlockAllocateKnown(
154 u_int32_t
*actualStartBlock
,
155 u_int32_t
*actualNumBlocks
);
159 ;________________________________________________________________________________
163 ; Function: Allocate space on a volume. If contiguous allocation is requested,
164 ; at least the requested number of bytes will be allocated or an
165 ; error will be returned. If contiguous allocation is not forced,
166 ; the space will be allocated at the first free fragment following
167 ; the requested starting allocation block. If there is not enough
168 ; room there, a block of less than the requested size will be
171 ; If the requested starting block is 0 (for new file allocations),
172 ; the volume's allocation block pointer will be used as a starting
176 ; vcb - Pointer to ExtendedVCB for the volume to allocate space on
177 ; fcb - Pointer to FCB for the file for which storage is being allocated
178 ; startingBlock - Preferred starting allocation block, 0 = no preference
179 ; forceContiguous - Force contiguous flag - if bit 0 set (NE), allocation is contiguous
180 ; or an error is returned
182 ; minBlocks - Number of blocks requested. If the allocation is non-contiguous,
183 ; less than this may actually be allocated
184 ; maxBlocks - The maximum number of blocks to allocate. If there is additional free
185 ; space after bytesRequested, then up to maxBlocks bytes should really
186 ; be allocated. (Used by ExtendFileC to round up allocations to a multiple
187 ; of the file's clump size.)
190 ; (result) - Error code, zero for successful allocation
191 ; *startBlock - Actual starting allocation block
192 ; *actualBlocks - Actual number of allocation blocks allocated
195 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
196 ;________________________________________________________________________________
199 sanity_check_free_ext(__unused ExtendedVCB
*vcb
, __unused
int check_allocated
)
204 for(i
=0; i
< vcb
->vcbFreeExtCnt
; i
++) {
205 u_int32_t start
, nblocks
;
207 start
= vcb
->vcbFreeExt
[i
].startBlock
;
208 nblocks
= vcb
->vcbFreeExt
[i
].blockCount
;
212 panic("hfs: %p: slot %d in the free extent array had a zero count (%d)\n", vcb
, i
, start
);
215 if (check_allocated
&& hfs_isallocated(vcb
, start
, nblocks
)) {
216 panic("hfs: %p: slot %d in the free extent array is bad (%d / %d)\n",
217 vcb
, i
, start
, nblocks
);
220 for(j
=i
+1; j
< vcb
->vcbFreeExtCnt
; j
++) {
221 if (start
== vcb
->vcbFreeExt
[j
].startBlock
) {
222 panic("hfs: %p: slot %d/%d are dups?! (%d / %d ; %d / %d)\n",
223 vcb
, i
, j
, start
, nblocks
, vcb
->vcbFreeExt
[i
].startBlock
,
224 vcb
->vcbFreeExt
[i
].blockCount
);
233 OSErr
BlockAllocate (
234 ExtendedVCB
*vcb
, /* which volume to allocate space on */
235 u_int32_t startingBlock
, /* preferred starting block, or 0 for no preference */
236 u_int32_t minBlocks
, /* desired number of blocks to allocate */
237 u_int32_t maxBlocks
, /* maximum number of blocks to allocate */
238 Boolean forceContiguous
, /* non-zero to force contiguous allocation and to force */
239 /* minBlocks bytes to actually be allocated */
242 u_int32_t
*actualStartBlock
, /* actual first block of allocation */
243 u_int32_t
*actualNumBlocks
) /* number of blocks actually allocated; if forceContiguous */
244 /* was zero, then this may represent fewer than minBlocks */
246 u_int32_t freeBlocks
;
248 Boolean updateAllocPtr
= false; // true if nextAllocation needs to be updated
251 // Initialize outputs in case we get an error
253 *actualStartBlock
= 0;
254 *actualNumBlocks
= 0;
255 freeBlocks
= hfs_freeblks(VCBTOHFS(vcb
), 0);
258 // If the disk is already full, don't bother.
260 if (freeBlocks
== 0) {
264 if (forceContiguous
&& freeBlocks
< minBlocks
) {
269 * Clip if necessary so we don't over-subscribe the free blocks.
271 if (minBlocks
> freeBlocks
) {
272 minBlocks
= freeBlocks
;
274 if (maxBlocks
> freeBlocks
) {
275 maxBlocks
= freeBlocks
;
279 // If caller didn't specify a starting block number, then use the volume's
280 // next block to allocate from.
282 if (startingBlock
== 0) {
283 HFS_MOUNT_LOCK(vcb
, TRUE
);
284 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
285 startingBlock
= vcb
->sparseAllocation
;
287 startingBlock
= vcb
->nextAllocation
;
289 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
290 updateAllocPtr
= true;
292 if (startingBlock
>= vcb
->allocLimit
) {
293 startingBlock
= 0; /* overflow so start at beginning */
297 // If the request must be contiguous, then find a sequence of free blocks
298 // that is long enough. Otherwise, find the first free block.
300 if (forceContiguous
) {
301 err
= BlockAllocateContig(vcb
, startingBlock
, minBlocks
, maxBlocks
,
302 useMetaZone
, actualStartBlock
, actualNumBlocks
);
304 * If we allocated from a new position then
305 * also update the roving allocator.
307 if ((err
== noErr
) &&
308 (*actualStartBlock
> startingBlock
) &&
309 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
310 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
312 updateAllocPtr
= true;
316 * Scan the bitmap once, gather the N largest free extents, then
317 * allocate from these largest extents. Repeat as needed until
318 * we get all the space we needed. We could probably build up
319 * that list when the higher level caller tried (and failed) a
320 * contiguous allocation first.
322 err
= BlockAllocateKnown(vcb
, maxBlocks
, actualStartBlock
, actualNumBlocks
);
323 if (err
== dskFulErr
)
324 err
= BlockAllocateAny(vcb
, startingBlock
, vcb
->allocLimit
,
325 maxBlocks
, useMetaZone
, actualStartBlock
,
327 if (err
== dskFulErr
)
328 err
= BlockAllocateAny(vcb
, 1, startingBlock
, maxBlocks
,
329 useMetaZone
, actualStartBlock
,
334 // if we actually allocated something then go update the
335 // various bits of state that we maintain regardless of
336 // whether there was an error (i.e. partial allocations
337 // still need to update things like the free block count).
339 if (*actualNumBlocks
!= 0) {
343 // If we used the volume's roving allocation pointer, then we need to update it.
344 // Adding in the length of the current allocation might reduce the next allocate
345 // call by avoiding a re-scan of the already allocated space. However, the clump
346 // just allocated can quite conceivably end up being truncated or released when
347 // the file is closed or its EOF changed. Leaving the allocation pointer at the
348 // start of the last allocation will avoid unnecessary fragmentation in this case.
350 HFS_MOUNT_LOCK(vcb
, TRUE
);
352 if (vcb
->vcbFreeExtCnt
== 0 && vcb
->hfs_freed_block_count
== 0) {
353 vcb
->sparseAllocation
= *actualStartBlock
;
355 if (*actualNumBlocks
< vcb
->hfs_freed_block_count
) {
356 vcb
->hfs_freed_block_count
-= *actualNumBlocks
;
358 vcb
->hfs_freed_block_count
= 0;
361 if (updateAllocPtr
&&
362 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
363 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
364 HFS_UPDATE_NEXT_ALLOCATION(vcb
, *actualStartBlock
);
367 for(i
=0; i
< (int)vcb
->vcbFreeExtCnt
; i
++) {
368 u_int32_t start
, end
;
370 start
= vcb
->vcbFreeExt
[i
].startBlock
;
371 end
= start
+ vcb
->vcbFreeExt
[i
].blockCount
;
373 if ( (*actualStartBlock
>= start
&& *actualStartBlock
< end
)
374 || ((*actualStartBlock
+ *actualNumBlocks
) > start
&& *actualStartBlock
< start
)) {
376 for(j
=i
; j
< (int)vcb
->vcbFreeExtCnt
-1; j
++) {
377 vcb
->vcbFreeExt
[j
] = vcb
->vcbFreeExt
[j
+1];
380 vcb
->vcbFreeExtCnt
--;
381 i
--; // so we'll check the guy we just copied down...
383 // keep looping because we may have invalidated more
384 // than one entry in the array
389 // Update the number of free blocks on the volume
391 vcb
->freeBlocks
-= *actualNumBlocks
;
393 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
395 sanity_check_free_ext(vcb
, 1);
397 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
405 ;________________________________________________________________________________
407 ; Routine: BlkDealloc
409 ; Function: Update the bitmap to deallocate a run of disk allocation blocks
412 ; vcb - Pointer to ExtendedVCB for the volume to free space on
413 ; firstBlock - First allocation block to be freed
414 ; numBlocks - Number of allocation blocks to free up (must be > 0!)
417 ; (result) - Result code
420 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
421 ;________________________________________________________________________________
425 OSErr
BlockDeallocate (
426 ExtendedVCB
*vcb
, // Which volume to deallocate space on
427 u_int32_t firstBlock
, // First block in range to deallocate
428 u_int32_t numBlocks
) // Number of contiguous blocks to deallocate
434 // If no blocks to deallocate, then exit early
436 if (numBlocks
== 0) {
442 // Call internal routine to free the sequence of blocks
444 err
= BlockMarkFree(vcb
, firstBlock
, numBlocks
);
449 // Update the volume's free block count, and mark the VCB as dirty.
451 HFS_MOUNT_LOCK(vcb
, TRUE
);
452 vcb
->freeBlocks
+= numBlocks
;
453 vcb
->hfs_freed_block_count
+= numBlocks
;
454 if (firstBlock
< vcb
->sparseAllocation
) {
455 vcb
->sparseAllocation
= firstBlock
;
458 if (vcb
->nextAllocation
== (firstBlock
+ numBlocks
)) {
459 HFS_UPDATE_NEXT_ALLOCATION(vcb
, (vcb
->nextAllocation
- numBlocks
));
462 tempWord
= vcb
->vcbFreeExtCnt
;
463 // Add this free chunk to the free extent list
464 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
465 // Sorted by start block
466 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].startBlock
> firstBlock
)
468 if (tempWord
< kMaxFreeExtents
)
470 // We're going to add this extent. Bubble any smaller extents down in the list.
471 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].startBlock
> firstBlock
)
473 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
474 if (vcb
->vcbFreeExt
[tempWord
].startBlock
< vcb
->sparseAllocation
) {
475 vcb
->sparseAllocation
= vcb
->vcbFreeExt
[tempWord
].startBlock
;
479 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
480 vcb
->vcbFreeExt
[tempWord
].blockCount
= numBlocks
;
482 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
483 ++vcb
->vcbFreeExtCnt
;
487 // Sorted by num blocks
488 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< numBlocks
)
490 if (tempWord
< kMaxFreeExtents
)
492 // We're going to add this extent. Bubble any smaller extents down in the list.
493 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< numBlocks
)
495 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
496 if (vcb
->vcbFreeExt
[tempWord
].startBlock
< vcb
->sparseAllocation
) {
497 vcb
->sparseAllocation
= vcb
->vcbFreeExt
[tempWord
].startBlock
;
501 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
502 vcb
->vcbFreeExt
[tempWord
].blockCount
= numBlocks
;
504 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
505 ++vcb
->vcbFreeExtCnt
;
511 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
513 sanity_check_free_ext(vcb
, 1);
515 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
522 u_int8_t freebitcount
[16] = {
523 4, 3, 3, 2, 3, 2, 2, 1, /* 0 1 2 3 4 5 6 7 */
524 3, 2, 2, 1, 2, 1, 1, 0, /* 8 9 A B C D E F */
529 MetaZoneFreeBlocks(ExtendedVCB
*vcb
)
531 u_int32_t freeblocks
;
532 u_int32_t
*currCache
;
542 bytesleft
= freeblocks
= 0;
544 bit
= VCBTOHFS(vcb
)->hfs_metazone_start
;
548 lastbit
= VCBTOHFS(vcb
)->hfs_metazone_end
;
549 bytesperblock
= vcb
->vcbVBMIOSize
;
552 * Count all the bits from bit to lastbit.
554 while (bit
< lastbit
) {
556 * Get next bitmap block.
558 if (bytesleft
== 0) {
560 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
563 if (ReadBitmapBlock(vcb
, bit
, &currCache
, &blockRef
) != 0) {
566 buffer
= (u_int8_t
*)currCache
;
567 bytesleft
= bytesperblock
;
570 freeblocks
+= freebitcount
[byte
& 0x0F];
571 freeblocks
+= freebitcount
[(byte
>> 4) & 0x0F];
576 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
583 * Obtain the next allocation block (bit) that's
584 * outside the metadata allocation zone.
586 static u_int32_t
NextBitmapBlock(
590 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
592 if ((hfsmp
->hfs_flags
& HFS_METADATA_ZONE
) == 0)
595 * Skip over metadata allocation zone.
597 if ((bit
>= hfsmp
->hfs_metazone_start
) &&
598 (bit
<= hfsmp
->hfs_metazone_end
)) {
599 bit
= hfsmp
->hfs_metazone_end
+ 1;
606 ;_______________________________________________________________________
608 ; Routine: ReadBitmapBlock
610 ; Function: Read in a bitmap block corresponding to a given allocation
611 ; block (bit). Return a pointer to the bitmap block.
614 ; vcb -- Pointer to ExtendedVCB
615 ; bit -- Allocation block whose bitmap block is desired
618 ; buffer -- Pointer to bitmap block corresonding to "block"
620 ;_______________________________________________________________________
622 static OSErr
ReadBitmapBlock(
629 struct buf
*bp
= NULL
;
630 struct vnode
*vp
= NULL
;
635 * volume bitmap blocks are protected by the allocation file lock
637 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
639 blockSize
= (u_int32_t
)vcb
->vcbVBMIOSize
;
640 block
= (daddr64_t
)(bit
/ (blockSize
* kBitsPerByte
));
642 if (vcb
->vcbSigWord
== kHFSPlusSigWord
) {
643 vp
= vcb
->hfs_allocation_vp
; /* use allocation file vnode */
646 vp
= VCBTOHFS(vcb
)->hfs_devvp
; /* use device I/O vnode */
647 block
+= vcb
->vcbVBMSt
; /* map to physical block */
650 err
= (int)buf_meta_bread(vp
, block
, blockSize
, NOCRED
, &bp
);
658 *blockRef
= (uintptr_t)bp
;
659 *buffer
= (u_int32_t
*)buf_dataptr(bp
);
668 ;_______________________________________________________________________
670 ; Routine: ReleaseBitmapBlock
672 ; Function: Relase a bitmap block.
678 ;_______________________________________________________________________
680 static OSErr
ReleaseBitmapBlock(
685 struct buf
*bp
= (struct buf
*)blockRef
;
689 panic("hfs: ReleaseBitmapBlock: missing bp");
696 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
699 journal_modify_block_end(hfsmp
->jnl
, bp
, NULL
, NULL
);
713 _______________________________________________________________________
715 Routine: BlockAllocateContig
717 Function: Allocate a contiguous group of allocation blocks. The
718 allocation is all-or-nothing. The caller guarantees that
719 there are enough free blocks (though they may not be
720 contiguous, in which case this call will fail).
723 vcb Pointer to volume where space is to be allocated
724 startingBlock Preferred first block for allocation
725 minBlocks Minimum number of contiguous blocks to allocate
726 maxBlocks Maximum number of contiguous blocks to allocate
730 actualStartBlock First block of range allocated, or 0 if error
731 actualNumBlocks Number of blocks allocated, or 0 if error
732 _______________________________________________________________________
734 static OSErr
BlockAllocateContig(
736 u_int32_t startingBlock
,
740 u_int32_t
*actualStartBlock
,
741 u_int32_t
*actualNumBlocks
)
746 // Find a contiguous group of blocks at least minBlocks long.
747 // Determine the number of contiguous blocks available (up
752 * NOTE: If the only contiguous free extent of at least minBlocks
753 * crosses startingBlock (i.e. starts before, ends after), then we
754 * won't find it. Earlier versions *did* find this case by letting
755 * the second search look past startingBlock by minBlocks. But
756 * with the free extent cache, this can lead to duplicate entries
757 * in the cache, causing the same blocks to be allocated twice.
759 err
= BlockFindContiguous(vcb
, startingBlock
, vcb
->allocLimit
, minBlocks
,
760 maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
761 if (err
== dskFulErr
&& startingBlock
!= 0) {
763 * Constrain the endingBlock so we don't bother looking for ranges
764 * that would overlap those found in the previous call.
766 err
= BlockFindContiguous(vcb
, 1, startingBlock
, minBlocks
, maxBlocks
,
767 useMetaZone
, actualStartBlock
, actualNumBlocks
);
770 // Now mark those blocks allocated.
773 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
779 _______________________________________________________________________
781 Routine: BlockAllocateAny
783 Function: Allocate one or more allocation blocks. If there are fewer
784 free blocks than requested, all free blocks will be
785 allocated. The caller guarantees that there is at least
789 vcb Pointer to volume where space is to be allocated
790 startingBlock Preferred first block for allocation
791 endingBlock Last block to check + 1
792 maxBlocks Maximum number of contiguous blocks to allocate
796 actualStartBlock First block of range allocated, or 0 if error
797 actualNumBlocks Number of blocks allocated, or 0 if error
798 _______________________________________________________________________
800 static OSErr
BlockAllocateAny(
802 u_int32_t startingBlock
,
803 register u_int32_t endingBlock
,
806 u_int32_t
*actualStartBlock
,
807 u_int32_t
*actualNumBlocks
)
810 register u_int32_t block
; // current block number
811 register u_int32_t currentWord
; // Pointer to current word within bitmap block
812 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
813 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
814 u_int32_t
*buffer
= NULL
;
815 u_int32_t
*currCache
= NULL
;
817 u_int32_t bitsPerBlock
;
818 u_int32_t wordsPerBlock
;
819 Boolean dirty
= false;
820 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
823 * When we're skipping the metadata zone and the start/end
824 * range overlaps with the metadata zone then adjust the
825 * start to be outside of the metadata zone. If the range
826 * is entirely inside the metadata zone then we can deny the
827 * request (dskFulErr).
829 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
830 if (startingBlock
<= vcb
->hfs_metazone_end
) {
831 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
832 startingBlock
= vcb
->hfs_metazone_end
+ 1;
840 // Since this routine doesn't wrap around
841 if (maxBlocks
> (endingBlock
- startingBlock
)) {
842 maxBlocks
= endingBlock
- startingBlock
;
846 // Pre-read the first bitmap block
848 err
= ReadBitmapBlock(vcb
, startingBlock
, &currCache
, &blockRef
);
849 if (err
!= noErr
) goto Exit
;
853 // Set up the current position within the block
856 u_int32_t wordIndexInBlock
;
858 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
859 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
861 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
862 buffer
+= wordIndexInBlock
;
863 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
864 currentWord
= SWAP_BE32 (*buffer
);
865 bitMask
= kHighBitInWordMask
>> (startingBlock
& kBitsWithinWordMask
);
869 // Find the first unallocated block
872 while (block
< endingBlock
) {
873 if ((currentWord
& bitMask
) == 0)
881 bitMask
= kHighBitInWordMask
;
884 if (--wordsLeft
== 0) {
886 buffer
= currCache
= NULL
;
887 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
888 if (err
!= noErr
) goto Exit
;
891 * Skip over metadata blocks.
894 block
= NextBitmapBlock(vcb
, block
);
896 if (block
>= endingBlock
) {
901 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
902 if (err
!= noErr
) goto Exit
;
905 wordsLeft
= wordsPerBlock
;
907 currentWord
= SWAP_BE32 (*buffer
);
911 // Did we get to the end of the bitmap before finding a free block?
912 // If so, then couldn't allocate anything.
913 if (block
>= endingBlock
) {
918 // Return the first block in the allocated range
919 *actualStartBlock
= block
;
922 // If we could get the desired number of blocks before hitting endingBlock,
923 // then adjust endingBlock so we won't keep looking. Ideally, the comparison
924 // would be (block + maxBlocks) < endingBlock, but that could overflow. The
925 // comparison below yields identical results, but without overflow.
926 if (block
< (endingBlock
-maxBlocks
)) {
927 endingBlock
= block
+ maxBlocks
; // if we get this far, we've found enough
932 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
936 // Allocate all of the consecutive blocks
938 while ((currentWord
& bitMask
) == 0) {
939 // Allocate this block
940 currentWord
|= bitMask
;
942 // Move to the next block. If no more, then exit.
944 if (block
== endingBlock
)
950 *buffer
= SWAP_BE32 (currentWord
); // update value in bitmap
953 bitMask
= kHighBitInWordMask
;
956 if (--wordsLeft
== 0) {
958 buffer
= currCache
= NULL
;
959 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
960 if (err
!= noErr
) goto Exit
;
963 * Skip over metadata blocks.
968 nextBlock
= NextBitmapBlock(vcb
, block
);
969 if (nextBlock
!= block
) {
970 goto Exit
; /* allocation gap, so stop */
974 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
975 if (err
!= noErr
) goto Exit
;
980 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
983 wordsLeft
= wordsPerBlock
;
986 currentWord
= SWAP_BE32 (*buffer
);
989 *buffer
= SWAP_BE32 (currentWord
); // update the last change
993 *actualNumBlocks
= block
- *actualStartBlock
;
996 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
997 panic("hfs: BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
1000 *actualStartBlock
= 0;
1001 *actualNumBlocks
= 0;
1005 (void) ReleaseBitmapBlock(vcb
, blockRef
, dirty
);
1012 _______________________________________________________________________
1014 Routine: BlockAllocateKnown
1016 Function: Try to allocate space from known free space in the free
1020 vcb Pointer to volume where space is to be allocated
1021 maxBlocks Maximum number of contiguous blocks to allocate
1024 actualStartBlock First block of range allocated, or 0 if error
1025 actualNumBlocks Number of blocks allocated, or 0 if error
1028 dskFulErr Free extent cache is empty
1029 _______________________________________________________________________
1032 static OSErr
BlockAllocateKnown(
1034 u_int32_t maxBlocks
,
1035 u_int32_t
*actualStartBlock
,
1036 u_int32_t
*actualNumBlocks
)
1040 u_int32_t foundBlocks
;
1041 u_int32_t newStartBlock
, newBlockCount
;
1043 if (vcb
->vcbFreeExtCnt
== 0 || vcb
->vcbFreeExt
[0].blockCount
== 0)
1046 // Just grab up to maxBlocks of the first (largest) free exent.
1047 *actualStartBlock
= vcb
->vcbFreeExt
[0].startBlock
;
1048 foundBlocks
= vcb
->vcbFreeExt
[0].blockCount
;
1049 if (foundBlocks
> maxBlocks
)
1050 foundBlocks
= maxBlocks
;
1051 *actualNumBlocks
= foundBlocks
;
1053 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
1054 // since sparse volumes keep the free extent list sorted by starting
1055 // block number, the list won't get re-ordered, it may only shrink
1057 vcb
->vcbFreeExt
[0].startBlock
+= foundBlocks
;
1058 vcb
->vcbFreeExt
[0].blockCount
-= foundBlocks
;
1059 if (vcb
->vcbFreeExt
[0].blockCount
== 0) {
1060 for(i
=1; i
< vcb
->vcbFreeExtCnt
; i
++) {
1061 vcb
->vcbFreeExt
[i
-1] = vcb
->vcbFreeExt
[i
];
1063 vcb
->vcbFreeExtCnt
--;
1069 // Adjust the start and length of that extent.
1070 newStartBlock
= vcb
->vcbFreeExt
[0].startBlock
+ foundBlocks
;
1071 newBlockCount
= vcb
->vcbFreeExt
[0].blockCount
- foundBlocks
;
1074 // The first extent might not be the largest anymore. Bubble up any
1075 // (now larger) extents to the top of the list.
1076 for (i
=1; i
<vcb
->vcbFreeExtCnt
; ++i
)
1078 if (vcb
->vcbFreeExt
[i
].blockCount
> newBlockCount
)
1080 vcb
->vcbFreeExt
[i
-1].startBlock
= vcb
->vcbFreeExt
[i
].startBlock
;
1081 vcb
->vcbFreeExt
[i
-1].blockCount
= vcb
->vcbFreeExt
[i
].blockCount
;
1089 // If this is now the smallest known free extent, then it might be smaller than
1090 // other extents we didn't keep track of. So, just forget about this extent.
1091 // After the previous loop, (i-1) is the index of the extent we just allocated from.
1092 if (newBlockCount
== 0)
1094 // then just reduce the number of free extents since this guy got deleted
1095 --vcb
->vcbFreeExtCnt
;
1099 // It's not the smallest, so store it in its proper place
1100 vcb
->vcbFreeExt
[i
-1].startBlock
= newStartBlock
;
1101 vcb
->vcbFreeExt
[i
-1].blockCount
= newBlockCount
;
1106 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
1108 printf ("hfs: BlockAllocateKnown() found allocation overflow on \"%s\"", vcb
->vcbVN
);
1109 hfs_mark_volume_inconsistent(vcb
);
1110 *actualStartBlock
= 0;
1111 *actualNumBlocks
= 0;
1117 // Now mark the found extent in the bitmap
1119 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
1122 sanity_check_free_ext(vcb
, 1);
1130 _______________________________________________________________________
1132 Routine: BlockMarkAllocated
1134 Function: Mark a contiguous group of blocks as allocated (set in the
1135 bitmap). It assumes those bits are currently marked
1136 deallocated (clear in the bitmap).
1139 vcb Pointer to volume where space is to be allocated
1140 startingBlock First block number to mark as allocated
1141 numBlocks Number of blocks to mark as allocated
1142 _______________________________________________________________________
1145 OSErr
BlockMarkAllocated(
1147 u_int32_t startingBlock
,
1148 register u_int32_t numBlocks
)
1151 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1152 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1153 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1154 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1155 u_int32_t numBits
; // Number of bits in word to allocate
1156 u_int32_t
*buffer
= NULL
;
1158 u_int32_t bitsPerBlock
;
1159 u_int32_t wordsPerBlock
;
1161 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1165 // Pre-read the bitmap block containing the first word of allocation
1168 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1169 if (err
!= noErr
) goto Exit
;
1171 // Initialize currentWord, and wordsLeft.
1174 u_int32_t wordIndexInBlock
;
1176 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1177 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1179 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1180 currentWord
= buffer
+ wordIndexInBlock
;
1181 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1186 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1190 // If the first block to allocate doesn't start on a word
1191 // boundary in the bitmap, then treat that first word
1195 firstBit
= startingBlock
% kBitsPerWord
;
1196 if (firstBit
!= 0) {
1197 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1198 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1199 if (numBits
> numBlocks
) {
1200 numBits
= numBlocks
; // entire allocation is inside this one word
1201 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1204 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1205 panic("hfs: BlockMarkAllocated: blocks already allocated!");
1208 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1209 numBlocks
-= numBits
; // adjust number of blocks left to allocate
1211 ++currentWord
; // move to next word
1212 --wordsLeft
; // one less word left in this block
1216 // Allocate whole words (32 blocks) at a time.
1219 bitMask
= kAllBitsSetInWord
; // put this in a register for 68K
1220 while (numBlocks
>= kBitsPerWord
) {
1221 if (wordsLeft
== 0) {
1222 // Read in the next bitmap block
1223 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1226 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1227 if (err
!= noErr
) goto Exit
;
1229 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1230 if (err
!= noErr
) goto Exit
;
1234 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1237 // Readjust currentWord and wordsLeft
1238 currentWord
= buffer
;
1239 wordsLeft
= wordsPerBlock
;
1242 if (*currentWord
!= 0) {
1243 panic("hfs: BlockMarkAllocated: blocks already allocated!");
1246 *currentWord
= SWAP_BE32 (bitMask
);
1247 numBlocks
-= kBitsPerWord
;
1249 ++currentWord
; // move to next word
1250 --wordsLeft
; // one less word left in this block
1254 // Allocate any remaining blocks.
1257 if (numBlocks
!= 0) {
1258 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1259 if (wordsLeft
== 0) {
1260 // Read in the next bitmap block
1261 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1264 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1265 if (err
!= noErr
) goto Exit
;
1267 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1268 if (err
!= noErr
) goto Exit
;
1272 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1275 // Readjust currentWord and wordsLeft
1276 currentWord
= buffer
;
1277 wordsLeft
= wordsPerBlock
;
1280 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1281 panic("hfs: BlockMarkAllocated: blocks already allocated!");
1284 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1286 // No need to update currentWord or wordsLeft
1292 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1299 _______________________________________________________________________
1301 Routine: BlockMarkFree
1303 Function: Mark a contiguous group of blocks as free (clear in the
1304 bitmap). It assumes those bits are currently marked
1305 allocated (set in the bitmap).
1308 vcb Pointer to volume where space is to be freed
1309 startingBlock First block number to mark as freed
1310 numBlocks Number of blocks to mark as freed
1311 _______________________________________________________________________
1314 OSErr
BlockMarkFree(
1316 u_int32_t startingBlock
,
1317 register u_int32_t numBlocks
)
1320 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1321 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1322 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1323 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1324 u_int32_t numBits
; // Number of bits in word to allocate
1325 u_int32_t
*buffer
= NULL
;
1327 u_int32_t bitsPerBlock
;
1328 u_int32_t wordsPerBlock
;
1330 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1331 dk_discard_t discard
;
1334 * NOTE: We use vcb->totalBlocks instead of vcb->allocLimit because we
1335 * need to be able to free blocks being relocated during hfs_truncatefs.
1337 if (startingBlock
+ numBlocks
> vcb
->totalBlocks
) {
1338 printf ("hfs: BlockMarkFree() trying to free non-existent blocks starting at %u (numBlock=%u) on volume %s\n", startingBlock
, numBlocks
, vcb
->vcbVN
);
1339 hfs_mark_volume_inconsistent(vcb
);
1344 memset(&discard
, 0, sizeof(dk_discard_t
));
1345 discard
.offset
= (uint64_t)startingBlock
* (uint64_t)vcb
->blockSize
;
1346 discard
.length
= (uint64_t)numBlocks
* (uint64_t)vcb
->blockSize
;
1350 // Pre-read the bitmap block containing the first word of allocation
1353 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1354 if (err
!= noErr
) goto Exit
;
1357 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1361 // Initialize currentWord, and wordsLeft.
1364 u_int32_t wordIndexInBlock
;
1366 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1367 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1369 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1370 currentWord
= buffer
+ wordIndexInBlock
;
1371 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1375 // If the first block to free doesn't start on a word
1376 // boundary in the bitmap, then treat that first word
1380 firstBit
= startingBlock
% kBitsPerWord
;
1381 if (firstBit
!= 0) {
1382 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1383 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1384 if (numBits
> numBlocks
) {
1385 numBits
= numBlocks
; // entire allocation is inside this one word
1386 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1388 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1391 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1392 numBlocks
-= numBits
; // adjust number of blocks left to free
1394 ++currentWord
; // move to next word
1395 --wordsLeft
; // one less word left in this block
1399 // Free whole words (32 blocks) at a time.
1402 while (numBlocks
>= kBitsPerWord
) {
1403 if (wordsLeft
== 0) {
1404 // Read in the next bitmap block
1405 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1408 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1409 if (err
!= noErr
) goto Exit
;
1411 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1412 if (err
!= noErr
) goto Exit
;
1416 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1419 // Readjust currentWord and wordsLeft
1420 currentWord
= buffer
;
1421 wordsLeft
= wordsPerBlock
;
1423 if (*currentWord
!= SWAP_BE32 (kAllBitsSetInWord
)) {
1426 *currentWord
= 0; // clear the entire word
1427 numBlocks
-= kBitsPerWord
;
1429 ++currentWord
; // move to next word
1430 --wordsLeft
; // one less word left in this block
1434 // Free any remaining blocks.
1437 if (numBlocks
!= 0) {
1438 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1439 if (wordsLeft
== 0) {
1440 // Read in the next bitmap block
1441 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1444 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1445 if (err
!= noErr
) goto Exit
;
1447 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1448 if (err
!= noErr
) goto Exit
;
1452 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1455 // Readjust currentWord and wordsLeft
1456 currentWord
= buffer
;
1457 wordsLeft
= wordsPerBlock
;
1459 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1462 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1464 // No need to update currentWord or wordsLeft
1470 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1473 // it doesn't matter if this fails, it's just informational anyway
1474 VNOP_IOCTL(vcb
->hfs_devvp
, DKIOCDISCARD
, (caddr_t
)&discard
, 0, vfs_context_kernel());
1482 panic("hfs: BlockMarkFree: blocks not allocated!");
1484 printf ("hfs: BlockMarkFree() trying to free unallocated blocks on volume %s\n", vcb
->vcbVN
);
1485 hfs_mark_volume_inconsistent(vcb
);
1493 _______________________________________________________________________
1495 Routine: BlockFindContiguous
1497 Function: Find a contiguous range of blocks that are free (bits
1498 clear in the bitmap). If a contiguous range of the
1499 minimum size can't be found, an error will be returned.
1502 vcb Pointer to volume where space is to be allocated
1503 startingBlock Preferred first block of range
1504 endingBlock Last possible block in range + 1
1505 minBlocks Minimum number of blocks needed. Must be > 0.
1506 maxBlocks Maximum (ideal) number of blocks desired
1507 useMetaZone OK to dip into metadata allocation zone
1510 actualStartBlock First block of range found, or 0 if error
1511 actualNumBlocks Number of blocks found, or 0 if error
1514 noErr Found at least minBlocks contiguous
1515 dskFulErr No contiguous space found, or all less than minBlocks
1516 _______________________________________________________________________
1519 static OSErr
BlockFindContiguous(
1521 u_int32_t startingBlock
,
1522 u_int32_t endingBlock
,
1523 u_int32_t minBlocks
,
1524 u_int32_t maxBlocks
,
1525 Boolean useMetaZone
,
1526 u_int32_t
*actualStartBlock
,
1527 u_int32_t
*actualNumBlocks
)
1530 register u_int32_t currentBlock
; // Block we're currently looking at.
1531 u_int32_t firstBlock
; // First free block in current extent.
1532 u_int32_t stopBlock
; // If we get to this block, stop searching for first free block.
1533 u_int32_t foundBlocks
; // Number of contiguous free blocks in current extent.
1534 u_int32_t
*buffer
= NULL
;
1535 register u_int32_t
*currentWord
;
1536 register u_int32_t bitMask
;
1537 register u_int32_t wordsLeft
;
1538 register u_int32_t tempWord
;
1540 u_int32_t wordsPerBlock
;
1541 u_int32_t j
, updated_free_extents
= 0, really_add
;
1544 * When we're skipping the metadata zone and the start/end
1545 * range overlaps with the metadata zone then adjust the
1546 * start to be outside of the metadata zone. If the range
1547 * is entirely inside the metadata zone then we can deny the
1548 * request (dskFulErr).
1550 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
1551 if (startingBlock
<= vcb
->hfs_metazone_end
) {
1552 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
1553 startingBlock
= vcb
->hfs_metazone_end
+ 1;
1559 if ((endingBlock
- startingBlock
) < minBlocks
)
1561 // The set of blocks we're checking is smaller than the minimum number
1562 // of blocks, so we couldn't possibly find a good range.
1566 stopBlock
= endingBlock
- minBlocks
+ 1;
1567 currentBlock
= startingBlock
;
1571 * Skip over metadata blocks.
1574 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1577 // Pre-read the first bitmap block.
1579 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1580 if ( err
!= noErr
) goto ErrorExit
;
1583 // Figure out where currentBlock is within the buffer.
1585 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1587 wordsLeft
= (currentBlock
/ kBitsPerWord
) & (wordsPerBlock
-1); // Current index into buffer
1588 currentWord
= buffer
+ wordsLeft
;
1589 wordsLeft
= wordsPerBlock
- wordsLeft
;
1595 //============================================================
1596 // Look for a free block, skipping over allocated blocks.
1597 //============================================================
1600 // Check an initial partial word (if any)
1602 bitMask
= currentBlock
& kBitsWithinWordMask
;
1605 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1606 bitMask
= kHighBitInWordMask
>> bitMask
;
1607 while (tempWord
& bitMask
)
1613 // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)?
1617 // Didn't find any unused bits, so we're done with this word.
1623 // Check whole words
1625 while (currentBlock
< stopBlock
)
1627 // See if it's time to read another block.
1631 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1632 if (err
!= noErr
) goto ErrorExit
;
1635 * Skip over metadata blocks.
1638 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1639 if (currentBlock
>= stopBlock
) {
1644 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1645 if ( err
!= noErr
) goto ErrorExit
;
1647 currentWord
= buffer
;
1648 wordsLeft
= wordsPerBlock
;
1651 // See if any of the bits are clear
1652 if ((tempWord
= SWAP_BE32(*currentWord
)) + 1) // non-zero if any bits were clear
1654 // Figure out which bit is clear
1655 bitMask
= kHighBitInWordMask
;
1656 while (tempWord
& bitMask
)
1662 break; // Found the free bit; break out to FoundUnused.
1665 // Keep looking at the next word
1666 currentBlock
+= kBitsPerWord
;
1672 // Make sure the unused bit is early enough to use
1673 if (currentBlock
>= stopBlock
)
1678 // Remember the start of the extent
1679 firstBlock
= currentBlock
;
1681 //============================================================
1682 // Count the number of contiguous free blocks.
1683 //============================================================
1686 // Check an initial partial word (if any)
1688 bitMask
= currentBlock
& kBitsWithinWordMask
;
1691 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1692 bitMask
= kHighBitInWordMask
>> bitMask
;
1693 while (bitMask
&& !(tempWord
& bitMask
))
1699 // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)?
1703 // Didn't find any used bits, so we're done with this word.
1709 // Check whole words
1711 while (currentBlock
< endingBlock
)
1713 // See if it's time to read another block.
1717 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1718 if (err
!= noErr
) goto ErrorExit
;
1721 * Skip over metadata blocks.
1724 u_int32_t nextBlock
;
1726 nextBlock
= NextBitmapBlock(vcb
, currentBlock
);
1727 if (nextBlock
!= currentBlock
) {
1728 goto LoopExit
; /* allocation gap, so stop */
1732 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1733 if ( err
!= noErr
) goto ErrorExit
;
1735 currentWord
= buffer
;
1736 wordsLeft
= wordsPerBlock
;
1739 // See if any of the bits are set
1740 if ((tempWord
= SWAP_BE32(*currentWord
)) != 0)
1742 // Figure out which bit is set
1743 bitMask
= kHighBitInWordMask
;
1744 while (!(tempWord
& bitMask
))
1750 break; // Found the used bit; break out to FoundUsed.
1753 // Keep looking at the next word
1754 currentBlock
+= kBitsPerWord
;
1758 // If we found at least maxBlocks, we can quit early.
1759 if ((currentBlock
- firstBlock
) >= maxBlocks
)
1764 // Make sure we didn't run out of bitmap looking for a used block.
1765 // If so, pin to the end of the bitmap.
1766 if (currentBlock
> endingBlock
)
1767 currentBlock
= endingBlock
;
1769 // Figure out how many contiguous free blocks there were.
1770 // Pin the answer to maxBlocks.
1771 foundBlocks
= currentBlock
- firstBlock
;
1772 if (foundBlocks
> maxBlocks
)
1773 foundBlocks
= maxBlocks
;
1774 if (foundBlocks
>= minBlocks
)
1775 break; // Found what we needed!
1777 // This free chunk wasn't big enough. Try inserting it into the free extent cache in case
1778 // the allocation wasn't forced contiguous.
1780 for(j
=0; j
< vcb
->vcbFreeExtCnt
; j
++) {
1781 u_int32_t start
, end
;
1783 start
= vcb
->vcbFreeExt
[j
].startBlock
;
1784 end
= start
+ vcb
->vcbFreeExt
[j
].blockCount
;
1786 if ( (firstBlock
>= start
&& firstBlock
< end
)
1787 || ((firstBlock
+ foundBlocks
) > start
&& firstBlock
< start
)) {
1789 // there's overlap with an existing entry so do not add this
1795 if (j
>= vcb
->vcbFreeExtCnt
) {
1799 tempWord
= vcb
->vcbFreeExtCnt
;
1800 if (really_add
&& (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
)) {
1801 // Sorted by starting block
1802 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].startBlock
> firstBlock
)
1804 if (tempWord
< kMaxFreeExtents
)
1806 // We're going to add this extent. Bubble any smaller extents down in the list.
1807 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].startBlock
> firstBlock
)
1809 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1812 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1813 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1815 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
1816 ++vcb
->vcbFreeExtCnt
;
1818 updated_free_extents
= 1;
1820 } else if (really_add
) {
1821 // Sorted by blockCount
1822 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< foundBlocks
)
1824 if (tempWord
< kMaxFreeExtents
)
1826 // We're going to add this extent. Bubble any smaller extents down in the list.
1827 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< foundBlocks
)
1829 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1832 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1833 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1835 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
1836 ++vcb
->vcbFreeExtCnt
;
1838 updated_free_extents
= 1;
1842 sanity_check_free_ext(vcb
, 0);
1844 } while (currentBlock
< stopBlock
);
1847 // Return the outputs.
1848 if (foundBlocks
< minBlocks
)
1853 *actualStartBlock
= 0;
1854 *actualNumBlocks
= 0;
1859 *actualStartBlock
= firstBlock
;
1860 *actualNumBlocks
= foundBlocks
;
1862 * Sanity check for overflow
1864 if ((firstBlock
+ foundBlocks
) > vcb
->allocLimit
) {
1865 panic("hfs: 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",
1866 vcb
->vcbVN
, startingBlock
, endingBlock
, currentBlock
,
1867 firstBlock
, stopBlock
, minBlocks
, foundBlocks
);
1871 if (updated_free_extents
&& (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
)) {
1873 u_int32_t min_start
= vcb
->totalBlocks
;
1875 // set the nextAllocation pointer to the smallest free block number
1876 // we've seen so on the next mount we won't rescan unnecessarily
1877 for(i
=0; i
< (int)vcb
->vcbFreeExtCnt
; i
++) {
1878 if (vcb
->vcbFreeExt
[i
].startBlock
< min_start
) {
1879 min_start
= vcb
->vcbFreeExt
[i
].startBlock
;
1882 if (min_start
!= vcb
->totalBlocks
) {
1883 if (min_start
< vcb
->nextAllocation
) {
1884 vcb
->nextAllocation
= min_start
;
1886 if (min_start
< vcb
->sparseAllocation
) {
1887 vcb
->sparseAllocation
= min_start
;
1893 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1895 sanity_check_free_ext(vcb
, 1);
1901 * Test to see if any blocks in a range are allocated.
1903 * The journal or allocation file lock must be held.
1907 hfs_isallocated(struct hfsmount
*hfsmp
, u_int32_t startingBlock
, u_int32_t numBlocks
)
1909 u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1910 u_int32_t wordsLeft
; // Number of words left in this bitmap block
1911 u_int32_t bitMask
; // Word with given bits already set (ready to test)
1912 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1913 u_int32_t numBits
; // Number of bits in word to allocate
1914 u_int32_t
*buffer
= NULL
;
1916 u_int32_t bitsPerBlock
;
1917 u_int32_t wordsPerBlock
;
1922 * Pre-read the bitmap block containing the first word of allocation
1924 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1929 * Initialize currentWord, and wordsLeft.
1932 u_int32_t wordIndexInBlock
;
1934 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
1935 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
1937 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1938 currentWord
= buffer
+ wordIndexInBlock
;
1939 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1943 * First test any non word aligned bits.
1945 firstBit
= startingBlock
% kBitsPerWord
;
1946 if (firstBit
!= 0) {
1947 bitMask
= kAllBitsSetInWord
>> firstBit
;
1948 numBits
= kBitsPerWord
- firstBit
;
1949 if (numBits
> numBlocks
) {
1950 numBits
= numBlocks
;
1951 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
1953 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1957 numBlocks
-= numBits
;
1963 * Test whole words (32 blocks) at a time.
1965 while (numBlocks
>= kBitsPerWord
) {
1966 if (wordsLeft
== 0) {
1967 /* Read in the next bitmap block. */
1968 startingBlock
+= bitsPerBlock
;
1971 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
1972 if (error
) goto Exit
;
1974 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1975 if (error
) goto Exit
;
1977 /* Readjust currentWord and wordsLeft. */
1978 currentWord
= buffer
;
1979 wordsLeft
= wordsPerBlock
;
1981 if (*currentWord
!= 0) {
1985 numBlocks
-= kBitsPerWord
;
1991 * Test any remaining blocks.
1993 if (numBlocks
!= 0) {
1994 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
);
1995 if (wordsLeft
== 0) {
1996 /* Read in the next bitmap block */
1997 startingBlock
+= bitsPerBlock
;
2000 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
2001 if (error
) goto Exit
;
2003 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
2004 if (error
) goto Exit
;
2006 currentWord
= buffer
;
2007 wordsLeft
= wordsPerBlock
;
2009 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
2016 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);