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.
49 invalidate_free_extent_cache Invalidate free extent cache for a given volume.
53 Mark a contiguous range of blocks as free. The corresponding
54 bits in the volume bitmap will be cleared.
56 Mark a contiguous range of blocks as allocated. The cor-
57 responding bits in the volume bitmap are set. Also tests to see
58 if any of the blocks were previously unallocated.
60 Find a contiguous range of blocks of a given size. The caller
61 specifies where to begin the search (by block number). The
62 block number of the first block in the range is returned.
64 Find and allocate a contiguous range of blocks up to a given size. The
65 first range of contiguous free blocks found are allocated, even if there
66 are fewer blocks than requested (and even if a contiguous range of blocks
67 of the given size exists elsewhere).
69 Find and allocate a contiguous range of blocks of a given size. If
70 a contiguous range of free blocks of the given size isn't found, then
71 the allocation fails (i.e. it is "all or nothing").
74 Try to allocate space from known free space in the volume's
78 Given an allocation block number, read the bitmap block that
79 contains that allocation block into a caller-supplied buffer.
82 Release a bitmap block back into the buffer cache.
85 #include "../../hfs_macos_defs.h"
87 #include <sys/types.h>
89 #include <sys/systm.h>
92 #include "../../hfs.h"
93 #include "../../hfs_dbg.h"
94 #include "../../hfs_format.h"
95 #include "../../hfs_endian.h"
97 #include "../headers/FileMgrInternal.h"
105 kBitsWithinWordMask
= kBitsPerWord
-1
108 #define kLowBitInWordMask 0x00000001ul
109 #define kHighBitInWordMask 0x80000000ul
110 #define kAllBitsSetInWord 0xFFFFFFFFul
113 static OSErr
ReadBitmapBlock(
117 uintptr_t *blockRef
);
119 static OSErr
ReleaseBitmapBlock(
124 static OSErr
BlockAllocateAny(
126 u_int32_t startingBlock
,
127 u_int32_t endingBlock
,
130 u_int32_t
*actualStartBlock
,
131 u_int32_t
*actualNumBlocks
);
133 static OSErr
BlockAllocateContig(
135 u_int32_t startingBlock
,
139 u_int32_t
*actualStartBlock
,
140 u_int32_t
*actualNumBlocks
);
142 static OSErr
BlockFindContiguous(
144 u_int32_t startingBlock
,
145 u_int32_t endingBlock
,
149 u_int32_t
*actualStartBlock
,
150 u_int32_t
*actualNumBlocks
);
152 static OSErr
BlockAllocateKnown(
155 u_int32_t
*actualStartBlock
,
156 u_int32_t
*actualNumBlocks
);
158 static int free_extent_cache_active(
162 ;________________________________________________________________________________
166 ; Function: Allocate space on a volume. If contiguous allocation is requested,
167 ; at least the requested number of bytes will be allocated or an
168 ; error will be returned. If contiguous allocation is not forced,
169 ; the space will be allocated at the first free fragment following
170 ; the requested starting allocation block. If there is not enough
171 ; room there, a block of less than the requested size will be
174 ; If the requested starting block is 0 (for new file allocations),
175 ; the volume's allocation block pointer will be used as a starting
179 ; vcb - Pointer to ExtendedVCB for the volume to allocate space on
180 ; fcb - Pointer to FCB for the file for which storage is being allocated
181 ; startingBlock - Preferred starting allocation block, 0 = no preference
182 ; forceContiguous - Force contiguous flag - if bit 0 set (NE), allocation is contiguous
183 ; or an error is returned
185 ; minBlocks - Number of blocks requested. If the allocation is non-contiguous,
186 ; less than this may actually be allocated
187 ; maxBlocks - The maximum number of blocks to allocate. If there is additional free
188 ; space after bytesRequested, then up to maxBlocks bytes should really
189 ; be allocated. (Used by ExtendFileC to round up allocations to a multiple
190 ; of the file's clump size.)
193 ; (result) - Error code, zero for successful allocation
194 ; *startBlock - Actual starting allocation block
195 ; *actualBlocks - Actual number of allocation blocks allocated
198 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
199 ;________________________________________________________________________________
202 sanity_check_free_ext(__unused ExtendedVCB
*vcb
, __unused
int check_allocated
)
207 for(i
=0; i
< vcb
->vcbFreeExtCnt
; i
++) {
208 u_int32_t start
, nblocks
;
210 start
= vcb
->vcbFreeExt
[i
].startBlock
;
211 nblocks
= vcb
->vcbFreeExt
[i
].blockCount
;
215 panic("hfs: %p: slot %d in the free extent array had a zero count (%d)\n", vcb
, i
, start
);
218 if (check_allocated
&& hfs_isallocated(vcb
, start
, nblocks
)) {
219 panic("hfs: %p: slot %d in the free extent array is bad (%d / %d)\n",
220 vcb
, i
, start
, nblocks
);
223 for(j
=i
+1; j
< vcb
->vcbFreeExtCnt
; j
++) {
224 if (start
== vcb
->vcbFreeExt
[j
].startBlock
) {
225 panic("hfs: %p: slot %d/%d are dups?! (%d / %d ; %d / %d)\n",
226 vcb
, i
, j
, start
, nblocks
, vcb
->vcbFreeExt
[i
].startBlock
,
227 vcb
->vcbFreeExt
[i
].blockCount
);
236 OSErr
BlockAllocate (
237 ExtendedVCB
*vcb
, /* which volume to allocate space on */
238 u_int32_t startingBlock
, /* preferred starting block, or 0 for no preference */
239 u_int32_t minBlocks
, /* desired number of blocks to allocate */
240 u_int32_t maxBlocks
, /* maximum number of blocks to allocate */
241 u_int32_t flags
, /* option flags */
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
250 Boolean forceContiguous
;
252 if (flags
& HFS_ALLOC_FORCECONTIG
) {
253 forceContiguous
= true;
255 forceContiguous
= false;
258 if (flags
& HFS_ALLOC_METAZONE
) {
265 // Initialize outputs in case we get an error
267 *actualStartBlock
= 0;
268 *actualNumBlocks
= 0;
269 freeBlocks
= hfs_freeblks(VCBTOHFS(vcb
), 0);
271 /* Skip free block check if blocks are being allocated for relocating
272 * data during truncating a volume.
274 * During hfs_truncatefs(), the volume free block count is updated
275 * before relocating data to reflect the total number of free blocks
276 * that will exist on the volume after resize is successful. This
277 * means that we have reserved allocation blocks required for relocating
278 * the data and hence there is no need to check the free blocks.
279 * It will also prevent resize failure when the number of blocks in
280 * an extent being relocated is more than the free blocks that will
281 * exist after the volume is resized.
283 if ((flags
& HFS_ALLOC_SKIPFREEBLKS
) == 0) {
284 // If the disk is already full, don't bother.
285 if (freeBlocks
== 0) {
289 if (forceContiguous
&& freeBlocks
< minBlocks
) {
295 * Clip if necessary so we don't over-subscribe the free blocks.
297 if (minBlocks
> freeBlocks
) {
298 minBlocks
= freeBlocks
;
300 if (maxBlocks
> freeBlocks
) {
301 maxBlocks
= freeBlocks
;
306 // If caller didn't specify a starting block number, then use the volume's
307 // next block to allocate from.
309 if (startingBlock
== 0) {
310 HFS_MOUNT_LOCK(vcb
, TRUE
);
311 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
312 startingBlock
= vcb
->sparseAllocation
;
314 startingBlock
= vcb
->nextAllocation
;
316 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
317 updateAllocPtr
= true;
319 if (startingBlock
>= vcb
->allocLimit
) {
320 startingBlock
= 0; /* overflow so start at beginning */
324 // If the request must be contiguous, then find a sequence of free blocks
325 // that is long enough. Otherwise, find the first free block.
327 if (forceContiguous
) {
328 err
= BlockAllocateContig(vcb
, startingBlock
, minBlocks
, maxBlocks
,
329 useMetaZone
, actualStartBlock
, actualNumBlocks
);
331 * If we allocated from a new position then
332 * also update the roving allocator.
334 if ((err
== noErr
) &&
335 (*actualStartBlock
> startingBlock
) &&
336 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
337 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
339 updateAllocPtr
= true;
343 * Scan the bitmap once, gather the N largest free extents, then
344 * allocate from these largest extents. Repeat as needed until
345 * we get all the space we needed. We could probably build up
346 * that list when the higher level caller tried (and failed) a
347 * contiguous allocation first.
349 err
= BlockAllocateKnown(vcb
, maxBlocks
, actualStartBlock
, actualNumBlocks
);
350 if (err
== dskFulErr
)
351 err
= BlockAllocateAny(vcb
, startingBlock
, vcb
->allocLimit
,
352 maxBlocks
, useMetaZone
, actualStartBlock
,
354 if (err
== dskFulErr
)
355 err
= BlockAllocateAny(vcb
, 1, startingBlock
, maxBlocks
,
356 useMetaZone
, actualStartBlock
,
361 // if we actually allocated something then go update the
362 // various bits of state that we maintain regardless of
363 // whether there was an error (i.e. partial allocations
364 // still need to update things like the free block count).
366 if (*actualNumBlocks
!= 0) {
370 // If we used the volume's roving allocation pointer, then we need to update it.
371 // Adding in the length of the current allocation might reduce the next allocate
372 // call by avoiding a re-scan of the already allocated space. However, the clump
373 // just allocated can quite conceivably end up being truncated or released when
374 // the file is closed or its EOF changed. Leaving the allocation pointer at the
375 // start of the last allocation will avoid unnecessary fragmentation in this case.
377 HFS_MOUNT_LOCK(vcb
, TRUE
);
379 if (vcb
->vcbFreeExtCnt
== 0 && vcb
->hfs_freed_block_count
== 0) {
380 vcb
->sparseAllocation
= *actualStartBlock
;
382 if (*actualNumBlocks
< vcb
->hfs_freed_block_count
) {
383 vcb
->hfs_freed_block_count
-= *actualNumBlocks
;
385 vcb
->hfs_freed_block_count
= 0;
388 if (updateAllocPtr
&&
389 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
390 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
391 HFS_UPDATE_NEXT_ALLOCATION(vcb
, *actualStartBlock
);
394 for(i
=0; i
< (int)vcb
->vcbFreeExtCnt
; i
++) {
395 u_int32_t start
, end
;
397 start
= vcb
->vcbFreeExt
[i
].startBlock
;
398 end
= start
+ vcb
->vcbFreeExt
[i
].blockCount
;
400 if ( (*actualStartBlock
>= start
&& *actualStartBlock
< end
)
401 || ((*actualStartBlock
+ *actualNumBlocks
) > start
&& *actualStartBlock
< start
)) {
403 for(j
=i
; j
< (int)vcb
->vcbFreeExtCnt
-1; j
++) {
404 vcb
->vcbFreeExt
[j
] = vcb
->vcbFreeExt
[j
+1];
407 vcb
->vcbFreeExtCnt
--;
408 i
--; // so we'll check the guy we just copied down...
410 // keep looping because we may have invalidated more
411 // than one entry in the array
416 * Update the number of free blocks on the volume
418 * Skip updating the free blocks count if the block are
419 * being allocated to relocate data as part of hfs_truncatefs()
421 if ((flags
& HFS_ALLOC_SKIPFREEBLKS
) == 0) {
422 vcb
->freeBlocks
-= *actualNumBlocks
;
425 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
427 sanity_check_free_ext(vcb
, 1);
429 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
437 ;________________________________________________________________________________
439 ; Routine: BlkDealloc
441 ; Function: Update the bitmap to deallocate a run of disk allocation blocks
444 ; vcb - Pointer to ExtendedVCB for the volume to free space on
445 ; firstBlock - First allocation block to be freed
446 ; numBlocks - Number of allocation blocks to free up (must be > 0!)
449 ; (result) - Result code
452 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
453 ;________________________________________________________________________________
457 OSErr
BlockDeallocate (
458 ExtendedVCB
*vcb
, // Which volume to deallocate space on
459 u_int32_t firstBlock
, // First block in range to deallocate
460 u_int32_t numBlocks
, // Number of contiguous blocks to deallocate
467 // If no blocks to deallocate, then exit early
469 if (numBlocks
== 0) {
475 // Call internal routine to free the sequence of blocks
477 err
= BlockMarkFree(vcb
, firstBlock
, numBlocks
);
482 // Update the volume's free block count, and mark the VCB as dirty.
484 HFS_MOUNT_LOCK(vcb
, TRUE
);
487 * Do not update the free block count. This flags is specified
488 * when a volume is being truncated.
490 if ((flags
& HFS_ALLOC_SKIPFREEBLKS
) == 0) {
491 vcb
->freeBlocks
+= numBlocks
;
494 vcb
->hfs_freed_block_count
+= numBlocks
;
495 if (firstBlock
< vcb
->sparseAllocation
) {
496 vcb
->sparseAllocation
= firstBlock
;
499 if (vcb
->nextAllocation
== (firstBlock
+ numBlocks
)) {
500 HFS_UPDATE_NEXT_ALLOCATION(vcb
, (vcb
->nextAllocation
- numBlocks
));
503 if (free_extent_cache_active(vcb
) == 0) {
507 tempWord
= vcb
->vcbFreeExtCnt
;
508 // Add this free chunk to the free extent list
509 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
510 // Sorted by start block
511 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].startBlock
> firstBlock
)
513 if (tempWord
< kMaxFreeExtents
)
515 // We're going to add this extent. Bubble any smaller extents down in the list.
516 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].startBlock
> firstBlock
)
518 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
519 if (vcb
->vcbFreeExt
[tempWord
].startBlock
< vcb
->sparseAllocation
) {
520 vcb
->sparseAllocation
= vcb
->vcbFreeExt
[tempWord
].startBlock
;
524 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
525 vcb
->vcbFreeExt
[tempWord
].blockCount
= numBlocks
;
527 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
528 ++vcb
->vcbFreeExtCnt
;
532 // Sorted by num blocks
533 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< numBlocks
)
535 if (tempWord
< kMaxFreeExtents
)
537 // We're going to add this extent. Bubble any smaller extents down in the list.
538 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< numBlocks
)
540 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
541 if (vcb
->vcbFreeExt
[tempWord
].startBlock
< vcb
->sparseAllocation
) {
542 vcb
->sparseAllocation
= vcb
->vcbFreeExt
[tempWord
].startBlock
;
546 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
547 vcb
->vcbFreeExt
[tempWord
].blockCount
= numBlocks
;
549 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
550 ++vcb
->vcbFreeExtCnt
;
557 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
559 sanity_check_free_ext(vcb
, 1);
561 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
568 u_int8_t freebitcount
[16] = {
569 4, 3, 3, 2, 3, 2, 2, 1, /* 0 1 2 3 4 5 6 7 */
570 3, 2, 2, 1, 2, 1, 1, 0, /* 8 9 A B C D E F */
575 MetaZoneFreeBlocks(ExtendedVCB
*vcb
)
577 u_int32_t freeblocks
;
578 u_int32_t
*currCache
;
588 bytesleft
= freeblocks
= 0;
590 bit
= VCBTOHFS(vcb
)->hfs_metazone_start
;
594 lastbit
= VCBTOHFS(vcb
)->hfs_metazone_end
;
595 bytesperblock
= vcb
->vcbVBMIOSize
;
598 * Count all the bits from bit to lastbit.
600 while (bit
< lastbit
) {
602 * Get next bitmap block.
604 if (bytesleft
== 0) {
606 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
609 if (ReadBitmapBlock(vcb
, bit
, &currCache
, &blockRef
) != 0) {
612 buffer
= (u_int8_t
*)currCache
;
613 bytesleft
= bytesperblock
;
616 freeblocks
+= freebitcount
[byte
& 0x0F];
617 freeblocks
+= freebitcount
[(byte
>> 4) & 0x0F];
622 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
629 * Obtain the next allocation block (bit) that's
630 * outside the metadata allocation zone.
632 static u_int32_t
NextBitmapBlock(
636 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
638 if ((hfsmp
->hfs_flags
& HFS_METADATA_ZONE
) == 0)
641 * Skip over metadata allocation zone.
643 if ((bit
>= hfsmp
->hfs_metazone_start
) &&
644 (bit
<= hfsmp
->hfs_metazone_end
)) {
645 bit
= hfsmp
->hfs_metazone_end
+ 1;
652 ;_______________________________________________________________________
654 ; Routine: ReadBitmapBlock
656 ; Function: Read in a bitmap block corresponding to a given allocation
657 ; block (bit). Return a pointer to the bitmap block.
660 ; vcb -- Pointer to ExtendedVCB
661 ; bit -- Allocation block whose bitmap block is desired
664 ; buffer -- Pointer to bitmap block corresonding to "block"
666 ;_______________________________________________________________________
668 static OSErr
ReadBitmapBlock(
675 struct buf
*bp
= NULL
;
676 struct vnode
*vp
= NULL
;
681 * volume bitmap blocks are protected by the allocation file lock
683 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
685 blockSize
= (u_int32_t
)vcb
->vcbVBMIOSize
;
686 block
= (daddr64_t
)(bit
/ (blockSize
* kBitsPerByte
));
688 if (vcb
->vcbSigWord
== kHFSPlusSigWord
) {
689 vp
= vcb
->hfs_allocation_vp
; /* use allocation file vnode */
692 vp
= VCBTOHFS(vcb
)->hfs_devvp
; /* use device I/O vnode */
693 block
+= vcb
->vcbVBMSt
; /* map to physical block */
696 err
= (int)buf_meta_bread(vp
, block
, blockSize
, NOCRED
, &bp
);
704 *blockRef
= (uintptr_t)bp
;
705 *buffer
= (u_int32_t
*)buf_dataptr(bp
);
714 ;_______________________________________________________________________
716 ; Routine: ReleaseBitmapBlock
718 ; Function: Relase a bitmap block.
724 ;_______________________________________________________________________
726 static OSErr
ReleaseBitmapBlock(
731 struct buf
*bp
= (struct buf
*)blockRef
;
735 panic("hfs: ReleaseBitmapBlock: missing bp");
742 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
745 journal_modify_block_end(hfsmp
->jnl
, bp
, NULL
, NULL
);
759 _______________________________________________________________________
761 Routine: BlockAllocateContig
763 Function: Allocate a contiguous group of allocation blocks. The
764 allocation is all-or-nothing. The caller guarantees that
765 there are enough free blocks (though they may not be
766 contiguous, in which case this call will fail).
769 vcb Pointer to volume where space is to be allocated
770 startingBlock Preferred first block for allocation
771 minBlocks Minimum number of contiguous blocks to allocate
772 maxBlocks Maximum number of contiguous blocks to allocate
776 actualStartBlock First block of range allocated, or 0 if error
777 actualNumBlocks Number of blocks allocated, or 0 if error
778 _______________________________________________________________________
780 static OSErr
BlockAllocateContig(
782 u_int32_t startingBlock
,
786 u_int32_t
*actualStartBlock
,
787 u_int32_t
*actualNumBlocks
)
792 // Find a contiguous group of blocks at least minBlocks long.
793 // Determine the number of contiguous blocks available (up
798 * NOTE: If the only contiguous free extent of at least minBlocks
799 * crosses startingBlock (i.e. starts before, ends after), then we
800 * won't find it. Earlier versions *did* find this case by letting
801 * the second search look past startingBlock by minBlocks. But
802 * with the free extent cache, this can lead to duplicate entries
803 * in the cache, causing the same blocks to be allocated twice.
805 err
= BlockFindContiguous(vcb
, startingBlock
, vcb
->allocLimit
, minBlocks
,
806 maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
807 if (err
== dskFulErr
&& startingBlock
!= 0) {
809 * Constrain the endingBlock so we don't bother looking for ranges
810 * that would overlap those found in the previous call.
812 err
= BlockFindContiguous(vcb
, 1, startingBlock
, minBlocks
, maxBlocks
,
813 useMetaZone
, actualStartBlock
, actualNumBlocks
);
816 // Now mark those blocks allocated.
819 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
825 _______________________________________________________________________
827 Routine: BlockAllocateAny
829 Function: Allocate one or more allocation blocks. If there are fewer
830 free blocks than requested, all free blocks will be
831 allocated. The caller guarantees that there is at least
835 vcb Pointer to volume where space is to be allocated
836 startingBlock Preferred first block for allocation
837 endingBlock Last block to check + 1
838 maxBlocks Maximum number of contiguous blocks to allocate
842 actualStartBlock First block of range allocated, or 0 if error
843 actualNumBlocks Number of blocks allocated, or 0 if error
844 _______________________________________________________________________
846 static OSErr
BlockAllocateAny(
848 u_int32_t startingBlock
,
849 register u_int32_t endingBlock
,
852 u_int32_t
*actualStartBlock
,
853 u_int32_t
*actualNumBlocks
)
856 register u_int32_t block
; // current block number
857 register u_int32_t currentWord
; // Pointer to current word within bitmap block
858 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
859 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
860 u_int32_t
*buffer
= NULL
;
861 u_int32_t
*currCache
= NULL
;
863 u_int32_t bitsPerBlock
;
864 u_int32_t wordsPerBlock
;
865 Boolean dirty
= false;
866 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
869 * When we're skipping the metadata zone and the start/end
870 * range overlaps with the metadata zone then adjust the
871 * start to be outside of the metadata zone. If the range
872 * is entirely inside the metadata zone then we can deny the
873 * request (dskFulErr).
875 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
876 if (startingBlock
<= vcb
->hfs_metazone_end
) {
877 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
878 startingBlock
= vcb
->hfs_metazone_end
+ 1;
886 // Since this routine doesn't wrap around
887 if (maxBlocks
> (endingBlock
- startingBlock
)) {
888 maxBlocks
= endingBlock
- startingBlock
;
892 // Pre-read the first bitmap block
894 err
= ReadBitmapBlock(vcb
, startingBlock
, &currCache
, &blockRef
);
895 if (err
!= noErr
) goto Exit
;
899 // Set up the current position within the block
902 u_int32_t wordIndexInBlock
;
904 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
905 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
907 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
908 buffer
+= wordIndexInBlock
;
909 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
910 currentWord
= SWAP_BE32 (*buffer
);
911 bitMask
= kHighBitInWordMask
>> (startingBlock
& kBitsWithinWordMask
);
915 // Find the first unallocated block
918 while (block
< endingBlock
) {
919 if ((currentWord
& bitMask
) == 0)
927 bitMask
= kHighBitInWordMask
;
930 if (--wordsLeft
== 0) {
932 buffer
= currCache
= NULL
;
933 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
934 if (err
!= noErr
) goto Exit
;
937 * Skip over metadata blocks.
940 block
= NextBitmapBlock(vcb
, block
);
942 if (block
>= endingBlock
) {
947 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
948 if (err
!= noErr
) goto Exit
;
951 wordsLeft
= wordsPerBlock
;
953 currentWord
= SWAP_BE32 (*buffer
);
957 // Did we get to the end of the bitmap before finding a free block?
958 // If so, then couldn't allocate anything.
959 if (block
>= endingBlock
) {
964 // Return the first block in the allocated range
965 *actualStartBlock
= block
;
968 // If we could get the desired number of blocks before hitting endingBlock,
969 // then adjust endingBlock so we won't keep looking. Ideally, the comparison
970 // would be (block + maxBlocks) < endingBlock, but that could overflow. The
971 // comparison below yields identical results, but without overflow.
972 if (block
< (endingBlock
-maxBlocks
)) {
973 endingBlock
= block
+ maxBlocks
; // if we get this far, we've found enough
978 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
982 // Allocate all of the consecutive blocks
984 while ((currentWord
& bitMask
) == 0) {
985 // Allocate this block
986 currentWord
|= bitMask
;
988 // Move to the next block. If no more, then exit.
990 if (block
== endingBlock
)
996 *buffer
= SWAP_BE32 (currentWord
); // update value in bitmap
999 bitMask
= kHighBitInWordMask
;
1002 if (--wordsLeft
== 0) {
1004 buffer
= currCache
= NULL
;
1005 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1006 if (err
!= noErr
) goto Exit
;
1009 * Skip over metadata blocks.
1012 u_int32_t nextBlock
;
1014 nextBlock
= NextBitmapBlock(vcb
, block
);
1015 if (nextBlock
!= block
) {
1016 goto Exit
; /* allocation gap, so stop */
1020 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
1021 if (err
!= noErr
) goto Exit
;
1026 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1029 wordsLeft
= wordsPerBlock
;
1032 currentWord
= SWAP_BE32 (*buffer
);
1035 *buffer
= SWAP_BE32 (currentWord
); // update the last change
1039 *actualNumBlocks
= block
- *actualStartBlock
;
1042 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
1043 panic("hfs: BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
1046 *actualStartBlock
= 0;
1047 *actualNumBlocks
= 0;
1051 (void) ReleaseBitmapBlock(vcb
, blockRef
, dirty
);
1058 _______________________________________________________________________
1060 Routine: BlockAllocateKnown
1062 Function: Try to allocate space from known free space in the free
1066 vcb Pointer to volume where space is to be allocated
1067 maxBlocks Maximum number of contiguous blocks to allocate
1070 actualStartBlock First block of range allocated, or 0 if error
1071 actualNumBlocks Number of blocks allocated, or 0 if error
1074 dskFulErr Free extent cache is empty
1075 _______________________________________________________________________
1078 static OSErr
BlockAllocateKnown(
1080 u_int32_t maxBlocks
,
1081 u_int32_t
*actualStartBlock
,
1082 u_int32_t
*actualNumBlocks
)
1086 u_int32_t foundBlocks
;
1087 u_int32_t newStartBlock
, newBlockCount
;
1089 HFS_MOUNT_LOCK(vcb
, TRUE
);
1090 if (free_extent_cache_active(vcb
) == 0 ||
1091 vcb
->vcbFreeExtCnt
== 0 ||
1092 vcb
->vcbFreeExt
[0].blockCount
== 0) {
1093 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1096 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1098 // Just grab up to maxBlocks of the first (largest) free exent.
1099 *actualStartBlock
= vcb
->vcbFreeExt
[0].startBlock
;
1100 foundBlocks
= vcb
->vcbFreeExt
[0].blockCount
;
1101 if (foundBlocks
> maxBlocks
)
1102 foundBlocks
= maxBlocks
;
1103 *actualNumBlocks
= foundBlocks
;
1105 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
1106 // since sparse volumes keep the free extent list sorted by starting
1107 // block number, the list won't get re-ordered, it may only shrink
1109 vcb
->vcbFreeExt
[0].startBlock
+= foundBlocks
;
1110 vcb
->vcbFreeExt
[0].blockCount
-= foundBlocks
;
1111 if (vcb
->vcbFreeExt
[0].blockCount
== 0) {
1112 for(i
=1; i
< vcb
->vcbFreeExtCnt
; i
++) {
1113 vcb
->vcbFreeExt
[i
-1] = vcb
->vcbFreeExt
[i
];
1115 vcb
->vcbFreeExtCnt
--;
1121 // Adjust the start and length of that extent.
1122 newStartBlock
= vcb
->vcbFreeExt
[0].startBlock
+ foundBlocks
;
1123 newBlockCount
= vcb
->vcbFreeExt
[0].blockCount
- foundBlocks
;
1126 // The first extent might not be the largest anymore. Bubble up any
1127 // (now larger) extents to the top of the list.
1128 for (i
=1; i
<vcb
->vcbFreeExtCnt
; ++i
)
1130 if (vcb
->vcbFreeExt
[i
].blockCount
> newBlockCount
)
1132 vcb
->vcbFreeExt
[i
-1].startBlock
= vcb
->vcbFreeExt
[i
].startBlock
;
1133 vcb
->vcbFreeExt
[i
-1].blockCount
= vcb
->vcbFreeExt
[i
].blockCount
;
1141 // If this is now the smallest known free extent, then it might be smaller than
1142 // other extents we didn't keep track of. So, just forget about this extent.
1143 // After the previous loop, (i-1) is the index of the extent we just allocated from.
1144 if (newBlockCount
== 0)
1146 // then just reduce the number of free extents since this guy got deleted
1147 --vcb
->vcbFreeExtCnt
;
1151 // It's not the smallest, so store it in its proper place
1152 vcb
->vcbFreeExt
[i
-1].startBlock
= newStartBlock
;
1153 vcb
->vcbFreeExt
[i
-1].blockCount
= newBlockCount
;
1158 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
1160 printf ("hfs: BlockAllocateKnown() found allocation overflow on \"%s\"", vcb
->vcbVN
);
1161 hfs_mark_volume_inconsistent(vcb
);
1162 *actualStartBlock
= 0;
1163 *actualNumBlocks
= 0;
1169 // Now mark the found extent in the bitmap
1171 err
= BlockMarkAllocated(vcb
, *actualStartBlock
, *actualNumBlocks
);
1174 sanity_check_free_ext(vcb
, 1);
1182 _______________________________________________________________________
1184 Routine: BlockMarkAllocated
1186 Function: Mark a contiguous group of blocks as allocated (set in the
1187 bitmap). It assumes those bits are currently marked
1188 deallocated (clear in the bitmap).
1191 vcb Pointer to volume where space is to be allocated
1192 startingBlock First block number to mark as allocated
1193 numBlocks Number of blocks to mark as allocated
1194 _______________________________________________________________________
1197 OSErr
BlockMarkAllocated(
1199 u_int32_t startingBlock
,
1200 register u_int32_t numBlocks
)
1203 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1204 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1205 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1206 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1207 u_int32_t numBits
; // Number of bits in word to allocate
1208 u_int32_t
*buffer
= NULL
;
1210 u_int32_t bitsPerBlock
;
1211 u_int32_t wordsPerBlock
;
1213 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1217 // Pre-read the bitmap block containing the first word of allocation
1220 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1221 if (err
!= noErr
) goto Exit
;
1223 // Initialize currentWord, and wordsLeft.
1226 u_int32_t wordIndexInBlock
;
1228 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1229 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1231 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1232 currentWord
= buffer
+ wordIndexInBlock
;
1233 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1238 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1242 // If the first block to allocate doesn't start on a word
1243 // boundary in the bitmap, then treat that first word
1247 firstBit
= startingBlock
% kBitsPerWord
;
1248 if (firstBit
!= 0) {
1249 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1250 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1251 if (numBits
> numBlocks
) {
1252 numBits
= numBlocks
; // entire allocation is inside this one word
1253 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1256 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1257 panic("hfs: BlockMarkAllocated: blocks already allocated!");
1260 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1261 numBlocks
-= numBits
; // adjust number of blocks left to allocate
1263 ++currentWord
; // move to next word
1264 --wordsLeft
; // one less word left in this block
1268 // Allocate whole words (32 blocks) at a time.
1271 bitMask
= kAllBitsSetInWord
; // put this in a register for 68K
1272 while (numBlocks
>= kBitsPerWord
) {
1273 if (wordsLeft
== 0) {
1274 // Read in the next bitmap block
1275 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1278 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1279 if (err
!= noErr
) goto Exit
;
1281 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1282 if (err
!= noErr
) goto Exit
;
1286 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1289 // Readjust currentWord and wordsLeft
1290 currentWord
= buffer
;
1291 wordsLeft
= wordsPerBlock
;
1294 if (*currentWord
!= 0) {
1295 panic("hfs: BlockMarkAllocated: blocks already allocated!");
1298 *currentWord
= SWAP_BE32 (bitMask
);
1299 numBlocks
-= kBitsPerWord
;
1301 ++currentWord
; // move to next word
1302 --wordsLeft
; // one less word left in this block
1306 // Allocate any remaining blocks.
1309 if (numBlocks
!= 0) {
1310 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1311 if (wordsLeft
== 0) {
1312 // Read in the next bitmap block
1313 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1316 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1317 if (err
!= noErr
) goto Exit
;
1319 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1320 if (err
!= noErr
) goto Exit
;
1324 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1327 // Readjust currentWord and wordsLeft
1328 currentWord
= buffer
;
1329 wordsLeft
= wordsPerBlock
;
1332 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
1333 panic("hfs: BlockMarkAllocated: blocks already allocated!");
1336 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
1338 // No need to update currentWord or wordsLeft
1344 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1351 _______________________________________________________________________
1353 Routine: BlockMarkFree
1355 Function: Mark a contiguous group of blocks as free (clear in the
1356 bitmap). It assumes those bits are currently marked
1357 allocated (set in the bitmap).
1360 vcb Pointer to volume where space is to be freed
1361 startingBlock First block number to mark as freed
1362 numBlocks Number of blocks to mark as freed
1363 _______________________________________________________________________
1366 OSErr
BlockMarkFree(
1368 u_int32_t startingBlock
,
1369 register u_int32_t numBlocks
)
1372 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1373 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1374 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1375 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1376 u_int32_t numBits
; // Number of bits in word to allocate
1377 u_int32_t
*buffer
= NULL
;
1379 u_int32_t bitsPerBlock
;
1380 u_int32_t wordsPerBlock
;
1382 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1383 dk_discard_t discard
;
1386 * NOTE: We use vcb->totalBlocks instead of vcb->allocLimit because we
1387 * need to be able to free blocks being relocated during hfs_truncatefs.
1389 if (startingBlock
+ numBlocks
> vcb
->totalBlocks
) {
1390 printf ("hfs: BlockMarkFree() trying to free non-existent blocks starting at %u (numBlock=%u) on volume %s\n", startingBlock
, numBlocks
, vcb
->vcbVN
);
1391 hfs_mark_volume_inconsistent(vcb
);
1396 memset(&discard
, 0, sizeof(dk_discard_t
));
1397 discard
.offset
= (uint64_t)startingBlock
* (uint64_t)vcb
->blockSize
;
1398 discard
.length
= (uint64_t)numBlocks
* (uint64_t)vcb
->blockSize
;
1402 // Pre-read the bitmap block containing the first word of allocation
1405 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1406 if (err
!= noErr
) goto Exit
;
1409 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1413 // Initialize currentWord, and wordsLeft.
1416 u_int32_t wordIndexInBlock
;
1418 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1419 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1421 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1422 currentWord
= buffer
+ wordIndexInBlock
;
1423 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1427 // If the first block to free doesn't start on a word
1428 // boundary in the bitmap, then treat that first word
1432 firstBit
= startingBlock
% kBitsPerWord
;
1433 if (firstBit
!= 0) {
1434 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
1435 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
1436 if (numBits
> numBlocks
) {
1437 numBits
= numBlocks
; // entire allocation is inside this one word
1438 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
1440 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1443 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1444 numBlocks
-= numBits
; // adjust number of blocks left to free
1446 ++currentWord
; // move to next word
1447 --wordsLeft
; // one less word left in this block
1451 // Free whole words (32 blocks) at a time.
1454 while (numBlocks
>= kBitsPerWord
) {
1455 if (wordsLeft
== 0) {
1456 // Read in the next bitmap block
1457 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1460 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1461 if (err
!= noErr
) goto Exit
;
1463 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1464 if (err
!= noErr
) goto Exit
;
1468 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1471 // Readjust currentWord and wordsLeft
1472 currentWord
= buffer
;
1473 wordsLeft
= wordsPerBlock
;
1475 if (*currentWord
!= SWAP_BE32 (kAllBitsSetInWord
)) {
1478 *currentWord
= 0; // clear the entire word
1479 numBlocks
-= kBitsPerWord
;
1481 ++currentWord
; // move to next word
1482 --wordsLeft
; // one less word left in this block
1486 // Free any remaining blocks.
1489 if (numBlocks
!= 0) {
1490 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
1491 if (wordsLeft
== 0) {
1492 // Read in the next bitmap block
1493 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
1496 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1497 if (err
!= noErr
) goto Exit
;
1499 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
1500 if (err
!= noErr
) goto Exit
;
1504 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1507 // Readjust currentWord and wordsLeft
1508 currentWord
= buffer
;
1509 wordsLeft
= wordsPerBlock
;
1511 if ((*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
1514 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
1516 // No need to update currentWord or wordsLeft
1522 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
1525 // it doesn't matter if this fails, it's just informational anyway
1526 VNOP_IOCTL(vcb
->hfs_devvp
, DKIOCDISCARD
, (caddr_t
)&discard
, 0, vfs_context_kernel());
1534 panic("hfs: BlockMarkFree: blocks not allocated!");
1536 printf ("hfs: BlockMarkFree() trying to free unallocated blocks on volume %s\n", vcb
->vcbVN
);
1537 hfs_mark_volume_inconsistent(vcb
);
1545 _______________________________________________________________________
1547 Routine: BlockFindContiguous
1549 Function: Find a contiguous range of blocks that are free (bits
1550 clear in the bitmap). If a contiguous range of the
1551 minimum size can't be found, an error will be returned.
1554 vcb Pointer to volume where space is to be allocated
1555 startingBlock Preferred first block of range
1556 endingBlock Last possible block in range + 1
1557 minBlocks Minimum number of blocks needed. Must be > 0.
1558 maxBlocks Maximum (ideal) number of blocks desired
1559 useMetaZone OK to dip into metadata allocation zone
1562 actualStartBlock First block of range found, or 0 if error
1563 actualNumBlocks Number of blocks found, or 0 if error
1566 noErr Found at least minBlocks contiguous
1567 dskFulErr No contiguous space found, or all less than minBlocks
1568 _______________________________________________________________________
1571 static OSErr
BlockFindContiguous(
1573 u_int32_t startingBlock
,
1574 u_int32_t endingBlock
,
1575 u_int32_t minBlocks
,
1576 u_int32_t maxBlocks
,
1577 Boolean useMetaZone
,
1578 u_int32_t
*actualStartBlock
,
1579 u_int32_t
*actualNumBlocks
)
1582 register u_int32_t currentBlock
; // Block we're currently looking at.
1583 u_int32_t firstBlock
; // First free block in current extent.
1584 u_int32_t stopBlock
; // If we get to this block, stop searching for first free block.
1585 u_int32_t foundBlocks
; // Number of contiguous free blocks in current extent.
1586 u_int32_t
*buffer
= NULL
;
1587 register u_int32_t
*currentWord
;
1588 register u_int32_t bitMask
;
1589 register u_int32_t wordsLeft
;
1590 register u_int32_t tempWord
;
1592 u_int32_t wordsPerBlock
;
1593 u_int32_t j
, updated_free_extents
= 0, really_add
;
1596 * When we're skipping the metadata zone and the start/end
1597 * range overlaps with the metadata zone then adjust the
1598 * start to be outside of the metadata zone. If the range
1599 * is entirely inside the metadata zone then we can deny the
1600 * request (dskFulErr).
1602 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
1603 if (startingBlock
<= vcb
->hfs_metazone_end
) {
1604 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
1605 startingBlock
= vcb
->hfs_metazone_end
+ 1;
1611 if ((endingBlock
- startingBlock
) < minBlocks
)
1613 // The set of blocks we're checking is smaller than the minimum number
1614 // of blocks, so we couldn't possibly find a good range.
1618 stopBlock
= endingBlock
- minBlocks
+ 1;
1619 currentBlock
= startingBlock
;
1623 * Skip over metadata blocks.
1626 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1629 // Pre-read the first bitmap block.
1631 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1632 if ( err
!= noErr
) goto ErrorExit
;
1635 // Figure out where currentBlock is within the buffer.
1637 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1639 wordsLeft
= (currentBlock
/ kBitsPerWord
) & (wordsPerBlock
-1); // Current index into buffer
1640 currentWord
= buffer
+ wordsLeft
;
1641 wordsLeft
= wordsPerBlock
- wordsLeft
;
1647 //============================================================
1648 // Look for a free block, skipping over allocated blocks.
1649 //============================================================
1652 // Check an initial partial word (if any)
1654 bitMask
= currentBlock
& kBitsWithinWordMask
;
1657 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1658 bitMask
= kHighBitInWordMask
>> bitMask
;
1659 while (tempWord
& bitMask
)
1665 // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)?
1669 // Didn't find any unused bits, so we're done with this word.
1675 // Check whole words
1677 while (currentBlock
< stopBlock
)
1679 // See if it's time to read another block.
1683 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1684 if (err
!= noErr
) goto ErrorExit
;
1687 * Skip over metadata blocks.
1690 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
1691 if (currentBlock
>= stopBlock
) {
1696 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1697 if ( err
!= noErr
) goto ErrorExit
;
1699 currentWord
= buffer
;
1700 wordsLeft
= wordsPerBlock
;
1703 // See if any of the bits are clear
1704 if ((tempWord
= SWAP_BE32(*currentWord
)) + 1) // non-zero if any bits were clear
1706 // Figure out which bit is clear
1707 bitMask
= kHighBitInWordMask
;
1708 while (tempWord
& bitMask
)
1714 break; // Found the free bit; break out to FoundUnused.
1717 // Keep looking at the next word
1718 currentBlock
+= kBitsPerWord
;
1724 // Make sure the unused bit is early enough to use
1725 if (currentBlock
>= stopBlock
)
1730 // Remember the start of the extent
1731 firstBlock
= currentBlock
;
1733 //============================================================
1734 // Count the number of contiguous free blocks.
1735 //============================================================
1738 // Check an initial partial word (if any)
1740 bitMask
= currentBlock
& kBitsWithinWordMask
;
1743 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
1744 bitMask
= kHighBitInWordMask
>> bitMask
;
1745 while (bitMask
&& !(tempWord
& bitMask
))
1751 // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)?
1755 // Didn't find any used bits, so we're done with this word.
1761 // Check whole words
1763 while (currentBlock
< endingBlock
)
1765 // See if it's time to read another block.
1769 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1770 if (err
!= noErr
) goto ErrorExit
;
1773 * Skip over metadata blocks.
1776 u_int32_t nextBlock
;
1778 nextBlock
= NextBitmapBlock(vcb
, currentBlock
);
1779 if (nextBlock
!= currentBlock
) {
1780 goto LoopExit
; /* allocation gap, so stop */
1784 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
1785 if ( err
!= noErr
) goto ErrorExit
;
1787 currentWord
= buffer
;
1788 wordsLeft
= wordsPerBlock
;
1791 // See if any of the bits are set
1792 if ((tempWord
= SWAP_BE32(*currentWord
)) != 0)
1794 // Figure out which bit is set
1795 bitMask
= kHighBitInWordMask
;
1796 while (!(tempWord
& bitMask
))
1802 break; // Found the used bit; break out to FoundUsed.
1805 // Keep looking at the next word
1806 currentBlock
+= kBitsPerWord
;
1810 // If we found at least maxBlocks, we can quit early.
1811 if ((currentBlock
- firstBlock
) >= maxBlocks
)
1816 // Make sure we didn't run out of bitmap looking for a used block.
1817 // If so, pin to the end of the bitmap.
1818 if (currentBlock
> endingBlock
)
1819 currentBlock
= endingBlock
;
1821 // Figure out how many contiguous free blocks there were.
1822 // Pin the answer to maxBlocks.
1823 foundBlocks
= currentBlock
- firstBlock
;
1824 if (foundBlocks
> maxBlocks
)
1825 foundBlocks
= maxBlocks
;
1826 if (foundBlocks
>= minBlocks
)
1827 break; // Found what we needed!
1829 HFS_MOUNT_LOCK(vcb
, TRUE
);
1830 if (free_extent_cache_active(vcb
) == 0) {
1831 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1834 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1836 // This free chunk wasn't big enough. Try inserting it into the free extent cache in case
1837 // the allocation wasn't forced contiguous.
1839 for(j
=0; j
< vcb
->vcbFreeExtCnt
; j
++) {
1840 u_int32_t start
, end
;
1842 start
= vcb
->vcbFreeExt
[j
].startBlock
;
1843 end
= start
+ vcb
->vcbFreeExt
[j
].blockCount
;
1845 if ( (firstBlock
>= start
&& firstBlock
< end
)
1846 || ((firstBlock
+ foundBlocks
) > start
&& firstBlock
< start
)) {
1848 // there's overlap with an existing entry so do not add this
1854 if (j
>= vcb
->vcbFreeExtCnt
) {
1858 tempWord
= vcb
->vcbFreeExtCnt
;
1859 if (really_add
&& (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
)) {
1860 // Sorted by starting block
1861 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].startBlock
> firstBlock
)
1863 if (tempWord
< kMaxFreeExtents
)
1865 // We're going to add this extent. Bubble any smaller extents down in the list.
1866 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].startBlock
> firstBlock
)
1868 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1871 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1872 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1874 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
1875 ++vcb
->vcbFreeExtCnt
;
1877 updated_free_extents
= 1;
1879 } else if (really_add
) {
1880 // Sorted by blockCount
1881 if (tempWord
== kMaxFreeExtents
&& vcb
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
< foundBlocks
)
1883 if (tempWord
< kMaxFreeExtents
)
1885 // We're going to add this extent. Bubble any smaller extents down in the list.
1886 while (tempWord
&& vcb
->vcbFreeExt
[tempWord
-1].blockCount
< foundBlocks
)
1888 vcb
->vcbFreeExt
[tempWord
] = vcb
->vcbFreeExt
[tempWord
-1];
1891 vcb
->vcbFreeExt
[tempWord
].startBlock
= firstBlock
;
1892 vcb
->vcbFreeExt
[tempWord
].blockCount
= foundBlocks
;
1894 if (vcb
->vcbFreeExtCnt
< kMaxFreeExtents
) {
1895 ++vcb
->vcbFreeExtCnt
;
1897 updated_free_extents
= 1;
1901 sanity_check_free_ext(vcb
, 0);
1903 } while (currentBlock
< stopBlock
);
1906 // Return the outputs.
1907 if (foundBlocks
< minBlocks
)
1912 *actualStartBlock
= 0;
1913 *actualNumBlocks
= 0;
1918 *actualStartBlock
= firstBlock
;
1919 *actualNumBlocks
= foundBlocks
;
1921 * Sanity check for overflow
1923 if ((firstBlock
+ foundBlocks
) > vcb
->allocLimit
) {
1924 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",
1925 vcb
->vcbVN
, startingBlock
, endingBlock
, currentBlock
,
1926 firstBlock
, stopBlock
, minBlocks
, foundBlocks
);
1930 if (updated_free_extents
&& (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
)) {
1932 u_int32_t min_start
= vcb
->totalBlocks
;
1934 // set the nextAllocation pointer to the smallest free block number
1935 // we've seen so on the next mount we won't rescan unnecessarily
1936 for(i
=0; i
< (int)vcb
->vcbFreeExtCnt
; i
++) {
1937 if (vcb
->vcbFreeExt
[i
].startBlock
< min_start
) {
1938 min_start
= vcb
->vcbFreeExt
[i
].startBlock
;
1941 if (min_start
!= vcb
->totalBlocks
) {
1942 if (min_start
< vcb
->nextAllocation
) {
1943 vcb
->nextAllocation
= min_start
;
1945 if (min_start
< vcb
->sparseAllocation
) {
1946 vcb
->sparseAllocation
= min_start
;
1952 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1954 sanity_check_free_ext(vcb
, 1);
1960 * Test to see if any blocks in a range are allocated.
1962 * The journal or allocation file lock must be held.
1966 hfs_isallocated(struct hfsmount
*hfsmp
, u_int32_t startingBlock
, u_int32_t numBlocks
)
1968 u_int32_t
*currentWord
; // Pointer to current word within bitmap block
1969 u_int32_t wordsLeft
; // Number of words left in this bitmap block
1970 u_int32_t bitMask
; // Word with given bits already set (ready to test)
1971 u_int32_t firstBit
; // Bit index within word of first bit to allocate
1972 u_int32_t numBits
; // Number of bits in word to allocate
1973 u_int32_t
*buffer
= NULL
;
1975 u_int32_t bitsPerBlock
;
1976 u_int32_t wordsPerBlock
;
1981 * Pre-read the bitmap block containing the first word of allocation
1983 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
1988 * Initialize currentWord, and wordsLeft.
1991 u_int32_t wordIndexInBlock
;
1993 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
1994 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
1996 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1997 currentWord
= buffer
+ wordIndexInBlock
;
1998 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
2002 * First test any non word aligned bits.
2004 firstBit
= startingBlock
% kBitsPerWord
;
2005 if (firstBit
!= 0) {
2006 bitMask
= kAllBitsSetInWord
>> firstBit
;
2007 numBits
= kBitsPerWord
- firstBit
;
2008 if (numBits
> numBlocks
) {
2009 numBits
= numBlocks
;
2010 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
2012 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
2016 numBlocks
-= numBits
;
2022 * Test whole words (32 blocks) at a time.
2024 while (numBlocks
>= kBitsPerWord
) {
2025 if (wordsLeft
== 0) {
2026 /* Read in the next bitmap block. */
2027 startingBlock
+= bitsPerBlock
;
2030 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
2031 if (error
) goto Exit
;
2033 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
2034 if (error
) goto Exit
;
2036 /* Readjust currentWord and wordsLeft. */
2037 currentWord
= buffer
;
2038 wordsLeft
= wordsPerBlock
;
2040 if (*currentWord
!= 0) {
2044 numBlocks
-= kBitsPerWord
;
2050 * Test any remaining blocks.
2052 if (numBlocks
!= 0) {
2053 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
);
2054 if (wordsLeft
== 0) {
2055 /* Read in the next bitmap block */
2056 startingBlock
+= bitsPerBlock
;
2059 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
2060 if (error
) goto Exit
;
2062 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
2063 if (error
) goto Exit
;
2065 currentWord
= buffer
;
2066 wordsLeft
= wordsPerBlock
;
2068 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
2075 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);
2080 /* Invalidate free extent cache for a given volume.
2081 * This cache is invalidated and disabled when a volume is being resized
2082 * (via hfs_trucatefs() or hfs_extendefs()).
2086 void invalidate_free_extent_cache(ExtendedVCB
*vcb
)
2090 HFS_MOUNT_LOCK(vcb
, TRUE
);
2091 for (i
= 0; i
< vcb
->vcbFreeExtCnt
; i
++) {
2092 vcb
->vcbFreeExt
[i
].startBlock
= 0;
2093 vcb
->vcbFreeExt
[i
].blockCount
= 0;
2095 vcb
->vcbFreeExtCnt
= 0;
2096 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
2101 /* Check whether free extent cache is active or not.
2102 * This cache is invalidated and disabled when a volume is being resized
2103 * (via hfs_trucatefs() or hfs_extendefs()).
2105 * This function assumes that the caller is holding the lock on
2108 * Returns: 0 if the cache is not active,
2109 * 1 if the cache is active.
2111 static int free_extent_cache_active(ExtendedVCB
*vcb
)
2115 if (vcb
->hfs_flags
& HFS_RESIZE_IN_PROGRESS
) {