X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/bd504ef0e0b883cdd7917b73b3574eb9ce669905..39236c6e673c41db228275375ab7fdb0f837b292:/bsd/hfs/hfscommon/Misc/FileExtentMapping.c diff --git a/bsd/hfs/hfscommon/Misc/FileExtentMapping.c b/bsd/hfs/hfscommon/Misc/FileExtentMapping.c index cae3db8e2..6d6c228d9 100644 --- a/bsd/hfs/hfscommon/Misc/FileExtentMapping.c +++ b/bsd/hfs/hfscommon/Misc/FileExtentMapping.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -108,9 +108,11 @@ enum }; +#if CONFIG_HFS_STD static OSErr HFSPlusToHFSExtents( const HFSPlusExtentRecord oldExtents, HFSExtentRecord newExtents); +#endif static OSErr FindExtentRecord( const ExtendedVCB *vcb, @@ -241,18 +243,20 @@ static OSErr FindExtentRecord( } bzero(btIterator, sizeof(*btIterator)); - if (vcb->vcbSigWord == kHFSSigWord) { - HFSExtentKey * extentKeyPtr; - HFSExtentRecord extentData; + /* HFS Plus / HFSX */ + if (vcb->vcbSigWord != kHFSSigWord) { + HFSPlusExtentKey * extentKeyPtr; + HFSPlusExtentRecord extentData; - extentKeyPtr = (HFSExtentKey*) &btIterator->key; - extentKeyPtr->keyLength = kHFSExtentKeyMaximumLength; - extentKeyPtr->forkType = forkType; - extentKeyPtr->fileID = fileID; + extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key; + extentKeyPtr->keyLength = kHFSPlusExtentKeyMaximumLength; + extentKeyPtr->forkType = forkType; + extentKeyPtr->pad = 0; + extentKeyPtr->fileID = fileID; extentKeyPtr->startBlock = startBlock; btRecord.bufferAddress = &extentData; - btRecord.itemSize = sizeof(HFSExtentRecord); + btRecord.itemSize = sizeof(HFSPlusExtentRecord); btRecord.itemCount = 1; err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator); @@ -273,44 +277,26 @@ static OSErr FindExtentRecord( } if (err == noErr) { - u_int16_t i; - // 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; - } + if (foundKey) + BlockMoveData(extentKeyPtr, foundKey, sizeof(HFSPlusExtentKey)); // 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; - foundData[1].blockCount = extentData[1].blockCount; - foundData[2].startBlock = extentData[2].startBlock; - foundData[2].blockCount = extentData[2].blockCount; - - for (i = 3; i < kHFSPlusExtentDensity; ++i) - { - foundData[i].startBlock = 0; - foundData[i].blockCount = 0; - } + BlockMoveData(&extentData, foundData, sizeof(HFSPlusExtentRecord)); } } - else { // HFS Plus volume - HFSPlusExtentKey * extentKeyPtr; - HFSPlusExtentRecord extentData; +#if CONFIG_HFS_STD + else { + HFSExtentKey * extentKeyPtr; + HFSExtentRecord extentData; - extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key; - extentKeyPtr->keyLength = kHFSPlusExtentKeyMaximumLength; - extentKeyPtr->forkType = forkType; - extentKeyPtr->pad = 0; - extentKeyPtr->fileID = fileID; + extentKeyPtr = (HFSExtentKey*) &btIterator->key; + extentKeyPtr->keyLength = kHFSExtentKeyMaximumLength; + extentKeyPtr->forkType = forkType; + extentKeyPtr->fileID = fileID; extentKeyPtr->startBlock = startBlock; btRecord.bufferAddress = &extentData; - btRecord.itemSize = sizeof(HFSPlusExtentRecord); + btRecord.itemSize = sizeof(HFSExtentRecord); btRecord.itemCount = 1; err = BTSearchRecord(fcb, btIterator, &btRecord, &btRecordSize, btIterator); @@ -331,13 +317,32 @@ static OSErr FindExtentRecord( } if (err == noErr) { + u_int16_t i; + // Copy the found key back for the caller - if (foundKey) - BlockMoveData(extentKeyPtr, foundKey, sizeof(HFSPlusExtentKey)); + 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 - BlockMoveData(&extentData, foundData, sizeof(HFSPlusExtentRecord)); + foundData[0].startBlock = extentData[0].startBlock; + foundData[0].blockCount = extentData[0].blockCount; + foundData[1].startBlock = extentData[1].startBlock; + foundData[1].blockCount = extentData[1].blockCount; + foundData[2].startBlock = extentData[2].startBlock; + foundData[2].blockCount = extentData[2].blockCount; + + for (i = 3; i < kHFSPlusExtentDensity; ++i) + { + foundData[i].startBlock = 0; + foundData[i].blockCount = 0; + } } } +#endif if (foundHint) *foundHint = btIterator->hint.nodeNum; @@ -378,7 +383,18 @@ static OSErr CreateExtentRecord( */ lockflags = hfs_systemfile_lock(vcb, SFL_EXTENTS, HFS_EXCLUSIVE_LOCK); - if (vcb->vcbSigWord == kHFSSigWord) { + /* HFS+/HFSX */ + if (vcb->vcbSigWord != kHFSSigWord) { + btRecordSize = sizeof(HFSPlusExtentRecord); + btRecord.bufferAddress = extents; + btRecord.itemSize = btRecordSize; + btRecord.itemCount = 1; + + BlockMoveData(key, &btIterator->key, sizeof(HFSPlusExtentKey)); + } +#if CONFIG_HFS_STD + else { + /* HFS Standard */ HFSExtentKey * keyPtr; HFSExtentRecord data; @@ -395,14 +411,7 @@ static OSErr CreateExtentRecord( err = HFSPlusToHFSExtents(extents, data); } - else { // HFS Plus volume - btRecordSize = sizeof(HFSPlusExtentRecord); - btRecord.bufferAddress = extents; - btRecord.itemSize = btRecordSize; - btRecord.itemCount = 1; - - BlockMoveData(key, &btIterator->key, sizeof(HFSPlusExtentKey)); - } +#endif if (err == noErr) err = BTInsertRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator, &btRecord, btRecordSize); @@ -436,25 +445,29 @@ static OSErr DeleteExtentRecord( } bzero(btIterator, sizeof(*btIterator)); - if (vcb->vcbSigWord == kHFSSigWord) { - HFSExtentKey * keyPtr; + /* HFS+ / HFSX */ + if (vcb->vcbSigWord != kHFSSigWord) { // HFS Plus volume + HFSPlusExtentKey * keyPtr; - keyPtr = (HFSExtentKey*) &btIterator->key; - keyPtr->keyLength = kHFSExtentKeyMaximumLength; + keyPtr = (HFSPlusExtentKey*) &btIterator->key; + keyPtr->keyLength = kHFSPlusExtentKeyMaximumLength; keyPtr->forkType = forkType; + keyPtr->pad = 0; keyPtr->fileID = fileID; keyPtr->startBlock = startBlock; } - else { // HFS Plus volume - HFSPlusExtentKey * keyPtr; +#if CONFIG_HFS_STD + else { + /* HFS standard */ + HFSExtentKey * keyPtr; - keyPtr = (HFSPlusExtentKey*) &btIterator->key; - keyPtr->keyLength = kHFSPlusExtentKeyMaximumLength; + keyPtr = (HFSExtentKey*) &btIterator->key; + keyPtr->keyLength = kHFSExtentKeyMaximumLength; keyPtr->forkType = forkType; - keyPtr->pad = 0; keyPtr->fileID = fileID; keyPtr->startBlock = startBlock; } +#endif err = BTDeleteRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator); (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum)); @@ -735,6 +748,7 @@ OSErr FlushExtentFile( ExtendedVCB *vcb ) } +#if CONFIG_HFS_STD //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ // Routine: CompareExtentKeys // @@ -796,7 +810,7 @@ int32_t CompareExtentKeys( const HFSExtentKey *searchKey, const HFSExtentKey *tr return( result ); } - +#endif //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ @@ -959,6 +973,7 @@ OSErr ExtendFileC ( Boolean wantContig; Boolean useMetaZone; Boolean needsFlush; + int allowFlushTxns; u_int32_t actualStartBlock; u_int32_t actualNumBlocks; u_int32_t numExtentsPerRecord; @@ -966,8 +981,8 @@ OSErr ExtendFileC ( int64_t availbytes; int64_t peof; u_int32_t prevblocks; - - + struct hfsmount *hfsmp = (struct hfsmount*)vcb; + allowFlushTxns = 0; needsFlush = false; *actualBytesAdded = 0; volumeBlockSize = vcb->blockSize; @@ -975,20 +990,22 @@ OSErr ExtendFileC ( forceContig = ((flags & kEFContigMask) != 0); prevblocks = fcb->ff_blocks; - if (vcb->vcbSigWord == kHFSPlusSigWord) + if (vcb->vcbSigWord != kHFSSigWord) { numExtentsPerRecord = kHFSPlusExtentDensity; - else + } +#if CONFIG_HFS_STD + else { + /* HFS Standard */ numExtentsPerRecord = kHFSExtentDensity; - // - // Make sure the request and new PEOF are less than 2GB if HFS. - // - if (vcb->vcbSigWord == kHFSSigWord) { + /* Make sure the request and new PEOF are less than 2GB if HFS std*/ if (bytesToAdd >= kTwoGigabytes) - goto Overflow; + goto HFS_Std_Overflow; if ((((int64_t)fcb->ff_blocks * (int64_t)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes) - goto Overflow; + goto HFS_Std_Overflow; } +#endif + // // Determine how many blocks need to be allocated. // Round up the number of desired bytes to add. @@ -1003,9 +1020,9 @@ OSErr ExtendFileC ( && (vcb->vcbSigWord == kHFSPlusSigWord) && (bytesToAdd < (int64_t)HFS_MAX_DEFERED_ALLOC) && (blocksToAdd < hfs_freeblks(VCBTOHFS(vcb), 1))) { - HFS_MOUNT_LOCK(vcb, TRUE); + hfs_lock_mount (hfsmp); vcb->loanedBlocks += blocksToAdd; - HFS_MOUNT_UNLOCK(vcb, TRUE); + hfs_unlock_mount(hfsmp); fcb->ff_unallocblocks += blocksToAdd; FTOC(fcb)->c_blocks += blocksToAdd; @@ -1028,9 +1045,9 @@ OSErr ExtendFileC ( fcb->ff_blocks -= loanedBlocks; fcb->ff_unallocblocks = 0; - HFS_MOUNT_LOCK(vcb, TRUE); + hfs_lock_mount(hfsmp); vcb->loanedBlocks -= loanedBlocks; - HFS_MOUNT_UNLOCK(vcb, TRUE); + hfs_unlock_mount(hfsmp); } // @@ -1047,18 +1064,20 @@ OSErr ExtendFileC ( maximumBytes = bytesToAdd; } +#if CONFIG_HFS_STD // // Compute new physical EOF, rounded up to a multiple of a block. // if ( (vcb->vcbSigWord == kHFSSigWord) && // Too big? ((((int64_t)fcb->ff_blocks * (int64_t)volumeBlockSize) + bytesToAdd) >= kTwoGigabytes) ) { if (allOrNothing) // Yes, must they have it all? - goto Overflow; // Yes, can't have it + goto HFS_Std_Overflow; // Yes, can't have it else { --blocksToAdd; // No, give give 'em one block less bytesToAdd -= volumeBlockSize; } } +#endif // // If allocation is all-or-nothing, make sure there are @@ -1169,20 +1188,40 @@ OSErr ExtendFileC ( if (wantContig && (availbytes < bytesToAdd)) err = dskFulErr; else { + uint32_t ba_flags = 0; + if (wantContig) { + ba_flags |= HFS_ALLOC_FORCECONTIG; + } + if (useMetaZone) { + ba_flags |= HFS_ALLOC_METAZONE; + } + if (allowFlushTxns) { + ba_flags |= HFS_ALLOC_FLUSHTXN; + } + err = BlockAllocate( vcb, startBlock, howmany(MIN(bytesToAdd, availbytes), volumeBlockSize), howmany(MIN(maximumBytes, availbytes), volumeBlockSize), - (wantContig ? HFS_ALLOC_FORCECONTIG : 0) | - (useMetaZone ? HFS_ALLOC_METAZONE : 0), + ba_flags, &actualStartBlock, &actualNumBlocks); } } if (err == dskFulErr) { - if (forceContig) - break; // AllocContig failed because not enough contiguous space + if (forceContig) { + if (allowFlushTxns == 0) { + /* If we're forcing contiguity, re-try but allow plucking from recently freed regions */ + allowFlushTxns = 1; + wantContig = 1; + err = noErr; + continue; + } + else { + break; // AllocContig failed because not enough contiguous space + } + } if (wantContig) { // Couldn't get one big chunk, so get whatever we can. err = noErr; @@ -1191,12 +1230,21 @@ 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 we couldn't find what we needed without flushing the journal, then go ahead and do it now */ + if (allowFlushTxns == 0) { + allowFlushTxns = 1; + err = noErr; + continue; + } + } if (err == noErr) { if (actualNumBlocks != 0) { @@ -1300,10 +1348,10 @@ Exit: /* Keep the roving allocator out of the metadata zone. */ if (vcb->nextAllocation >= VCBTOHFS(vcb)->hfs_metazone_start && vcb->nextAllocation <= VCBTOHFS(vcb)->hfs_metazone_end) { - HFS_MOUNT_LOCK(vcb, TRUE); + hfs_lock_mount (hfsmp); HFS_UPDATE_NEXT_ALLOCATION(vcb, VCBTOHFS(vcb)->hfs_metazone_end + 1); MarkVCBDirty(vcb); - HFS_MOUNT_UNLOCK(vcb, TRUE); + hfs_unlock_mount(hfsmp); } } if (prevblocks < fcb->ff_blocks) { @@ -1317,7 +1365,9 @@ Exit: return err; -Overflow: +#if CONFIG_HFS_STD +HFS_Std_Overflow: +#endif err = fileBoundsErr; goto ErrorExit; } @@ -1387,6 +1437,8 @@ OSErr TruncateFileC ( // nextBlock = howmany(peof, vcb->blockSize); // number of allocation blocks to remain in file peof = (int64_t)((int64_t)nextBlock * (int64_t)vcb->blockSize); // number of bytes in those blocks + +#if CONFIG_HFS_STD if ((vcb->vcbSigWord == kHFSSigWord) && (peof >= kTwoGigabytes)) { #if DEBUG_BUILD DebugStr("HFS: Trying to truncate a file to 2GB or more"); @@ -1394,6 +1446,7 @@ OSErr TruncateFileC ( err = fileBoundsErr; goto ErrorExit; } +#endif // // Update FCB's length @@ -1701,7 +1754,8 @@ static OSErr SearchExtentRecord( { OSErr err = noErr; u_int32_t extentIndex; - u_int32_t numberOfExtents; + /* Set it to the HFS std value */ + u_int32_t numberOfExtents = kHFSExtentDensity; u_int32_t numAllocationBlocks; Boolean foundExtent; @@ -1709,10 +1763,10 @@ static OSErr SearchExtentRecord( *noMoreExtents = false; foundExtent = false; - if (vcb->vcbSigWord == kHFSPlusSigWord) + /* Override numberOfExtents for HFS+/HFSX */ + if (vcb->vcbSigWord != kHFSSigWord) { numberOfExtents = kHFSPlusExtentDensity; - else - numberOfExtents = kHFSExtentDensity; + } for( extentIndex = 0; extentIndex < numberOfExtents; ++extentIndex ) { @@ -1935,7 +1989,30 @@ static OSErr UpdateExtentRecord (ExtendedVCB *vcb, FCB *fcb, int deleted, */ lockflags = hfs_systemfile_lock(vcb, SFL_EXTENTS, HFS_EXCLUSIVE_LOCK); - if (vcb->vcbSigWord == kHFSSigWord) { + /* HFS+/HFSX */ + if (vcb->vcbSigWord != kHFSSigWord) { // HFS Plus volume + HFSPlusExtentRecord foundData; // The extent data actually found + + BlockMoveData(extentFileKey, &btIterator->key, sizeof(HFSPlusExtentKey)); + + btIterator->hint.index = 0; + btIterator->hint.nodeNum = extentBTreeHint; + + btRecord.bufferAddress = &foundData; + btRecord.itemSize = sizeof(HFSPlusExtentRecord); + btRecord.itemCount = 1; + + err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator); + + if (err == noErr) { + BlockMoveData(extentData, &foundData, sizeof(HFSPlusExtentRecord)); + err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize); + } + (void) BTFlushPath(btFCB); + } +#if CONFIG_HFS_STD + else { + /* HFS Standard */ HFSExtentKey * key; // Actual extent key used on disk in HFS HFSExtentRecord foundData; // The extent data actually found @@ -1953,34 +2030,17 @@ static OSErr UpdateExtentRecord (ExtendedVCB *vcb, FCB *fcb, int deleted, btRecord.itemCount = 1; err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator); - + if (err == noErr) err = HFSPlusToHFSExtents(extentData, (HFSExtentDescriptor *)&foundData); if (err == noErr) 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)); - - btIterator->hint.index = 0; - btIterator->hint.nodeNum = extentBTreeHint; - - btRecord.bufferAddress = &foundData; - btRecord.itemSize = sizeof(HFSPlusExtentRecord); - btRecord.itemCount = 1; - err = BTSearchRecord(btFCB, btIterator, &btRecord, &btRecordSize, btIterator); - - if (err == noErr) { - BlockMoveData(extentData, &foundData, sizeof(HFSPlusExtentRecord)); - err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize); - } - (void) BTFlushPath(btFCB); } +#endif + hfs_systemfile_unlock(vcb, lockflags); FREE(btIterator, M_TEMP); @@ -1991,7 +2051,7 @@ static OSErr UpdateExtentRecord (ExtendedVCB *vcb, FCB *fcb, int deleted, - +#if CONFIG_HFS_STD static OSErr HFSPlusToHFSExtents( const HFSPlusExtentRecord oldExtents, HFSExtentRecord newExtents) @@ -2017,7 +2077,7 @@ static OSErr HFSPlusToHFSExtents( return err; } - +#endif