-/*
-;_______________________________________________________________________
-;
-; Routine: UpdateFree
-; Arguments: vcb -- ExtendedVCB for volume
-;
-; Called By: MountVol
-; Function: This routine is used as part of the MountVol consistency check
-; to figure out the number of free allocation blocks in the volume.
-;
-; Modification History:
-; <08Sep85> LAK New today.
-; <06Oct85> PWD Added explicit check for errors after calls to ReadBM, NextWord
-; Now calls NextBit.
-;_______________________________________________________________________
-*/
-
-OSErr UpdateFreeCount (
- ExtendedVCB *vcb) // Volume whose free block count should be updated
-{
- OSErr err;
- register UInt32 wordsLeft; // Number of words left in this bitmap block
- register UInt32 numBlocks; // Number of blocks left to scan
- register UInt32 freeCount; // Running count of free blocks found so far
- register UInt32 temp;
- UInt32 blockNum; // Block number of first block in this bitmap block
- UInt32 *buffer = NULL; // Pointer to bitmap block
- register UInt32 *currentWord; // Pointer to current word in bitmap block
-
-#if HFSInstrumentation
- InstTraceClassRef trace;
- InstEventTag eventTag;
-
- err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:UpdateFreeCount", 'hfs+', kInstEnableClassMask, &trace);
- if (err != noErr) DebugStr("\pError from InstCreateTraceClass");
-
- eventTag = InstCreateEventTag();
- InstLogTraceEvent( trace, eventTag, kInstStartEvent);
-#endif
-
- //
- // Pre-read the first bitmap block
- //
-
- err = ReadBitmapBlock(vcb, 0, &buffer);
- if (err != noErr) goto Exit;
-
- //
- // Initialize buffer stuff
- //
- currentWord = buffer;
- wordsLeft = kWordsPerBlock;
- numBlocks = vcb->totalBlocks;
- freeCount = 0;
- blockNum = 0;
-
- //
- // Scan whole words first
- //
-
- while (numBlocks >= kBitsPerWord) {
- // See if it's time to move to the next bitmap block
- if (wordsLeft == 0) {
- // Read in the next bitmap block
- blockNum += kBitsPerBlock; // generate a block number in the next bitmap block
-
-#if EXPLICIT_BUFFER_RELEASES
- err = RelBlock_glue((Ptr)buffer, rbDefault);
- if (err != noErr) goto Exit;
- buffer = NULL;
-#endif
- err = ReadBitmapBlock(vcb, blockNum, &buffer);
- if (err != noErr) goto Exit;
-
- // Readjust currentWord, wordsLeft
- currentWord = buffer;
- wordsLeft = kWordsPerBlock;
- }
-
- // We count free blocks by inverting the word in the bitmap and counting set bits.
- temp = ~(*currentWord);
- while (temp) {
- ++freeCount;
- temp &= temp-1; // this clears least significant bit that is currently set
- }
-
- numBlocks -= kBitsPerWord;
- ++currentWord; // move to next word
- --wordsLeft; // one less word left in this block
- }
-
- //
- // Check any remaining blocks.
- //
-
- if (numBlocks != 0) {
- if (wordsLeft == 0) {
- // Read in the next bitmap block
- blockNum += kBitsPerBlock; // generate a block number in the next bitmap block
-
-#if EXPLICIT_BUFFER_RELEASES
- err = RelBlock_glue((Ptr)buffer, rbDefault);
- if (err != noErr) goto Exit;
- buffer = NULL;
-#endif
- err = ReadBitmapBlock(vcb, blockNum, &buffer);
- if (err != noErr) goto Exit;
-
- // Readjust currentWord, wordsLeft
- currentWord = buffer;
- wordsLeft = kWordsPerBlock;
- }
-
- // We count free blocks by inverting the word in the bitmap and counting set bits.
- temp = SWAP_BE32 (~(*currentWord));
- while (numBlocks != 0) {
- if (temp & kHighBitInWordMask)
- ++freeCount;
- temp <<= 1;
- --numBlocks;
- }
- }
-
- VCB_LOCK(vcb);
- vcb->freeBlocks = freeCount;
- VCB_UNLOCK(vcb);
- UpdateVCBFreeBlks( vcb );
-
-Exit:
-
-#if EXPLICIT_BUFFER_RELEASES
- if (buffer) {
- (void)RelBlock_glue((Ptr)buffer, rbDefault); /* Ignore any additional errors */
- };
-#endif
-
-#if HFSInstrumentation
- InstLogTraceEvent( trace, eventTag, kInstEndEvent);
-#endif
-
- return err;
-}
-
-
-
-/*
-;_______________________________________________________________________
-;
-; Routine: AllocateFreeSpace
-; Arguments: vcb -- ExtendedVCB for volume
-;
-; Called By: HFSDiskInitComponent
-; Function: This routine is used as part of DiskInit to create an
-; embedded HFS+ volume.
-;
-; Note: Assumes that the free space is contiguous (true for a freshly erased disk)
-;_______________________________________________________________________
-*/
-
-OSErr AllocateFreeSpace (
- ExtendedVCB *vcb, // Volume whose free space is about to be expropriated
- UInt32 *startBlock, // return where free space starts
- UInt32 *actualBlocks) // return the number of blocks in free space
-{
- OSErr err;
-
- err = BlockAllocateAny(vcb, 0, vcb->totalBlocks, vcb->freeBlocks, startBlock, actualBlocks);
-
- if (err == noErr) {
- VCB_LOCK(vcb);
- vcb->freeBlocks = 0; // sorry, no more blocks left!
- VCB_UNLOCK(vcb);
- MarkVCBDirty(vcb);
- }
-
- return err;
-}
-