Windows: AFSFindObjectInfo update last access time
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSGeneric.cpp
index ce9fffc..6417b19 100644 (file)
@@ -689,7 +689,20 @@ AFSInitializeGlobalDirectoryEntries()
         if( pDirNode == NULL)
         {
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
                           AFS_TRACE_LEVEL_ERROR,
@@ -712,7 +725,20 @@ AFSInitializeGlobalDirectoryEntries()
 
             ExFreePool( pDirNode);
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
@@ -806,7 +832,20 @@ AFSInitializeGlobalDirectoryEntries()
                           AFS_TRACE_LEVEL_ERROR,
                           "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocation failure\n"));
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
@@ -825,7 +864,20 @@ AFSInitializeGlobalDirectoryEntries()
 
             ExFreePool( pDirNode);
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
@@ -882,7 +934,20 @@ try_exit:
             if( AFSGlobalDotDirEntry != NULL)
             {
 
-                AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
+                lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
+                                                 AFS_OBJECT_REFERENCE_GLOBAL);
+
+                AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
+                              AFSGlobalDotDirEntry->ObjectInformation,
+                              lCount));
+
+                if ( lCount == 0)
+                {
+
+                    AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
+                }
 
                 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
 
@@ -896,7 +961,20 @@ try_exit:
             if( AFSGlobalDotDotDirEntry != NULL)
             {
 
-                AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
+                lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
+                                                 AFS_OBJECT_REFERENCE_GLOBAL);
+
+                AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
+                              AFSGlobalDotDotDirEntry->ObjectInformation,
+                              lCount));
+
+                if ( lCount == 0)
+                {
+
+                    AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
+                }
 
                 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
 
@@ -924,7 +1002,6 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
     NTSTATUS ntStatus = STATUS_SUCCESS;
     ULONG ulEntryLength = 0;
     AFSObjectInfoCB *pObjectInfoCB = NULL;
-    BOOLEAN bAllocatedObjectCB = FALSE;
     ULONGLONG ullIndex = 0;
     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
     LONG lCount;
@@ -955,8 +1032,7 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
                                        ullIndex,
                                        (AFSBTreeEntry **)&pObjectInfoCB);
 
-        if( !NT_SUCCESS( ntStatus) ||
-            pObjectInfoCB == NULL)
+        if( !NT_SUCCESS( ntStatus))
         {
 
             //
@@ -974,16 +1050,106 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
             }
 
-            bAllocatedObjectCB = TRUE;
-
             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
                           pObjectInfoCB,
                           ParentObjectInfo,
                           FileName));
+
+            //
+            // If we allocated the object information cb then set the information
+            //
+
+            pObjectInfoCB->FileId = DirEnumEntry->FileId;
+
+            pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
+
+            pObjectInfoCB->FileType = DirEnumEntry->FileType;
+
+            pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
+
+            if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
+                pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
+            {
+
+                pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
+            }
+
+            if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
+            {
+
+                if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
+                {
+
+                    pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
+                }
+                else
+                {
+
+                    pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
+                }
+            }
+
+            //
+            // Check for the case where we have a filetype of SymLink but both the TargetFid and the
+            // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
+            // the code
+            //
+
+            if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
+                pObjectInfoCB->TargetFileId.Vnode == 0 &&
+                pObjectInfoCB->TargetFileId.Unique == 0 &&
+                (TargetName == NULL || TargetName->Length == 0))
+            {
+
+                //
+                // This will ensure we perform a validation on the node
+                //
+
+                pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
+            }
+
+            if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
+            {
+
+                SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
+            }
+
+            SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
+        }
+
+        if ( BooleanFlagOn( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY))
+        {
+
+            pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
+
+            pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
+
+            pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
+
+            pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
+
+            pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
+
+            pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
+
+            pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
+
+            pObjectInfoCB->Links = DirEnumEntry->Links;
+
+            pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
+
+            pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
+
+            ClearFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
         }
 
+        //
+        // This reference count is either stored into the return DirectoryCB
+        // or released before function exit.
+        //
+
         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
                                          AFS_OBJECT_REFERENCE_DIRENTRY);
 
@@ -1106,96 +1272,6 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
                            pDirNode->NameInformation.TargetName.Length);
         }
 
-        //
-        // If we allocated the object information cb then update the information
-        //
-
-        if( bAllocatedObjectCB)
-        {
-
-            //
-            // Populate the rest of the data
-            //
-
-            pObjectInfoCB->FileId = DirEnumEntry->FileId;
-
-            pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
-
-            pObjectInfoCB->FileType = DirEnumEntry->FileType;
-
-            pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
-
-            pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
-
-            pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
-
-            pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
-
-            pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
-
-            pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
-
-            pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
-
-            if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
-                pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
-            {
-
-                pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
-            }
-
-            if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
-            {
-
-                if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
-                {
-
-                    pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
-                }
-                else
-                {
-
-                    pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
-                }
-            }
-
-            pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
-
-            //
-            // Check for the case where we have a filetype of SymLink but both the TargetFid and the
-            // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
-            // the code
-            //
-
-            if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
-                pObjectInfoCB->TargetFileId.Vnode == 0 &&
-                pObjectInfoCB->TargetFileId.Unique == 0 &&
-                pDirNode->NameInformation.TargetName.Length == 0)
-            {
-
-                //
-                // This will ensure we perform a validation on the node
-                //
-
-                pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
-            }
-
-            if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
-            {
-
-                SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
-            }
-        }
-
-        //
-        // Object specific information
-        //
-
-        pObjectInfoCB->Links = DirEnumEntry->Links;
-
-        pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
-
-        pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
 
 try_exit:
 
@@ -1230,6 +1306,9 @@ try_exit:
             if( pObjectInfoCB != NULL)
             {
 
+                AFSAcquireShared( pObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
+                                  TRUE);
+
                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
 
@@ -1239,13 +1318,7 @@ try_exit:
                               pObjectInfoCB,
                               lCount));
 
-                if( bAllocatedObjectCB)
-                {
-
-                    ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
-
-                    AFSDeleteObjectInfo( &pObjectInfoCB);
-                }
+                AFSReleaseResource( pObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
             }
         }
     }
@@ -1632,7 +1705,8 @@ AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
     {
 
         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
-                                               &(*ppObjectInfo)->ParentFileId);
+                                               &(*ppObjectInfo)->ParentFileId,
+                                               FALSE);
     }
 
     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
@@ -2178,7 +2252,8 @@ AFSIsChildOfParent( IN AFSFcb *Dcb,
         }
 
         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
-                                               &pCurrentFcb->ObjectInformation->ParentFileId);
+                                               &pCurrentFcb->ObjectInformation->ParentFileId,
+                                               FALSE);
 
         if ( pParentObjectInfo != NULL)
         {
@@ -2686,6 +2761,9 @@ AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
             AFSInvalidateObject( &pCurrentObject,
                                  Reason);
 
+            AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
+                              TRUE);
+
             if ( pCurrentObject )
             {
 
@@ -2699,9 +2777,6 @@ AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
                               lCount));
             }
 
-            AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
-                              TRUE);
-
             pCurrentObject = pNextObject;
         }
 
@@ -3500,7 +3575,7 @@ AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
                                   &pCurrentDirEntry->NameInformation.FileName));
 
                     AFSDeleteDirEntry( ObjectInfo,
-                                       pCurrentDirEntry);
+                                       &pCurrentDirEntry);
                 }
                 else
                 {
@@ -3633,7 +3708,7 @@ AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
                               ObjectInfo->FileId.Unique));
 
                 AFSDeleteDirEntry( ObjectInfo,
-                                   pCurrentDirEntry);
+                                   &pCurrentDirEntry);
             }
             else
             {
@@ -4436,7 +4511,20 @@ AFSInitializeSpecialShareNameList()
         if( pDirNode == NULL)
         {
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
@@ -4455,7 +4543,20 @@ AFSInitializeSpecialShareNameList()
 
             ExFreePool( pDirNode);
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
@@ -4529,7 +4630,20 @@ AFSInitializeSpecialShareNameList()
         if( pDirNode == NULL)
         {
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
@@ -4548,7 +4662,20 @@ AFSInitializeSpecialShareNameList()
 
             ExFreePool( pDirNode);
 
-            AFSDeleteObjectInfo( &pObjectInfoCB);
+            lCount = AFSObjectInfoDecrement( pObjectInfoCB,
+                                             AFS_OBJECT_REFERENCE_GLOBAL);
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
+                          pObjectInfoCB,
+                          lCount));
+
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &pObjectInfoCB);
+            }
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
@@ -4603,7 +4730,20 @@ try_exit:
 
                     pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
 
-                    AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
+                    lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
+                                                     AFS_OBJECT_REFERENCE_GLOBAL);
+
+                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
+                                  pDirNode->ObjectInformation,
+                                  lCount));
+
+                    if ( lCount == 0)
+                    {
+
+                        AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
+                    }
 
                     ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
 
@@ -4762,7 +4902,7 @@ AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
                               &pCurrentDirEntry->NameInformation.FileName));
 
                 AFSDeleteDirEntry( ObjectInfoCB,
-                                   pCurrentDirEntry);
+                                   &pCurrentDirEntry);
             }
             else
             {
@@ -5191,17 +5331,22 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ParentObjectInfo)
     __Enter
     {
 
+        AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
+                        TRUE);
+
         pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
                                                0);
 
         if( pObjectInfoCB == NULL)
         {
 
+            AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
+
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
 
         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
-                                         AFS_OBJECT_REFERENCE_DIRENTRY);
+                                         AFS_OBJECT_REFERENCE_PIOCTL);
 
         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
@@ -5209,6 +5354,8 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ParentObjectInfo)
                       pObjectInfoCB,
                       lCount));
 
+        AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
+
         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
 
         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
@@ -5313,7 +5460,7 @@ try_exit:
             {
 
                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
-                                                 AFS_OBJECT_REFERENCE_DIRENTRY);
+                                                 AFS_OBJECT_REFERENCE_PIOCTL);
 
                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
@@ -5321,7 +5468,11 @@ try_exit:
                               pObjectInfoCB,
                               lCount));
 
-                AFSDeleteObjectInfo( &pObjectInfoCB);
+                if ( lCount == 0)
+                {
+
+                    AFSDeleteObjectInfo( &pObjectInfoCB);
+                }
             }
         }
     }
@@ -6021,13 +6172,19 @@ AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
 
 AFSObjectInfoCB *
 AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
-                   IN AFSFileID   *FileId)
+                   IN AFSFileID   *FileId,
+                   IN BOOLEAN      bUpdateLastUse)
 {
     DWORD            ntStatus = STATUS_SUCCESS;
     ULONGLONG        ullIndex;
     AFSObjectInfoCB *pObjectInfo = NULL;
     LONG             lCount;
 
+    ullIndex = AFSCreateLowIndex( FileId);
+
+    AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
+                      TRUE);
+
     if ( AFSIsEqualFID( &VolumeCB->ObjectInformation.FileId, FileId))
     {
 
@@ -6036,16 +6193,9 @@ AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
     else
     {
 
-        AFSAcquireExcl( VolumeCB->ObjectInfoTree.TreeLock,
-                        TRUE);
-
-        ullIndex = AFSCreateLowIndex( FileId);
-
         ntStatus = AFSLocateHashEntry( VolumeCB->ObjectInfoTree.TreeHead,
                                        ullIndex,
                                        (AFSBTreeEntry **)&pObjectInfo);
-
-        AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
     }
 
     if ( NT_SUCCESS( ntStatus)) {
@@ -6058,8 +6208,16 @@ AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
                       "AFSFindObjectInfo Decrement count on object %p Cnt %d\n",
                       pObjectInfo,
                       lCount));
+
+        if ( bUpdateLastUse)
+        {
+
+            KeQueryTickCount( &pObjectInfo->LastAccessCount);
+        }
     }
 
+    AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
+
     return pObjectInfo;
 }
 
@@ -6083,155 +6241,171 @@ AFSReleaseObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
 void
 AFSDeleteObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
 {
-
     BOOLEAN bAcquiredTreeLock = FALSE;
     AFSObjectInfoCB *pObjectInfo = NULL;
+    AFSVolumeCB * pVolume = NULL;
     BOOLEAN bHeldInService;
     AFSObjectInfoCB * pParentObjectInfo = NULL;
     AFSFileID FileId;
     LONG lCount;
 
-    if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
+    __Enter
     {
+        if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
+        {
 
-        //
-        // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
-        // embedded in the VolumeCB.
-        //
-
-        ASSERT( FALSE);
+            //
+            // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
+            // embedded in the VolumeCB.
+            //
 
-        return;
-    }
+            ASSERT( FALSE);
 
-    pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
-                                                                         NULL,
-                                                                         *ppObjectInfo);
+            return;
+        }
 
-    if ( pObjectInfo == NULL)
-    {
+        pVolume = (*ppObjectInfo)->VolumeCB;
 
-        return;
-    }
+        if( !ExIsResourceAcquiredExclusiveLite( pVolume->ObjectInfoTree.TreeLock))
+        {
 
-    ASSERT( *ppObjectInfo == NULL);
+            ASSERT( !ExIsResourceAcquiredLite( pVolume->ObjectInfoTree.TreeLock));
 
-    ASSERT( pObjectInfo->ObjectReferenceCount == 0);
+            AFSAcquireExcl( pVolume->ObjectInfoTree.TreeLock,
+                            TRUE);
 
-    bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
+            bAcquiredTreeLock = TRUE;
+        }
 
-    if( !ExIsResourceAcquiredExclusiveLite( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
-    {
+        for ( lCount = 0; lCount < AFS_OBJECT_REFERENCE_MAX; lCount++)
+        {
 
-        ASSERT( !ExIsResourceAcquiredLite( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
+            ASSERT( (*ppObjectInfo)->ObjectReferences[ lCount] >= 0);
+        }
 
-        AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
-                        TRUE);
+        ASSERT( (*ppObjectInfo)->ObjectReferenceCount == 0);
 
-        bAcquiredTreeLock = TRUE;
-    }
+        pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
+                                                                             NULL,
+                                                                             *ppObjectInfo);
 
-    if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
-    {
+        if ( pObjectInfo == NULL)
+        {
 
-        pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
-                                               &pObjectInfo->ParentFileId);
-    }
+            try_return( NOTHING);
+        }
 
-    //
-    // Remove it from the tree and list if it was inserted
-    //
+        ASSERT( *ppObjectInfo == NULL);
 
-    if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
-    {
+        if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
+        {
 
-        AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
-                            &pObjectInfo->TreeEntry);
-    }
+            pParentObjectInfo = AFSFindObjectInfo( pVolume,
+                                                   &pObjectInfo->ParentFileId,
+                                                   FALSE);
 
-    if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
-    {
+            if( pParentObjectInfo != NULL)
+            {
 
-        if( pObjectInfo->ListEntry.fLink == NULL)
-        {
+                ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
 
-            pObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
+                lCount = AFSObjectInfoDecrement( pParentObjectInfo,
+                                                 AFS_OBJECT_REFERENCE_CHILD);
 
-            if( pObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
-            {
+                AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
+                              pParentObjectInfo,
+                              lCount));
 
-                pObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
+                AFSReleaseObjectInfo( &pParentObjectInfo);
             }
         }
-        else
+
+        //
+        // Remove it from the tree and list if it was inserted
+        //
+
+        if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
         {
 
-            ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
+            AFSRemoveHashEntry( &pVolume->ObjectInfoTree.TreeHead,
+                                &pObjectInfo->TreeEntry);
         }
 
-        if( pObjectInfo->ListEntry.bLink == NULL)
+        if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
         {
 
-            pObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
+            if( pObjectInfo->ListEntry.fLink == NULL)
+            {
+
+                pVolume->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
+
+                if( pVolume->ObjectInfoListTail != NULL)
+                {
 
-            if( pObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
+                    pVolume->ObjectInfoListTail->ListEntry.fLink = NULL;
+                }
+            }
+            else
             {
 
-                pObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
+                ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
             }
-        }
-        else
-        {
 
-            ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
-        }
-    }
+            if( pObjectInfo->ListEntry.bLink == NULL)
+            {
 
-    if( pParentObjectInfo != NULL)
-    {
+                pVolume->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
 
-        ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
+                if( pVolume->ObjectInfoListHead != NULL)
+                {
 
-        lCount = AFSObjectInfoDecrement( pParentObjectInfo,
-                                         AFS_OBJECT_REFERENCE_CHILD);
+                    pVolume->ObjectInfoListHead->ListEntry.bLink = NULL;
+                }
+            }
+            else
+            {
 
-        AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
-                      pParentObjectInfo,
-                      lCount));
+                ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
+            }
+        }
 
-        AFSReleaseObjectInfo( &pParentObjectInfo);
-    }
+        bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
 
-    if( bAcquiredTreeLock)
-    {
+        if( bHeldInService)
+        {
 
-        AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
-    }
+            FileId = pObjectInfo->FileId;
+        }
 
-    if( bHeldInService)
-    {
+        ASSERT( pObjectInfo->ObjectReferenceCount == 0);
 
-        FileId = pObjectInfo->FileId;
-    }
+        ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
 
-    ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
+        ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
 
-    ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
+        AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
 
-    AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
+        AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
 
-    AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
+try_exit:
 
-    //
-    // Release the fid in the service
-    //
+        if( bAcquiredTreeLock)
+        {
 
-    if( bHeldInService)
-    {
+            AFSReleaseResource( pVolume->ObjectInfoTree.TreeLock);
+        }
+
+        //
+        // Release the fid in the service
+        //
 
-        AFSReleaseFid( &FileId);
+        if( bHeldInService)
+        {
+
+            AFSReleaseFid( &FileId);
+        }
     }
 
     return;
@@ -7134,6 +7308,8 @@ AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
     __Enter
     {
 
+        ASSERT( Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY);
+
         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                           TRUE);
 
@@ -7347,27 +7523,27 @@ AFSUnwindFileInfo( IN AFSFcb *Fcb,
     UNREFERENCED_PARAMETER(Fcb);
     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
     {
-        Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
+        Fcb->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
     }
 
     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
     {
-        Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
+        Fcb->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
     }
 
     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
     {
-        Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
+        Fcb->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
     }
 
     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
     {
-        Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
+        Fcb->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
     }
 
     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
     {
-        Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
+        Fcb->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
     }
 
     return;
@@ -7635,7 +7811,11 @@ AFSCloseLibrary()
                           AFSGlobalDotDirEntry->ObjectInformation,
                           lCount));
 
-            AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
+            }
 
             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
 
@@ -7658,7 +7838,11 @@ AFSCloseLibrary()
                           AFSGlobalDotDotDirEntry->ObjectInformation,
                           lCount));
 
-            AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
+            if ( lCount == 0)
+            {
+
+                AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
+            }
 
             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
 
@@ -7688,7 +7872,11 @@ AFSCloseLibrary()
                               pDirNode->ObjectInformation,
                               lCount));
 
-                AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
+                if ( lCount == 0)
+                {
+
+                    AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
+                }
 
                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
 
@@ -8752,6 +8940,7 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
                             IN ULONG InvalidateReason)
 {
 
+    AFSDeviceExt       *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     NTSTATUS            ntStatus = STATUS_SUCCESS;
     LIST_ENTRY         *le;
     AFSExtent          *pEntry;
@@ -8817,244 +9006,256 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
 
                     bLocked = TRUE;
 
-                    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
-                                  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
-                                  PsGetCurrentThread()));
+                    if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
+                    {
 
-                    AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
-                                      TRUE);
+                        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSPerformObjectInvalidation DirectIO Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                                      &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                      PsGetCurrentThread()));
 
-                    bExtentsLocked = TRUE;
+                        AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                        TRUE);
 
-                    //
-                    // There are several possibilities here:
-                    //
-                    // 0. If there are no extents or all of the extents are dirty, do nothing.
-                    //
-                    // 1. There could be nothing dirty and an open reference count of zero
-                    //    in which case we can just tear down all of the extents without
-                    //    holding any resources.
-                    //
-                    // 2. There could be nothing dirty and a non-zero open reference count
-                    //    in which case we can issue a CcPurge against the entire file
-                    //    while holding just the Fcb Resource.
-                    //
-                    // 3. There can be dirty extents in which case we need to identify
-                    //    the non-dirty ranges and then perform a CcPurge on just the
-                    //    non-dirty ranges while holding just the Fcb Resource.
-                    //
+                        AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
 
-                    if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
-                    {
+                        bLocked = FALSE;
 
-                        if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
+                        __try
                         {
 
-                            AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
-
-                            bExtentsLocked = FALSE;
-
-                            if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
+                            if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
+                                !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                      NULL,
+                                                      0,
+                                                      FALSE))
                             {
 
-                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
-
-                                bLocked = FALSE;
+                                AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+                                              AFS_TRACE_LEVEL_WARNING,
+                                              "AFSPerformObjectInvalidation DirectIO CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                              ObjectInfo->FileId.Cell,
+                                              ObjectInfo->FileId.Volume,
+                                              ObjectInfo->FileId.Vnode,
+                                              ObjectInfo->FileId.Unique));
 
-                                AFSTearDownFcbExtents( ObjectInfo->Fcb,
-                                                       NULL);
+                                SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
                             }
                             else
                             {
 
-                                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                                              AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
-                                              &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
-                                              PsGetCurrentThread()));
-
-                                AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
-                                                TRUE);
+                                bCleanExtents = TRUE;
+                            }
+                        }
+                        __except( EXCEPTION_EXECUTE_HANDLER)
+                        {
 
-                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
+                            ntStatus = GetExceptionCode();
 
-                                bLocked = FALSE;
+                            AFSDbgTrace(( 0,
+                                          0,
+                                          "EXCEPTION - AFSPerformObjectInvalidation DirectIO FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
+                                          ObjectInfo->FileId.Cell,
+                                          ObjectInfo->FileId.Volume,
+                                          ObjectInfo->FileId.Vnode,
+                                          ObjectInfo->FileId.Unique,
+                                          ntStatus));
 
-                                __try
-                                {
+                            SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                        }
 
-                                    if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
-                                        !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                              NULL,
-                                                              0,
-                                                              FALSE))
-                                    {
+                        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSPerformObjectInvalidation DirectIO Releasing Fcb SectionObject lock %p EXCL %08lX\n",
+                                      &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                      PsGetCurrentThread()));
 
-                                        AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
-                                                      AFS_TRACE_LEVEL_WARNING,
-                                                      "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
-                                                      ObjectInfo->FileId.Cell,
-                                                      ObjectInfo->FileId.Volume,
-                                                      ObjectInfo->FileId.Vnode,
-                                                      ObjectInfo->FileId.Unique));
+                        AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
+                    }
+                    else
+                    {
 
-                                        SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
-                                    }
-                                    else
-                                    {
+                        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
+                                      &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                      PsGetCurrentThread()));
 
-                                        bCleanExtents = TRUE;
-                                    }
-                                }
-                                __except( EXCEPTION_EXECUTE_HANDLER)
-                                {
+                        AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                          TRUE);
 
-                                    ntStatus = GetExceptionCode();
+                        bExtentsLocked = TRUE;
+
+                        //
+                        // There are several possibilities here:
+                        //
+                        // 0. If there are no extents or all of the extents are dirty, do nothing.
+                        //
+                        // 1. There could be nothing dirty and an open reference count of zero
+                        //    in which case we can just tear down all of the extents without
+                        //    holding any resources.
+                        //
+                        // 2. There could be nothing dirty and a non-zero open reference count
+                        //    in which case we can issue a CcPurge against the entire file
+                        //    while holding just the Fcb Resource.
+                        //
+                        // 3. There can be dirty extents in which case we need to identify
+                        //    the non-dirty ranges and then perform a CcPurge on just the
+                        //    non-dirty ranges while holding just the Fcb Resource.
+                        //
+
+                        if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
+                        {
 
-                                    AFSDbgTrace(( 0,
-                                                  0,
-                                                  "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
-                                                  ObjectInfo->FileId.Cell,
-                                                  ObjectInfo->FileId.Volume,
-                                                  ObjectInfo->FileId.Vnode,
-                                                  ObjectInfo->FileId.Unique,
-                                                  ntStatus));
+                            if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
+                            {
 
-                                    SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
-                                }
+                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
 
-                                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                                              AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
-                                              &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
-                                              PsGetCurrentThread()));
+                                bExtentsLocked = FALSE;
 
-                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
-                            }
-                        }
-                        else
-                        {
+                                if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
+                                {
 
-                            AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
+                                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
 
-                            bExtentsLocked = FALSE;
+                                    bLocked = FALSE;
 
-                            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                                          AFS_TRACE_LEVEL_VERBOSE,
-                                          "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
-                                          &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
-                                          PsGetCurrentThread()));
+                                    AFSTearDownFcbExtents( ObjectInfo->Fcb,
+                                                           NULL);
+                                }
+                                else
+                                {
 
-                            AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
-                                            TRUE);
+                                    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                                                  &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                                  PsGetCurrentThread()));
 
-                            AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
+                                    AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                                    TRUE);
 
-                            bLocked = FALSE;
+                                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
 
-                            //
-                            // Must build a list of non-dirty ranges from the beginning of the file
-                            // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
-                            // ranges.  In all but the most extreme random data write scenario there will
-                            // be significantly fewer.
-                            //
-                            // For each range we need offset and size.
-                            //
+                                    bLocked = FALSE;
 
-                            AFSByteRange * ByteRangeList = NULL;
-                            ULONG          ulByteRangeCount = 0;
-                            ULONG          ulIndex;
-                            BOOLEAN        bPurgeOnClose = FALSE;
+                                    __try
+                                    {
 
-                            __try
-                            {
+                                        if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
+                                            !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                  NULL,
+                                                                  0,
+                                                                  FALSE))
+                                        {
 
-                                ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
-                                                                                   &ByteRangeList);
+                                            AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+                                                          AFS_TRACE_LEVEL_WARNING,
+                                                          "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                                          ObjectInfo->FileId.Cell,
+                                                          ObjectInfo->FileId.Volume,
+                                                          ObjectInfo->FileId.Vnode,
+                                                          ObjectInfo->FileId.Unique));
 
-                                if ( ByteRangeList != NULL ||
-                                     ulByteRangeCount == 0)
-                                {
+                                            SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                                        }
+                                        else
+                                        {
 
-                                    for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
+                                            bCleanExtents = TRUE;
+                                        }
+                                    }
+                                    __except( EXCEPTION_EXECUTE_HANDLER)
                                     {
 
-                                        ULONG ulSize;
+                                        ntStatus = GetExceptionCode();
 
-                                        do {
+                                        AFSDbgTrace(( 0,
+                                                      0,
+                                                      "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
+                                                      ObjectInfo->FileId.Cell,
+                                                      ObjectInfo->FileId.Volume,
+                                                      ObjectInfo->FileId.Vnode,
+                                                      ObjectInfo->FileId.Unique,
+                                                      ntStatus));
 
-                                            ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
+                                        SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                                    }
 
-                                            if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
-                                                !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                                      &ByteRangeList[ulIndex].FileOffset,
-                                                                      ulSize,
-                                                                      FALSE))
-                                            {
+                                    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
+                                                  &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                                  PsGetCurrentThread()));
 
-                                                AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
-                                                              AFS_TRACE_LEVEL_WARNING,
-                                                              "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
-                                                              ObjectInfo->FileId.Cell,
-                                                              ObjectInfo->FileId.Volume,
-                                                              ObjectInfo->FileId.Vnode,
-                                                              ObjectInfo->FileId.Unique));
+                                    AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
+                                }
+                            }
+                            else
+                            {
 
-                                                bPurgeOnClose = TRUE;
-                                            }
-                                            else
-                                            {
+                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
 
-                                                bCleanExtents = TRUE;
-                                            }
+                                bExtentsLocked = FALSE;
 
-                                            ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
+                                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                                              &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                              PsGetCurrentThread()));
 
-                                            ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
+                                AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                                TRUE);
 
-                                        } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
-                                    }
-                                }
-                                else
-                                {
+                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
 
-                                    //
-                                    // We couldn't allocate the memory to build the purge list
-                                    // so just walk the extent list while holding the ExtentsList Resource.
-                                    // This could deadlock but we do not have much choice.
-                                    //
+                                bLocked = FALSE;
 
-                                    AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
-                                                    TRUE);
-                                    bExtentsLocked = TRUE;
+                                //
+                                // Must build a list of non-dirty ranges from the beginning of the file
+                                // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
+                                // ranges.  In all but the most extreme random data write scenario there will
+                                // be significantly fewer.
+                                //
+                                // For each range we need offset and size.
+                                //
 
-                                    le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
+                                AFSByteRange * ByteRangeList = NULL;
+                                ULONG          ulByteRangeCount = 0;
+                                ULONG          ulIndex;
+                                BOOLEAN        bPurgeOnClose = FALSE;
 
-                                    ulProcessCount = 0;
+                                __try
+                                {
 
-                                    ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
+                                    ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
+                                                                                       &ByteRangeList);
 
-                                    if( ulCount > 0)
+                                    if ( ByteRangeList != NULL ||
+                                         ulByteRangeCount == 0)
                                     {
-                                        pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
 
-                                        while( ulProcessCount < ulCount)
+                                        for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
                                         {
-                                            pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
 
-                                            if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
-                                            {
-                                                if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                                          &pEntry->FileOffset,
-                                                                          pEntry->Size,
+                                            ULONG ulSize;
+
+                                            do {
+
+                                                ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
+
+                                                if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
+                                                    !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                          &ByteRangeList[ulIndex].FileOffset,
+                                                                          ulSize,
                                                                           FALSE))
                                                 {
 
                                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
                                                                   AFS_TRACE_LEVEL_WARNING,
-                                                                  "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                                                  "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
                                                                   ObjectInfo->FileId.Cell,
                                                                   ObjectInfo->FileId.Volume,
                                                                   ObjectInfo->FileId.Vnode,
@@ -9067,34 +9268,52 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
 
                                                     bCleanExtents = TRUE;
                                                 }
-                                            }
 
-                                            if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
-                                            {
+                                                ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
 
-                                                liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
+                                                ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
 
-                                                while( liFlushLength.QuadPart > 0)
-                                                {
+                                            } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
+                                        }
+                                    }
+                                    else
+                                    {
 
-                                                    if( liFlushLength.QuadPart > 512 * 1024000)
-                                                    {
-                                                        ulFlushLength = 512 * 1024000;
-                                                    }
-                                                    else
-                                                    {
-                                                        ulFlushLength = liFlushLength.LowPart;
-                                                    }
+                                        //
+                                        // We couldn't allocate the memory to build the purge list
+                                        // so just walk the extent list while holding the ExtentsList Resource.
+                                        // This could deadlock but we do not have much choice.
+                                        //
+
+                                        AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
+                                                        TRUE);
+                                        bExtentsLocked = TRUE;
+
+                                        le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
+
+                                        ulProcessCount = 0;
+
+                                        ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
+
+                                        if( ulCount > 0)
+                                        {
+                                            pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
+
+                                            while( ulProcessCount < ulCount)
+                                            {
+                                                pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
 
+                                                if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
+                                                {
                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                                              &liCurrentOffset,
-                                                                              ulFlushLength,
+                                                                              &pEntry->FileOffset,
+                                                                              pEntry->Size,
                                                                               FALSE))
                                                     {
 
                                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
                                                                       AFS_TRACE_LEVEL_WARNING,
-                                                                      "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                                                      "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
                                                                       ObjectInfo->FileId.Cell,
                                                                       ObjectInfo->FileId.Volume,
                                                                       ObjectInfo->FileId.Vnode,
@@ -9107,78 +9326,119 @@ AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
 
                                                         bCleanExtents = TRUE;
                                                     }
+                                                }
+
+                                                if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
+                                                {
+
+                                                    liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
+
+                                                    while( liFlushLength.QuadPart > 0)
+                                                    {
 
-                                                    liFlushLength.QuadPart -= ulFlushLength;
+                                                        if( liFlushLength.QuadPart > 512 * 1024000)
+                                                        {
+                                                            ulFlushLength = 512 * 1024000;
+                                                        }
+                                                        else
+                                                        {
+                                                            ulFlushLength = liFlushLength.LowPart;
+                                                        }
+
+                                                        if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                                  &liCurrentOffset,
+                                                                                  ulFlushLength,
+                                                                                  FALSE))
+                                                        {
+
+                                                            AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+                                                                          AFS_TRACE_LEVEL_WARNING,
+                                                                          "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                                                          ObjectInfo->FileId.Cell,
+                                                                          ObjectInfo->FileId.Volume,
+                                                                          ObjectInfo->FileId.Vnode,
+                                                                          ObjectInfo->FileId.Unique));
+
+                                                            bPurgeOnClose = TRUE;
+                                                        }
+                                                        else
+                                                        {
+
+                                                            bCleanExtents = TRUE;
+                                                        }
+
+                                                        liFlushLength.QuadPart -= ulFlushLength;
+                                                    }
                                                 }
-                                            }
 
-                                            liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
+                                                liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
 
-                                            ulProcessCount++;
-                                            le = le->Flink;
+                                                ulProcessCount++;
+                                                le = le->Flink;
+                                            }
                                         }
-                                    }
-                                    else
-                                    {
-                                        if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
-                                                                  NULL,
-                                                                  0,
-                                                                  FALSE))
+                                        else
                                         {
+                                            if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
+                                                                      NULL,
+                                                                      0,
+                                                                      FALSE))
+                                            {
 
-                                            AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
-                                                          AFS_TRACE_LEVEL_WARNING,
-                                                          "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
-                                                          ObjectInfo->FileId.Cell,
-                                                          ObjectInfo->FileId.Volume,
-                                                          ObjectInfo->FileId.Vnode,
-                                                          ObjectInfo->FileId.Unique));
+                                                AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
+                                                              AFS_TRACE_LEVEL_WARNING,
+                                                              "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
+                                                              ObjectInfo->FileId.Cell,
+                                                              ObjectInfo->FileId.Volume,
+                                                              ObjectInfo->FileId.Vnode,
+                                                              ObjectInfo->FileId.Unique));
+
+                                                bPurgeOnClose = TRUE;
+                                            }
+                                            else
+                                            {
 
-                                            bPurgeOnClose = TRUE;
+                                                bCleanExtents = TRUE;
+                                            }
                                         }
-                                        else
+
+                                        if ( bPurgeOnClose)
                                         {
 
-                                            bCleanExtents = TRUE;
+                                            SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
                                         }
                                     }
+                                }
+                                __except( EXCEPTION_EXECUTE_HANDLER)
+                                {
 
-                                    if ( bPurgeOnClose)
-                                    {
+                                    ntStatus = GetExceptionCode();
 
-                                        SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
-                                    }
+                                    AFSDbgTrace(( 0,
+                                                  0,
+                                                  "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                                                  ObjectInfo->FileId.Cell,
+                                                  ObjectInfo->FileId.Volume,
+                                                  ObjectInfo->FileId.Vnode,
+                                                  ObjectInfo->FileId.Unique,
+                                                  ntStatus));
                                 }
-                            }
-                            __except( EXCEPTION_EXECUTE_HANDLER)
-                            {
 
-                                ntStatus = GetExceptionCode();
+                                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
+                                              &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
+                                              PsGetCurrentThread()));
 
-                                AFSDbgTrace(( 0,
-                                              0,
-                                              "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
-                                              ObjectInfo->FileId.Cell,
-                                              ObjectInfo->FileId.Volume,
-                                              ObjectInfo->FileId.Vnode,
-                                              ObjectInfo->FileId.Unique,
-                                              ntStatus));
+                                AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
                             }
-
-                            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
-                                          AFS_TRACE_LEVEL_VERBOSE,
-                                          "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
-                                          &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
-                                          PsGetCurrentThread()));
-
-                            AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
                         }
-                    }
 
-                    if ( bExtentsLocked)
-                    {
+                        if ( bExtentsLocked)
+                        {
 
-                        AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
+                            AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
+                        }
                     }
 
                     if ( bLocked)