2 * Copyright (c) 2000-2011 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-2009 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.
50 Exported wrapper to mark blocks as in-use. This will correctly determine
51 whether or not the red-black tree is enabled and call the appropriate function
54 Exported wrapper to mark blocks as freed. This will correctly determine whether or
55 not the red-black tree is enabled and call the appropriate function if applicable.
59 Since the red-black tree obviates the need to maintain the free extent cache, we do
60 not update it if the tree is also live. As a result, if we ever need to destroy the trees
61 we should reset the free extent cache so it doesn't confuse us when we need to fall back to the
62 bitmap scanning allocator.
63 We also reset and disable the free extent cache when volume resizing is
67 Adjusts the AllocLimit field in the hfs mount point. This is used when we need to prevent
68 allocations from occupying space in the region we are modifying during a filesystem resize.
69 At other times, it should be consistent with the total number of allocation blocks in the
70 filesystem. It is also used to shrink or grow the number of blocks that the red-black tree should
71 know about. If growing, scan the new range of bitmap, and if shrinking, reduce the
72 number of items in the tree that we can allocate from.
75 Note that the RBTree routines are guarded by a cpp check for CONFIG_HFS_ALLOC_RBTREE. This
76 is to cut down on space for functions that could not possibly be used if they are not planning to
77 use the red-black tree code.
80 Make an internal call to BlockMarkFree and then update
81 and/or create Red-Black Tree allocation tree nodes to correspond
82 to the free space being generated.
84 Mark a contiguous range of blocks as free. The corresponding
85 bits in the volume bitmap will be cleared. This will actually do the work
86 of modifying the bitmap for us.
88 BlockMarkAllocatedRBTree
89 Make an internal call to BlockAllocateMarked, which will update the
90 bitmap on-disk when we allocate blocks. If that is successful, then
91 we'll remove the appropriate entries from the red-black tree.
92 BlockMarkAllocatedInternal
93 Mark a contiguous range of blocks as allocated. The cor-
94 responding bits in the volume bitmap are set. Also tests to see
95 if any of the blocks were previously unallocated.
97 Find a contiguous range of blocks of a given size. The caller
98 specifies where to begin the search (by block number). The
99 block number of the first block in the range is returned. This is only
100 called by the bitmap scanning logic as the red-black tree should be able
101 to do this internally by searching its tree.
103 Find and allocate a contiguous range of blocks up to a given size. The
104 first range of contiguous free blocks found are allocated, even if there
105 are fewer blocks than requested (and even if a contiguous range of blocks
106 of the given size exists elsewhere).
107 BlockAllocateAnyBitmap
108 Finds a range of blocks per the above requirements without using the
109 Allocation RB Tree. This relies on the bitmap-scanning logic in order to find
110 any valid range of free space needed.
111 BlockAllocateAnyRBTree
112 Finds a valid range of blocks per the above requirements by searching
113 the red-black tree. We can just make an internal call to
114 BlockAllocateContigRBTree to find the valid range.
116 Find and allocate a contiguous range of blocks of a given size. If
117 a contiguous range of free blocks of the given size isn't found, then
118 the allocation fails (i.e. it is "all or nothing"). This routine is
119 essentially a wrapper function around its related sub-functions,
120 BlockAllocateContigBitmap and BlockAllocateContigRBTree, which use,
121 respectively, the original HFS+ bitmap scanning logic and the new
122 Red-Black Tree to search and manage free-space decisions. This function
123 contains logic for when to use which of the allocation algorithms,
124 depending on the free space contained in the volume.
125 BlockAllocateContigBitmap
126 Finds and allocates a range of blocks specified by the size parameters
127 using the original HFS+ bitmap scanning logic. The red-black tree
128 will not be updated if this function is used.
129 BlockAllocateContigRBTree
130 Finds and allocates a range of blocks specified by the size parameters
131 using the new red/black tree data structure and search algorithms
132 provided by the tree library. Updates the red/black tree nodes after
133 the on-disk data structure (bitmap) has been updated.
135 Try to allocate space from known free space in the volume's
139 Given an allocation block number, read the bitmap block that
140 contains that allocation block into a caller-supplied buffer.
143 Release a bitmap block back into the buffer cache.
148 Test to see if any blocks in a range are allocated. Journal or
149 allocation file lock must be held.
152 Test to see if any blocks in a range are allocated. Releases and
153 invalidates the block used when finished.
156 Test to see if the allocation red-black tree is live. This function
157 requires either an exclusive or shared lock on the allocation bitmap file
158 in the HFS mount structure, to prevent red-black tree pointers from disappearing.
160 hfs_isrbtree_allocated
161 Test to see if the specified extent is marked as allocated in the red-black tree.
162 Multiplexes between the metadata zone trees and the normal allocation zone trees
163 depending on the offset of the extent specified.
166 Void function that wraps around the above function (hfs_isrbtree_allocated)
167 and checks to see that the return value was appropriate based on the assertion we're
168 trying to validate (whether or not the specified extent should be marked as free
172 Exhaustive search function that will check every allocation block for its status in the
173 red-black tree and then check the corresponding status in the bitmap file. If the two are out
174 of sync, it will panic. Note that this function is extremely expensive and must NEVER
175 be run outside of debug code.
178 Checks the embedded linked list structure of the red black tree for integrity. The next pointer
179 should always point to whatever extent_tree_offset_next returns.
182 Red Black Tree Specific Routines
184 Build a red-black tree for the given filesystem's bitmap.
187 Destroy the tree on the given filesystem
191 Given a starting allocation block number, figures out which physical block contains that
192 allocation block's bit, and scans it from the starting bit until either the ending bit or
193 the end of the block. Free space extents are inserted into the appropriate red-black tree.
197 #include "../../hfs_macos_defs.h"
199 #include <sys/types.h>
201 #include <sys/systm.h>
202 #include <sys/sysctl.h>
203 #include <sys/disk.h>
206 #include <kern/kalloc.h>
208 #include "../../hfs.h"
209 #include "../../hfs_dbg.h"
210 #include "../../hfs_format.h"
211 #include "../../hfs_endian.h"
212 #include "../../hfs_macos_defs.h"
213 #include "../headers/FileMgrInternal.h"
214 #include "../headers/HybridAllocator.h"
215 #include "../../hfs_kdebug.h"
217 #ifndef CONFIG_HFS_TRIM
218 #define CONFIG_HFS_TRIM 0
222 * Use sysctl vfs.generic.hfs.kdebug.allocation to control which
223 * KERNEL_DEBUG_CONSTANT events are enabled at runtime. (They're
224 * disabled by default because there can be a lot of these events,
225 * and we don't want to overwhelm the kernel debug buffer. If you
226 * want to watch these events in particular, just set the sysctl.)
228 static int hfs_kdebug_allocation
= 0;
229 SYSCTL_DECL(_vfs_generic
);
230 SYSCTL_NODE(_vfs_generic
, OID_AUTO
, hfs
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "HFS file system");
231 SYSCTL_NODE(_vfs_generic_hfs
, OID_AUTO
, kdebug
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "HFS kdebug");
232 SYSCTL_INT(_vfs_generic_hfs_kdebug
, OID_AUTO
, allocation
, CTLFLAG_RW
|CTLFLAG_LOCKED
, &hfs_kdebug_allocation
, 0, "Enable kdebug logging for HFS allocations");
235 * HFSDBG_ALLOC_ENABLED: Log calls to BlockAllocate and
236 * BlockDeallocate, including the internal BlockAllocateXxx
237 * routines so we can see how an allocation was satisfied.
239 * HFSDBG_EXT_CACHE_ENABLED: Log routines that read or write the
242 * HFSDBG_UNMAP_ENABLED: Log events involving the trim list.
244 * HFSDBG_BITMAP_ENABLED: Log accesses to the volume bitmap (setting
245 * or clearing bits, scanning the bitmap).
247 HFSDBG_ALLOC_ENABLED
= 1,
248 HFSDBG_EXT_CACHE_ENABLED
= 2,
249 HFSDBG_UNMAP_ENABLED
= 4,
250 HFSDBG_BITMAP_ENABLED
= 8
258 kBitsWithinWordMask
= kBitsPerWord
-1
261 #define kLowBitInWordMask 0x00000001ul
262 #define kHighBitInWordMask 0x80000000ul
263 #define kAllBitsSetInWord 0xFFFFFFFFul
266 #define ALLOC_DEBUG 0
268 static OSErr
ReadBitmapBlock(
272 uintptr_t *blockRef
);
274 static OSErr
ReleaseBitmapBlock(
279 static OSErr
BlockAllocateAny(
281 u_int32_t startingBlock
,
282 u_int32_t endingBlock
,
285 u_int32_t
*actualStartBlock
,
286 u_int32_t
*actualNumBlocks
);
288 static OSErr
BlockAllocateAnyBitmap(
290 u_int32_t startingBlock
,
291 u_int32_t endingBlock
,
294 u_int32_t
*actualStartBlock
,
295 u_int32_t
*actualNumBlocks
);
297 static OSErr
BlockAllocateContig(
299 u_int32_t startingBlock
,
303 u_int32_t
*actualStartBlock
,
304 u_int32_t
*actualNumBlocks
);
306 static OSErr
BlockAllocateContigBitmap(
308 u_int32_t startingBlock
,
312 u_int32_t
*actualStartBlock
,
313 u_int32_t
*actualNumBlocks
);
315 static OSErr
BlockFindContiguous(
317 u_int32_t startingBlock
,
318 u_int32_t endingBlock
,
322 u_int32_t
*actualStartBlock
,
323 u_int32_t
*actualNumBlocks
);
325 static OSErr
BlockAllocateKnown(
328 u_int32_t
*actualStartBlock
,
329 u_int32_t
*actualNumBlocks
);
331 static OSErr
BlockMarkAllocatedInternal (
333 u_int32_t startingBlock
,
334 register u_int32_t numBlocks
);
336 static OSErr
BlockMarkFreeInternal(
338 u_int32_t startingBlock
,
340 Boolean do_validate
);
342 #if CONFIG_HFS_ALLOC_RBTREE
344 static OSErr
ReleaseRBScanBitmapBlock( struct buf
*bp
);
346 static OSErr
BlockAllocateAnyRBTree(
348 u_int32_t startingBlock
,
351 u_int32_t
*actualStartBlock
,
352 u_int32_t
*actualNumBlocks
);
354 static OSErr
BlockAllocateContigRBTree(
356 u_int32_t startingBlock
,
360 u_int32_t
*actualStartBlock
,
361 u_int32_t
*actualNumBlocks
,
362 u_int32_t forceContig
);
364 static OSErr
BlockMarkAllocatedRBTree(
366 u_int32_t startingBlock
,
367 u_int32_t numBlocks
);
369 static OSErr
BlockMarkFreeRBTree(
371 u_int32_t startingBlock
,
372 u_int32_t numBlocks
);
375 hfs_isrbtree_allocated (struct hfsmount
* hfsmp
,
376 u_int32_t startBlock
,
378 extent_node_t
** node1
);
381 hfs_validate_rbtree (struct hfsmount
*hfsmp
,
385 static void hfs_checktreelinks (struct hfsmount
*hfsmp
);
388 void check_rbtree_extents (struct hfsmount
*hfsmp
,
393 int hfs_isallocated_scan (struct hfsmount
*hfsmp
,
394 u_int32_t startingBlock
,
397 static int hfs_alloc_scan_block(struct hfsmount
*hfsmp
,
400 u_int32_t
*bitToScan
);
402 #define ASSERT_FREE 1
403 #define ASSERT_ALLOC 0
405 #endif /* CONFIG_HFS_ALLOC_RBTREE */
407 /* Functions for manipulating free extent cache */
408 static void remove_free_extent_cache(struct hfsmount
*hfsmp
, u_int32_t startBlock
, u_int32_t blockCount
);
409 static Boolean
add_free_extent_cache(struct hfsmount
*hfsmp
, u_int32_t startBlock
, u_int32_t blockCount
);
410 static void sanity_check_free_ext(struct hfsmount
*hfsmp
, int check_allocated
);
414 * Extra #includes for the debug function below. These are not normally #included because
415 * they would constitute a layering violation
417 #include <vfs/vfs_journal.h>
418 #include <sys/disk.h>
421 * Validation Routine to verify that the TRIM list maintained by the journal
422 * is in good shape relative to what we think the bitmap should have. We should
423 * never encounter allocated blocks in the TRIM list, so if we ever encounter them,
426 int trim_validate_bitmap (struct hfsmount
*hfsmp
) {
427 u_int64_t blockno_offset
;
434 uint32_t alloccount
= 0;
437 struct journal
*jnl
= (struct journal
*)hfsmp
->jnl
;
438 if (jnl
->active_tr
) {
439 struct jnl_trim_list
*trim
= &(jnl
->active_tr
->trim
);
440 count
= trim
->extent_count
;
441 for (i
= 0; i
< count
; i
++) {
442 blockno_offset
= trim
->extents
[i
].offset
;
443 blockno_offset
= blockno_offset
- (uint64_t)hfsmp
->hfsPlusIOPosOffset
;
444 blockno_offset
= blockno_offset
/ hfsmp
->blockSize
;
445 numblocks
= trim
->extents
[i
].length
/ hfsmp
->blockSize
;
447 startblk
= (u_int32_t
)blockno_offset
;
448 blks
= (u_int32_t
) numblocks
;
449 err
= hfs_count_allocated (hfsmp
, startblk
, blks
, &alloccount
);
451 if (err
== 0 && alloccount
!= 0) {
452 panic ("trim_validate_bitmap: %d blocks @ ABN %d are allocated!", alloccount
, startblk
);
463 ;________________________________________________________________________________
465 ; Routine: hfs_unmap_free_extent
467 ; Function: Make note of a range of allocation blocks that should be
468 ; unmapped (trimmed). That is, the given range of blocks no
469 ; longer have useful content, and the device can unmap the
470 ; previous contents. For example, a solid state disk may reuse
471 ; the underlying storage for other blocks.
473 ; This routine is only supported for journaled volumes. The extent
474 ; being freed is passed to the journal code, and the extent will
475 ; be unmapped after the current transaction is written to disk.
478 ; hfsmp - The volume containing the allocation blocks.
479 ; startingBlock - The first allocation block of the extent being freed.
480 ; numBlocks - The number of allocation blocks of the extent being freed.
481 ;________________________________________________________________________________
483 static void hfs_unmap_free_extent(struct hfsmount
*hfsmp
, u_int32_t startingBlock
, u_int32_t numBlocks
)
489 if (hfs_kdebug_allocation
& HFSDBG_UNMAP_ENABLED
)
490 KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_FREE
| DBG_FUNC_START
, startingBlock
, numBlocks
, 0, 0, 0);
492 if (hfsmp
->jnl
!= NULL
) {
493 offset
= (u_int64_t
) startingBlock
* hfsmp
->blockSize
+ (u_int64_t
) hfsmp
->hfsPlusIOPosOffset
;
494 length
= (u_int64_t
) numBlocks
* hfsmp
->blockSize
;
496 err
= journal_trim_add_extent(hfsmp
->jnl
, offset
, length
);
498 printf("hfs_unmap_free_extent: error %d from journal_trim_add_extent", err
);
502 if (hfs_kdebug_allocation
& HFSDBG_UNMAP_ENABLED
)
503 KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_FREE
| DBG_FUNC_END
, err
, 0, 0, 0, 0);
508 ;________________________________________________________________________________
510 ; Routine: hfs_unmap_alloc_extent
512 ; Function: Make note of a range of allocation blocks, some of
513 ; which may have previously been passed to hfs_unmap_free_extent,
514 ; is now in use on the volume. The given blocks will be removed
515 ; from any pending DKIOCUNMAP.
518 ; hfsmp - The volume containing the allocation blocks.
519 ; startingBlock - The first allocation block of the extent being allocated.
520 ; numBlocks - The number of allocation blocks being allocated.
521 ;________________________________________________________________________________
523 static void hfs_unmap_alloc_extent(struct hfsmount
*hfsmp
, u_int32_t startingBlock
, u_int32_t numBlocks
)
529 if (hfs_kdebug_allocation
& HFSDBG_UNMAP_ENABLED
)
530 KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_ALLOC
| DBG_FUNC_START
, startingBlock
, numBlocks
, 0, 0, 0);
532 if (hfsmp
->jnl
!= NULL
) {
533 offset
= (u_int64_t
) startingBlock
* hfsmp
->blockSize
+ (u_int64_t
) hfsmp
->hfsPlusIOPosOffset
;
534 length
= (u_int64_t
) numBlocks
* hfsmp
->blockSize
;
536 err
= journal_trim_remove_extent(hfsmp
->jnl
, offset
, length
);
538 printf("hfs_unmap_alloc_extent: error %d from journal_trim_remove_extent", err
);
542 if (hfs_kdebug_allocation
& HFSDBG_UNMAP_ENABLED
)
543 KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_ALLOC
| DBG_FUNC_END
, err
, 0, 0, 0, 0);
548 ;________________________________________________________________________________
550 ; Routine: hfs_trim_callback
552 ; Function: This function is called when a transaction that freed extents
553 ; (via hfs_unmap_free_extent/journal_trim_add_extent) has been
554 ; written to the on-disk journal. This routine will add those
555 ; extents to the free extent cache so that they can be reused.
557 ; CAUTION: This routine is called while the journal's trim lock
558 ; is held shared, so that no other thread can reuse any portion
559 ; of those extents. We must be very careful about which locks
560 ; we take from within this callback, to avoid deadlock. The
561 ; call to add_free_extent_cache will end up taking the cache's
562 ; lock (just long enough to add these extents to the cache).
564 ; CAUTION: If the journal becomes invalid (eg., due to an I/O
565 ; error when trying to write to the journal), this callback
566 ; will stop getting called, even if extents got freed before
567 ; the journal became invalid!
570 ; arg - The hfsmount of the volume containing the extents.
571 ; extent_count - The number of extents freed in the transaction.
572 ; extents - An array of extents (byte ranges) that were freed.
573 ;________________________________________________________________________________
575 __private_extern__
void
576 hfs_trim_callback(void *arg
, uint32_t extent_count
, const dk_extent_t
*extents
)
579 uint32_t startBlock
, numBlocks
;
580 struct hfsmount
*hfsmp
= arg
;
582 if (hfs_kdebug_allocation
& HFSDBG_UNMAP_ENABLED
)
583 KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_CALLBACK
| DBG_FUNC_START
, 0, extent_count
, 0, 0, 0);
585 for (i
=0; i
<extent_count
; ++i
) {
586 /* Convert the byte range in *extents back to a range of allocation blocks. */
587 startBlock
= (extents
[i
].offset
- hfsmp
->hfsPlusIOPosOffset
) / hfsmp
->blockSize
;
588 numBlocks
= extents
[i
].length
/ hfsmp
->blockSize
;
589 (void) add_free_extent_cache(hfsmp
, startBlock
, numBlocks
);
592 if (hfs_kdebug_allocation
& HFSDBG_UNMAP_ENABLED
)
593 KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_CALLBACK
| DBG_FUNC_END
, 0, 0, 0, 0, 0);
598 ;________________________________________________________________________________
600 ; Routine: BlockAllocate
602 ; Function: Allocate space on a volume. If contiguous allocation is requested,
603 ; at least the requested number of bytes will be allocated or an
604 ; error will be returned. If contiguous allocation is not forced,
605 ; the space will be allocated with the first largest extent available
606 ; at the requested starting allocation block. If there is not enough
607 ; room there, a block allocation of less than the requested size will be
610 ; If the requested starting block is 0 (for new file allocations),
611 ; the volume's allocation block pointer will be used as a starting
615 ; vcb - Pointer to ExtendedVCB for the volume to allocate space on
616 ; fcb - Pointer to FCB for the file for which storage is being allocated
617 ; startingBlock - Preferred starting allocation block, 0 = no preference
618 ; minBlocks - Number of blocks requested. If the allocation is non-contiguous,
619 ; less than this may actually be allocated
620 ; maxBlocks - The maximum number of blocks to allocate. If there is additional free
621 ; space after bytesRequested, then up to maxBlocks bytes should really
622 ; be allocated. (Used by ExtendFileC to round up allocations to a multiple
623 ; of the file's clump size.)
624 ; flags - Flags to specify options like contiguous, use metadata zone,
625 ; skip free block check, etc.
628 ; (result) - Error code, zero for successful allocation
629 ; *startBlock - Actual starting allocation block
630 ; *actualBlocks - Actual number of allocation blocks allocated
633 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
634 ;________________________________________________________________________________
636 OSErr
BlockAllocate (
637 ExtendedVCB
*vcb
, /* which volume to allocate space on */
638 u_int32_t startingBlock
, /* preferred starting block, or 0 for no preference */
639 u_int32_t minBlocks
, /* desired number of blocks to allocate */
640 u_int32_t maxBlocks
, /* maximum number of blocks to allocate */
641 u_int32_t flags
, /* option flags */
642 u_int32_t
*actualStartBlock
, /* actual first block of allocation */
643 u_int32_t
*actualNumBlocks
) /* number of blocks actually allocated; if forceContiguous */
644 /* was zero, then this may represent fewer than minBlocks */
646 u_int32_t freeBlocks
;
648 Boolean updateAllocPtr
= false; // true if nextAllocation needs to be updated
649 struct hfsmount
*hfsmp
;
651 Boolean forceContiguous
;
653 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
654 KERNEL_DEBUG_CONSTANT(HFSDBG_BLOCK_ALLOCATE
| DBG_FUNC_START
, startingBlock
, minBlocks
, maxBlocks
, flags
, 0);
656 if (flags
& HFS_ALLOC_FORCECONTIG
) {
657 forceContiguous
= true;
659 forceContiguous
= false;
662 if (flags
& HFS_ALLOC_METAZONE
) {
668 //TODO: Figure out when we need to re-enable the RB-Tree.
671 //TODO: Make sure we use allocLimit when appropriate.
674 * TODO: Update BlockAllocate and its sub-functions to do cooperative allocation and bitmap scanning
675 * in conjunction with the Generate Tree function. If the red-black tree does not currently contain
676 * an allocation block of appropriate size, then start scanning blocks FOR the tree generation function until
677 * we find what we need. We'll update the tree fields when we're done, indicating that we've advanced the
678 * high water mark for the tree.
682 // Initialize outputs in case we get an error
684 *actualStartBlock
= 0;
685 *actualNumBlocks
= 0;
686 hfsmp
= VCBTOHFS (vcb
);
687 freeBlocks
= hfs_freeblks(hfsmp
, 0);
690 /* Skip free block check if blocks are being allocated for relocating
691 * data during truncating a volume.
693 * During hfs_truncatefs(), the volume free block count is updated
694 * before relocating data to reflect the total number of free blocks
695 * that will exist on the volume after resize is successful. This
696 * means that we have reserved allocation blocks required for relocating
697 * the data and hence there is no need to check the free blocks.
698 * It will also prevent resize failure when the number of blocks in
699 * an extent being relocated is more than the free blocks that will
700 * exist after the volume is resized.
702 if ((flags
& HFS_ALLOC_SKIPFREEBLKS
) == 0) {
703 // If the disk is already full, don't bother.
704 if (freeBlocks
== 0) {
708 if (forceContiguous
&& freeBlocks
< minBlocks
) {
714 * Clip if necessary so we don't over-subscribe the free blocks.
716 if (minBlocks
> freeBlocks
) {
717 minBlocks
= freeBlocks
;
719 if (maxBlocks
> freeBlocks
) {
720 maxBlocks
= freeBlocks
;
725 // If caller didn't specify a starting block number, then use the volume's
726 // next block to allocate from.
728 if (startingBlock
== 0) {
729 HFS_MOUNT_LOCK(vcb
, TRUE
);
731 /* Sparse Allocation and nextAllocation are both used even if the R/B Tree is on */
732 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
733 startingBlock
= vcb
->sparseAllocation
;
736 startingBlock
= vcb
->nextAllocation
;
738 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
739 updateAllocPtr
= true;
743 if (startingBlock
>= vcb
->allocLimit
) {
744 startingBlock
= 0; /* overflow so start at beginning */
748 // If the request must be contiguous, then find a sequence of free blocks
749 // that is long enough. Otherwise, find the first free block.
751 if (forceContiguous
) {
752 err
= BlockAllocateContig(vcb
, startingBlock
, minBlocks
, maxBlocks
,
753 useMetaZone
, actualStartBlock
, actualNumBlocks
);
755 * If we allocated from a new position then also update the roving allocator.
756 * This will keep the roving allocation pointer up-to-date even
757 * if we are using the new R/B tree allocator, since
758 * it doesn't matter to us here, how the underlying allocator found
759 * the block to vend out.
761 if ((err
== noErr
) &&
762 (*actualStartBlock
> startingBlock
) &&
763 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
764 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
765 updateAllocPtr
= true;
768 #if CONFIG_HFS_ALLOC_RBTREE
770 * If the RB-Tree Allocator is live, just go straight for a
771 * BlockAllocateAny call and return the result. Otherwise,
772 * resort to the bitmap scanner.
774 if (hfs_isrbtree_active(VCBTOHFS(vcb
))) {
775 /* Start by trying to allocate from the starting block forward */
776 err
= BlockAllocateAny(vcb
, startingBlock
, vcb
->allocLimit
,
777 maxBlocks
, useMetaZone
, actualStartBlock
,
781 * Because the RB-Tree is live, the previous call to BlockAllocateAny
782 * will use the rbtree variant. As a result, it will automatically search the
783 * metadata zone for a valid extent if needed. If we get a return value of
784 * noErr, we found a valid extent and we can skip to the end. If the error indicates
785 * the disk is full, that's an equally valid return code and we can skip to the end, too.
787 if (err
== noErr
|| err
== dskFulErr
) {
791 //TODO: only tear down tree if the tree is finished building.
792 //Make sure to handle the ENOSPC condition properly. We shouldn't error out in that case.
793 /* Tear down tree if we encounter an error */
794 if (hfsmp
->extent_tree_flags
& HFS_ALLOC_RB_ACTIVE
) {
795 hfsmp
->extent_tree_flags
|= HFS_ALLOC_RB_ERRORED
;
797 ResetVCBFreeExtCache(hfsmp
);
802 // fall through to the normal allocation since the rb-tree allocation failed.
808 * Scan the bitmap once, gather the N largest free extents, then
809 * allocate from these largest extents. Repeat as needed until
810 * we get all the space we needed. We could probably build up
811 * that list when the higher level caller tried (and failed) a
812 * contiguous allocation first.
814 * Note that the free-extent cache will be cease to be updated if
815 * we are using the red-black tree for allocations. If we jettison
816 * the tree, then we will reset the free-extent cache and start over.
819 err
= BlockAllocateKnown(vcb
, maxBlocks
, actualStartBlock
, actualNumBlocks
);
820 /* dskFulErr out of BlockAllocateKnown indicates an empty Free Extent Cache */
822 if (err
== dskFulErr
) {
824 * Now we have to do a bigger scan. Start at startingBlock and go up until the
827 err
= BlockAllocateAny(vcb
, startingBlock
, vcb
->allocLimit
,
828 maxBlocks
, useMetaZone
, actualStartBlock
,
831 if (err
== dskFulErr
) {
833 * We may be out of space in the normal zone; go up to the starting block from
834 * the start of the volume.
836 err
= BlockAllocateAny(vcb
, 1, startingBlock
, maxBlocks
,
837 useMetaZone
, actualStartBlock
,
843 // if we actually allocated something then go update the
844 // various bits of state that we maintain regardless of
845 // whether there was an error (i.e. partial allocations
846 // still need to update things like the free block count).
848 if (*actualNumBlocks
!= 0) {
850 // If we used the volume's roving allocation pointer, then we need to update it.
851 // Adding in the length of the current allocation might reduce the next allocate
852 // call by avoiding a re-scan of the already allocated space. However, the clump
853 // just allocated can quite conceivably end up being truncated or released when
854 // the file is closed or its EOF changed. Leaving the allocation pointer at the
855 // start of the last allocation will avoid unnecessary fragmentation in this case.
857 HFS_MOUNT_LOCK(vcb
, TRUE
);
859 lck_spin_lock(&hfsmp
->vcbFreeExtLock
);
860 if (vcb
->vcbFreeExtCnt
== 0 && vcb
->hfs_freed_block_count
== 0) {
861 vcb
->sparseAllocation
= *actualStartBlock
;
863 lck_spin_unlock(&hfsmp
->vcbFreeExtLock
);
864 if (*actualNumBlocks
< vcb
->hfs_freed_block_count
) {
865 vcb
->hfs_freed_block_count
-= *actualNumBlocks
;
867 vcb
->hfs_freed_block_count
= 0;
870 if (updateAllocPtr
&&
871 ((*actualStartBlock
< VCBTOHFS(vcb
)->hfs_metazone_start
) ||
872 (*actualStartBlock
> VCBTOHFS(vcb
)->hfs_metazone_end
))) {
873 HFS_UPDATE_NEXT_ALLOCATION(vcb
, *actualStartBlock
);
876 (void) remove_free_extent_cache(hfsmp
, *actualStartBlock
, *actualNumBlocks
);
879 * Update the number of free blocks on the volume
881 * Skip updating the free blocks count if the block are
882 * being allocated to relocate data as part of hfs_truncatefs()
884 if ((flags
& HFS_ALLOC_SKIPFREEBLKS
) == 0) {
885 vcb
->freeBlocks
-= *actualNumBlocks
;
888 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
890 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
895 if (*actualStartBlock
>= hfsmp
->totalBlocks
) {
896 panic ("BlockAllocate: vending invalid blocks!");
898 if (*actualStartBlock
>= hfsmp
->allocLimit
) {
899 panic ("BlockAllocate: vending block past allocLimit!");
902 if ((*actualStartBlock
+ *actualNumBlocks
) >= hfsmp
->totalBlocks
) {
903 panic ("BlockAllocate: vending too many invalid blocks!");
906 if ((*actualStartBlock
+ *actualNumBlocks
) >= hfsmp
->allocLimit
) {
907 panic ("BlockAllocate: vending too many invalid blocks past allocLimit!");
912 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
913 KERNEL_DEBUG_CONSTANT(HFSDBG_BLOCK_ALLOCATE
| DBG_FUNC_END
, err
, *actualStartBlock
, *actualNumBlocks
, 0, 0);
920 ;________________________________________________________________________________
922 ; Routine: BlockDeallocate
924 ; Function: Update the bitmap to deallocate a run of disk allocation blocks
927 ; vcb - Pointer to ExtendedVCB for the volume to free space on
928 ; firstBlock - First allocation block to be freed
929 ; numBlocks - Number of allocation blocks to free up (must be > 0!)
932 ; (result) - Result code
935 ; The volume bitmap is read and updated; the volume bitmap cache may be changed.
936 ; The Allocator's red-black trees may also be modified as a result.
937 ;________________________________________________________________________________
940 OSErr
BlockDeallocate (
941 ExtendedVCB
*vcb
, // Which volume to deallocate space on
942 u_int32_t firstBlock
, // First block in range to deallocate
943 u_int32_t numBlocks
, // Number of contiguous blocks to deallocate
947 struct hfsmount
*hfsmp
;
948 hfsmp
= VCBTOHFS(vcb
);
950 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
951 KERNEL_DEBUG_CONSTANT(HFSDBG_BLOCK_DEALLOCATE
| DBG_FUNC_START
, firstBlock
, numBlocks
, flags
, 0, 0);
954 // If no blocks to deallocate, then exit early
956 if (numBlocks
== 0) {
963 if (firstBlock
>= hfsmp
->totalBlocks
) {
964 panic ("BlockDeallocate: freeing invalid blocks!");
967 if ((firstBlock
+ numBlocks
) >= hfsmp
->totalBlocks
) {
968 panic ("BlockDeallocate: freeing too many invalid blocks!");
976 * If we're using the red-black tree code, then try to free the
977 * blocks by marking them in the red-black tree first. If the tree
978 * is not active for whatever reason (or we're not using the
979 * R/B Tree code at all), then go straight for the BlockMarkFree
982 * Remember that we can get into this function if the tree isn't finished
983 * building. In that case, check to see if the block we're de-allocating is
984 * past the high watermark
986 #if CONFIG_HFS_ALLOC_RBTREE
987 if (hfs_isrbtree_active(VCBTOHFS(vcb
))) {
989 * BlockMarkFreeRBTree deals with the case where we are resizing the
990 * filesystem (shrinking), and we need to manipulate the bitmap beyond the portion
991 * that is currenly controlled by the r/b tree.
994 //TODO: Update multiplexing code for the half-finished case.
995 err
= BlockMarkFreeRBTree(vcb
, firstBlock
, numBlocks
);
996 adjustFreeExtCache
= 0;
999 err
= BlockMarkFreeInternal(vcb
, firstBlock
, numBlocks
, true);
1003 err
= BlockMarkFreeInternal(vcb
, firstBlock
, numBlocks
, true);
1009 // Update the volume's free block count, and mark the VCB as dirty.
1011 HFS_MOUNT_LOCK(vcb
, TRUE
);
1014 * Do not update the free block count. This flags is specified
1015 * when a volume is being truncated.
1017 if ((flags
& HFS_ALLOC_SKIPFREEBLKS
) == 0) {
1018 vcb
->freeBlocks
+= numBlocks
;
1021 vcb
->hfs_freed_block_count
+= numBlocks
;
1023 if (vcb
->nextAllocation
== (firstBlock
+ numBlocks
)) {
1024 HFS_UPDATE_NEXT_ALLOCATION(vcb
, (vcb
->nextAllocation
- numBlocks
));
1027 if (hfsmp
->jnl
== NULL
) {
1029 * In the journal case, we'll add the free extent once the journal
1030 * calls us back to tell us it wrote the transaction to disk.
1032 (void) add_free_extent_cache(vcb
, firstBlock
, numBlocks
);
1035 * If the journal case, we'll only update sparseAllocation once the
1036 * free extent cache becomes empty (when we remove the last entry
1037 * from the cache). Skipping it here means we're less likely to
1038 * find a recently freed extent via the bitmap before it gets added
1039 * to the free extent cache.
1041 if (firstBlock
< vcb
->sparseAllocation
) {
1042 vcb
->sparseAllocation
= firstBlock
;
1047 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1049 hfs_generate_volume_notifications(VCBTOHFS(vcb
));
1052 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1053 KERNEL_DEBUG_CONSTANT(HFSDBG_BLOCK_DEALLOCATE
| DBG_FUNC_END
, err
, 0, 0, 0, 0);
1059 u_int8_t freebitcount
[16] = {
1060 4, 3, 3, 2, 3, 2, 2, 1, /* 0 1 2 3 4 5 6 7 */
1061 3, 2, 2, 1, 2, 1, 1, 0, /* 8 9 A B C D E F */
1065 MetaZoneFreeBlocks(ExtendedVCB
*vcb
)
1067 u_int32_t freeblocks
;
1068 u_int32_t
*currCache
;
1078 bytesleft
= freeblocks
= 0;
1080 bit
= VCBTOHFS(vcb
)->hfs_metazone_start
;
1084 lastbit
= VCBTOHFS(vcb
)->hfs_metazone_end
;
1085 bytesperblock
= vcb
->vcbVBMIOSize
;
1088 * Count all the bits from bit to lastbit.
1090 while (bit
< lastbit
) {
1092 * Get next bitmap block.
1094 if (bytesleft
== 0) {
1096 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1099 if (ReadBitmapBlock(vcb
, bit
, &currCache
, &blockRef
) != 0) {
1102 buffer
= (u_int8_t
*)currCache
;
1103 bytesleft
= bytesperblock
;
1106 freeblocks
+= freebitcount
[byte
& 0x0F];
1107 freeblocks
+= freebitcount
[(byte
>> 4) & 0x0F];
1108 bit
+= kBitsPerByte
;
1112 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
1114 return (freeblocks
);
1119 * Obtain the next allocation block (bit) that's
1120 * outside the metadata allocation zone.
1122 static u_int32_t
NextBitmapBlock(
1126 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1128 if ((hfsmp
->hfs_flags
& HFS_METADATA_ZONE
) == 0)
1131 * Skip over metadata allocation zone.
1133 if ((bit
>= hfsmp
->hfs_metazone_start
) &&
1134 (bit
<= hfsmp
->hfs_metazone_end
)) {
1135 bit
= hfsmp
->hfs_metazone_end
+ 1;
1142 ;_______________________________________________________________________
1144 ; Routine: ReadBitmapBlock
1146 ; Function: Read in a bitmap block corresponding to a given allocation
1147 ; block (bit). Return a pointer to the bitmap block.
1150 ; vcb -- Pointer to ExtendedVCB
1151 ; bit -- Allocation block whose bitmap block is desired
1154 ; buffer -- Pointer to bitmap block corresonding to "block"
1156 ;_______________________________________________________________________
1158 static OSErr
ReadBitmapBlock(
1162 uintptr_t *blockRef
)
1165 struct buf
*bp
= NULL
;
1166 struct vnode
*vp
= NULL
;
1168 u_int32_t blockSize
;
1170 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
1171 KERNEL_DEBUG_CONSTANT(HFSDBG_READ_BITMAP_BLOCK
| DBG_FUNC_START
, bit
, 0, 0, 0, 0);
1174 * volume bitmap blocks are protected by the allocation file lock
1176 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
1178 blockSize
= (u_int32_t
)vcb
->vcbVBMIOSize
;
1179 block
= (daddr64_t
)(bit
/ (blockSize
* kBitsPerByte
));
1181 if (vcb
->vcbSigWord
== kHFSPlusSigWord
) {
1182 vp
= vcb
->hfs_allocation_vp
; /* use allocation file vnode */
1185 vp
= VCBTOHFS(vcb
)->hfs_devvp
; /* use device I/O vnode */
1186 block
+= vcb
->vcbVBMSt
; /* map to physical block */
1189 err
= (int)buf_meta_bread(vp
, block
, blockSize
, NOCRED
, &bp
);
1197 *blockRef
= (uintptr_t)bp
;
1198 *buffer
= (u_int32_t
*)buf_dataptr(bp
);
1202 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
1203 KERNEL_DEBUG_CONSTANT(HFSDBG_READ_BITMAP_BLOCK
| DBG_FUNC_END
, err
, 0, 0, 0, 0);
1210 ;_______________________________________________________________________
1212 ; Routine: ReleaseBitmapBlock
1214 ; Function: Relase a bitmap block.
1220 ;_______________________________________________________________________
1222 static OSErr
ReleaseBitmapBlock(
1227 struct buf
*bp
= (struct buf
*)blockRef
;
1229 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
1230 KERNEL_DEBUG_CONSTANT(HFSDBG_RELEASE_BITMAP_BLOCK
| DBG_FUNC_START
, dirty
, 0, 0, 0, 0);
1232 if (blockRef
== 0) {
1234 panic("hfs: ReleaseBitmapBlock: missing bp");
1241 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1244 journal_modify_block_end(hfsmp
->jnl
, bp
, NULL
, NULL
);
1253 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
1254 KERNEL_DEBUG_CONSTANT(HFSDBG_RELEASE_BITMAP_BLOCK
| DBG_FUNC_END
, 0, 0, 0, 0, 0);
1259 #if CONFIG_HFS_ALLOC_RBTREE
1261 * ReleaseRBScanBitmapBlock is used to release struct bufs that were
1262 * created for use by the Red-Black tree generation code. We want to force
1263 * them to be purged out of the buffer cache ASAP, so we'll release them differently
1264 * than in the ReleaseBitmapBlock case. Alternately, we know that we're only reading
1265 * the blocks, so we will never dirty them as part of the tree building scan.
1268 static OSErr
ReleaseRBScanBitmapBlock(struct buf
*bp
) {
1275 /* Mark the buffer invalid if it isn't locked, then release it */
1276 if ((buf_flags(bp
) & B_LOCKED
) == 0) {
1277 buf_markinvalid(bp
);
1291 _______________________________________________________________________
1293 Routine: BlockAllocateContig
1295 Function: Allocate a contiguous group of allocation blocks. The
1296 allocation is all-or-nothing. The caller guarantees that
1297 there are enough free blocks (though they may not be
1298 contiguous, in which case this call will fail).
1301 vcb Pointer to volume where space is to be allocated
1302 startingBlock Preferred first block for allocation
1303 minBlocks Minimum number of contiguous blocks to allocate
1304 maxBlocks Maximum number of contiguous blocks to allocate
1308 actualStartBlock First block of range allocated, or 0 if error
1309 actualNumBlocks Number of blocks allocated, or 0 if error
1310 _______________________________________________________________________
1312 static OSErr
BlockAllocateContig(
1314 u_int32_t startingBlock
,
1315 u_int32_t minBlocks
,
1316 u_int32_t maxBlocks
,
1317 Boolean useMetaZone
,
1318 u_int32_t
*actualStartBlock
,
1319 u_int32_t
*actualNumBlocks
)
1322 #if CONFIG_HFS_ALLOC_RBTREE
1323 if (hfs_isrbtree_active(VCBTOHFS(vcb
))) {
1324 return BlockAllocateContigRBTree(vcb
, startingBlock
, minBlocks
, maxBlocks
, useMetaZone
,
1325 actualStartBlock
, actualNumBlocks
, 1);
1328 return BlockAllocateContigBitmap(vcb
, startingBlock
, minBlocks
,
1329 maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
1333 * Variant of BlockAllocateContig that uses the original bitmap-searching logic
1336 static OSErr
BlockAllocateContigBitmap(
1338 u_int32_t startingBlock
,
1339 u_int32_t minBlocks
,
1340 u_int32_t maxBlocks
,
1341 Boolean useMetaZone
,
1342 u_int32_t
*actualStartBlock
,
1343 u_int32_t
*actualNumBlocks
)
1347 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1348 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_CONTIG_BITMAP
| DBG_FUNC_START
, startingBlock
, minBlocks
, maxBlocks
, useMetaZone
, 0);
1351 // Find a contiguous group of blocks at least minBlocks long.
1352 // Determine the number of contiguous blocks available (up
1357 * NOTE: If the only contiguous free extent of at least minBlocks
1358 * crosses startingBlock (i.e. starts before, ends after), then we
1359 * won't find it. Earlier versions *did* find this case by letting
1360 * the second search look past startingBlock by minBlocks. But
1361 * with the free extent cache, this can lead to duplicate entries
1362 * in the cache, causing the same blocks to be allocated twice.
1364 err
= BlockFindContiguous(vcb
, startingBlock
, vcb
->allocLimit
, minBlocks
,
1365 maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
1366 if (err
== dskFulErr
&& startingBlock
!= 0) {
1368 * Constrain the endingBlock so we don't bother looking for ranges
1369 * that would overlap those found in the previous call.
1371 err
= BlockFindContiguous(vcb
, 1, startingBlock
, minBlocks
, maxBlocks
,
1372 useMetaZone
, actualStartBlock
, actualNumBlocks
);
1375 // Now mark those blocks allocated.
1378 err
= BlockMarkAllocatedInternal(vcb
, *actualStartBlock
, *actualNumBlocks
);
1380 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1381 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_CONTIG_BITMAP
| DBG_FUNC_END
, err
, *actualStartBlock
, *actualNumBlocks
, 0, 0);
1386 #if CONFIG_HFS_ALLOC_RBTREE
1388 * Variant of BlockAllocateContig that uses the newer red-black tree library
1389 * in order to manage free space extents. This will search the red-black tree
1390 * and return results in the same fashion as BlockAllocateContigBitmap.
1392 * Note that this function is invoked from both the red-black tree variant of BlockAllocateany
1393 * as well as BlockAllocateContig. In order to determine when we should vend contiguous chunks over
1394 * locality-based-searches, we use the forceContig argument to determine who called us.
1397 static OSErr
BlockAllocateContigRBTree(
1399 u_int32_t startingBlock
,
1400 u_int32_t minBlocks
,
1401 u_int32_t maxBlocks
,
1402 Boolean useMetaZone
,
1403 u_int32_t
*actualStartBlock
,
1404 u_int32_t
*actualNumBlocks
,
1405 u_int32_t forceContig
)
1408 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1409 extent_node_t search_sentinel
;
1410 extent_node_t
*node
= NULL
;
1411 extent_node_t tempnode
;
1413 bzero (&tempnode
, sizeof(extent_node_t
));
1415 /* Begin search at the end of the file, via startingBlock */
1416 memset (&search_sentinel
, 0, sizeof(extent_node_t
));
1417 search_sentinel
.offset
= startingBlock
;
1419 *actualStartBlock
= 0;
1420 *actualNumBlocks
= 0;
1423 * Find the first available extent that satifies the allocation by searching
1424 * from the starting point and moving forward
1426 node
= extent_tree_off_search_next(&hfsmp
->offset_tree
, &search_sentinel
);
1429 *actualStartBlock
= node
->offset
;
1430 *actualNumBlocks
= node
->length
;
1433 /* If we managed to grab at least minBlocks of space, then we're done. */
1435 if (*actualNumBlocks
>= minBlocks
) {
1436 if (*actualNumBlocks
> maxBlocks
) {
1437 *actualNumBlocks
= maxBlocks
;
1441 /* Check to see if blocks are already marked as in-use */
1443 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
1444 if (hfs_isallocated(hfsmp
, *actualStartBlock
, *actualNumBlocks
)) {
1445 printf("bad node: %p, offset %d, length %d\n", node
, node
->offset
,node
->length
);
1446 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks in use already\n",
1447 *actualStartBlock
, *actualNumBlocks
);
1452 * BlockMarkAllocatedRBTree is responsible for removing the nodes
1453 * from the red-black tree after the bitmap has been updated on-disk.
1455 err
= BlockMarkAllocatedRBTree(vcb
, *actualStartBlock
, *actualNumBlocks
);
1458 if ( ALLOC_DEBUG
) {
1459 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
1460 if (!hfs_isallocated(hfsmp
, *actualStartBlock
, *actualNumBlocks
)) {
1461 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks not in use yet\n",
1462 *actualStartBlock
, *actualNumBlocks
);
1464 check_rbtree_extents (VCBTOHFS(vcb
), *actualStartBlock
, *actualNumBlocks
, ASSERT_ALLOC
);
1472 * We may have failed to grow at the end of the file. We'll try to find
1473 * appropriate free extents, searching by size in the normal allocation zone.
1475 * However, if we're allocating on behalf of a sparse device that hasn't explicitly
1476 * requested a contiguous chunk, then we try to search by offset, even if it
1477 * means fragmenting the file. We want all available entries starting
1478 * from the front of the disk to avoid creating new bandfiles. As a result,
1479 * we'll start by searching the offset tree rather than the normal length
1480 * tree. Note that this function can be invoked from BlockAllocateAny, in
1481 * which the minimum block size is 1 block, making it easy to succeed.
1483 search_sentinel
.offset
= hfsmp
->hfs_metazone_end
;
1484 search_sentinel
.length
= minBlocks
;
1486 if ((vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) && (forceContig
== 0)) {
1487 /* just start with the first offset node */
1488 node
= extent_tree_off_search_next(&hfsmp
->offset_tree
, &search_sentinel
);
1492 * Otherwise, start from the end of the metadata zone or our next allocation pointer,
1493 * and try to find the first chunk of size >= min.
1495 node
= extent_tree_off_search_nextWithSize (&hfsmp
->offset_tree
, &search_sentinel
);
1498 extent_node_t
*metaend_node
;
1500 * Maybe there's a free extent coalesced with the space still in the metadata
1501 * zone. If there is, find it and allocate from the middle of it, starting at
1502 * the end of the metadata zone.
1504 * If search_prev yields a result that is not offset == metazone_end, then that
1505 * means no node existed at that offset. If the previous node's offset + length crosses
1506 * the metazone boundary, then allocate from there. If it is too small to
1507 * cross the metazone boundary, then it is of no importance and we'd have to
1510 metaend_node
= extent_tree_off_search_prev(&hfsmp
->offset_tree
, &search_sentinel
);
1512 if ((metaend_node
) && (metaend_node
->offset
< hfsmp
->hfs_metazone_end
)) {
1513 u_int32_t node_end
= metaend_node
->offset
+ metaend_node
->length
;
1514 if (node_end
> hfsmp
->hfs_metazone_end
) {
1515 u_int32_t modified_length
= node_end
- hfsmp
->hfs_metazone_end
;
1516 if (modified_length
>= minBlocks
) {
1518 * Then we can allocate it. Fill in the contents into tempnode,
1519 * and BlockMarkAllocatedRBTree below will take care of the rest.
1521 tempnode
.offset
= hfsmp
->hfs_metazone_end
;
1522 tempnode
.length
= MIN(minBlocks
, node_end
- tempnode
.offset
);
1530 /* If we can't find anything useful, search the metadata zone as a last resort. */
1532 if ((!node
) && useMetaZone
) {
1533 search_sentinel
.offset
= 0;
1534 search_sentinel
.length
= minBlocks
;
1535 node
= extent_tree_off_search_nextWithSize (&hfsmp
->offset_tree
, &search_sentinel
);
1538 /* If we found something useful, then go ahead and update the bitmap */
1539 if ((node
) && (node
->length
>= minBlocks
)) {
1540 *actualStartBlock
= node
->offset
;
1541 if (node
->length
>= maxBlocks
) {
1542 *actualNumBlocks
= maxBlocks
;
1545 *actualNumBlocks
= node
->length
;
1548 err
= BlockMarkAllocatedRBTree(vcb
, *actualStartBlock
, *actualNumBlocks
);
1551 if ( ALLOC_DEBUG
) {
1552 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
1553 if (!hfs_isallocated(hfsmp
, *actualStartBlock
, *actualNumBlocks
)) {
1554 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks not in use yet\n",
1555 *actualStartBlock
, *actualNumBlocks
);
1557 check_rbtree_extents (VCBTOHFS(vcb
), *actualStartBlock
, *actualNumBlocks
, ASSERT_ALLOC
);
1562 int destroy_trees
= 0;
1564 * TODO: Add High-water mark check here. If we couldn't find anything useful,
1565 * when do we tear down the tree? Or should the logic be in BlockAllocateContig??
1567 if (destroy_trees
) {
1568 DestroyTrees(VCBTOHFS(vcb
));
1569 /* Reset the Free Ext Cache since we'll be using it now. */
1570 ResetVCBFreeExtCache(VCBTOHFS(vcb
));
1574 printf("HFS allocator: No space on FS (%s). Node %p Start %d Min %d, Max %d, Tree still alive.\n",
1575 hfsmp
->vcbVN
, node
, startingBlock
, minBlocks
, maxBlocks
);
1577 /* Dump the list ? */
1578 extent_tree_offset_print(&hfsmp
->offset_tree
);
1580 printf("HFS allocator: Done printing list on FS (%s). Min %d, Max %d, Tree still alive.\n",
1581 hfsmp
->vcbVN
, minBlocks
, maxBlocks
);
1591 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
1592 panic("hfs: BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
1596 *actualStartBlock
= 0;
1597 *actualNumBlocks
= 0;
1608 _______________________________________________________________________
1610 Routine: BlockAllocateAny
1612 Function: Allocate one or more allocation blocks. If there are fewer
1613 free blocks than requested, all free blocks will be
1614 allocated. The caller guarantees that there is at least
1618 vcb Pointer to volume where space is to be allocated
1619 startingBlock Preferred first block for allocation
1620 endingBlock Last block to check + 1
1621 maxBlocks Maximum number of contiguous blocks to allocate
1625 actualStartBlock First block of range allocated, or 0 if error
1626 actualNumBlocks Number of blocks allocated, or 0 if error
1627 _______________________________________________________________________
1631 * BlockAllocateAny acts as a multiplexer between BlockAllocateAnyRBTree
1632 * and BlockAllocateAnyBitmap, which uses the bitmap scanning logic.
1635 static OSErr
BlockAllocateAny(
1637 u_int32_t startingBlock
,
1638 register u_int32_t endingBlock
,
1639 u_int32_t maxBlocks
,
1640 Boolean useMetaZone
,
1641 u_int32_t
*actualStartBlock
,
1642 u_int32_t
*actualNumBlocks
)
1645 #if CONFIG_HFS_ALLOC_RBTREE
1646 if (hfs_isrbtree_active(VCBTOHFS(vcb
))) {
1647 return BlockAllocateAnyRBTree(vcb
, startingBlock
, maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
1650 return BlockAllocateAnyBitmap(vcb
, startingBlock
, endingBlock
, maxBlocks
, useMetaZone
, actualStartBlock
, actualNumBlocks
);
1655 #if CONFIG_HFS_ALLOC_RBTREE
1657 * BlockAllocateAnyRBTree finds one or more allocation blocks by using
1658 * the red-black allocation tree to figure out where the free ranges are.
1659 * This function is typically used as a last resort becuase we were unable to
1660 * find the right ranges. Outputs are the same as BlockAllocateAnyBitmap.
1662 static OSErr
BlockAllocateAnyRBTree(
1664 u_int32_t startingBlock
,
1665 u_int32_t maxBlocks
,
1666 Boolean useMetaZone
,
1667 u_int32_t
*actualStartBlock
,
1668 u_int32_t
*actualNumBlocks
)
1673 * BlockAllocateContig
1675 /* If we're using the red-black tree, try searching at the specified offsets. */
1676 err
= BlockAllocateContigRBTree(vcb
, startingBlock
, 1, maxBlocks
, useMetaZone
,
1677 actualStartBlock
, actualNumBlocks
, 0);
1684 * BlockAllocateAnyBitmap finds free ranges by scanning the bitmap to figure out
1685 * where the free allocation blocks are. Inputs and outputs are the same as for
1686 * BlockAllocateAny and BlockAllocateAnyRBTree
1689 static OSErr
BlockAllocateAnyBitmap(
1691 u_int32_t startingBlock
,
1692 register u_int32_t endingBlock
,
1693 u_int32_t maxBlocks
,
1694 Boolean useMetaZone
,
1695 u_int32_t
*actualStartBlock
,
1696 u_int32_t
*actualNumBlocks
)
1699 register u_int32_t block
; // current block number
1700 register u_int32_t currentWord
; // Pointer to current word within bitmap block
1701 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
1702 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
1703 u_int32_t
*buffer
= NULL
;
1704 u_int32_t
*currCache
= NULL
;
1706 u_int32_t bitsPerBlock
;
1707 u_int32_t wordsPerBlock
;
1708 Boolean dirty
= false;
1709 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
1711 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1712 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_ANY_BITMAP
| DBG_FUNC_START
, startingBlock
, endingBlock
, maxBlocks
, useMetaZone
, 0);
1715 * When we're skipping the metadata zone and the start/end
1716 * range overlaps with the metadata zone then adjust the
1717 * start to be outside of the metadata zone. If the range
1718 * is entirely inside the metadata zone then we can deny the
1719 * request (dskFulErr).
1721 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
1722 if (startingBlock
<= vcb
->hfs_metazone_end
) {
1723 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
1724 startingBlock
= vcb
->hfs_metazone_end
+ 1;
1732 // Since this routine doesn't wrap around
1733 if (maxBlocks
> (endingBlock
- startingBlock
)) {
1734 maxBlocks
= endingBlock
- startingBlock
;
1738 // Pre-read the first bitmap block
1740 err
= ReadBitmapBlock(vcb
, startingBlock
, &currCache
, &blockRef
);
1741 if (err
!= noErr
) goto Exit
;
1745 // Set up the current position within the block
1748 u_int32_t wordIndexInBlock
;
1750 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
1751 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
1753 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
1754 buffer
+= wordIndexInBlock
;
1755 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
1756 currentWord
= SWAP_BE32 (*buffer
);
1757 bitMask
= kHighBitInWordMask
>> (startingBlock
& kBitsWithinWordMask
);
1761 // Find the first unallocated block
1763 block
=startingBlock
;
1764 while (block
< endingBlock
) {
1765 if ((currentWord
& bitMask
) == 0)
1773 bitMask
= kHighBitInWordMask
;
1776 if (--wordsLeft
== 0) {
1778 buffer
= currCache
= NULL
;
1779 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
1780 if (err
!= noErr
) goto Exit
;
1783 * Skip over metadata blocks.
1786 block
= NextBitmapBlock(vcb
, block
);
1788 if (block
>= endingBlock
) {
1793 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
1794 if (err
!= noErr
) goto Exit
;
1797 wordsLeft
= wordsPerBlock
;
1799 currentWord
= SWAP_BE32 (*buffer
);
1803 // Did we get to the end of the bitmap before finding a free block?
1804 // If so, then couldn't allocate anything.
1805 if (block
>= endingBlock
) {
1810 // Return the first block in the allocated range
1811 *actualStartBlock
= block
;
1814 // If we could get the desired number of blocks before hitting endingBlock,
1815 // then adjust endingBlock so we won't keep looking. Ideally, the comparison
1816 // would be (block + maxBlocks) < endingBlock, but that could overflow. The
1817 // comparison below yields identical results, but without overflow.
1818 if (block
< (endingBlock
-maxBlocks
)) {
1819 endingBlock
= block
+ maxBlocks
; // if we get this far, we've found enough
1824 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1828 // Allocate all of the consecutive blocks
1830 while ((currentWord
& bitMask
) == 0) {
1831 // Allocate this block
1832 currentWord
|= bitMask
;
1834 // Move to the next block. If no more, then exit.
1836 if (block
== endingBlock
)
1842 *buffer
= SWAP_BE32 (currentWord
); // update value in bitmap
1845 bitMask
= kHighBitInWordMask
;
1848 if (--wordsLeft
== 0) {
1850 buffer
= currCache
= NULL
;
1851 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
1852 if (err
!= noErr
) goto Exit
;
1855 * Skip over metadata blocks.
1858 u_int32_t nextBlock
;
1860 nextBlock
= NextBitmapBlock(vcb
, block
);
1861 if (nextBlock
!= block
) {
1862 goto Exit
; /* allocation gap, so stop */
1866 err
= ReadBitmapBlock(vcb
, block
, &currCache
, &blockRef
);
1867 if (err
!= noErr
) goto Exit
;
1872 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
1875 wordsLeft
= wordsPerBlock
;
1878 currentWord
= SWAP_BE32 (*buffer
);
1881 *buffer
= SWAP_BE32 (currentWord
); // update the last change
1885 *actualNumBlocks
= block
- *actualStartBlock
;
1888 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
) {
1889 panic("hfs: BlockAllocateAny: allocation overflow on \"%s\"", vcb
->vcbVN
);
1894 * Because this function directly manipulates the bitmap to mark the
1895 * blocks it came across as allocated, we must inform the journal (and
1896 * subsequently, the journal's trim list) that we are allocating these
1897 * blocks, just like in BlockMarkAllocatedInternal. hfs_unmap_alloc_extent
1898 * and the functions it calls will serialize behind the journal trim list lock
1899 * to ensure that either the asynchronous flush/TRIM/UNMAP happens prior to
1900 * us manipulating the trim list, or we get there first and successfully remove
1901 * these bitmap blocks before the TRIM happens.
1903 hfs_unmap_alloc_extent (vcb
, *actualStartBlock
, *actualNumBlocks
);
1906 *actualStartBlock
= 0;
1907 *actualNumBlocks
= 0;
1911 (void) ReleaseBitmapBlock(vcb
, blockRef
, dirty
);
1913 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1914 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_ANY_BITMAP
| DBG_FUNC_END
, err
, *actualStartBlock
, *actualNumBlocks
, 0, 0);
1921 _______________________________________________________________________
1923 Routine: BlockAllocateKnown
1925 Function: Try to allocate space from known free space in the free
1929 vcb Pointer to volume where space is to be allocated
1930 maxBlocks Maximum number of contiguous blocks to allocate
1933 actualStartBlock First block of range allocated, or 0 if error
1934 actualNumBlocks Number of blocks allocated, or 0 if error
1937 dskFulErr Free extent cache is empty
1938 _______________________________________________________________________
1941 static OSErr
BlockAllocateKnown(
1943 u_int32_t maxBlocks
,
1944 u_int32_t
*actualStartBlock
,
1945 u_int32_t
*actualNumBlocks
)
1949 u_int32_t foundBlocks
;
1950 u_int32_t newStartBlock
, newBlockCount
;
1952 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1953 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_KNOWN_BITMAP
| DBG_FUNC_START
, 0, 0, maxBlocks
, 0, 0);
1955 HFS_MOUNT_LOCK(vcb
, TRUE
);
1956 lck_spin_lock(&vcb
->vcbFreeExtLock
);
1957 if ((hfs_isrbtree_active(vcb
) == true) ||
1958 vcb
->vcbFreeExtCnt
== 0 ||
1959 vcb
->vcbFreeExt
[0].blockCount
== 0) {
1960 lck_spin_unlock(&vcb
->vcbFreeExtLock
);
1961 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1962 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
1963 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_KNOWN_BITMAP
| DBG_FUNC_END
, dskFulErr
, *actualStartBlock
, *actualNumBlocks
, 0, 0);
1966 lck_spin_unlock(&vcb
->vcbFreeExtLock
);
1967 HFS_MOUNT_UNLOCK(vcb
, TRUE
);
1969 lck_spin_lock(&vcb
->vcbFreeExtLock
);
1971 // Just grab up to maxBlocks of the first (largest) free exent.
1972 *actualStartBlock
= vcb
->vcbFreeExt
[0].startBlock
;
1973 foundBlocks
= vcb
->vcbFreeExt
[0].blockCount
;
1974 if (foundBlocks
> maxBlocks
)
1975 foundBlocks
= maxBlocks
;
1976 *actualNumBlocks
= foundBlocks
;
1978 if (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
1979 // since sparse volumes keep the free extent list sorted by starting
1980 // block number, the list won't get re-ordered, it may only shrink
1982 vcb
->vcbFreeExt
[0].startBlock
+= foundBlocks
;
1983 vcb
->vcbFreeExt
[0].blockCount
-= foundBlocks
;
1984 if (vcb
->vcbFreeExt
[0].blockCount
== 0) {
1985 for(i
=1; i
< vcb
->vcbFreeExtCnt
; i
++) {
1986 vcb
->vcbFreeExt
[i
-1] = vcb
->vcbFreeExt
[i
];
1988 vcb
->vcbFreeExtCnt
--;
1994 // Adjust the start and length of that extent.
1995 newStartBlock
= vcb
->vcbFreeExt
[0].startBlock
+ foundBlocks
;
1996 newBlockCount
= vcb
->vcbFreeExt
[0].blockCount
- foundBlocks
;
1999 // The first extent might not be the largest anymore. Bubble up any
2000 // (now larger) extents to the top of the list.
2001 for (i
=1; i
<vcb
->vcbFreeExtCnt
; ++i
)
2003 if (vcb
->vcbFreeExt
[i
].blockCount
> newBlockCount
)
2005 vcb
->vcbFreeExt
[i
-1].startBlock
= vcb
->vcbFreeExt
[i
].startBlock
;
2006 vcb
->vcbFreeExt
[i
-1].blockCount
= vcb
->vcbFreeExt
[i
].blockCount
;
2014 // If this is now the smallest known free extent, then it might be smaller than
2015 // other extents we didn't keep track of. So, just forget about this extent.
2016 // After the previous loop, (i-1) is the index of the extent we just allocated from.
2017 if (newBlockCount
== 0)
2019 // then just reduce the number of free extents since this guy got deleted
2020 --vcb
->vcbFreeExtCnt
;
2024 // It's not the smallest, so store it in its proper place
2025 vcb
->vcbFreeExt
[i
-1].startBlock
= newStartBlock
;
2026 vcb
->vcbFreeExt
[i
-1].blockCount
= newBlockCount
;
2030 lck_spin_unlock(&vcb
->vcbFreeExtLock
);
2032 if ((*actualStartBlock
+ *actualNumBlocks
) > vcb
->allocLimit
)
2034 printf ("hfs: BlockAllocateKnown() found allocation overflow on \"%s\"", vcb
->vcbVN
);
2035 hfs_mark_volume_inconsistent(vcb
);
2036 *actualStartBlock
= 0;
2037 *actualNumBlocks
= 0;
2043 // Now mark the found extent in the bitmap
2045 err
= BlockMarkAllocatedInternal(vcb
, *actualStartBlock
, *actualNumBlocks
);
2048 sanity_check_free_ext(vcb
, 0);
2050 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
2051 KERNEL_DEBUG_CONSTANT(HFSDBG_ALLOC_KNOWN_BITMAP
| DBG_FUNC_END
, err
, *actualStartBlock
, *actualNumBlocks
, 0, 0);
2057 * BlockMarkAllocated
2059 * This is a wrapper function around the internal calls which will actually mark the blocks
2060 * as in-use. It will mark the blocks in the red-black tree if appropriate. We need to do
2061 * this logic here to avoid callers having to deal with whether or not the red-black tree
2066 OSErr
BlockMarkAllocated(
2068 u_int32_t startingBlock
,
2069 register u_int32_t numBlocks
)
2071 struct hfsmount
*hfsmp
;
2073 hfsmp
= VCBTOHFS(vcb
);
2074 #if CONFIG_HFS_ALLOC_RBTREE
2075 if (hfs_isrbtree_active(hfsmp
)) {
2078 if ((startingBlock
>= hfsmp
->offset_block_end
) &&
2079 (hfsmp
->hfs_flags
& HFS_RESIZE_IN_PROGRESS
)) {
2081 * We're manipulating a portion of the bitmap that is not controlled by the
2082 * red-black tree. Just update the bitmap and don't bother manipulating the tree
2087 err
= BlockMarkAllocatedRBTree(vcb
, startingBlock
, numBlocks
);
2089 if ( ALLOC_DEBUG
) {
2090 REQUIRE_FILE_LOCK(hfsmp
->hfs_allocation_vp
, false);
2091 if (!hfs_isallocated(hfsmp
, startingBlock
, numBlocks
)) {
2092 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks not in use yet\n",
2093 startingBlock
, numBlocks
);
2095 check_rbtree_extents (hfsmp
, startingBlock
, numBlocks
, ASSERT_ALLOC
);
2104 return BlockMarkAllocatedInternal(vcb
, startingBlock
, numBlocks
);
2111 _______________________________________________________________________
2113 Routine: BlockMarkAllocatedInternal
2115 Function: Mark a contiguous group of blocks as allocated (set in the
2116 bitmap). It assumes those bits are currently marked
2117 deallocated (clear in the bitmap). Note that this function
2118 must be called regardless of whether or not the bitmap or
2119 tree-based allocator is used, as all allocations must correctly
2120 be marked on-disk. If the tree-based approach is running, then
2121 this will be done before the node is removed from the tree.
2124 vcb Pointer to volume where space is to be allocated
2125 startingBlock First block number to mark as allocated
2126 numBlocks Number of blocks to mark as allocated
2127 _______________________________________________________________________
2130 OSErr
BlockMarkAllocatedInternal (
2132 u_int32_t startingBlock
,
2133 register u_int32_t numBlocks
)
2136 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
2137 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
2138 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
2139 u_int32_t firstBit
; // Bit index within word of first bit to allocate
2140 u_int32_t numBits
; // Number of bits in word to allocate
2141 u_int32_t
*buffer
= NULL
;
2143 u_int32_t bitsPerBlock
;
2144 u_int32_t wordsPerBlock
;
2146 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
2148 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
2149 KERNEL_DEBUG_CONSTANT(HFSDBG_MARK_ALLOC_BITMAP
| DBG_FUNC_START
, startingBlock
, numBlocks
, 0, 0, 0);
2151 hfs_unmap_alloc_extent(vcb
, startingBlock
, numBlocks
);
2154 // Pre-read the bitmap block containing the first word of allocation
2157 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
2158 if (err
!= noErr
) goto Exit
;
2160 // Initialize currentWord, and wordsLeft.
2163 u_int32_t wordIndexInBlock
;
2165 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
2166 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
2168 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
2169 currentWord
= buffer
+ wordIndexInBlock
;
2170 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
2175 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
2179 // If the first block to allocate doesn't start on a word
2180 // boundary in the bitmap, then treat that first word
2184 firstBit
= startingBlock
% kBitsPerWord
;
2185 if (firstBit
!= 0) {
2186 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
2187 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
2188 if (numBits
> numBlocks
) {
2189 numBits
= numBlocks
; // entire allocation is inside this one word
2190 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
2193 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
2194 panic("hfs: BlockMarkAllocatedInternal: blocks already allocated!");
2197 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
2198 numBlocks
-= numBits
; // adjust number of blocks left to allocate
2200 ++currentWord
; // move to next word
2201 --wordsLeft
; // one less word left in this block
2205 // Allocate whole words (32 blocks) at a time.
2208 bitMask
= kAllBitsSetInWord
; // put this in a register for 68K
2209 while (numBlocks
>= kBitsPerWord
) {
2210 if (wordsLeft
== 0) {
2211 // Read in the next bitmap block
2212 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
2215 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
2216 if (err
!= noErr
) goto Exit
;
2218 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
2219 if (err
!= noErr
) goto Exit
;
2223 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
2226 // Readjust currentWord and wordsLeft
2227 currentWord
= buffer
;
2228 wordsLeft
= wordsPerBlock
;
2231 if (*currentWord
!= 0) {
2232 panic("hfs: BlockMarkAllocatedInternal: blocks already allocated!");
2235 *currentWord
= SWAP_BE32 (bitMask
);
2236 numBlocks
-= kBitsPerWord
;
2238 ++currentWord
; // move to next word
2239 --wordsLeft
; // one less word left in this block
2243 // Allocate any remaining blocks.
2246 if (numBlocks
!= 0) {
2247 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
2248 if (wordsLeft
== 0) {
2249 // Read in the next bitmap block
2250 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
2253 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
2254 if (err
!= noErr
) goto Exit
;
2256 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
2257 if (err
!= noErr
) goto Exit
;
2261 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
2264 // Readjust currentWord and wordsLeft
2265 currentWord
= buffer
;
2266 wordsLeft
= wordsPerBlock
;
2269 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
2270 panic("hfs: BlockMarkAllocatedInternal: blocks already allocated!");
2273 *currentWord
|= SWAP_BE32 (bitMask
); // set the bits in the bitmap
2275 // No need to update currentWord or wordsLeft
2281 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
2283 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
2284 KERNEL_DEBUG_CONSTANT(HFSDBG_MARK_ALLOC_BITMAP
| DBG_FUNC_END
, err
, 0, 0, 0, 0);
2289 #if CONFIG_HFS_ALLOC_RBTREE
2291 * This is a wrapper function around BlockMarkAllocated. This function is
2292 * called when the RB Tree-based allocator needs to mark a block as in-use.
2293 * This function should take the locks that would not normally be
2294 * necessary for the normal bitmap allocator, and then call the function. Once
2295 * the on-disk data structures are updated properly, then this will remove the
2296 * appropriate node from the tree.
2299 static OSErr
BlockMarkAllocatedRBTree(
2301 u_int32_t startingBlock
,
2302 u_int32_t numBlocks
)
2305 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
2310 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
2311 if (hfs_isallocated(hfsmp
, startingBlock
, numBlocks
)) {
2312 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks in use already\n",
2313 startingBlock
, numBlocks
);
2315 check_rbtree_extents (VCBTOHFS(vcb
), startingBlock
, numBlocks
, ASSERT_FREE
);
2318 err
= BlockMarkAllocatedInternal (vcb
, startingBlock
, numBlocks
);
2323 if (!hfs_isallocated(hfsmp
, startingBlock
, numBlocks
)) {
2324 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks not in use yet!\n",
2325 startingBlock
, numBlocks
);
2330 * Mark the blocks in the offset tree.
2332 rb_err
= extent_tree_offset_alloc_space(&hfsmp
->offset_tree
, numBlocks
, startingBlock
);
2335 printf("HFS RBTree Allocator: Could not mark blocks as in-use! %d \n", rb_err
);
2339 * We may be called from the BlockMarkAllocated interface, in which case, they would
2340 * not be picking extents from their start. Do a check here, find if the specified
2341 * extent is free, and if it is, then find the containing node.
2343 extent_node_t
*node
= NULL
;
2344 extent_node_t search_sentinel
;
2345 search_sentinel
.offset
= startingBlock
;
2347 node
= extent_tree_off_search_prev(&hfsmp
->offset_tree
, &search_sentinel
);
2350 rb_err
= extent_tree_offset_alloc_unaligned (&hfsmp
->offset_tree
, numBlocks
, startingBlock
);
2355 printf ("HFS RBTree Allocator: Still Couldn't mark blocks as in-use! %d\n", rb_err
);
2360 check_rbtree_extents (VCBTOHFS(vcb
), startingBlock
, numBlocks
, ASSERT_ALLOC
);
2365 * If we encountered a red-black tree error, for now, we immediately back off and force
2366 * destruction of rb-tree. Set the persistent error-detected bit in the mount point.
2367 * That will ensure that even if we reach a low-water-mark in the future we will still
2368 * not allow the rb-tree to be used. On next mount, we will force a re-construction from
2369 * on-disk state. As a fallback, we will now resort to the bitmap-scanning behavior.
2372 /* Mark RB-Trees with error */
2373 hfsmp
->extent_tree_flags
|= HFS_ALLOC_RB_ERRORED
;
2374 DestroyTrees(hfsmp
);
2375 /* Reset the Free Ext Cache since we'll be using it now. */
2376 ResetVCBFreeExtCache(hfsmp
);
2377 printf("HFS: Red-Black Allocator Tree BlockMarkAllocated error\n");
2389 * This is a wrapper function around the internal calls which will actually mark the blocks
2390 * as freed. It will mark the blocks in the red-black tree if appropriate. We need to do
2391 * this logic here to avoid callers having to deal with whether or not the red-black tree
2395 OSErr
BlockMarkFree(
2397 u_int32_t startingBlock
,
2398 register u_int32_t numBlocks
)
2400 struct hfsmount
*hfsmp
;
2401 hfsmp
= VCBTOHFS(vcb
);
2402 #if CONFIG_HFS_ALLOC_RBTREE
2403 if (hfs_isrbtree_active(hfsmp
)) {
2406 if ((startingBlock
>= hfsmp
->offset_block_end
) &&
2407 (hfsmp
->hfs_flags
& HFS_RESIZE_IN_PROGRESS
)) {
2409 * We're manipulating a portion of the bitmap that is not controlled by the
2410 * red-black tree. Just update the bitmap and don't bother manipulating the tree
2415 err
= BlockMarkFreeRBTree(vcb
, startingBlock
, numBlocks
);
2417 if ( ALLOC_DEBUG
) {
2418 REQUIRE_FILE_LOCK(hfsmp
->hfs_allocation_vp
, false);
2419 if (hfs_isallocated(hfsmp
, startingBlock
, numBlocks
)) {
2420 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks in use!\n",
2421 startingBlock
, numBlocks
);
2423 check_rbtree_extents (hfsmp
, startingBlock
, numBlocks
, ASSERT_FREE
);
2430 return BlockMarkFreeInternal(vcb
, startingBlock
, numBlocks
, true);
2436 * BlockMarkFreeUnused
2438 * Scan the bitmap block beyond end of current file system for bits
2439 * that are marked as used. If any of the bits are marked as used,
2440 * this function marks them free.
2442 * Note: This was specifically written to mark all bits beyond
2443 * end of current file system during hfs_extendfs(), which makes
2444 * sure that all the new blocks added to the file system are
2445 * marked as free. We expect that all the blocks beyond end of
2446 * current file system are always marked as free, but there might
2447 * be cases where are marked as used. This function assumes that
2448 * the number of blocks marked as used incorrectly are relatively
2449 * small, otherwise this can overflow journal transaction size
2450 * on certain file system configurations (example, large unused
2451 * bitmap with relatively small journal).
2454 * startingBlock: First block of the range to mark unused
2455 * numBlocks: Number of blocks in the range to mark unused
2457 * Returns: zero on success, non-zero on error.
2459 OSErr
BlockMarkFreeUnused(ExtendedVCB
*vcb
, u_int32_t startingBlock
, register u_int32_t numBlocks
)
2462 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
2463 u_int32_t curNumBlocks
;
2464 u_int32_t bitsPerBlock
;
2467 /* Use the optimal bitmap I/O size instead of bitmap block size */
2468 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
2471 * First clear any non bitmap allocation block aligned bits
2473 * Calculate the first bit in the bitmap block next to
2474 * the bitmap block containing the bit for startingBlock.
2475 * Using this value, we calculate the total number of
2476 * bits to be marked unused from startingBlock to the
2477 * end of bitmap block containing startingBlock.
2479 lastBit
= ((startingBlock
+ (bitsPerBlock
- 1))/bitsPerBlock
) * bitsPerBlock
;
2480 curNumBlocks
= lastBit
- startingBlock
;
2481 if (curNumBlocks
> numBlocks
) {
2482 curNumBlocks
= numBlocks
;
2484 error
= BlockMarkFreeInternal(vcb
, startingBlock
, curNumBlocks
, false);
2488 startingBlock
+= curNumBlocks
;
2489 numBlocks
-= curNumBlocks
;
2492 * Check a full bitmap block for any 'used' bit. If any bit is used,
2493 * mark all the bits only in that bitmap block as free. This ensures
2494 * that we do not write unmodified bitmap blocks and do not
2495 * overwhelm the journal.
2497 * The code starts by checking full bitmap block at a time, and
2498 * marks entire bitmap block as free only if any bit in that bitmap
2499 * block is marked as used. In the end, it handles the last bitmap
2500 * block which might be partially full by only checking till the
2501 * caller-specified last bit and if any bit is set, only mark that
2505 if (numBlocks
>= bitsPerBlock
) {
2506 curNumBlocks
= bitsPerBlock
;
2508 curNumBlocks
= numBlocks
;
2510 if (hfs_isallocated(hfsmp
, startingBlock
, curNumBlocks
) == true) {
2511 error
= BlockMarkFreeInternal(vcb
, startingBlock
, curNumBlocks
, false);
2516 startingBlock
+= curNumBlocks
;
2517 numBlocks
-= curNumBlocks
;
2524 _______________________________________________________________________
2526 Routine: BlockMarkFreeInternal
2528 Function: Mark a contiguous group of blocks as free (clear in the
2529 bitmap). It assumes those bits are currently marked
2530 allocated (set in the bitmap).
2533 vcb Pointer to volume where space is to be freed
2534 startingBlock First block number to mark as freed
2535 numBlocks Number of blocks to mark as freed
2536 do_validate If true, validate that the blocks being
2537 deallocated to check if they are within totalBlocks
2538 for current volume and whether they were allocated
2539 before they are marked free.
2540 _______________________________________________________________________
2543 OSErr
BlockMarkFreeInternal(
2545 u_int32_t startingBlock_in
,
2546 register u_int32_t numBlocks_in
,
2547 Boolean do_validate
)
2550 u_int32_t startingBlock
= startingBlock_in
;
2551 u_int32_t numBlocks
= numBlocks_in
;
2552 register u_int32_t
*currentWord
; // Pointer to current word within bitmap block
2553 register u_int32_t wordsLeft
; // Number of words left in this bitmap block
2554 register u_int32_t bitMask
; // Word with given bits already set (ready to OR in)
2555 u_int32_t firstBit
; // Bit index within word of first bit to allocate
2556 u_int32_t numBits
; // Number of bits in word to allocate
2557 u_int32_t
*buffer
= NULL
;
2559 u_int32_t bitsPerBlock
;
2560 u_int32_t wordsPerBlock
;
2562 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
2564 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
2565 KERNEL_DEBUG_CONSTANT(HFSDBG_MARK_FREE_BITMAP
| DBG_FUNC_START
, startingBlock_in
, numBlocks_in
, do_validate
, 0, 0);
2568 * NOTE: We use vcb->totalBlocks instead of vcb->allocLimit because we
2569 * need to be able to free blocks being relocated during hfs_truncatefs.
2571 if ((do_validate
== true) &&
2572 (startingBlock
+ numBlocks
> vcb
->totalBlocks
)) {
2574 panic ("BlockMarkFreeInternal() free non-existent blocks at %u (numBlock=%u) on vol %s\n", startingBlock
, numBlocks
, vcb
->vcbVN
);
2577 printf ("hfs: BlockMarkFreeInternal() trying to free non-existent blocks starting at %u (numBlock=%u) on volume %s\n", startingBlock
, numBlocks
, vcb
->vcbVN
);
2578 hfs_mark_volume_inconsistent(vcb
);
2584 // Pre-read the bitmap block containing the first word of allocation
2587 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
2588 if (err
!= noErr
) goto Exit
;
2591 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
2595 // Initialize currentWord, and wordsLeft.
2598 u_int32_t wordIndexInBlock
;
2600 bitsPerBlock
= vcb
->vcbVBMIOSize
* kBitsPerByte
;
2601 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
2603 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
2604 currentWord
= buffer
+ wordIndexInBlock
;
2605 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
2609 // If the first block to free doesn't start on a word
2610 // boundary in the bitmap, then treat that first word
2614 firstBit
= startingBlock
% kBitsPerWord
;
2615 if (firstBit
!= 0) {
2616 bitMask
= kAllBitsSetInWord
>> firstBit
; // turn off all bits before firstBit
2617 numBits
= kBitsPerWord
- firstBit
; // number of remaining bits in this word
2618 if (numBits
> numBlocks
) {
2619 numBits
= numBlocks
; // entire allocation is inside this one word
2620 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
)); // turn off bits after last
2622 if ((do_validate
== true) &&
2623 (*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
2626 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
2627 numBlocks
-= numBits
; // adjust number of blocks left to free
2629 ++currentWord
; // move to next word
2630 --wordsLeft
; // one less word left in this block
2634 // Free whole words (32 blocks) at a time.
2637 while (numBlocks
>= kBitsPerWord
) {
2638 if (wordsLeft
== 0) {
2639 // Read in the next bitmap block
2640 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
2643 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
2644 if (err
!= noErr
) goto Exit
;
2646 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
2647 if (err
!= noErr
) goto Exit
;
2651 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
2654 // Readjust currentWord and wordsLeft
2655 currentWord
= buffer
;
2656 wordsLeft
= wordsPerBlock
;
2658 if ((do_validate
== true) &&
2659 (*currentWord
!= SWAP_BE32 (kAllBitsSetInWord
))) {
2662 *currentWord
= 0; // clear the entire word
2663 numBlocks
-= kBitsPerWord
;
2665 ++currentWord
; // move to next word
2666 --wordsLeft
; // one less word left in this block
2670 // Free any remaining blocks.
2673 if (numBlocks
!= 0) {
2674 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
); // set first numBlocks bits
2675 if (wordsLeft
== 0) {
2676 // Read in the next bitmap block
2677 startingBlock
+= bitsPerBlock
; // generate a block number in the next bitmap block
2680 err
= ReleaseBitmapBlock(vcb
, blockRef
, true);
2681 if (err
!= noErr
) goto Exit
;
2683 err
= ReadBitmapBlock(vcb
, startingBlock
, &buffer
, &blockRef
);
2684 if (err
!= noErr
) goto Exit
;
2688 journal_modify_block_start(hfsmp
->jnl
, (struct buf
*)blockRef
);
2691 // Readjust currentWord and wordsLeft
2692 currentWord
= buffer
;
2693 wordsLeft
= wordsPerBlock
;
2695 if ((do_validate
== true) &&
2696 (*currentWord
& SWAP_BE32 (bitMask
)) != SWAP_BE32 (bitMask
)) {
2699 *currentWord
&= SWAP_BE32 (~bitMask
); // clear the bits in the bitmap
2701 // No need to update currentWord or wordsLeft
2707 (void)ReleaseBitmapBlock(vcb
, blockRef
, true);
2710 hfs_unmap_free_extent(vcb
, startingBlock_in
, numBlocks_in
);
2713 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
2714 KERNEL_DEBUG_CONSTANT(HFSDBG_MARK_FREE_BITMAP
| DBG_FUNC_END
, err
, 0, 0, 0, 0);
2720 panic("hfs: BlockMarkFreeInternal: blocks not allocated!");
2722 printf ("hfs: BlockMarkFreeInternal() trying to free unallocated blocks (%u,%u) on volume %s\n", startingBlock
, numBlocks
, vcb
->vcbVN
);
2723 hfs_mark_volume_inconsistent(vcb
);
2729 #if CONFIG_HFS_ALLOC_RBTREE
2731 * This is a wrapper function around BlockMarkFree. This function is
2732 * called when the RB Tree-based allocator needs to mark a block as no longer
2733 * in use. This function should take the locks that would not normally be
2734 * necessary for the normal bitmap deallocator, and then call the function. Once
2735 * the on-disk data structures are updated properly, then this will update an
2736 * existing rb-tree node if possible, or else create a new one.
2739 OSErr
BlockMarkFreeRBTree(
2741 u_int32_t startingBlock
,
2742 register u_int32_t numBlocks
)
2745 struct hfsmount
*hfsmp
= VCBTOHFS(vcb
);
2749 REQUIRE_FILE_LOCK(vcb
->hfs_allocation_vp
, false);
2750 if (!hfs_isallocated(hfsmp
, startingBlock
, numBlocks
)) {
2751 panic ("HFS RBTree Allocator: Trying to free blocks starting @ %x for %x but blocks not in use! \n",
2752 startingBlock
, numBlocks
);
2754 check_rbtree_extents (VCBTOHFS(vcb
), startingBlock
, numBlocks
, ASSERT_ALLOC
);
2757 err
= BlockMarkFreeInternal(vcb
, startingBlock
, numBlocks
, true);
2762 * During a filesystem truncation, we may need to relocate files out of the
2763 * portion of the bitmap that is no longer controlled by the r/b tree.
2764 * In this case, just update the bitmap and do not attempt to manipulate the tree.
2766 if ((startingBlock
>= hfsmp
->offset_block_end
) &&
2767 (hfsmp
->hfs_flags
& HFS_RESIZE_IN_PROGRESS
)) {
2771 extent_node_t
*newnode
;
2775 * Validate that the blocks in question are not allocated in the bitmap, and that they're
2776 * not in the offset tree, since it should be tracking free extents, rather than allocated
2779 if (hfs_isallocated(hfsmp
, startingBlock
, numBlocks
)) {
2780 panic ("HFS RBTree Allocator: Blocks starting @ %x for %x blocks still marked in-use!\n",
2781 startingBlock
, numBlocks
);
2785 if ((hfsmp
->extent_tree_flags
& HFS_ALLOC_RB_ACTIVE
) == 0) {
2786 if (startingBlock
>= hfsmp
->offset_block_end
) {
2788 * If the tree generation code has not yet finished scanning the
2789 * bitmap region containing this extent, do nothing. If the start
2790 * of the range to be deallocated is greater than the current high
2791 * watermark on the offset tree, just bail out and let the scanner catch up with us.
2798 newnode
= extent_tree_free_space(&hfsmp
->offset_tree
, numBlocks
, startingBlock
);
2799 if (newnode
== NULL
) {
2805 check_rbtree_extents (VCBTOHFS(vcb
), startingBlock
, numBlocks
, ASSERT_FREE
);
2812 * We follow the same principle as in BlockMarkAllocatedRB.
2813 * If we encounter an error in adding the extents to the rb-tree, then immediately
2814 * back off, destroy the trees, and persistently set a bit in the runtime hfsmp flags
2815 * to indicate we should not use the rb-tree until next mount, when we can force a rebuild.
2818 /* Mark RB-Trees with error */
2819 hfsmp
->extent_tree_flags
|= HFS_ALLOC_RB_ERRORED
;
2820 DestroyTrees(hfsmp
);
2821 /* Reset the Free Ext Cache since we'll be using it now. */
2822 ResetVCBFreeExtCache(hfsmp
);
2823 printf("HFS: Red-Black Allocator Tree BlockMarkFree error\n");
2833 _______________________________________________________________________
2835 Routine: BlockFindContiguous
2837 Function: Find a contiguous range of blocks that are free (bits
2838 clear in the bitmap). If a contiguous range of the
2839 minimum size can't be found, an error will be returned.
2840 This is only needed to support the bitmap-scanning logic,
2841 as the red-black tree should be able to do this by internally
2845 vcb Pointer to volume where space is to be allocated
2846 startingBlock Preferred first block of range
2847 endingBlock Last possible block in range + 1
2848 minBlocks Minimum number of blocks needed. Must be > 0.
2849 maxBlocks Maximum (ideal) number of blocks desired
2850 useMetaZone OK to dip into metadata allocation zone
2853 actualStartBlock First block of range found, or 0 if error
2854 actualNumBlocks Number of blocks found, or 0 if error
2857 noErr Found at least minBlocks contiguous
2858 dskFulErr No contiguous space found, or all less than minBlocks
2859 _______________________________________________________________________
2862 static OSErr
BlockFindContiguous(
2864 u_int32_t startingBlock
,
2865 u_int32_t endingBlock
,
2866 u_int32_t minBlocks
,
2867 u_int32_t maxBlocks
,
2868 Boolean useMetaZone
,
2869 u_int32_t
*actualStartBlock
,
2870 u_int32_t
*actualNumBlocks
)
2873 register u_int32_t currentBlock
; // Block we're currently looking at.
2874 u_int32_t firstBlock
; // First free block in current extent.
2875 u_int32_t stopBlock
; // If we get to this block, stop searching for first free block.
2876 u_int32_t foundBlocks
; // Number of contiguous free blocks in current extent.
2877 u_int32_t
*buffer
= NULL
;
2878 register u_int32_t
*currentWord
;
2879 register u_int32_t bitMask
;
2880 register u_int32_t wordsLeft
;
2881 register u_int32_t tempWord
;
2883 u_int32_t wordsPerBlock
;
2884 u_int32_t updated_free_extent
= 0;
2886 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
2887 KERNEL_DEBUG_CONSTANT(HFSDBG_BLOCK_FIND_CONTIG
| DBG_FUNC_START
, startingBlock
, endingBlock
, minBlocks
, maxBlocks
, 0);
2890 * When we're skipping the metadata zone and the start/end
2891 * range overlaps with the metadata zone then adjust the
2892 * start to be outside of the metadata zone. If the range
2893 * is entirely inside the metadata zone then we can deny the
2894 * request (dskFulErr).
2896 if (!useMetaZone
&& (vcb
->hfs_flags
& HFS_METADATA_ZONE
)) {
2897 if (startingBlock
<= vcb
->hfs_metazone_end
) {
2898 if (endingBlock
> (vcb
->hfs_metazone_end
+ 2))
2899 startingBlock
= vcb
->hfs_metazone_end
+ 1;
2905 if ((endingBlock
- startingBlock
) < minBlocks
)
2907 // The set of blocks we're checking is smaller than the minimum number
2908 // of blocks, so we couldn't possibly find a good range.
2912 stopBlock
= endingBlock
- minBlocks
+ 1;
2913 currentBlock
= startingBlock
;
2917 * Skip over metadata blocks.
2920 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
2923 // Pre-read the first bitmap block.
2925 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
2926 if ( err
!= noErr
) goto ErrorExit
;
2929 // Figure out where currentBlock is within the buffer.
2931 wordsPerBlock
= vcb
->vcbVBMIOSize
/ kBytesPerWord
;
2933 wordsLeft
= (currentBlock
/ kBitsPerWord
) & (wordsPerBlock
-1); // Current index into buffer
2934 currentWord
= buffer
+ wordsLeft
;
2935 wordsLeft
= wordsPerBlock
- wordsLeft
;
2941 //============================================================
2942 // Look for a free block, skipping over allocated blocks.
2943 //============================================================
2946 // Check an initial partial word (if any)
2948 bitMask
= currentBlock
& kBitsWithinWordMask
;
2951 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
2952 bitMask
= kHighBitInWordMask
>> bitMask
;
2953 while (tempWord
& bitMask
)
2959 // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)?
2963 // Didn't find any unused bits, so we're done with this word.
2969 // Check whole words
2971 while (currentBlock
< stopBlock
)
2973 // See if it's time to read another block.
2977 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
2978 if (err
!= noErr
) goto ErrorExit
;
2981 * Skip over metadata blocks.
2984 currentBlock
= NextBitmapBlock(vcb
, currentBlock
);
2985 if (currentBlock
>= stopBlock
) {
2990 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
2991 if ( err
!= noErr
) goto ErrorExit
;
2993 currentWord
= buffer
;
2994 wordsLeft
= wordsPerBlock
;
2997 // See if any of the bits are clear
2998 if ((tempWord
= SWAP_BE32(*currentWord
)) + 1) // non-zero if any bits were clear
3000 // Figure out which bit is clear
3001 bitMask
= kHighBitInWordMask
;
3002 while (tempWord
& bitMask
)
3008 break; // Found the free bit; break out to FoundUnused.
3011 // Keep looking at the next word
3012 currentBlock
+= kBitsPerWord
;
3018 // Make sure the unused bit is early enough to use
3019 if (currentBlock
>= stopBlock
)
3024 // Remember the start of the extent
3025 firstBlock
= currentBlock
;
3027 //============================================================
3028 // Count the number of contiguous free blocks.
3029 //============================================================
3032 // Check an initial partial word (if any)
3034 bitMask
= currentBlock
& kBitsWithinWordMask
;
3037 tempWord
= SWAP_BE32(*currentWord
); // Fetch the current word only once
3038 bitMask
= kHighBitInWordMask
>> bitMask
;
3039 while (bitMask
&& !(tempWord
& bitMask
))
3045 // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)?
3049 // Didn't find any used bits, so we're done with this word.
3055 // Check whole words
3057 while (currentBlock
< endingBlock
)
3059 // See if it's time to read another block.
3063 err
= ReleaseBitmapBlock(vcb
, blockRef
, false);
3064 if (err
!= noErr
) goto ErrorExit
;
3067 * Skip over metadata blocks.
3070 u_int32_t nextBlock
;
3072 nextBlock
= NextBitmapBlock(vcb
, currentBlock
);
3073 if (nextBlock
!= currentBlock
) {
3074 goto LoopExit
; /* allocation gap, so stop */
3078 err
= ReadBitmapBlock(vcb
, currentBlock
, &buffer
, &blockRef
);
3079 if ( err
!= noErr
) goto ErrorExit
;
3081 currentWord
= buffer
;
3082 wordsLeft
= wordsPerBlock
;
3085 // See if any of the bits are set
3086 if ((tempWord
= SWAP_BE32(*currentWord
)) != 0)
3088 // Figure out which bit is set
3089 bitMask
= kHighBitInWordMask
;
3090 while (!(tempWord
& bitMask
))
3096 break; // Found the used bit; break out to FoundUsed.
3099 // Keep looking at the next word
3100 currentBlock
+= kBitsPerWord
;
3104 // If we found at least maxBlocks, we can quit early.
3105 if ((currentBlock
- firstBlock
) >= maxBlocks
)
3110 // Make sure we didn't run out of bitmap looking for a used block.
3111 // If so, pin to the end of the bitmap.
3112 if (currentBlock
> endingBlock
)
3113 currentBlock
= endingBlock
;
3115 // Figure out how many contiguous free blocks there were.
3116 // Pin the answer to maxBlocks.
3117 foundBlocks
= currentBlock
- firstBlock
;
3118 if (foundBlocks
> maxBlocks
)
3119 foundBlocks
= maxBlocks
;
3120 if (foundBlocks
>= minBlocks
)
3121 break; // Found what we needed!
3123 /* We did not find the total blocks were were looking for, but
3124 * lets add this free block run to our free extent cache list
3126 updated_free_extent
= add_free_extent_cache(vcb
, firstBlock
, foundBlocks
);
3128 } while (currentBlock
< stopBlock
);
3131 // Return the outputs.
3132 if (foundBlocks
< minBlocks
)
3137 *actualStartBlock
= 0;
3138 *actualNumBlocks
= 0;
3143 *actualStartBlock
= firstBlock
;
3144 *actualNumBlocks
= foundBlocks
;
3146 * Sanity check for overflow
3148 if ((firstBlock
+ foundBlocks
) > vcb
->allocLimit
) {
3149 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",
3150 vcb
->vcbVN
, startingBlock
, endingBlock
, currentBlock
,
3151 firstBlock
, stopBlock
, minBlocks
, foundBlocks
);
3155 if (updated_free_extent
&& (vcb
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
)) {
3157 u_int32_t min_start
= vcb
->totalBlocks
;
3159 // set the nextAllocation pointer to the smallest free block number
3160 // we've seen so on the next mount we won't rescan unnecessarily
3161 lck_spin_lock(&vcb
->vcbFreeExtLock
);
3162 for(i
=0; i
< (int)vcb
->vcbFreeExtCnt
; i
++) {
3163 if (vcb
->vcbFreeExt
[i
].startBlock
< min_start
) {
3164 min_start
= vcb
->vcbFreeExt
[i
].startBlock
;
3167 lck_spin_unlock(&vcb
->vcbFreeExtLock
);
3168 if (min_start
!= vcb
->totalBlocks
) {
3169 if (min_start
< vcb
->nextAllocation
) {
3170 vcb
->nextAllocation
= min_start
;
3172 if (min_start
< vcb
->sparseAllocation
) {
3173 vcb
->sparseAllocation
= min_start
;
3179 (void) ReleaseBitmapBlock(vcb
, blockRef
, false);
3181 if (hfs_kdebug_allocation
& HFSDBG_ALLOC_ENABLED
)
3182 KERNEL_DEBUG_CONSTANT(HFSDBG_BLOCK_FIND_CONTIG
| DBG_FUNC_END
, err
, *actualStartBlock
, *actualNumBlocks
, 0, 0);
3188 #if CONFIG_HFS_ALLOC_RBTREE
3190 * Wrapper function around hfs_isrbtree_allocated. This just takes the start offset,
3191 * and the number of blocks, and whether or not we should check if the blocks are
3192 * free or not. This function is designed to be used primarily with the debug #ifdef
3193 * enabled, so it results in a panic if anything unexpected occurs.
3195 * shouldBeFree will be nonzero if the caller expects the zone to be free.
3198 void check_rbtree_extents (struct hfsmount
*hfsmp
, u_int32_t startBlocks
,
3199 u_int32_t numBlocks
, int shouldBeFree
) {
3201 extent_node_t
*node1
= NULL
;
3204 alloc
= hfs_isrbtree_allocated (hfsmp
, startBlocks
, numBlocks
, &node1
);
3207 off1
= node1
->offset
;
3208 len1
= node1
->length
;
3213 * If the region should be free, then we expect to see extents in the tree
3214 * matching this start and length. Alloc != 0 means some portion of the extent
3215 * specified was allocated.
3218 panic ("HFS check_rbtree_extents: Node (%p) do not exist! "
3219 "node1 off (%d),len(%d),, start(%d) end(%d)\n",
3220 node1
, off1
, len1
, startBlocks
, numBlocks
);
3225 * Otherwise, this means that the region should be allocated, and if we find
3226 * an extent matching it, that's bad.
3229 panic ("HFS check_rbtree_extents: Node (%p) exists! "
3230 "node1 off (%d),len(%d), start(%d) end(%d)\n",
3231 node1
, off1
, len1
, startBlocks
, numBlocks
);
3237 #if CONFIG_HFS_ALLOC_RBTREE
3239 * Exhaustive validation search. This function iterates over all allocation blocks and
3240 * compares their status in the red-black tree vs. the allocation bitmap. If the two are out of sync
3241 * then it will panic. Bitmap lock must be held while this function is run.
3243 * Because this function requires a red-black tree search to validate every allocation block, it is
3244 * very expensive and should ONLY be run in debug mode, and even then, infrequently.
3246 * 'end' is non-inclusive, so it should represent the total number of blocks in the volume.
3250 hfs_validate_rbtree (struct hfsmount
*hfsmp
, u_int32_t start
, u_int32_t end
){
3253 extent_node_t
* node1
;
3255 hfs_checktreelinks (hfsmp
);
3257 for (current
= start
; current
< end
; current
++) {
3259 int rbtree
= hfs_isrbtree_allocated(hfsmp
, current
, 1, &node1
);
3260 int bitmap
= hfs_isallocated(hfsmp
, current
, 1);
3262 if (bitmap
!= rbtree
){
3263 panic("HFS: Allocator mismatch @ block %d -- bitmap %d : rbtree %d\n",
3264 current
, bitmap
, rbtree
);
3270 * Exhaustive Red-Black Tree Linked List verification routine.
3272 * This function iterates through the red-black tree's nodes, and then verifies that the linked list
3273 * embedded within each of the nodes accurately points to the correct node as its "next" pointer.
3274 * The bitmap lock must be held while this function is run.
3278 hfs_checktreelinks (struct hfsmount
*hfsmp
) {
3279 extent_tree_offset_t
*tree
= &hfsmp
->offset_tree
;
3281 extent_node_t
*current
= NULL
;
3282 extent_node_t
*next
= NULL
;
3283 extent_node_t
*treenext
;
3285 current
= extent_tree_off_first (tree
);
3288 next
= current
->offset_next
;
3289 treenext
= extent_tree_off_next (tree
, current
);
3290 if (next
!= treenext
) {
3291 panic("hfs_checktreelinks: mismatch for node (%p), next: %p , treenext %p !\n", current
, next
, treenext
);
3300 #if CONFIG_HFS_ALLOC_RBTREE
3302 * Test to see if any free blocks exist at a given offset.
3303 * If there exists a node at the specified offset, it will return the appropriate
3306 * NULL indicates allocated blocks exist at that offset.
3308 * Allocation file lock must be held.
3311 * 1 if blocks in the range are allocated.
3312 * 0 if all blocks in the range are free.
3316 hfs_isrbtree_allocated (struct hfsmount
*hfsmp
, u_int32_t startBlock
,
3317 u_int32_t numBlocks
, extent_node_t
**ret_node
) {
3319 extent_node_t search_sentinel
;
3320 extent_node_t
*node
= NULL
;
3321 extent_node_t
*nextnode
= NULL
;
3324 * With only one tree, then we just have to validate that there are entries
3325 * in the R/B tree at the specified offset if it really is free.
3327 search_sentinel
.offset
= startBlock
;
3328 search_sentinel
.length
= numBlocks
;
3330 node
= extent_tree_off_search_prev(&hfsmp
->offset_tree
, &search_sentinel
);
3334 nextnode
= extent_tree_off_next (&hfsmp
->offset_tree
, node
);
3335 if (nextnode
!= node
->offset_next
) {
3336 panic ("hfs_rbtree_isallocated: Next pointers out of sync!\n");
3340 * Check to see if it is a superset of our target range. Because we started
3341 * with the offset or some offset prior to it, then we know the node's offset is
3342 * at least <= startBlock. So, if the end of the node is greater than the end of
3343 * our target range, then the whole range is free.
3346 if ((node
->offset
+ node
->length
) >= (startBlock
+ numBlocks
)) {
3347 if (node
->offset
> startBlock
) {
3348 panic ("hfs_rbtree_isallocated: bad node ordering!");
3354 * We got here if either our node search resulted in a node whose extent
3355 * was strictly before our target offset, or we couldnt' find a previous node
3356 * at all (the beginning of the volume). If the former, then we can infer that
3357 * at least one block in the target range is allocated since the next node's offset
3358 * must be greater than startBlock.
3360 * Either way, this means that the target node is unavailable to allocate, so
3370 * Count number of bits set in the given 32-bit unsigned number
3373 * Number of bits set
3375 static int num_bits_set(u_int32_t num
)
3379 for (count
= 0; num
; count
++) {
3387 * For a given range of blocks, find the total number of blocks
3388 * allocated. If 'stop_on_first' is true, it stops as soon as it
3389 * encounters the first allocated block. This option is useful
3390 * to determine if any block is allocated or not.
3393 * startingBlock First allocation block number of the range to be scanned.
3394 * numBlocks Total number of blocks that need to be scanned.
3395 * stop_on_first Stop the search after the first allocated block is found.
3398 * allocCount Total number of allocation blocks allocated in the given range.
3400 * On error, it is the number of allocated blocks found
3401 * before the function got an error.
3403 * If 'stop_on_first' is set,
3404 * allocCount = 1 if any allocated block was found.
3405 * allocCount = 0 if no allocated block was found.
3408 * 0 on success, non-zero on failure.
3411 hfs_isallocated_internal(struct hfsmount
*hfsmp
, u_int32_t startingBlock
,
3412 u_int32_t numBlocks
, Boolean stop_on_first
, u_int32_t
*allocCount
)
3414 u_int32_t
*currentWord
; // Pointer to current word within bitmap block
3415 u_int32_t wordsLeft
; // Number of words left in this bitmap block
3416 u_int32_t bitMask
; // Word with given bits already set (ready to test)
3417 u_int32_t firstBit
; // Bit index within word of first bit to allocate
3418 u_int32_t numBits
; // Number of bits in word to allocate
3419 u_int32_t
*buffer
= NULL
;
3421 u_int32_t bitsPerBlock
;
3422 u_int32_t wordsPerBlock
;
3423 u_int32_t blockCount
= 0;
3426 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
3427 KERNEL_DEBUG_CONSTANT(HFSDBG_IS_ALLOCATED
| DBG_FUNC_START
, startingBlock
, numBlocks
, stop_on_first
, 0, 0);
3430 * Pre-read the bitmap block containing the first word of allocation
3432 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
3437 * Initialize currentWord, and wordsLeft.
3440 u_int32_t wordIndexInBlock
;
3442 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
3443 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
3445 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
3446 currentWord
= buffer
+ wordIndexInBlock
;
3447 wordsLeft
= wordsPerBlock
- wordIndexInBlock
;
3451 * First test any non word aligned bits.
3453 firstBit
= startingBlock
% kBitsPerWord
;
3454 if (firstBit
!= 0) {
3455 bitMask
= kAllBitsSetInWord
>> firstBit
;
3456 numBits
= kBitsPerWord
- firstBit
;
3457 if (numBits
> numBlocks
) {
3458 numBits
= numBlocks
;
3459 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
3461 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
3462 if (stop_on_first
) {
3466 blockCount
+= num_bits_set(*currentWord
& SWAP_BE32 (bitMask
));
3468 numBlocks
-= numBits
;
3474 * Test whole words (32 blocks) at a time.
3476 while (numBlocks
>= kBitsPerWord
) {
3477 if (wordsLeft
== 0) {
3478 /* Read in the next bitmap block. */
3479 startingBlock
+= bitsPerBlock
;
3482 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
3483 if (error
) goto Exit
;
3485 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
3486 if (error
) goto Exit
;
3488 /* Readjust currentWord and wordsLeft. */
3489 currentWord
= buffer
;
3490 wordsLeft
= wordsPerBlock
;
3492 if (*currentWord
!= 0) {
3493 if (stop_on_first
) {
3497 blockCount
+= num_bits_set(*currentWord
);
3499 numBlocks
-= kBitsPerWord
;
3505 * Test any remaining blocks.
3507 if (numBlocks
!= 0) {
3508 bitMask
= ~(kAllBitsSetInWord
>> numBlocks
);
3509 if (wordsLeft
== 0) {
3510 /* Read in the next bitmap block */
3511 startingBlock
+= bitsPerBlock
;
3514 error
= ReleaseBitmapBlock(hfsmp
, blockRef
, false);
3515 if (error
) goto Exit
;
3517 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
3518 if (error
) goto Exit
;
3520 currentWord
= buffer
;
3521 wordsLeft
= wordsPerBlock
;
3523 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
3524 if (stop_on_first
) {
3528 blockCount
+= num_bits_set(*currentWord
& SWAP_BE32 (bitMask
));
3533 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);
3536 *allocCount
= blockCount
;
3540 if (hfs_kdebug_allocation
& HFSDBG_BITMAP_ENABLED
)
3541 KERNEL_DEBUG_CONSTANT(HFSDBG_IS_ALLOCATED
| DBG_FUNC_END
, error
, 0, blockCount
, 0, 0);
3547 * Count total number of blocks that are allocated in the given
3548 * range from the bitmap. This is used to preflight total blocks
3549 * that need to be relocated during volume resize.
3551 * The journal or allocation file lock must be held.
3554 * 0 on success, non-zero on failure.
3555 * On failure, allocCount is zero.
3558 hfs_count_allocated(struct hfsmount
*hfsmp
, u_int32_t startBlock
,
3559 u_int32_t numBlocks
, u_int32_t
*allocCount
)
3561 return hfs_isallocated_internal(hfsmp
, startBlock
, numBlocks
, false, allocCount
);
3565 * Test to see if any blocks in a range are allocated.
3567 * Note: On error, this function returns 1, which means that
3568 * one or more blocks in the range are allocated. This function
3569 * is primarily used for volume resize and we do not want
3570 * to report to the caller that the blocks are free when we
3571 * were not able to deterministically find it out. So on error,
3572 * we always report that the blocks are allocated.
3574 * The journal or allocation file lock must be held.
3577 * 0 if all blocks in the range are free.
3578 * 1 if blocks in the range are allocated, or there was an error.
3581 hfs_isallocated(struct hfsmount
*hfsmp
, u_int32_t startingBlock
, u_int32_t numBlocks
)
3584 u_int32_t allocCount
;
3586 error
= hfs_isallocated_internal(hfsmp
, startingBlock
, numBlocks
, true, &allocCount
);
3588 /* On error, we always say that the blocks are allocated
3589 * so that volume resize does not return false success.
3593 /* The function was deterministically able to find out
3594 * if there was any block allocated or not. In that case,
3595 * the value in allocCount is good enough to be returned
3596 * back to the caller.
3603 * Check to see if the red-black tree is live. Allocation file lock must be held
3604 * shared or exclusive to call this function. Note that we may call this even if
3605 * HFS is built without activating the red-black tree code.
3609 hfs_isrbtree_active(struct hfsmount
*hfsmp
){
3611 //TODO: Update this function to deal with a truncate/resize coming in when the tree
3612 //isn't fully finished. maybe we need to check the flags for something other than ENABLED?
3614 #if CONFIG_HFS_ALLOC_RBTREE
3616 REQUIRE_FILE_LOCK(hfsmp
->hfs_allocation_vp
, false);
3620 if (hfsmp
->extent_tree_flags
& HFS_ALLOC_RB_ENABLED
) {
3625 #pragma unused (hfsmp)
3627 /* If the RB Tree code is not enabled, then just always return 0 */
3631 #if CONFIG_HFS_ALLOC_RBTREE
3633 * This function is basically the same as hfs_isallocated, except it's designed for
3634 * use with the red-black tree validation code. It assumes we're only checking whether
3635 * one bit is active, and that we're going to pass in the buf to use, since GenerateTree
3636 * calls ReadBitmapBlock and will have that buf locked down for the duration of its operation.
3638 * This should not be called in general purpose scanning code.
3640 int hfs_isallocated_scan(struct hfsmount
*hfsmp
, u_int32_t startingBlock
, u_int32_t
*bp_buf
) {
3642 u_int32_t
*currentWord
; // Pointer to current word within bitmap block
3643 u_int32_t bitMask
; // Word with given bits already set (ready to test)
3644 u_int32_t firstBit
; // Bit index within word of first bit to allocate
3645 u_int32_t numBits
; // Number of bits in word to allocate
3646 u_int32_t bitsPerBlock
;
3648 u_int32_t wordsPerBlock
;
3649 u_int32_t numBlocks
= 1;
3650 u_int32_t
*buffer
= NULL
;
3657 /* just use passed-in buffer if avail. */
3662 * Pre-read the bitmap block containing the first word of allocation
3664 error
= ReadBitmapBlock(hfsmp
, startingBlock
, &buffer
, &blockRef
);
3670 * Initialize currentWord, and wordsLeft.
3672 u_int32_t wordIndexInBlock
;
3674 bitsPerBlock
= hfsmp
->vcbVBMIOSize
* kBitsPerByte
;
3675 wordsPerBlock
= hfsmp
->vcbVBMIOSize
/ kBytesPerWord
;
3677 wordIndexInBlock
= (startingBlock
& (bitsPerBlock
-1)) / kBitsPerWord
;
3678 currentWord
= buffer
+ wordIndexInBlock
;
3681 * First test any non word aligned bits.
3683 firstBit
= startingBlock
% kBitsPerWord
;
3684 bitMask
= kAllBitsSetInWord
>> firstBit
;
3685 numBits
= kBitsPerWord
- firstBit
;
3686 if (numBits
> numBlocks
) {
3687 numBits
= numBlocks
;
3688 bitMask
&= ~(kAllBitsSetInWord
>> (firstBit
+ numBits
));
3690 if ((*currentWord
& SWAP_BE32 (bitMask
)) != 0) {
3694 numBlocks
-= numBits
;
3698 if(bp_buf
== NULL
) {
3700 (void)ReleaseBitmapBlock(hfsmp
, blockRef
, false);
3710 * This function scans the specified block and adds it to the pair of trees specified
3711 * in its arguments. We break this behavior out of GenerateTree so that an allocating
3712 * thread can invoke this if the tree does not have enough extents to satisfy
3713 * an allocation request.
3715 * startbit - the allocation block represented by a bit in 'allocblock' where we need to
3716 * start our scan. For instance, we may need to start the normal allocation scan
3717 * in the middle of an existing allocation block.
3718 * endBit - the allocation block where we should end this search (inclusive).
3719 * bitToScan - output argument for this function to specify the next bit to scan.
3723 * nonzero on failure.
3726 static int hfs_alloc_scan_block(struct hfsmount
*hfsmp
, u_int32_t startbit
,
3727 u_int32_t endBit
, u_int32_t
*bitToScan
) {
3730 u_int32_t curAllocBlock
;
3731 struct buf
*blockRef
= NULL
;
3732 u_int32_t
*buffer
= NULL
;
3733 u_int32_t wordIndexInBlock
;
3734 u_int32_t blockSize
= (u_int32_t
)hfsmp
->vcbVBMIOSize
;
3735 u_int32_t wordsPerBlock
= blockSize
/ kBytesPerWord
;
3736 u_int32_t offset
= 0;
3740 * Read the appropriate block from the bitmap file. ReadBitmapBlock
3741 * figures out which actual on-disk block corresponds to the bit we're
3744 error
= ReadBitmapBlock(hfsmp
, startbit
, &buffer
, (uintptr_t*)&blockRef
);
3749 /* curAllocBlock represents the logical block we're analyzing. */
3750 curAllocBlock
= startbit
;
3752 /* Figure out which word curAllocBlock corresponds to in the block we read */
3753 wordIndexInBlock
= (curAllocBlock
/ kBitsPerWord
) % wordsPerBlock
;
3755 /* Scan a word at a time */
3756 while (wordIndexInBlock
< wordsPerBlock
) {
3757 u_int32_t currentWord
= SWAP_BE32(buffer
[wordIndexInBlock
]);
3760 /* modulate curBit because it may start in the middle of a word */
3761 for (curBit
= curAllocBlock
% kBitsPerWord
; curBit
< kBitsPerWord
; curBit
++) {
3763 u_int32_t is_allocated
= currentWord
& (1 << (kBitsWithinWordMask
- curBit
));
3765 u_int32_t res
= hfs_isallocated_scan (hfsmp
, curAllocBlock
, buffer
);
3766 if ( ((res
) && (!is_allocated
)) || ((!res
) && (is_allocated
))) {
3767 panic("hfs_alloc_scan: curAllocBit %u, curBit (%d), word (0x%x), is_allocated (0x%x) res(0x%x) \n",
3768 curAllocBlock
, curBit
, currentWord
, is_allocated
, res
);
3772 * If curBit is not allocated, keep track of the start of the free range.
3773 * Increment a running tally on how many free blocks in a row we've seen.
3775 if (!is_allocated
) {
3778 offset
= curAllocBlock
;
3783 * If we hit an allocated block, insert the extent that tracked the range
3784 * we saw, and reset our tally counter.
3787 extent_tree_free_space(&hfsmp
->offset_tree
, size
, offset
);
3794 * Exit early if the next bit we'd analyze would take us beyond the end of the
3795 * range that we're supposed to scan.
3797 if (curAllocBlock
>= endBit
) {
3805 /* We may have been tracking a range of free blocks that hasn't been inserted yet. */
3807 extent_tree_free_space(&hfsmp
->offset_tree
, size
, offset
);
3810 * curAllocBlock represents the next block we need to scan while we're in this
3813 *bitToScan
= curAllocBlock
;
3815 ReleaseRBScanBitmapBlock(blockRef
);
3821 * Extern function that is called from mount and upgrade mount routines
3822 * that enable us to initialize the tree.
3826 u_int32_t
InitTree(struct hfsmount
*hfsmp
) {
3827 extent_tree_init (&(hfsmp
->offset_tree
));
3833 * This function builds the trees specified in its arguments. It uses
3834 * buf_meta_breads to scan through the bitmap and re-build the tree state.
3835 * It is very important to use buf_meta_bread because we need to ensure that we
3836 * read the most current version of the blocks that we're scanning. If we used
3837 * cluster_io, then journaled transactions could still be sitting in RAM since they are
3838 * written to disk in the proper location asynchronously.
3840 * Because this could be still running when mount has finished, we need to check
3841 * after every allocation block that we're working on if an unmount or some other
3842 * operation that would cause us to teardown has come in. (think downgrade mount).
3843 * If an unmount has come in, then abort whatever we're doing and return -1
3844 * to indicate we hit an error. If we don't do this, we'd hold up unmount for
3847 * This function assumes that the bitmap lock is acquired exclusively before being
3848 * called. It will drop the lock and then re-acquire it during operation, but
3849 * will always return with the lock held.
3852 u_int32_t
GenerateTree(struct hfsmount
*hfsmp
, u_int32_t endBlock
, int *flags
, int initialscan
) {
3854 REQUIRE_FILE_LOCK(hfsmp
->hfs_allocation_vp
, false);
3856 u_int32_t
*cur_block_eof
;
3859 int USE_FINE_GRAINED_LOCKING
= 0;
3861 /* Initialize the block counter while we hold the bitmap lock */
3862 cur_block_eof
= &hfsmp
->offset_block_end
;
3865 * This loop advances over all allocation bitmap blocks of the current region
3866 * to scan them and add the results into the red-black tree. We use the mount point
3867 * variable offset_block_end as our loop counter. This gives us flexibility
3868 * because we can release the allocation bitmap lock and allow a thread that wants
3869 * to make an allocation to grab the lock and do some scanning on our behalf while we're
3870 * waiting to re-acquire the lock. Then, the allocating thread will only do as much bitmap
3871 * scanning as needed to fulfill its allocation.
3873 * If the other thread does IO for us, then it will update the offset_block_end
3874 * variable as well, since it will use the same hfs_alloc_scan_block function to do its bit
3875 * scanning. So when we re-grab the lock, our current EOF/loop will immediately skip us to the next
3876 * block that needs scanning.
3879 while (*cur_block_eof
< endBlock
) {
3882 * If the filesystem is being resized before the bitmap has been fully scanned, we'll
3883 * update our endBlock to match the current allocation limit in the hfsmp struct.
3884 * The allocLimit field would only be be updated while holding the bitmap lock, so we won't
3885 * be executing this code at the same time that the resize is going on.
3887 if ((initialscan
) && (endBlock
!= hfsmp
->allocLimit
)) {
3889 /* If we're past the new/modified allocLimit, then just stop immediately.*/
3890 if (*cur_block_eof
>= hfsmp
->allocLimit
) {
3893 endBlock
= hfsmp
->allocLimit
;
3897 * TODO: fix unmount stuff!
3898 * See rdar://7391404
3900 * Once the RB allocator is checked in, we'll want to augment it to not hold the
3901 * allocation bitmap lock for the entire duration of the tree scan. For a first check-in
3902 * it's ok to do that but we can't leave it like that forever.
3904 * The gist of the new algorithm will work as follows:
3905 * if an unmount is in flight and has been detected:
3907 * unset tree-in-progress bit.
3908 * wakeup unmount thread
3909 * unlock allocation bitmap lock, fail out.
3911 * The corresponding code in the unmount side should already be in place.
3914 error
= hfs_alloc_scan_block (hfsmp
, *cur_block_eof
, endBlock
, cur_block_eof
);
3916 //TODO: Fix this below!
3917 if (USE_FINE_GRAINED_LOCKING
){
3918 hfs_systemfile_unlock(hfsmp
, *flags
);
3919 *flags
= hfs_systemfile_lock(hfsmp
, SFL_BITMAP
, HFS_EXCLUSIVE_LOCK
);
3921 //TODO: Infer that if *flags == 0, we don't actually need to lock/unlock.
3928 * This function destroys the specified rb-trees associated with the mount point.
3931 void DestroyTrees(struct hfsmount
*hfsmp
) {
3934 REQUIRE_FILE_LOCK(hfsmp
->hfs_allocation_vp
, false);
3935 printf("DestroyTrees: Validating red/black tree for vol %s\n", (char*) hfsmp
->vcbVN
);
3936 hfs_validate_rbtree (hfsmp
, 0, hfsmp
->offset_block_end
);
3940 * extent_tree_destroy will start with the first entry in the tree (by offset), then
3941 * iterate through the tree quickly using its embedded linked list. This results in tree
3942 * destruction in O(n) time.
3945 if (hfsmp
->extent_tree_flags
& HFS_ALLOC_RB_ENABLED
) {
3946 extent_tree_destroy(&hfsmp
->offset_tree
);
3948 /* Mark Trees as disabled */
3949 hfsmp
->extent_tree_flags
&= ~HFS_ALLOC_RB_ENABLED
;
3958 * This function resets all of the data structures relevant to the
3959 * free extent cache stored in the hfsmount struct.
3961 * If we are using the red-black tree code then we need to account for the fact that
3962 * we may encounter situations where we need to jettison the tree. If that is the
3963 * case, then we fail-over to the bitmap scanning logic, but we need to ensure that
3964 * the free ext cache is zeroed before we start using it.
3966 * We also reset and disable the cache when allocLimit is updated... which
3967 * is when a volume is being resized (via hfs_truncatefs() or hfs_extendfs()).
3968 * It is independent of the type of allocator being used currently.
3970 void ResetVCBFreeExtCache(struct hfsmount
*hfsmp
)
3975 if (hfs_kdebug_allocation
& HFSDBG_EXT_CACHE_ENABLED
)
3976 KERNEL_DEBUG_CONSTANT(HFSDBG_RESET_EXTENT_CACHE
| DBG_FUNC_START
, 0, 0, 0, 0, 0);
3978 lck_spin_lock(&hfsmp
->vcbFreeExtLock
);
3980 /* reset Free Extent Count */
3981 hfsmp
->vcbFreeExtCnt
= 0;
3983 /* reset the actual array */
3984 bytes
= kMaxFreeExtents
* sizeof(HFSPlusExtentDescriptor
);
3985 freeExt
= (void*)(hfsmp
->vcbFreeExt
);
3987 bzero (freeExt
, bytes
);
3989 lck_spin_unlock(&hfsmp
->vcbFreeExtLock
);
3991 if (hfs_kdebug_allocation
& HFSDBG_EXT_CACHE_ENABLED
)
3992 KERNEL_DEBUG_CONSTANT(HFSDBG_RESET_EXTENT_CACHE
| DBG_FUNC_END
, 0, 0, 0, 0, 0);
3998 * This function is used to inform the allocator if we have to effectively shrink
3999 * or grow the total number of allocation blocks via hfs_truncatefs or hfs_extendfs.
4001 * The bitmap lock must be held when calling this function. This function also modifies the
4002 * allocLimit field in the hfs mount point structure in the general case.
4004 * In the shrinking case, we'll have to remove all free extents from the red-black
4005 * tree past the specified offset new_end_block. In the growth case, we'll have to force
4006 * a re-scan of the new allocation blocks from our current allocLimit to the new end block.
4008 * new_end_block represents the total number of blocks available for allocation in the resized
4009 * filesystem. Block #new_end_block should not be allocatable in the resized filesystem since it
4010 * will be out of the (0, n-1) range that are indexable in the bitmap.
4012 * Returns 0 on success
4016 u_int32_t
UpdateAllocLimit (struct hfsmount
*hfsmp
, u_int32_t new_end_block
) {
4019 * Update allocLimit to the argument specified, but don't do anything else
4020 * if the red/black tree is not enabled.
4022 hfsmp
->allocLimit
= new_end_block
;
4024 /* Invalidate the free extent cache completely so that
4025 * it does not have any extents beyond end of current
4028 ResetVCBFreeExtCache(hfsmp
);
4030 #if CONFIG_HFS_ALLOC_RBTREE
4031 /* Shrinking the existing filesystem */
4032 if ((new_end_block
< hfsmp
->offset_block_end
) &&
4033 (hfsmp
->extent_tree_flags
& HFS_ALLOC_RB_ACTIVE
)) {
4034 extent_node_t search_sentinel
;
4035 extent_node_t
*node
= NULL
;
4036 /* Remover points to the current item to free/remove from the tree */
4037 extent_node_t
*remover
= NULL
;
4039 /* Begin search at the specified offset */
4040 memset (&search_sentinel
, 0, sizeof(extent_node_t
));
4041 search_sentinel
.offset
= new_end_block
;
4044 * Find the first available extent that satifies the allocation by searching
4045 * from the starting point or 1 earlier. We may need to split apart an existing node
4046 * if it straddles the new alloc limit.
4048 node
= extent_tree_off_search_prev(&hfsmp
->offset_tree
, &search_sentinel
);
4050 /* If it's an exact match, then just remove them all from this point forward */
4051 if (node
->offset
== new_end_block
) {
4053 * Find the previous entry and update its next pointer to NULL
4054 * since this entry is biting the dust. Update remover to node.
4056 extent_node_t
*prev
= NULL
;
4057 prev
= extent_tree_off_prev (&hfsmp
->offset_tree
, node
);
4059 prev
->offset_next
= NULL
;
4064 /* See if we need to split this node */
4065 if ((node
->offset
+ node
->length
) > new_end_block
) {
4067 * Update node to reflect its new size up until new_end_block.
4069 remover
= node
->offset_next
;
4070 node
->length
= new_end_block
- node
->offset
;
4071 /* node is becoming the last free extent in the volume. */
4072 node
->offset_next
= NULL
;
4075 if (node
->offset_next
== NULL
) {
4077 * 'node' points to the last free extent in the volume.
4078 * Coincidentally, it is also before the new cut-off point at which
4079 * we will stop representing bitmap values in the tree. Just bail out now.
4084 * Otherwise, point our temp variable 'remover' to the node where
4085 * we'll need to start yanking things out of the tree, and make 'node'
4086 * the last element in the tree in the linked list.
4088 remover
= node
->offset_next
;
4089 if (remover
->offset
<= new_end_block
) {
4090 panic ("UpdateAllocLimit: Invalid RBTree node next ptr!");
4092 node
->offset_next
= NULL
;
4097 * Remover is our "temp" pointer that points to the current node to remove from
4098 * the offset tree. We'll simply iterate through the tree linked list, removing the current
4099 * element from the tree, freeing them as we come across them.
4102 extent_node_t
*next
= remover
->offset_next
;
4103 extent_tree_remove_node (&hfsmp
->offset_tree
, remover
);
4104 free_node (remover
);
4109 printf ("UpdateAllocLimit: Validating rbtree after truncation\n");
4110 hfs_validate_rbtree (hfsmp
, 0, new_end_block
-1);
4114 * Don't forget to shrink offset_block_end after a successful truncation
4115 * new_end_block should represent the number of blocks available on the
4119 hfsmp
->offset_block_end
= new_end_block
;
4125 panic ("UpdateAllocLimit: no prev!");
4130 /* Growing the existing filesystem */
4131 else if ((new_end_block
> hfsmp
->offset_block_end
) &&
4132 (hfsmp
->extent_tree_flags
& HFS_ALLOC_RB_ACTIVE
)) {
4137 printf ("UpdateAllocLimit: Validating rbtree prior to growth\n");
4138 hfs_validate_rbtree (hfsmp
, 0, hfsmp
->offset_block_end
);
4142 retval
= GenerateTree (hfsmp
, new_end_block
, &flags
, 0);
4145 * Don't forget to update offset_block_end after a successful tree extension.
4150 printf ("UpdateAllocLimit: Validating rbtree after growth\n");
4151 hfs_validate_rbtree (hfsmp
, 0, new_end_block
);
4154 hfsmp
->offset_block_end
= new_end_block
;
4159 /* Otherwise, do nothing. fall through to the code below. */
4160 printf ("error : off_block_end: %d, alloclimit: %d, new_end_block: %d\n",
4161 hfsmp
->offset_block_end
,hfsmp
->allocLimit
, new_end_block
);
4170 * Remove an entry from free extent cache after it has been allocated.
4172 * This function does not split extents to remove them from the allocated list.
4175 * hfsmp - mount point structure
4176 * startBlock - starting block of the extent to be removed.
4177 * blockCount - number of blocks of the extent to be removed.
4179 static void remove_free_extent_cache(struct hfsmount
*hfsmp
, u_int32_t startBlock
, u_int32_t blockCount
)
4182 int extentsRemoved
= 0;
4183 u_int32_t start
, end
;
4185 #if CONFIG_HFS_ALLOC_RBTREE
4186 /* If red-black tree is enabled, no free extent cache is necessary */
4187 if (hfs_isrbtree_active(hfsmp
) == true) {
4192 if (hfs_kdebug_allocation
& HFSDBG_EXT_CACHE_ENABLED
)
4193 KERNEL_DEBUG_CONSTANT(HFSDBG_REMOVE_EXTENT_CACHE
| DBG_FUNC_START
, startBlock
, blockCount
, 0, 0, 0);
4195 lck_spin_lock(&hfsmp
->vcbFreeExtLock
);
4197 for (i
= 0; i
< (int)hfsmp
->vcbFreeExtCnt
; i
++) {
4198 start
= hfsmp
->vcbFreeExt
[i
].startBlock
;
4199 end
= start
+ hfsmp
->vcbFreeExt
[i
].blockCount
;
4201 /* If the extent to remove from free extent list starts within
4202 * this free extent, or, if it starts before this free extent
4203 * but ends in this free extent, remove it by shifting all other
4206 if (((startBlock
>= start
) && (startBlock
< end
)) ||
4207 ((startBlock
< start
) && (startBlock
+ blockCount
) > start
)) {
4208 for (j
= i
; j
< (int)hfsmp
->vcbFreeExtCnt
- 1; j
++) {
4209 hfsmp
->vcbFreeExt
[j
] = hfsmp
->vcbFreeExt
[j
+1];
4211 hfsmp
->vcbFreeExtCnt
--;
4212 /* Decrement the index so that we check the extent
4213 * that just got shifted to the current index.
4218 /* Continue looping as we might have to invalidate multiple extents,
4219 * probably not possible in normal case, but does not hurt.
4223 lck_spin_unlock(&hfsmp
->vcbFreeExtLock
);
4225 sanity_check_free_ext(hfsmp
, 0);
4227 if (hfs_kdebug_allocation
& HFSDBG_EXT_CACHE_ENABLED
)
4228 KERNEL_DEBUG_CONSTANT(HFSDBG_REMOVE_EXTENT_CACHE
| DBG_FUNC_END
, 0, 0, 0, extentsRemoved
, 0);
4234 * Add an entry to free extent cache after it has been deallocated.
4236 * If the extent provided has blocks beyond current allocLimit, it
4237 * is clipped to allocLimit. This function does not merge contiguous
4238 * extents, if they already exist in the list.
4241 * hfsmp - mount point structure
4242 * startBlock - starting block of the extent to be removed.
4243 * blockCount - number of blocks of the extent to be removed.
4246 * true - if the extent was added successfully to the list
4247 * false - if the extent was no added to the list, maybe because
4248 * the extent was beyond allocLimit, or is not best
4249 * candidate to be put in the cache.
4251 static Boolean
add_free_extent_cache(struct hfsmount
*hfsmp
, u_int32_t startBlock
, u_int32_t blockCount
)
4253 Boolean retval
= false;
4254 u_int32_t start
, end
;
4257 if (hfs_kdebug_allocation
& HFSDBG_EXT_CACHE_ENABLED
)
4258 KERNEL_DEBUG_CONSTANT(HFSDBG_ADD_EXTENT_CACHE
| DBG_FUNC_START
, startBlock
, blockCount
, 0, 0, 0);
4261 * If using the red-black tree allocator, then there's no need to special case
4262 * for the sparse device case. We'll simply add the region we've recently freed
4263 * to the red-black tree, where it will get sorted by offset and length. The only special
4264 * casing will need to be done on the allocation side, where we may favor free extents
4265 * based on offset even if it will cause fragmentation. This may be true, for example, if
4266 * we are trying to reduce the number of bandfiles created in a sparse bundle disk image.
4268 #if CONFIG_HFS_ALLOC_RBTREE
4269 if (hfs_isrbtree_active(hfsmp
) == true) {
4270 goto out_not_locked
;
4274 /* No need to add extent that is beyond current allocLimit */
4275 if (startBlock
>= hfsmp
->allocLimit
) {
4276 goto out_not_locked
;
4279 /* If end of the free extent is beyond current allocLimit, clip the extent */
4280 if ((startBlock
+ blockCount
) > hfsmp
->allocLimit
) {
4281 blockCount
= hfsmp
->allocLimit
- startBlock
;
4284 lck_spin_lock(&hfsmp
->vcbFreeExtLock
);
4286 /* If the free extent cache is full and the new extent fails to
4287 * compare with the last extent, skip adding it to the list.
4289 if (hfsmp
->vcbFreeExtCnt
== kMaxFreeExtents
) {
4290 if (hfsmp
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
4291 /* For sparse disks, free extent cache list is sorted by start block, lowest first */
4292 if (startBlock
> hfsmp
->vcbFreeExt
[kMaxFreeExtents
-1].startBlock
) {
4296 /* For normal mounts, free extent cache list is sorted by total blocks, highest first */
4297 if (blockCount
<= hfsmp
->vcbFreeExt
[kMaxFreeExtents
-1].blockCount
) {
4303 /* Check if the current extent overlaps with any of the existing
4304 * extents. If yes, just skip adding it to the list. We have
4305 * to do this check before shifting the extent records.
4307 for (i
= 0; i
< (int)hfsmp
->vcbFreeExtCnt
; i
++) {
4309 start
= hfsmp
->vcbFreeExt
[i
].startBlock
;
4310 end
= start
+ hfsmp
->vcbFreeExt
[i
].blockCount
;
4312 if (((startBlock
>= start
) && (startBlock
< end
)) ||
4313 ((startBlock
< start
) && (startBlock
+ blockCount
) > start
)) {
4318 /* Scan the free extent cache array from tail to head till
4319 * we find the entry after which our new entry should be
4320 * inserted. After we break out of this loop, the new entry
4321 * will be inserted at 'i+1'.
4323 for (i
= (int)hfsmp
->vcbFreeExtCnt
-1; i
>= 0; i
--) {
4324 if (hfsmp
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
4325 /* For sparse devices, find entry with smaller start block than ours */
4326 if (hfsmp
->vcbFreeExt
[i
].startBlock
< startBlock
) {
4330 /* For normal devices, find entry with greater block count than ours */
4331 if (hfsmp
->vcbFreeExt
[i
].blockCount
>= blockCount
) {
4336 /* If this is not the right spot to insert, and this is
4337 * not the last entry in the array, just shift it and
4338 * continue check another one.
4340 if ((i
+1) < kMaxFreeExtents
) {
4341 hfsmp
->vcbFreeExt
[i
+1] = hfsmp
->vcbFreeExt
[i
];
4344 /* 'i' points to one index offset before which the new extent should be inserted */
4345 hfsmp
->vcbFreeExt
[i
+1].startBlock
= startBlock
;
4346 hfsmp
->vcbFreeExt
[i
+1].blockCount
= blockCount
;
4347 if (hfsmp
->vcbFreeExtCnt
< kMaxFreeExtents
) {
4348 hfsmp
->vcbFreeExtCnt
++;
4353 lck_spin_unlock(&hfsmp
->vcbFreeExtLock
);
4355 sanity_check_free_ext(hfsmp
, 0);
4357 if (hfs_kdebug_allocation
& HFSDBG_EXT_CACHE_ENABLED
)
4358 KERNEL_DEBUG_CONSTANT(HFSDBG_ADD_EXTENT_CACHE
| DBG_FUNC_END
, 0, 0, 0, retval
, 0);
4363 /* Debug function to check if the free extent cache is good or not */
4364 static void sanity_check_free_ext(struct hfsmount
*hfsmp
, int check_allocated
)
4368 /* Do not do anything if debug is not on, or if we're using the red-black tree */
4369 if ((ALLOC_DEBUG
== 0) || (hfs_isrbtree_active(hfsmp
) == true)) {
4373 lck_spin_lock(&hfsmp
->vcbFreeExtLock
);
4376 * Iterate the Free extent cache and ensure no entries are bogus or refer to
4379 for(i
=0; i
< hfsmp
->vcbFreeExtCnt
; i
++) {
4380 u_int32_t start
, nblocks
;
4382 start
= hfsmp
->vcbFreeExt
[i
].startBlock
;
4383 nblocks
= hfsmp
->vcbFreeExt
[i
].blockCount
;
4385 //printf ("hfs: %p: slot:%d (%u,%u)\n", hfsmp, i, start, nblocks);
4387 /* Check if any of the blocks in free extent cache are allocated.
4388 * This should not be enabled always because it might take
4389 * very long for large extents that get added to the list.
4391 * We have to drop vcbFreeExtLock while we call hfs_isallocated
4392 * because it is going to do I/O. Note that the free extent
4393 * cache could change. That's a risk we take when using this
4394 * debugging code. (Another alternative would be to try to
4395 * detect when the free extent cache changed, and perhaps
4396 * restart if the list changed while we dropped the lock.)
4398 if (check_allocated
) {
4399 lck_spin_unlock(&hfsmp
->vcbFreeExtLock
);
4400 if (hfs_isallocated(hfsmp
, start
, nblocks
)) {
4401 panic("hfs: %p: slot %d:(%u,%u) in the free extent array is allocated\n",
4402 hfsmp
, i
, start
, nblocks
);
4404 lck_spin_lock(&hfsmp
->vcbFreeExtLock
);
4407 /* Check if any part of the extent is beyond allocLimit */
4408 if ((start
> hfsmp
->allocLimit
) || ((start
+ nblocks
) > hfsmp
->allocLimit
)) {
4409 panic ("hfs: %p: slot %d:(%u,%u) in the free extent array is beyond allocLimit=%u\n",
4410 hfsmp
, i
, start
, nblocks
, hfsmp
->allocLimit
);
4413 /* Check if there are any duplicate start blocks */
4414 for(j
=i
+1; j
< hfsmp
->vcbFreeExtCnt
; j
++) {
4415 if (start
== hfsmp
->vcbFreeExt
[j
].startBlock
) {
4416 panic("hfs: %p: slot %d:(%u,%u) and %d:(%u,%u) are duplicate\n",
4417 hfsmp
, i
, start
, nblocks
, j
, hfsmp
->vcbFreeExt
[j
].startBlock
,
4418 hfsmp
->vcbFreeExt
[j
].blockCount
);
4422 /* Check if the entries are out of order */
4423 if ((i
+1) != hfsmp
->vcbFreeExtCnt
) {
4424 if (hfsmp
->hfs_flags
& HFS_HAS_SPARSE_DEVICE
) {
4425 /* sparse devices are sorted by starting block number (ascending) */
4426 if (hfsmp
->vcbFreeExt
[i
].startBlock
> hfsmp
->vcbFreeExt
[i
+1].startBlock
) {
4427 panic ("hfs: %p: SPARSE %d:(%u,%u) and %d:(%u,%u) are out of order\n",
4428 hfsmp
, i
, start
, nblocks
, i
+1, hfsmp
->vcbFreeExt
[i
+1].startBlock
,
4429 hfsmp
->vcbFreeExt
[i
+1].blockCount
);
4432 /* normally sorted by block count (descending) */
4433 if (hfsmp
->vcbFreeExt
[i
].blockCount
< hfsmp
->vcbFreeExt
[i
+1].blockCount
) {
4434 panic ("hfs: %p: %d:(%u,%u) and %d:(%u,%u) are out of order\n",
4435 hfsmp
, i
, start
, nblocks
, i
+1, hfsmp
->vcbFreeExt
[i
+1].startBlock
,
4436 hfsmp
->vcbFreeExt
[i
+1].blockCount
);
4441 lck_spin_unlock(&hfsmp
->vcbFreeExtLock
);