X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..e5568f75972dfc723778653c11cb6b4dc825716a:/bsd/hfs/hfscommon/Misc/FileExtentMapping.c diff --git a/bsd/hfs/hfscommon/Misc/FileExtentMapping.c b/bsd/hfs/hfscommon/Misc/FileExtentMapping.c index 92ae16ad6..6ac3df68d 100644 --- a/bsd/hfs/hfscommon/Misc/FileExtentMapping.c +++ b/bsd/hfs/hfscommon/Misc/FileExtentMapping.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -159,8 +159,6 @@ #include "../headers/BTreesInternal.h" #include "../headers/CatalogPrivate.h" // calling a private catalog routine (LocateCatalogNode) -#include "../headers/HFSInstrumentation.h" - #include /* @@ -239,27 +237,22 @@ Internal Routines: and was in the extents file, then delete the record instead. */ +static const SInt64 kTwoGigabytes = 0x80000000LL; + enum { - kTwoGigabytes = (UInt32) 0x80000000, - kDataForkType = 0, kResourceForkType = 0xFF, - kPreviousRecord = -1, - - kSectorSize = 512 // Size of a physical sector + kPreviousRecord = -1 }; -void HFSToHFSPlusExtents( - const HFSExtentRecord oldExtents, - HFSPlusExtentRecord newExtents); -OSErr HFSPlusToHFSExtents( +static OSErr HFSPlusToHFSExtents( const HFSPlusExtentRecord oldExtents, HFSExtentRecord newExtents); -OSErr FindExtentRecord( +static OSErr FindExtentRecord( const ExtendedVCB *vcb, UInt8 forkType, UInt32 fileID, @@ -269,7 +262,7 @@ OSErr FindExtentRecord( HFSPlusExtentRecord foundData, UInt32 *foundHint); -OSErr DeleteExtentRecord( +static OSErr DeleteExtentRecord( const ExtendedVCB *vcb, UInt8 forkType, UInt32 fileID, @@ -282,7 +275,7 @@ static OSErr CreateExtentRecord( UInt32 *hint); -OSErr GetFCBExtentRecord( +static OSErr GetFCBExtentRecord( const FCB *fcb, HFSPlusExtentRecord extents); @@ -332,14 +325,6 @@ static OSErr UpdateExtentRecord ( const HFSPlusExtentRecord extentData, UInt32 extentBTreeHint); -static OSErr MapFileBlockFromFCB( - const ExtendedVCB *vcb, - const FCB *fcb, - SInt64 offset, // Desired offset in bytes from start of file - UInt32 *firstFABN, // FABN of first block of found extent - UInt32 *firstBlock, // Corresponding allocation block number - UInt32 *nextFABN); // FABN of block after end of extent - static Boolean ExtentsAreIntegral( const HFSPlusExtentRecord extentRecord, UInt32 mask, @@ -368,7 +353,7 @@ static Boolean ExtentsAreIntegral( // fourth entry will be zeroes. // foundHint The BTree hint to find the node again //_________________________________________________________________________________ -OSErr FindExtentRecord( +static OSErr FindExtentRecord( const ExtendedVCB *vcb, UInt8 forkType, UInt32 fileID, @@ -379,22 +364,24 @@ OSErr FindExtentRecord( UInt32 *foundHint) { FCB * fcb; - BTreeIterator btIterator; + BTreeIterator *btIterator; FSBufferDescriptor btRecord; OSErr err; UInt16 btRecordSize; err = noErr; - *foundHint = 0; + if (foundHint) + *foundHint = 0; fcb = GetFileControlBlock(vcb->extentsRefNum); - (void) BTInvalidateHint(&btIterator); + MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK); + bzero(btIterator, sizeof(*btIterator)); if (vcb->vcbSigWord == kHFSSigWord) { HFSExtentKey * extentKeyPtr; HFSExtentRecord extentData; - extentKeyPtr = (HFSExtentKey*) &btIterator.key; + extentKeyPtr = (HFSExtentKey*) &btIterator->key; extentKeyPtr->keyLength = kHFSExtentKeyMaximumLength; extentKeyPtr->forkType = forkType; extentKeyPtr->fileID = fileID; @@ -404,10 +391,10 @@ OSErr FindExtentRecord( btRecord.itemSize = sizeof(HFSExtentRecord); btRecord.itemCount = 1; - err = BTSearchRecord(fcb, &btIterator, kInvalidMRUCacheKey, &btRecord, &btRecordSize, &btIterator); + err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator); if (err == btNotFound && allowPrevious) { - err = BTIterateRecord(fcb, kBTreePrevRecord, &btIterator, &btRecord, &btRecordSize); + err = BTIterateRecord(fcb, kBTreePrevRecord, btIterator, &btRecord, &btRecordSize); // A previous record may not exist, so just return btNotFound (like we would if // it was for the wrong file/fork). @@ -424,14 +411,15 @@ OSErr FindExtentRecord( if (err == noErr) { UInt16 i; - // Copy the found key back for the caller - foundKey->keyLength = kHFSPlusExtentKeyMaximumLength; - foundKey->forkType = extentKeyPtr->forkType; - foundKey->pad = 0; - foundKey->fileID = extentKeyPtr->fileID; - foundKey->startBlock = extentKeyPtr->startBlock; - - // Copy the found data back for the caller + // Copy the found key back for the caller + if (foundKey) { + foundKey->keyLength = kHFSPlusExtentKeyMaximumLength; + foundKey->forkType = extentKeyPtr->forkType; + foundKey->pad = 0; + foundKey->fileID = extentKeyPtr->fileID; + foundKey->startBlock = extentKeyPtr->startBlock; + } + // Copy the found data back for the caller foundData[0].startBlock = extentData[0].startBlock; foundData[0].blockCount = extentData[0].blockCount; foundData[1].startBlock = extentData[1].startBlock; @@ -450,7 +438,7 @@ OSErr FindExtentRecord( HFSPlusExtentKey * extentKeyPtr; HFSPlusExtentRecord extentData; - extentKeyPtr = (HFSPlusExtentKey*) &btIterator.key; + extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key; extentKeyPtr->keyLength = kHFSPlusExtentKeyMaximumLength; extentKeyPtr->forkType = forkType; extentKeyPtr->pad = 0; @@ -461,10 +449,10 @@ OSErr FindExtentRecord( btRecord.itemSize = sizeof(HFSPlusExtentRecord); btRecord.itemCount = 1; - err = BTSearchRecord(fcb, &btIterator, kInvalidMRUCacheKey, &btRecord, &btRecordSize, &btIterator); + err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator); if (err == btNotFound && allowPrevious) { - err = BTIterateRecord(fcb, kBTreePrevRecord, &btIterator, &btRecord, &btRecordSize); + err = BTIterateRecord(fcb, kBTreePrevRecord, btIterator, &btRecord, &btRecordSize); // A previous record may not exist, so just return btNotFound (like we would if // it was for the wrong file/fork). @@ -479,14 +467,17 @@ OSErr FindExtentRecord( } if (err == noErr) { - // Copy the found key back for the caller - BlockMoveData(extentKeyPtr, foundKey, sizeof(HFSPlusExtentKey)); - // Copy the found data back for the caller + // Copy the found key back for the caller + if (foundKey) + BlockMoveData(extentKeyPtr, foundKey, sizeof(HFSPlusExtentKey)); + // Copy the found data back for the caller BlockMoveData(&extentData, foundData, sizeof(HFSPlusExtentRecord)); } } - - *foundHint = btIterator.hint.nodeNum; + + if (foundHint) + *foundHint = btIterator->hint.nodeNum; + FREE(btIterator, M_TEMP); return err; } @@ -498,14 +489,16 @@ static OSErr CreateExtentRecord( HFSPlusExtentRecord extents, UInt32 *hint) { - BTreeIterator btIterator; + BTreeIterator * btIterator; FSBufferDescriptor btRecord; UInt16 btRecordSize; OSErr err; err = noErr; *hint = 0; - (void) BTInvalidateHint(&btIterator); + + MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK); + bzero(btIterator, sizeof(*btIterator)); if (vcb->vcbSigWord == kHFSSigWord) { HFSExtentKey * keyPtr; @@ -516,7 +509,7 @@ static OSErr CreateExtentRecord( btRecord.itemSize = btRecordSize; btRecord.itemCount = 1; - keyPtr = (HFSExtentKey*) &btIterator.key; + keyPtr = (HFSExtentKey*) &btIterator->key; keyPtr->keyLength = kHFSExtentKeyMaximumLength; keyPtr->forkType = key->forkType; keyPtr->fileID = key->fileID; @@ -530,35 +523,40 @@ static OSErr CreateExtentRecord( btRecord.itemSize = btRecordSize; btRecord.itemCount = 1; - BlockMoveData(key, &btIterator.key, sizeof(HFSPlusExtentKey)); + BlockMoveData(key, &btIterator->key, sizeof(HFSPlusExtentKey)); } if (err == noErr) - err = BTInsertRecord(GetFileControlBlock(vcb->extentsRefNum), &btIterator, &btRecord, btRecordSize); + err = BTInsertRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator, &btRecord, btRecordSize); if (err == noErr) - *hint = btIterator.hint.nodeNum; + *hint = btIterator->hint.nodeNum; + (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum)); + + FREE(btIterator, M_TEMP); return err; } -OSErr DeleteExtentRecord( +static OSErr DeleteExtentRecord( const ExtendedVCB *vcb, UInt8 forkType, UInt32 fileID, UInt32 startBlock) { - BTreeIterator btIterator; + BTreeIterator * btIterator; OSErr err; err = noErr; - (void) BTInvalidateHint(&btIterator); + + MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK); + bzero(btIterator, sizeof(*btIterator)); if (vcb->vcbSigWord == kHFSSigWord) { HFSExtentKey * keyPtr; - keyPtr = (HFSExtentKey*) &btIterator.key; + keyPtr = (HFSExtentKey*) &btIterator->key; keyPtr->keyLength = kHFSExtentKeyMaximumLength; keyPtr->forkType = forkType; keyPtr->fileID = fileID; @@ -567,7 +565,7 @@ OSErr DeleteExtentRecord( else { // HFS Plus volume HFSPlusExtentKey * keyPtr; - keyPtr = (HFSPlusExtentKey*) &btIterator.key; + keyPtr = (HFSPlusExtentKey*) &btIterator->key; keyPtr->keyLength = kHFSPlusExtentKeyMaximumLength; keyPtr->forkType = forkType; keyPtr->pad = 0; @@ -575,8 +573,10 @@ OSErr DeleteExtentRecord( keyPtr->startBlock = startBlock; } - err = BTDeleteRecord(GetFileControlBlock(vcb->extentsRefNum), &btIterator); + err = BTDeleteRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator); + (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum)); + FREE(btIterator, M_TEMP); return err; } @@ -604,16 +604,18 @@ OSErr DeleteExtentRecord( // Called By: Log2Phys (read/write in place), Cache (map a file block). //_________________________________________________________________________________ +__private_extern__ OSErr MapFileBlockC ( ExtendedVCB *vcb, // volume that file resides on FCB *fcb, // FCB of file size_t numberOfBytes, // number of contiguous bytes desired off_t offset, // starting offset within file (in bytes) - daddr_t *startSector, // first 512-byte sector (NOT an allocation block) + daddr_t *startSector, // first sector (NOT an allocation block) size_t *availableBytes) // number of contiguous bytes (up to numberOfBytes) { OSErr err; UInt32 allocBlockSize; // Size of the volume's allocation block + UInt32 sectorSize; HFSPlusExtentKey foundKey; HFSPlusExtentRecord foundData; UInt32 foundIndex; @@ -625,25 +627,18 @@ OSErr MapFileBlockC ( UInt32 startBlock; // volume allocation block corresponding to firstFABN daddr_t temp; off_t tmpOff; - - - LogStartTime(kTraceMapFileBlock); allocBlockSize = vcb->blockSize; + sectorSize = VCBTOHFS(vcb)->hfs_phys_block_size; - err = MapFileBlockFromFCB(vcb, fcb, offset, &firstFABN, &startBlock, &nextFABN); - if (err != noErr) { - err = SearchExtentFile(vcb, fcb, offset, &foundKey, foundData, &foundIndex, &hint, &nextFABN); - if (err == noErr) { - startBlock = foundData[foundIndex].startBlock; - firstFABN = nextFABN - foundData[foundIndex].blockCount; - } + err = SearchExtentFile(vcb, fcb, offset, &foundKey, foundData, &foundIndex, &hint, &nextFABN); + if (err == noErr) { + startBlock = foundData[foundIndex].startBlock; + firstFABN = nextFABN - foundData[foundIndex].blockCount; } if (err != noErr) { - LogEndTime(kTraceMapFileBlock, err); - return err; } @@ -651,22 +646,26 @@ OSErr MapFileBlockC ( // Determine the end of the available space. It will either be the end of the extent, // or the file's PEOF, whichever is smaller. // - dataEnd = (off_t)((off_t)(nextFABN) * (off_t)(allocBlockSize)); // Assume valid data through end of this extent - if (fcb->fcbPLen < dataEnd) // Is PEOF shorter? - dataEnd = fcb->fcbPLen; // Yes, so only map up to PEOF + dataEnd = (off_t)((off_t)(nextFABN) * (off_t)(allocBlockSize)); // Assume valid data through end of this extent + if (((off_t)fcb->ff_blocks * (off_t)allocBlockSize) < dataEnd) // Is PEOF shorter? + dataEnd = (off_t)fcb->ff_blocks * (off_t)allocBlockSize; // Yes, so only map up to PEOF // Compute the number of sectors in an allocation block - sectorsPerBlock = allocBlockSize / kSectorSize; // sectors per allocation block + sectorsPerBlock = allocBlockSize / sectorSize; // sectors per allocation block // // Compute the absolute sector number that contains the offset of the given file + // offset in sectors from start of the extent + + // offset in sectors from start of allocation block space // - temp = (daddr_t)((offset - (off_t)((off_t)(firstFABN) * (off_t)(allocBlockSize)))/kSectorSize); // offset in sectors from start of the extent - temp += startBlock * sectorsPerBlock; // offset in sectors from start of allocation block space - if (vcb->vcbSigWord == kHFSPlusSigWord) - temp += vcb->hfsPlusIOPosOffset/512; /* offset inside wrapper */ - else - temp += vcb->vcbAlBlSt; /* offset in sectors from start of volume */ + temp = (daddr_t)((offset - (off_t)((off_t)(firstFABN) * (off_t)(allocBlockSize)))/sectorSize); + temp += startBlock * sectorsPerBlock; + + /* Add in any volume offsets */ + if (vcb->vcbSigWord == kHFSPlusSigWord) + temp += vcb->hfsPlusIOPosOffset / sectorSize; + else + temp += vcb->vcbAlBlSt; // Return the desired sector for file position "offset" *startSector = temp; @@ -675,13 +674,14 @@ OSErr MapFileBlockC ( // Determine the number of contiguous bytes until the end of the extent // (or the amount they asked for, whichever comes first). // - tmpOff = dataEnd - offset; - if (tmpOff > (off_t)(numberOfBytes)) - *availableBytes = numberOfBytes; // more there than they asked for, so pin the output - else - *availableBytes = tmpOff; - LogEndTime(kTraceMapFileBlock, noErr); - + if (availableBytes) + { + tmpOff = dataEnd - offset; + if (tmpOff > (off_t)(numberOfBytes)) + *availableBytes = numberOfBytes; // more there than they asked for, so pin the output + else + *availableBytes = tmpOff; + } return noErr; } @@ -818,6 +818,7 @@ static OSErr DeallocateFork( // Function: Flushes the extent file for a specified volume //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ +__private_extern__ OSErr FlushExtentFile( ExtendedVCB *vcb ) { FCB * fcb; @@ -829,81 +830,16 @@ OSErr FlushExtentFile( ExtendedVCB *vcb ) { // If the FCB for the extent "file" is dirty, mark the VCB as dirty. - if ((fcb->fcbFlags & fcbModifiedMask) != 0) + if (FTOC(fcb)->c_flag & C_MODIFIED) { MarkVCBDirty( vcb ); - err = FlushVolumeControlBlock( vcb ); + // err = FlushVolumeControlBlock( vcb ); } } return( err ); } -//------------------------------------------------------------------------------- -// Routine: DeleteFile -// -// Function: De-allocates all disk space allocated to a specified file -// including the space used by the catalog (ie the catalog record). -// The space occupied by both forks is also deallocated. -// -//------------------------------------------------------------------------------- - -OSErr DeleteFile( ExtendedVCB *vcb, HFSCatalogNodeID parDirID, ConstUTF8Param catalogName, UInt32 catalogHint ) -{ - OSErr err; - OSErr errDF, errRF; - CatalogNodeData catalogData; - Boolean recordDeleted; - - recordDeleted = false; - - INIT_CATALOGDATA(&catalogData, kCatNameNoCopyName); - - // Find catalog data in catalog - err = GetCatalogNode( vcb, parDirID, catalogName, kUndefinedStrLen, catalogHint, &catalogData, &catalogHint); - if( err != noErr ) - goto Exit; - - - // Check to make sure record is for a file - if ( catalogData.cnd_type != kCatalogFileNode ) - { - err = notAFileErr; - goto Exit; - } - - // - // Always delete the Catalog record first (to minimize disk corruption) - // - err = DeleteCatalogNode(vcb, parDirID, catalogName, catalogHint); - if( err != noErr ) - goto Exit; - - // - // Note: we don't report errors from DeallocateFork since the - // file no longer exists (since DeleteCatalogNode succeeded). - // Any errors mean that there are possibly some orphaned disk - // blocks but from the clients perspective the file was deleted. - // - - // Deallocate data fork extents - errDF = DeallocateFork( vcb, catalogData.cnd_nodeID, kDataForkType, - catalogData.cnd_datafork.extents, &recordDeleted ); - - // Deallocate resource fork extents - errRF = DeallocateFork( vcb, catalogData.cnd_nodeID, kResourceForkType, - catalogData.cnd_rsrcfork.extents, &recordDeleted ); - - if (recordDeleted) - err = FlushExtentFile( vcb ); - - CLEAN_CATALOGDATA(&catalogData); - return (errDF ? errDF : (errRF ? errRF : err)); -Exit: - - CLEAN_CATALOGDATA(&catalogData); - return( err ); -} //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ // Routine: CompareExtentKeys @@ -912,6 +848,7 @@ Exit: // an HFS volume. //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ +__private_extern__ SInt32 CompareExtentKeys( const HFSExtentKey *searchKey, const HFSExtentKey *trialKey ) { SInt32 result; // ± 1 @@ -975,6 +912,7 @@ SInt32 CompareExtentKeys( const HFSExtentKey *searchKey, const HFSExtentKey *tri // an HFS volume. //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ +__private_extern__ SInt32 CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusExtentKey *trialKey ) { SInt32 result; // ± 1 @@ -1029,6 +967,72 @@ SInt32 CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusEx return( result ); } +/* + * Add a file extent to a file. + * + * Used by hfs_extendfs to extend the volume allocation bitmap file. + * + */ +__private_extern__ +int +AddFileExtent(ExtendedVCB *vcb, FCB *fcb, UInt32 startBlock, UInt32 blockCount) +{ + HFSPlusExtentKey foundKey; + HFSPlusExtentRecord foundData; + UInt32 foundIndex; + UInt32 hint; + UInt32 nextBlock; + SInt64 peof; + int i; + int error; + + peof = (SInt64)(fcb->ff_blocks + blockCount) * (SInt64)vcb->blockSize; + + error = SearchExtentFile(vcb, fcb, peof-1, &foundKey, foundData, &foundIndex, &hint, &nextBlock); + if (error != fxRangeErr) + return (EBUSY); + + /* + * Add new extent. See if there is room in the current record. + */ + if (foundData[foundIndex].blockCount != 0) + ++foundIndex; + if (foundIndex == kHFSPlusExtentDensity) { + /* + * Existing record is full so create a new one. + */ + foundKey.keyLength = kHFSPlusExtentKeyMaximumLength; + foundKey.forkType = kDataForkType; + foundKey.pad = 0; + foundKey.fileID = FTOC(fcb)->c_fileid; + foundKey.startBlock = nextBlock; + + foundData[0].startBlock = startBlock; + foundData[0].blockCount = blockCount; + + /* zero out remaining extents. */ + for (i = 1; i < kHFSPlusExtentDensity; ++i) { + foundData[i].startBlock = 0; + foundData[i].blockCount = 0; + } + + foundIndex = 0; + + error = CreateExtentRecord(vcb, &foundKey, foundData, &hint); + if (error == fxOvFlErr) + error = dskFulErr; + } else { + /* + * Add a new extent into existing record. + */ + foundData[foundIndex].startBlock = startBlock; + foundData[foundIndex].blockCount = blockCount; + error = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint); + } + (void) FlushExtentFile(vcb); + + return (error); +} //_________________________________________________________________________________ @@ -1056,10 +1060,12 @@ SInt32 CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusEx // Note: ExtendFile updates the PEOF in the FCB. //_________________________________________________________________________________ +__private_extern__ OSErr ExtendFileC ( ExtendedVCB *vcb, // volume that file resides on FCB *fcb, // FCB of file to truncate SInt64 bytesToAdd, // number of bytes to allocate + UInt32 blockHint, // desired starting allocation block UInt32 flags, // EFContig and/or EFAll SInt64 *actualBytesAdded) // number of bytes actually allocated { @@ -1076,36 +1082,22 @@ OSErr ExtendFileC ( Boolean allOrNothing; Boolean forceContig; Boolean wantContig; + Boolean useMetaZone; Boolean needsFlush; UInt32 actualStartBlock; UInt32 actualNumBlocks; UInt32 numExtentsPerRecord; SInt64 maximumBytes; SInt64 peof; - SInt64 previousPEOF; - - -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - InstDataDescriptorRef traceDescriptor; - FSVarsRec *fsVars = (FSVarsRec *) LMGetFSMVars(); - - traceDescriptor = (InstDataDescriptorRef) fsVars->later[2]; + UInt32 prevblocks; - err = InstCreateTraceClass(kInstRootClassRef, "HFS:Extents:ExtendFileC", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif needsFlush = false; *actualBytesAdded = 0; volumeBlockSize = vcb->blockSize; allOrNothing = ((flags & kEFAllMask) != 0); forceContig = ((flags & kEFContigMask) != 0); - previousPEOF = fcb->fcbPLen; + prevblocks = fcb->ff_blocks; if (vcb->vcbSigWord == kHFSPlusSigWord) numExtentsPerRecord = kHFSPlusExtentDensity; @@ -1118,33 +1110,63 @@ OSErr ExtendFileC ( if (vcb->vcbSigWord == kHFSSigWord) { if (bytesToAdd >= kTwoGigabytes) goto Overflow; - if ((fcb->fcbPLen + bytesToAdd) >= kTwoGigabytes) + if ((((SInt64)fcb->ff_blocks * (SInt64)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes) goto Overflow; - } + } // // Determine how many blocks need to be allocated. // Round up the number of desired bytes to add. // - blocksToAdd = FileBytesToBlocks(bytesToAdd, volumeBlockSize); + blocksToAdd = howmany(bytesToAdd, volumeBlockSize); bytesToAdd = (SInt64)((SInt64)blocksToAdd * (SInt64)volumeBlockSize); - + + /* + * For deferred allocations just reserve the blocks. + */ + if ((flags & kEFDeferMask) + && (vcb->vcbSigWord == kHFSPlusSigWord) + && (bytesToAdd < (SInt64)HFS_MAX_DEFERED_ALLOC) + && (blocksToAdd < hfs_freeblks(VCBTOHFS(vcb), 1))) { + fcb->ff_unallocblocks += blocksToAdd; + vcb->loanedBlocks += blocksToAdd; + FTOC(fcb)->c_blocks += blocksToAdd; + fcb->ff_blocks += blocksToAdd; + + FTOC(fcb)->c_flag |= C_MODIFIED | C_FORCEUPDATE; + *actualBytesAdded = bytesToAdd; + return (0); + } + /* + * Give back any unallocated blocks before doing real allocations. + */ + if (fcb->ff_unallocblocks > 0) { + blocksToAdd += fcb->ff_unallocblocks; + bytesToAdd = (SInt64)blocksToAdd * (SInt64)volumeBlockSize; + + vcb->loanedBlocks -= fcb->ff_unallocblocks; + FTOC(fcb)->c_blocks -= fcb->ff_unallocblocks; + fcb->ff_blocks -= fcb->ff_unallocblocks; + fcb->ff_unallocblocks = 0; + } + // // If the file's clump size is larger than the allocation block size, // then set the maximum number of bytes to the requested number of bytes // rounded up to a multiple of the clump size. // - if (fcb->fcbClmpSize > volumeBlockSize) { - maximumBytes = (SInt64)FileBytesToBlocks(bytesToAdd, fcb->fcbClmpSize); - maximumBytes *= fcb->fcbClmpSize; - } - else { + if ((vcb->vcbClpSiz > volumeBlockSize) + && (bytesToAdd < (SInt64)HFS_MAX_DEFERED_ALLOC) + && (flags & kEFNoClumpMask) == 0) { + maximumBytes = (SInt64)howmany(bytesToAdd, vcb->vcbClpSiz); + maximumBytes *= vcb->vcbClpSiz; + } else { maximumBytes = bytesToAdd; } // // Compute new physical EOF, rounded up to a multiple of a block. // - if ((vcb->vcbSigWord == kHFSSigWord) && ((fcb->fcbPLen + bytesToAdd) >= (SInt64) kTwoGigabytes)) // Too big? + if ((vcb->vcbSigWord == kHFSSigWord) && ((((SInt64)fcb->ff_blocks * (SInt64)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes)) // Too big? if (allOrNothing) // Yes, must they have it all? goto Overflow; // Yes, can't have it else { @@ -1156,7 +1178,8 @@ OSErr ExtendFileC ( // If allocation is all-or-nothing, make sure there are // enough free blocks on the volume (quick test). // - if (allOrNothing && (blocksToAdd > (SInt64)vcb->freeBlocks)) { + if (allOrNothing && + (blocksToAdd > hfs_freeblks(VCBTOHFS(vcb), flags & kEFReserveMask))) { err = dskFulErr; goto ErrorExit; } @@ -1164,13 +1187,13 @@ OSErr ExtendFileC ( // // See if there are already enough blocks allocated to the file. // - peof = fcb->fcbPLen + bytesToAdd; // potential new PEOF + peof = ((SInt64)fcb->ff_blocks * (SInt64)volumeBlockSize) + bytesToAdd; // potential new PEOF err = SearchExtentFile(vcb, fcb, peof-1, &foundKey, foundData, &foundIndex, &hint, &nextBlock); if (err == noErr) { // Enough blocks are already allocated. Just update the FCB to reflect the new length. - fcb->fcbPLen = peof; - H_EXTENDSIZE(fcb, bytesToAdd); - fcb->fcbFlags |= fcbModifiedMask; + fcb->ff_blocks = peof / volumeBlockSize; + FTOC(fcb)->c_blocks += (bytesToAdd / volumeBlockSize); + FTOC(fcb)->c_flag |= C_MODIFIED | C_FORCEUPDATE; goto Exit; } if (err != fxRangeErr) // Any real error? @@ -1180,11 +1203,11 @@ OSErr ExtendFileC ( // Adjust the PEOF to the end of the last extent. // peof = (SInt64)((SInt64)nextBlock * (SInt64)volumeBlockSize); // currently allocated PEOF - bytesThisExtent = peof - fcb->fcbPLen; + bytesThisExtent = (SInt64)(nextBlock - fcb->ff_blocks) * (SInt64)volumeBlockSize; if (bytesThisExtent != 0) { - fcb->fcbPLen = peof; - H_EXTENDSIZE(fcb, bytesThisExtent); - fcb->fcbFlags |= fcbModifiedMask; + fcb->ff_blocks = nextBlock; + FTOC(fcb)->c_blocks += (bytesThisExtent / volumeBlockSize); + FTOC(fcb)->c_flag |= C_MODIFIED; bytesToAdd -= bytesThisExtent; } @@ -1197,9 +1220,45 @@ OSErr ExtendFileC ( // else, keep getting bits and pieces (non-contig) err = noErr; wantContig = true; + useMetaZone = flags & kEFMetadataMask; + vcb->vcbFreeExtCnt = 0; /* For now, force rebuild of free extent list */ do { - startBlock = foundData[foundIndex].startBlock + foundData[foundIndex].blockCount; - err = BlockAllocate(vcb, startBlock, bytesToAdd, maximumBytes, wantContig, &actualStartBlock, &actualNumBlocks); + if (blockHint != 0) + startBlock = blockHint; + else + startBlock = foundData[foundIndex].startBlock + foundData[foundIndex].blockCount; + + /* Force reserve checking if requested. */ + if (flags & kEFReserveMask) { + SInt64 availbytes; + + actualNumBlocks = 0; + actualStartBlock = 0; + + availbytes = (SInt64)hfs_freeblks(VCBTOHFS(vcb), 1) * + (SInt64)volumeBlockSize; + if (availbytes <= 0) { + err = dskFulErr; + } else { + if (wantContig && (availbytes < bytesToAdd)) + err = dskFulErr; + else { + err = BlockAllocate( + vcb, + startBlock, + howmany(MIN(bytesToAdd, availbytes), volumeBlockSize), + howmany(MIN(maximumBytes, availbytes), volumeBlockSize), + wantContig, + useMetaZone, + &actualStartBlock, + &actualNumBlocks); + } + } + } else { + err = BlockAllocate(vcb, startBlock, howmany(bytesToAdd, volumeBlockSize), + howmany(maximumBytes, volumeBlockSize), wantContig, useMetaZone, + &actualStartBlock, &actualNumBlocks); + } if (err == dskFulErr) { if (forceContig) break; // AllocContig failed because not enough contiguous space @@ -1211,28 +1270,22 @@ OSErr ExtendFileC ( } if (actualNumBlocks != 0) err = noErr; + if (useMetaZone == 0) { + /* Couldn't get anything so dip into metadat zone */ + err = noErr; + useMetaZone = 1; + continue; + } } if (err == noErr) { -#if HFSInstrumentation - { - struct { - UInt32 fileID; - UInt32 start; - UInt32 count; - UInt32 fabn; - } x; - - x.fileID = H_FILEID(fcb); - x.start = actualStartBlock; - x.count = actualNumBlocks; - x.fabn = nextBlock; - - InstLogTraceEventWithDataStructure( trace, eventTag, kInstMiddleEvent, traceDescriptor, - (UInt8 *) &x, sizeof(x)); + if (actualNumBlocks != 0) { + // this catalog entry *must* get forced to disk when + // hfs_update() is called + FTOC(fcb)->c_flag |= C_FORCEUPDATE; } -#endif + // Add the new extent to the existing extent record, or create a new one. - if (actualStartBlock == startBlock) { + if ((actualStartBlock == startBlock) && (blockHint == 0)) { // We grew the file's last extent, so just adjust the number of blocks. foundData[foundIndex].blockCount += actualNumBlocks; err = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint); @@ -1246,18 +1299,19 @@ OSErr ExtendFileC ( ++foundIndex; // No, so use the next one. if (foundIndex == numExtentsPerRecord) { // This record is full. Need to create a new one. - if (H_FILEID(fcb) == kHFSExtentsFileID) { - err = fxOvFlErr; // Oops. Can't extend extents file (?? really ??) + if (FTOC(fcb)->c_fileid == kHFSExtentsFileID) { + (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks); + err = dskFulErr; // Oops. Can't extend extents file past first record. break; } foundKey.keyLength = kHFSPlusExtentKeyMaximumLength; - if (fcb->fcbFlags & fcbResourceMask) + if (FORK_IS_RSRC(fcb)) foundKey.forkType = kResourceForkType; else foundKey.forkType = kDataForkType; foundKey.pad = 0; - foundKey.fileID = H_FILEID(fcb); + foundKey.fileID = FTOC(fcb)->c_fileid; foundKey.startBlock = nextBlock; foundData[0].startBlock = actualStartBlock; @@ -1305,9 +1359,9 @@ OSErr ExtendFileC ( bytesToAdd -= bytesThisExtent; maximumBytes -= bytesThisExtent; } - fcb->fcbPLen += bytesThisExtent; - H_EXTENDSIZE(fcb, bytesThisExtent); - fcb->fcbFlags |= fcbModifiedMask; + fcb->ff_blocks += (bytesThisExtent / volumeBlockSize); + FTOC(fcb)->c_blocks += (bytesThisExtent / volumeBlockSize); + FTOC(fcb)->c_flag |= C_MODIFIED | C_FORCEUPDATE; // If contiguous allocation was requested, then we've already got one contiguous // chunk. If we didn't get all we wanted, then adjust the error to disk full. @@ -1321,15 +1375,18 @@ OSErr ExtendFileC ( ErrorExit: Exit: - *actualBytesAdded = fcb->fcbPLen - previousPEOF; + if (VCBTOHFS(vcb)->hfs_flags & HFS_METADATA_ZONE) { + /* Keep the roving allocator out of the metadata zone. */ + if (vcb->nextAllocation >= VCBTOHFS(vcb)->hfs_metazone_start && + vcb->nextAllocation <= VCBTOHFS(vcb)->hfs_metazone_end) { + vcb->nextAllocation = VCBTOHFS(vcb)->hfs_metazone_end + 1; + } + } + *actualBytesAdded = (SInt64)(fcb->ff_blocks - prevblocks) * (SInt64)volumeBlockSize; if (needsFlush) (void) FlushExtentFile(vcb); -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - return err; Overflow: @@ -1362,6 +1419,7 @@ Overflow: // Note: TruncateFile updates the PEOF in the FCB. //_________________________________________________________________________________ +__private_extern__ OSErr TruncateFileC ( ExtendedVCB *vcb, // volume that file resides on FCB *fcb, // FCB of file to truncate @@ -1384,20 +1442,6 @@ OSErr TruncateFileC ( Boolean extentChanged; // true if we actually changed an extent Boolean recordDeleted; // true if an extent record got deleted -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - InstDataDescriptorRef traceDescriptor; - FSVarsRec *fsVars = (FSVarsRec *) LMGetFSMVars(); - - traceDescriptor = (InstDataDescriptorRef) fsVars->later[2]; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:Extents:TruncateFileC", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif recordDeleted = false; @@ -1406,12 +1450,12 @@ OSErr TruncateFileC ( else numExtentsPerRecord = kHFSExtentDensity; - if (fcb->fcbFlags & fcbResourceMask) + if (FORK_IS_RSRC(fcb)) forkType = kResourceForkType; else forkType = kDataForkType; - temp64 = fcb->fcbPLen / (SInt64)vcb->blockSize; // number of allocation blocks currently in file + temp64 = fcb->ff_blocks; physNumBlocks = (UInt32)temp64; // @@ -1419,9 +1463,9 @@ OSErr TruncateFileC ( // two gigabytes or more, then round down by one allocation block (??? really? // shouldn't that be an error?). // - nextBlock = FileBytesToBlocks(peof, vcb->blockSize); // number of allocation blocks to remain in file + nextBlock = howmany(peof, vcb->blockSize); // number of allocation blocks to remain in file peof = (SInt64)((SInt64)nextBlock * (SInt64)vcb->blockSize); // number of bytes in those blocks - if ((vcb->vcbSigWord == kHFSSigWord) && (peof >= (UInt32) kTwoGigabytes)) { + if ((vcb->vcbSigWord == kHFSSigWord) && (peof >= kTwoGigabytes)) { #if DEBUG_BUILD DebugStr("\pHFS: Trying to truncate a file to 2GB or more"); #endif @@ -1432,9 +1476,16 @@ OSErr TruncateFileC ( // // Update FCB's length // - H_TRUNCSIZE(fcb, fcb->fcbPLen - peof); - fcb->fcbPLen = peof; - fcb->fcbFlags |= fcbModifiedMask; + /* + * XXX Any errors could cause ff_blocks and c_blocks to get out of sync... + */ + numBlocks = peof / vcb->blockSize; + FTOC(fcb)->c_blocks -= (fcb->ff_blocks - numBlocks); + fcb->ff_blocks = numBlocks; + + // this catalog entry is modified and *must* get forced + // to disk when hfs_update() is called + FTOC(fcb)->c_flag |= C_MODIFIED | C_FORCEUPDATE; // // If the new PEOF is 0, then truncateToExtent has no meaning (we should always deallocate @@ -1444,7 +1495,7 @@ OSErr TruncateFileC ( int i; // Deallocate all the extents for this fork - err = DeallocateFork(vcb, H_FILEID(fcb), forkType, fcb->fcbExtents, &recordDeleted); + err = DeallocateFork(vcb, FTOC(fcb)->c_fileid, forkType, fcb->fcbExtents, &recordDeleted); if (err != noErr) goto ErrorExit; // got some error, so return it // Update the catalog extent record (making sure it's zeroed out) @@ -1530,7 +1581,7 @@ OSErr TruncateFileC ( // blocks. // if (nextBlock < physNumBlocks) - err = TruncateExtents(vcb, forkType, H_FILEID(fcb), nextBlock, &recordDeleted); + err = TruncateExtents(vcb, forkType, FTOC(fcb)->c_fileid, nextBlock, &recordDeleted); Done: ErrorExit: @@ -1538,14 +1589,151 @@ ErrorExit: if (recordDeleted) (void) FlushExtentFile(vcb); -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - return err; } +/* + * HFS Plus only + * + */ +__private_extern__ +OSErr HeadTruncateFile ( + ExtendedVCB *vcb, + FCB *fcb, + UInt32 headblks) +{ + HFSPlusExtentRecord extents; + HFSPlusExtentRecord tailExtents; + HFSCatalogNodeID fileID; + UInt8 forkType; + UInt32 blkcnt; + UInt32 startblk; + UInt32 blksfreed; + int i, j; + int error; + + + if (vcb->vcbSigWord != kHFSPlusSigWord) + return (-1); + + forkType = FORK_IS_RSRC(fcb) ? kResourceForkType : kDataForkType; + fileID = FTOC(fcb)->c_fileid; + bzero(tailExtents, sizeof(tailExtents)); + + blksfreed = 0; + startblk = 0; + + /* + * Process catalog resident extents + */ + for (i = 0, j = 0; i < kHFSPlusExtentDensity; ++i) { + blkcnt = fcb->fcbExtents[i].blockCount; + if (blkcnt == 0) + break; /* end of extents */ + + if (blksfreed < headblks) { + error = BlockDeallocate(vcb, fcb->fcbExtents[i].startBlock, blkcnt); + /* + * Any errors after the first BlockDeallocate + * must be ignored so we can put the file in + * a known state. + */ + if (error ) { + if (i == 0) + goto ErrorExit; /* uh oh */ + else { + error = 0; + printf("HeadTruncateFile: problems deallocating %s (%d)\n", + FTOC(fcb)->c_desc.cd_nameptr ? FTOC(fcb)->c_desc.cd_nameptr : "", error); + } + } + + blksfreed += blkcnt; + fcb->fcbExtents[i].startBlock = 0; + fcb->fcbExtents[i].blockCount = 0; + } else { + tailExtents[j].startBlock = fcb->fcbExtents[i].startBlock; + tailExtents[j].blockCount = blkcnt; + ++j; + } + startblk += blkcnt; + } + + if (blkcnt == 0) + goto CopyExtents; + + /* + * Process overflow extents + */ + for (;;) { + UInt32 extblks; + + error = FindExtentRecord(vcb, forkType, fileID, startblk, false, NULL, extents, NULL); + if (error) { + /* + * Any errors after the first BlockDeallocate + * must be ignored so we can put the file in + * a known state. + */ + if (error != btNotFound) + printf("HeadTruncateFile: problems finding extents %s (%d)\n", + FTOC(fcb)->c_desc.cd_nameptr ? FTOC(fcb)->c_desc.cd_nameptr : "", error); + error = 0; + break; + } + + for(i = 0, extblks = 0; i < kHFSPlusExtentDensity; ++i) { + blkcnt = extents[i].blockCount; + if (blkcnt == 0) + break; /* end of extents */ + + if (blksfreed < headblks) { + error = BlockDeallocate(vcb, extents[i].startBlock, blkcnt); + if (error) { + printf("HeadTruncateFile: problems deallocating %s (%d)\n", + FTOC(fcb)->c_desc.cd_nameptr ? FTOC(fcb)->c_desc.cd_nameptr : "", error); + error = 0; + } + blksfreed += blkcnt; + } else { + tailExtents[j].startBlock = extents[i].startBlock; + tailExtents[j].blockCount = blkcnt; + ++j; + } + extblks += blkcnt; + } + + error = DeleteExtentRecord(vcb, forkType, fileID, startblk); + if (error) { + printf("HeadTruncateFile: problems deallocating %s (%d)\n", + FTOC(fcb)->c_desc.cd_nameptr ? FTOC(fcb)->c_desc.cd_nameptr : "", error); + error = 0; + } + + if (blkcnt == 0) + break; /* all done */ + + startblk += extblks; + } + +CopyExtents: + if (blksfreed) { + bcopy(tailExtents, fcb->fcbExtents, sizeof(tailExtents)); + blkcnt = fcb->ff_blocks - headblks; + FTOC(fcb)->c_blocks -= blkcnt; + fcb->ff_blocks = blkcnt; + + FTOC(fcb)->c_flag |= C_CHANGE | C_FORCEUPDATE; + + (void) FlushExtentFile(vcb); + } + +ErrorExit: + return MacToVFSError(error); +} + + //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ // Routine: SearchExtentRecord (was XRSearch) @@ -1716,8 +1904,8 @@ static OSErr SearchExtentFile( // // Find the desired record, or the previous record if it is the same fork // - err = FindExtentRecord(vcb, (fcb->fcbFlags & fcbResourceMask) ? kResourceForkType : kDataForkType, - H_FILEID(fcb), filePositionBlock, true, foundExtentKey, foundExtentData, extentBTreeHint); + err = FindExtentRecord(vcb, FORK_IS_RSRC(fcb) ? kResourceForkType : kDataForkType, + FTOC(fcb)->c_fileid, filePositionBlock, true, foundExtentKey, foundExtentData, extentBTreeHint); if (err == btNotFound) { // @@ -1776,68 +1964,73 @@ static OSErr UpdateExtentRecord ( const HFSPlusExtentRecord extentData, UInt32 extentBTreeHint) { - BTreeIterator btIterator; - FSBufferDescriptor btRecord; - UInt16 btRecordSize; - FCB * btFCB; - OSErr err = noErr; + OSErr err = noErr; if (extentFileKey->keyLength == 0) { // keyLength == 0 means the FCB's extent record BlockMoveData(extentData, fcb->fcbExtents, sizeof(HFSPlusExtentRecord)); - fcb->fcbFlags |= fcbModifiedMask; + FTOC(fcb)->c_flag |= C_MODIFIED; } else { + BTreeIterator * btIterator; + FSBufferDescriptor btRecord; + UInt16 btRecordSize; + FCB * btFCB; + // // Need to find and change a record in Extents BTree // btFCB = GetFileControlBlock(vcb->extentsRefNum); + MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK); + bzero(btIterator, sizeof(*btIterator)); + if (vcb->vcbSigWord == kHFSSigWord) { HFSExtentKey * key; // Actual extent key used on disk in HFS HFSExtentRecord foundData; // The extent data actually found - key = (HFSExtentKey*) &btIterator.key; + key = (HFSExtentKey*) &btIterator->key; key->keyLength = kHFSExtentKeyMaximumLength; key->forkType = extentFileKey->forkType; key->fileID = extentFileKey->fileID; key->startBlock = extentFileKey->startBlock; - btIterator.hint.index = 0; - btIterator.hint.nodeNum = extentBTreeHint; + btIterator->hint.index = 0; + btIterator->hint.nodeNum = extentBTreeHint; btRecord.bufferAddress = &foundData; btRecord.itemSize = sizeof(HFSExtentRecord); btRecord.itemCount = 1; - err = BTSearchRecord(btFCB, &btIterator, kInvalidMRUCacheKey, &btRecord, - &btRecordSize, &btIterator); + err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator); if (err == noErr) err = HFSPlusToHFSExtents(extentData, (HFSExtentDescriptor *)&foundData); if (err == noErr) - err = BTReplaceRecord(btFCB, &btIterator, &btRecord, btRecordSize); + err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize); + (void) BTFlushPath(btFCB); } else { // HFS Plus volume HFSPlusExtentRecord foundData; // The extent data actually found - BlockMoveData(extentFileKey, &btIterator.key, sizeof(HFSPlusExtentKey)); + BlockMoveData(extentFileKey, &btIterator->key, sizeof(HFSPlusExtentKey)); - btIterator.hint.index = 0; - btIterator.hint.nodeNum = extentBTreeHint; + btIterator->hint.index = 0; + btIterator->hint.nodeNum = extentBTreeHint; btRecord.bufferAddress = &foundData; btRecord.itemSize = sizeof(HFSPlusExtentRecord); btRecord.itemCount = 1; - err = BTSearchRecord(btFCB, &btIterator, kInvalidMRUCacheKey, &btRecord, - &btRecordSize, &btIterator); + err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator); if (err == noErr) { BlockMoveData(extentData, &foundData, sizeof(HFSPlusExtentRecord)); - err = BTReplaceRecord(btFCB, &btIterator, &btRecord, btRecordSize); + err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize); } + (void) BTFlushPath(btFCB); } + FREE(btIterator, M_TEMP); } return err; @@ -1845,31 +2038,8 @@ static OSErr UpdateExtentRecord ( -void HFSToHFSPlusExtents( - const HFSExtentRecord oldExtents, - HFSPlusExtentRecord newExtents) -{ - UInt32 i; - - // copy the first 3 extents - newExtents[0].startBlock = oldExtents[0].startBlock; - newExtents[0].blockCount = oldExtents[0].blockCount; - newExtents[1].startBlock = oldExtents[1].startBlock; - newExtents[1].blockCount = oldExtents[1].blockCount; - newExtents[2].startBlock = oldExtents[2].startBlock; - newExtents[2].blockCount = oldExtents[2].blockCount; - - // zero out the remaining ones - for (i = 3; i < kHFSPlusExtentDensity; ++i) - { - newExtents[i].startBlock = 0; - newExtents[i].blockCount = 0; - } -} - - -OSErr HFSPlusToHFSExtents( +static OSErr HFSPlusToHFSExtents( const HFSPlusExtentRecord oldExtents, HFSExtentRecord newExtents) { @@ -1898,7 +2068,7 @@ OSErr HFSPlusToHFSExtents( -OSErr GetFCBExtentRecord( +static OSErr GetFCBExtentRecord( const FCB *fcb, HFSPlusExtentRecord extents) { @@ -1909,104 +2079,6 @@ OSErr GetFCBExtentRecord( } - -//ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ -// Routine: MapFileBlockFromFCB -// -// Function: Determine if the given file offset is within the set of extents -// stored in the FCB. If so, return the file allocation -// block number of the start of the extent, volume allocation block number -// of the start of the extent, and file allocation block number immediately -// following the extent. -// -// Input: vcb - the volume containing the extents -// fcb - the file that owns the extents -// offset - desired offset in bytes -// -// Output: firstFABN - file alloc block number of start of extent -// firstBlock - volume alloc block number of start of extent -// nextFABN - file alloc block number of next extent -// -// Result: noErr = ok -// fxRangeErr = beyond FCB's extents -//ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ -static OSErr MapFileBlockFromFCB( - const ExtendedVCB *vcb, - const FCB *fcb, - SInt64 offset, // Desired offset in bytes from start of file - UInt32 *firstFABN, // FABN of first block of found extent - UInt32 *firstBlock, // Corresponding allocation block number - UInt32 *nextFABN) // FABN of block after end of extent -{ - UInt32 index; - UInt32 offsetBlocks; - SInt64 temp64; - - temp64 = offset / (SInt64)vcb->blockSize; - offsetBlocks = (UInt32)temp64; - - if (vcb->vcbSigWord == kHFSSigWord) { - /* XXX SER Do we need to test for overflow values ??? */ - UInt16 blockCount; - UInt16 currentFABN; - - currentFABN = 0; - - for (index=0; indexfcbExtents[index].blockCount; - - if (blockCount == 0) - return fxRangeErr; // ran out of extents! - - // Is it in this extent? - if (offsetBlocks < blockCount) { - *firstFABN = currentFABN; - *firstBlock = fcb->fcbExtents[index].startBlock; - currentFABN += blockCount; // faster to add these as UInt16 first, then extend to UInt32 - *nextFABN = currentFABN; - return noErr; // found the right extent - } - - // Not in current extent, so adjust counters and loop again - offsetBlocks -= blockCount; - currentFABN += blockCount; - } - } - else { - UInt32 blockCount; - UInt32 currentFABN; - - currentFABN = 0; - - for (index=0; indexfcbExtents[index].blockCount; - - if (blockCount == 0) - return fxRangeErr; // ran out of extents! - - // Is it in this extent? - if (offsetBlocks < blockCount) { - *firstFABN = currentFABN; - *firstBlock = fcb->fcbExtents[index].startBlock; - *nextFABN = currentFABN + blockCount; - return noErr; // found the right extent - } - - // Not in current extent, so adjust counters and loop again - offsetBlocks -= blockCount; - currentFABN += blockCount; - } - } - - // If we fall through here, the extent record was full, but the offset was - // beyond those extents. - - return fxRangeErr; -} - - //_________________________________________________________________________________ // // Routine: ExtentsAreIntegral @@ -2055,6 +2127,7 @@ static Boolean ExtentsAreIntegral( // Called by BTOpenPath during volume mount //_________________________________________________________________________________ +__private_extern__ Boolean NodesAreContiguous( ExtendedVCB *vcb, FCB *fcb, @@ -2080,7 +2153,7 @@ Boolean NodesAreContiguous( if ( !ExtentsAreIntegral(extents, mask, &blocksChecked, &lastExtentReached) ) return FALSE; - if (lastExtentReached || (SInt64)((SInt64)blocksChecked * (SInt64)vcb->blockSize) >= fcb->fcbPLen) + if (lastExtentReached || (SInt64)((SInt64)blocksChecked * (SInt64)vcb->blockSize) >= fcb->ff_size) return TRUE; startBlock = blocksChecked; @@ -2088,7 +2161,7 @@ Boolean NodesAreContiguous( // check the overflow extents (if any) while ( !lastExtentReached ) { - result = FindExtentRecord(vcb, kDataForkType, H_FILEID(fcb), startBlock, FALSE, &key, extents, &hint); + result = FindExtentRecord(vcb, kDataForkType, fcb->ff_cp->c_fileid, startBlock, FALSE, &key, extents, &hint); if (result) break; if ( !ExtentsAreIntegral(extents, mask, &blocksChecked, &lastExtentReached) )