]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfscommon/Misc/FileExtentMapping.c
xnu-1699.32.7.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Misc / FileExtentMapping.c
index 718a87bdc5cb7168dacec49f66a7dc1981014106..998f97fa930b04bf808cd011b091c16ec0b80988 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -180,7 +180,8 @@ static OSErr TruncateExtents(
 
 static OSErr UpdateExtentRecord (
        ExtendedVCB             *vcb,
-       FCB                                             *fcb,
+       FCB                             *fcb,
+       int                             deleted,
        const HFSPlusExtentKey  *extentFileKey,
        const HFSPlusExtentRecord       extentData,
        u_int32_t                                       extentBTreeHint);
@@ -224,7 +225,7 @@ static OSErr FindExtentRecord(
        u_int32_t                       *foundHint)
 {
        FCB *                           fcb;
-       BTreeIterator           *btIterator;
+       BTreeIterator           btIterator;
        FSBufferDescriptor      btRecord;
        OSErr                           err;
        u_int16_t                       btRecordSize;
@@ -234,14 +235,13 @@ static OSErr FindExtentRecord(
                *foundHint = 0;
        fcb = GetFileControlBlock(vcb->extentsRefNum);
        
-       MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
-       bzero(btIterator, sizeof(*btIterator));
+       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;
@@ -251,10 +251,10 @@ static OSErr FindExtentRecord(
                btRecord.itemSize = sizeof(HFSExtentRecord);
                btRecord.itemCount = 1;
 
-               err = BTSearchRecord(fcb, btIterator, &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).
@@ -298,7 +298,7 @@ static OSErr FindExtentRecord(
                HFSPlusExtentKey *      extentKeyPtr;
                HFSPlusExtentRecord     extentData;
 
-               extentKeyPtr = (HFSPlusExtentKey*) &btIterator->key;
+               extentKeyPtr = (HFSPlusExtentKey*) &btIterator.key;
                extentKeyPtr->keyLength  = kHFSPlusExtentKeyMaximumLength;
                extentKeyPtr->forkType   = forkType;
                extentKeyPtr->pad                = 0;
@@ -309,10 +309,10 @@ static OSErr FindExtentRecord(
                btRecord.itemSize = sizeof(HFSPlusExtentRecord);
                btRecord.itemCount = 1;
 
-               err = BTSearchRecord(fcb, btIterator, &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).
@@ -336,8 +336,7 @@ static OSErr FindExtentRecord(
        }
 
        if (foundHint)
-               *foundHint = btIterator->hint.nodeNum;
-       FREE(btIterator, M_TEMP);       
+               *foundHint = btIterator.hint.nodeNum;
        return err;
 }
 
@@ -349,7 +348,7 @@ static OSErr CreateExtentRecord(
        HFSPlusExtentRecord     extents,
        u_int32_t                       *hint)
 {
-       BTreeIterator btIterator;
+       BTreeIterator btIterator;
        FSBufferDescriptor      btRecord;
        u_int16_t  btRecordSize;
        int  lockflags;
@@ -358,8 +357,7 @@ static OSErr CreateExtentRecord(
        err = noErr;
        *hint = 0;
 
-       MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
-       bzero(btIterator, sizeof(*btIterator));
+       bzero(&btIterator, sizeof(btIterator));
 
        /*
         * The lock taken by callers of ExtendFileC is speculative and
@@ -379,7 +377,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;
@@ -393,20 +391,19 @@ 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));
        
        hfs_systemfile_unlock(vcb, lockflags);
        
-       FREE(btIterator, M_TEMP);       
        return err;
 }
 
@@ -417,18 +414,17 @@ static OSErr DeleteExtentRecord(
        u_int32_t                       fileID,
        u_int32_t                       startBlock)
 {
-       BTreeIterator btIterator;
+       BTreeIterator btIterator;
        OSErr                           err;
        
        err = noErr;
 
-       MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
-       bzero(btIterator, sizeof(*btIterator));
+       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;
@@ -437,7 +433,7 @@ static 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;
@@ -445,10 +441,9 @@ static 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;
 }
 
@@ -462,7 +457,6 @@ static OSErr DeleteExtentRecord(
 //
 //_________________________________________________________________________________
 
-__private_extern__
 OSErr MapFileBlockC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file
@@ -503,6 +497,7 @@ 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 (((off_t)fcb->ff_blocks * (off_t)allocBlockSize) < dataEnd)    // Is PEOF shorter?
@@ -535,6 +530,12 @@ OSErr MapFileBlockC (
        if (availableBytes)
        {
                tmpOff = dataEnd - offset;
+               /*
+                * Disallow negative runs.
+                */
+               if (tmpOff <= 0) {
+                       return EINVAL;
+               }
                if (tmpOff > (off_t)(numberOfBytes))
                        *availableBytes = numberOfBytes;  // more there than they asked for, so pin the output
                else
@@ -582,7 +583,7 @@ static OSErr ReleaseExtents(
                        break;
                }
 
-               err = BlockDeallocate( vcb, extentRecord[extentIndex].startBlock, numAllocationBlocks );
+               err = BlockDeallocate( vcb, extentRecord[extentIndex].startBlock, numAllocationBlocks , 0);
                if ( err != noErr )
                        break;
                                        
@@ -688,7 +689,6 @@ static OSErr DeallocateFork(
 //     Function:       Flushes the extent file for a specified volume
 //\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b\8b
 
-__private_extern__
 OSErr FlushExtentFile( ExtendedVCB *vcb )
 {
        FCB *   fcb;
@@ -730,9 +730,9 @@ int32_t CompareExtentKeys( const HFSExtentKey *searchKey, const HFSExtentKey *tr
        
        #if DEBUG_BUILD
                if (searchKey->keyLength != kHFSExtentKeyMaximumLength)
-                       DebugStr("\pHFS: search Key is wrong length");
+                       DebugStr("HFS: search Key is wrong length");
                if (trialKey->keyLength != kHFSExtentKeyMaximumLength)
-                       DebugStr("\pHFS: trial Key is wrong length");
+                       DebugStr("HFS: trial Key is wrong length");
        #endif
        
        result = -1;            //      assume searchKey < trialKey
@@ -794,9 +794,9 @@ int32_t CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusE
        
        #if DEBUG_BUILD
                if (searchKey->keyLength != kHFSPlusExtentKeyMaximumLength)
-                       DebugStr("\pHFS: search Key is wrong length");
+                       DebugStr("HFS: search Key is wrong length");
                if (trialKey->keyLength != kHFSPlusExtentKeyMaximumLength)
-                       DebugStr("\pHFS: trial Key is wrong length");
+                       DebugStr("HFS: trial Key is wrong length");
        #endif
        
        result = -1;            //      assume searchKey < trialKey
@@ -848,7 +848,6 @@ int32_t CompareExtentKeysPlus( const HFSPlusExtentKey *searchKey, const HFSPlusE
  * Used by hfs_extendfs to extend the volume allocation bitmap file.
  *
  */
-__private_extern__
 int
 AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockCount)
 {
@@ -902,7 +901,7 @@ AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockC
                 */
                foundData[foundIndex].startBlock = startBlock;
                foundData[foundIndex].blockCount = blockCount;
-               error = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint);
+               error = UpdateExtentRecord(vcb, fcb, 0, &foundKey, foundData, hint);
        }
        (void) FlushExtentFile(vcb);
 
@@ -918,7 +917,6 @@ AddFileExtent(ExtendedVCB *vcb, FCB *fcb, u_int32_t startBlock, u_int32_t blockC
 //
 //_________________________________________________________________________________
 
-__private_extern__
 OSErr ExtendFileC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file to truncate
@@ -1087,10 +1085,53 @@ OSErr ExtendFileC (
        //      If that fails, get whatever we can.
        //              If forceContig, then take whatever we got
        //              else, keep getting bits and pieces (non-contig)
+       
+       /*
+        * Note that for sparse devices (like sparse bundle dmgs), we
+        * should only be aggressive with re-using once-allocated pieces
+        * if we're not dealing with system files.  If we're trying to operate
+        * on behalf of a system file, we need the maximum contiguous amount
+        * possible.  For non-system files we favor locality and fragmentation over
+        * contiguity as it can result in fewer blocks being needed from the underlying
+        * filesystem that the sparse image resides upon. 
+        */
        err = noErr;
-       wantContig = true;
+       if (   (vcb->hfs_flags & HFS_HAS_SPARSE_DEVICE)
+                       && (fcb->ff_cp->c_fileid >= kHFSFirstUserCatalogNodeID)
+                       && (flags & kEFMetadataMask) == 0) {
+               /*
+                * We want locality over contiguity so by default we set wantContig to 
+                * false unless we hit one of the circumstances below.
+                */ 
+               wantContig = false;
+               if (hfs_isrbtree_active(VCBTOHFS(vcb))) {
+                       /* 
+                        * If the red-black tree is acive, we can always find a suitable contiguous
+                        * chunk.  So if the user specifically requests contiguous files,  we should 
+                        * honor that no matter what kind of device it is.
+                        */
+                       if (forceContig) {
+                               wantContig = true;
+                       }
+               }
+               else {
+                       /* 
+                        * If the red-black tree is not active, then only set wantContig to true
+                        * if we have never done a contig scan on the device, which would populate
+                        * the free extent cache.  Note that the caller may explicitly unset the 
+                        * DID_CONTIG_SCAN bit in order to force us to vend a contiguous extent here
+                        * if the caller wants to get a contiguous chunk.
+                        */
+                       if ((vcb->hfs_flags & HFS_DID_CONTIG_SCAN) == 0) { 
+                               vcb->hfs_flags |= HFS_DID_CONTIG_SCAN;  
+                               wantContig = true;
+                       }
+               }
+       } 
+       else {
+               wantContig = true;
+       }
        useMetaZone = flags & kEFMetadataMask;
-       vcb->vcbFreeExtCnt = 0; /* For now, force rebuild of free extent list */
        do {
                if (blockHint != 0)
                        startBlock = blockHint;
@@ -1114,8 +1155,8 @@ OSErr ExtendFileC (
                                                  startBlock,
                                                  howmany(MIN(bytesToAdd, availbytes), volumeBlockSize),
                                                  howmany(MIN(maximumBytes, availbytes), volumeBlockSize),
-                                                 wantContig,
-                                                 useMetaZone,
+                                                 (wantContig ? HFS_ALLOC_FORCECONTIG : 0) | 
+                                                 (useMetaZone ? HFS_ALLOC_METAZONE : 0),
                                                  &actualStartBlock,
                                                  &actualNumBlocks);
                        }
@@ -1149,7 +1190,7 @@ OSErr ExtendFileC (
                        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);
+                               err = UpdateExtentRecord(vcb, fcb, 0, &foundKey, foundData, hint);
                                if (err != noErr) break;
                        }
                        else {
@@ -1161,7 +1202,7 @@ OSErr ExtendFileC (
                                if (foundIndex == numExtentsPerRecord) {
                                        //      This record is full.  Need to create a new one.
                                        if (FTOC(fcb)->c_fileid == kHFSExtentsFileID) {
-                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks);
+                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks, 0);
                                                err = dskFulErr;                // Oops.  Can't extend extents file past first record.
                                                break;
                                        }
@@ -1192,7 +1233,7 @@ OSErr ExtendFileC (
                                                //      We couldn't create an extent record because extents B-tree
                                                //      couldn't grow.  Dellocate the extent just allocated and
                                                //      return a disk full error.
-                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks);
+                                               (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks, 0);
                                                err = dskFulErr;
                                        }
                                        if (err != noErr) break;
@@ -1203,7 +1244,7 @@ OSErr ExtendFileC (
                                        //      Add a new extent into this record and update.
                                        foundData[foundIndex].startBlock = actualStartBlock;
                                        foundData[foundIndex].blockCount = actualNumBlocks;
-                                       err = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint);
+                                       err = UpdateExtentRecord(vcb, fcb, 0, &foundKey, foundData, hint);
                                        if (err != noErr) break;
                                }
                        }
@@ -1275,12 +1316,15 @@ Overflow:
 //
 //_________________________________________________________________________________
 
-__private_extern__
 OSErr TruncateFileC (
        ExtendedVCB             *vcb,                           // volume that file resides on
        FCB                             *fcb,                           // FCB of file to truncate
        int64_t                 peof,                           // new physical size for file
+       int                             deleted,                        // if nonzero, the file's catalog record has already been deleted.
+       int                             rsrc,                           // does this represent a resource fork or not?
+       uint32_t                fileid,                         // the fileid of the file we're manipulating.
        Boolean                 truncateToExtent)       // if true, truncate to end of extent containing newPEOF
+
 {
        OSErr                           err;
        u_int32_t                       nextBlock;              //      next file allocation block to consider
@@ -1300,16 +1344,20 @@ OSErr TruncateFileC (
 
        recordDeleted = false;
        
-       if (vcb->vcbSigWord == kHFSPlusSigWord)
+       if (vcb->vcbSigWord == kHFSPlusSigWord) {
                numExtentsPerRecord = kHFSPlusExtentDensity;
-       else
+       }
+       else {
                numExtentsPerRecord = kHFSExtentDensity;
-
-       if (FORK_IS_RSRC(fcb))
+       }
+       
+       if (rsrc) {
                forkType = kResourceForkType;
-       else
+       }
+       else {
                forkType = kDataForkType;
-
+       }
+       
        temp64 = fcb->ff_blocks;
        physNumBlocks = (u_int32_t)temp64;
 
@@ -1322,7 +1370,7 @@ OSErr TruncateFileC (
        peof = (int64_t)((int64_t)nextBlock * (int64_t)vcb->blockSize);                                 // number of bytes in those blocks
        if ((vcb->vcbSigWord == kHFSSigWord) && (peof >= kTwoGigabytes)) {
                #if DEBUG_BUILD
-                       DebugStr("\pHFS: Trying to truncate a file to 2GB or more");
+                       DebugStr("HFS: Trying to truncate a file to 2GB or more");
                #endif
                err = fileBoundsErr;
                goto ErrorExit;
@@ -1335,13 +1383,21 @@ OSErr TruncateFileC (
         * 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);
+       if (!deleted) {
+               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 (!deleted) {
+               /* 
+                * If the file is already C_NOEXISTS, then the catalog record
+                * has been removed from disk already.  We wouldn't need to force 
+                * another update
+                */
+               FTOC(fcb)->c_flag |= (C_MODIFIED | C_FORCEUPDATE);
+       }
        //
        //      If the new PEOF is 0, then truncateToExtent has no meaning (we should always deallocate
        //      all storage).
@@ -1350,7 +1406,7 @@ OSErr TruncateFileC (
                int i;
                
                //      Deallocate all the extents for this fork
-               err = DeallocateFork(vcb, FTOC(fcb)->c_fileid, forkType, fcb->fcbExtents, &recordDeleted);
+               err = DeallocateFork(vcb, 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)
@@ -1384,7 +1440,7 @@ OSErr TruncateFileC (
                        //      Compute first volume allocation block to free
                        startBlock = extentRecord[extentIndex].startBlock + extentRecord[extentIndex].blockCount - numBlocks;
                        //      Free the blocks in bitmap
-                       err = BlockDeallocate(vcb, startBlock, numBlocks);
+                       err = BlockDeallocate(vcb, startBlock, numBlocks, 0);
                        if (err != noErr) goto ErrorExit;
                        //      Adjust length of this extent
                        extentRecord[extentIndex].blockCount -= numBlocks;
@@ -1408,7 +1464,7 @@ OSErr TruncateFileC (
        while (extentIndex < numExtentsPerRecord && extentRecord[extentIndex].blockCount != 0) {
                numBlocks = extentRecord[extentIndex].blockCount;
                //      Deallocate this extent
-               err = BlockDeallocate(vcb, extentRecord[extentIndex].startBlock, numBlocks);
+               err = BlockDeallocate(vcb, extentRecord[extentIndex].startBlock, numBlocks, 0);
                if (err != noErr) goto ErrorExit;
                //      Update next file allocation block number
                nextBlock += numBlocks;
@@ -1426,7 +1482,7 @@ OSErr TruncateFileC (
        //      record (in the FCB, or extents file).
        //
        if (extentChanged) {
-               err = UpdateExtentRecord(vcb, fcb, &key, extentRecord, hint);
+               err = UpdateExtentRecord(vcb, fcb, deleted, &key, extentRecord, hint);
                if (err != noErr) goto ErrorExit;
        }
        
@@ -1436,7 +1492,7 @@ OSErr TruncateFileC (
        //      blocks.
        //
        if (nextBlock < physNumBlocks)
-               err = TruncateExtents(vcb, forkType, FTOC(fcb)->c_fileid, nextBlock, &recordDeleted);
+               err = TruncateExtents(vcb, forkType, fileid, nextBlock, &recordDeleted);
 
 Done:
 ErrorExit:
@@ -1451,7 +1507,6 @@ ErrorExit:
  * HFS Plus only
  *
  */
-__private_extern__
 OSErr HeadTruncateFile (
        ExtendedVCB  *vcb,
        FCB  *fcb,
@@ -1488,7 +1543,7 @@ OSErr HeadTruncateFile (
                        break;  /* end of extents */
 
                if (blksfreed < headblks) {
-                       error = BlockDeallocate(vcb, fcb->fcbExtents[i].startBlock, blkcnt);
+                       error = BlockDeallocate(vcb, fcb->fcbExtents[i].startBlock, blkcnt, 0);
                        /*
                         * Any errors after the first BlockDeallocate
                         * must be ignored so we can put the file in
@@ -1499,7 +1554,7 @@ OSErr HeadTruncateFile (
                                        goto ErrorExit;  /* uh oh */
                                else {
                                        error = 0;
-                                       printf("HeadTruncateFile: problems deallocating %s (%d)\n",
+                                       printf("hfs: HeadTruncateFile: problems deallocating %s (%d)\n",
                                               FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                                }
                        }
@@ -1534,7 +1589,7 @@ OSErr HeadTruncateFile (
                         * a known state.
                         */
                        if (error != btNotFound)
-                               printf("HeadTruncateFile: problems finding extents %s (%d)\n",
+                               printf("hfs: HeadTruncateFile: problems finding extents %s (%d)\n",
                                       FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                        error = 0;
                        break;
@@ -1546,9 +1601,9 @@ OSErr HeadTruncateFile (
                                break;  /* end of extents */
 
                        if (blksfreed < headblks) {
-                               error = BlockDeallocate(vcb, extents[i].startBlock, blkcnt);
+                               error = BlockDeallocate(vcb, extents[i].startBlock, blkcnt, 0);
                                if (error) {
-                                       printf("HeadTruncateFile: problems deallocating %s (%d)\n",
+                                       printf("hfs: HeadTruncateFile: problems deallocating %s (%d)\n",
                                               FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                                        error = 0;
                                }
@@ -1563,7 +1618,7 @@ OSErr HeadTruncateFile (
                
                error = DeleteExtentRecord(vcb, forkType, fileID, startblk);
                if (error) {
-                       printf("HeadTruncateFile: problems deallocating %s (%d)\n",
+                       printf("hfs: HeadTruncateFile: problems deallocating %s (%d)\n",
                                FTOC(fcb)->c_desc.cd_nameptr ? (const char *)FTOC(fcb)->c_desc.cd_nameptr : "", error);
                        error = 0;
                }
@@ -1810,6 +1865,7 @@ Exit:
 //
 //     Input:          vcb                                             -       the volume containing the extents
 //                             fcb                                             -       the file that owns the extents
+//                             deleted                                 -       whether or not the file is already deleted
 //                             extentFileKey                   -       pointer to extent key record (xkr)
 //                                             If the key length is 0, then the extents are actually part
 //                                             of the catalog record, stored in the FCB.
@@ -1820,21 +1876,21 @@ Exit:
 //                             (other) = error from BTree
 //============================================================================
 
-static OSErr UpdateExtentRecord (
-       ExtendedVCB  *vcb,
-       FCB  *fcb,
-       const HFSPlusExtentKey  *extentFileKey,
-       const HFSPlusExtentRecord  extentData,
-       u_int32_t  extentBTreeHint)
+static OSErr UpdateExtentRecord (ExtendedVCB *vcb, FCB  *fcb, int deleted,
+                                                                const HFSPlusExtentKey  *extentFileKey,
+                                                                const HFSPlusExtentRecord  extentData,
+                                                                u_int32_t  extentBTreeHint) 
 {
     OSErr err = noErr;
        
        if (extentFileKey->keyLength == 0) {    // keyLength == 0 means the FCB's extent record
                BlockMoveData(extentData, fcb->fcbExtents, sizeof(HFSPlusExtentRecord));
-               FTOC(fcb)->c_flag |= C_MODIFIED;
+               if (!deleted) {
+                       FTOC(fcb)->c_flag |= C_MODIFIED;
+               }
        }
        else {
-               BTreeIterator btIterator;
+               BTreeIterator btIterator;
                FSBufferDescriptor btRecord;
                u_int16_t btRecordSize;
                FCB * btFCB;
@@ -1845,8 +1901,7 @@ static OSErr UpdateExtentRecord (
                //
                btFCB = GetFileControlBlock(vcb->extentsRefNum);
 
-               MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
-               bzero(btIterator, sizeof(*btIterator));
+               bzero(&btIterator, sizeof(btIterator));
 
                /*
                 * The lock taken by callers of ExtendFileC/TruncateFileC is
@@ -1861,50 +1916,49 @@ static OSErr UpdateExtentRecord (
                        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, &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, &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);
                }
                hfs_systemfile_unlock(vcb, lockflags);
-               FREE(btIterator, M_TEMP);       
        }
        
        return err;
@@ -1931,7 +1985,7 @@ static OSErr HFSPlusToHFSExtents(
 
        #if DEBUG_BUILD
                if (oldExtents[3].startBlock || oldExtents[3].blockCount) {
-                       DebugStr("\pExtentRecord with > 3 extents is invalid for HFS");
+                       DebugStr("ExtentRecord with > 3 extents is invalid for HFS");
                        err = fsDSIntErr;
                }
        #endif
@@ -2001,7 +2055,6 @@ static Boolean ExtentsAreIntegral(
 //                             Called by BTOpenPath during volume mount
 //_________________________________________________________________________________
 
-__private_extern__
 Boolean NodesAreContiguous(
        ExtendedVCB     *vcb,
        FCB                     *fcb,