/* _______________________________________________________________________ Routine: BlockAllocateContig Function: Allocate a contiguous group of allocation blocks. The allocation is all-or-nothing. The caller guarantees that there are enough free blocks (though they may not be contiguous, in which case this call will fail). Inputs: vcb Pointer to volume where space is to be allocated startingBlock Preferred first block for allocation minBlocks Minimum number of contiguous blocks to allocate maxBlocks Maximum number of contiguous blocks to allocate useMetaZone Outputs: actualStartBlock First block of range allocated, or 0 if error actualNumBlocks Number of blocks allocated, or 0 if error _______________________________________________________________________ */ static OSErr BlockAllocateContig( ExtendedVCB *vcb, u_int32_t startingBlock, u_int32_t minBlocks, u_int32_t maxBlocks, Boolean useMetaZone, u_int32_t *actualStartBlock, u_int32_t *actualNumBlocks) { OSErr err; // // Find a contiguous group of blocks at least minBlocks long. // Determine the number of contiguous blocks available (up // to maxBlocks). // /* * NOTE: If the only contiguous free extent of at least minBlocks * crosses startingBlock (i.e. starts before, ends after), then we * won't find it. Earlier versions *did* find this case by letting * the second search look past startingBlock by minBlocks. But * with the free extent cache, this can lead to duplicate entries * in the cache, causing the same blocks to be allocated twice. */ err = BlockFindContiguous(vcb, startingBlock, vcb->allocLimit, minBlocks, maxBlocks, useMetaZone, actualStartBlock, actualNumBlocks); if (err == dskFulErr && startingBlock != 0) { /* * Constrain the endingBlock so we don't bother looking for ranges * that would overlap those found in the previous call. */ err = BlockFindContiguous(vcb, 1, startingBlock, minBlocks, maxBlocks, useMetaZone, actualStartBlock, actualNumBlocks); } // // Now mark those blocks allocated. // if (err == noErr) err = BlockMarkAllocated(vcb, *actualStartBlock, *actualNumBlocks); return err; }
/* _______________________________________________________________________ Routine: BlockAllocateContig Function: Allocate a contiguous group of allocation blocks. The allocation is all-or-nothing. The caller guarantees that there are enough free blocks (though they may not be contiguous, in which case this call will fail). The function uses on-disk volume bitmap for allocation and updates it with newly allocated blocks. It also updates the in-memory volume bitmap. Inputs: vcb Pointer to volume where space is to be allocated startingBlock Preferred first block for allocation minBlocks Minimum number of contiguous blocks to allocate maxBlocks Maximum number of contiguous blocks to allocate Outputs: actualStartBlock First block of range allocated, or 0 if error actualNumBlocks Number of blocks allocated, or 0 if error _______________________________________________________________________ */ static OSErr BlockAllocateContig( SVCB *vcb, UInt32 startingBlock, UInt32 minBlocks, UInt32 maxBlocks, UInt32 *actualStartBlock, UInt32 *actualNumBlocks) { OSErr err; // // Find a contiguous group of blocks at least minBlocks long. // Determine the number of contiguous blocks available (up // to maxBlocks). // err = BlockFindContiguous(vcb, startingBlock, vcb->vcbTotalBlocks, minBlocks, maxBlocks, actualStartBlock, actualNumBlocks); if (err == dskFulErr) { //ее Should constrain the endingBlock here, so we don't bother looking for ranges //ее that start after startingBlock, since we already checked those. err = BlockFindContiguous(vcb, 0, vcb->vcbTotalBlocks, minBlocks, maxBlocks, actualStartBlock, actualNumBlocks); } if (err != noErr) goto Exit; // // Now mark those blocks allocated. // err = BlockMarkAllocated(vcb, *actualStartBlock, *actualNumBlocks); Exit: if (err != noErr) { *actualStartBlock = 0; *actualNumBlocks = 0; } return err; }