Windows: Performing async work after cache invalidation
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSExtentsSupport.cpp
index 9d702b5..f64381c 100644 (file)
@@ -39,7 +39,6 @@
 
 #define AFS_MAX_FCBS_TO_DROP 10
 
-static AFSExtent *ExtentFor( PLIST_ENTRY le, ULONG SkipList );
 static AFSExtent *NextExtent( AFSExtent *Extent, ULONG SkipList );
 static ULONG ExtentsMasks[AFS_NUM_EXTENT_LISTS] = AFS_EXTENTS_MASKS;
 static VOID VerifyExtentsLists(AFSFcb *Fcb);
@@ -121,6 +120,7 @@ AFSTearDownFcbExtents( IN AFSFcb *Fcb,
     AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
     GUID                *pAuthGroup = AuthGroup;
     GUID                 stAuthGroup;
+    LONG                 lCount;
 
     __Enter
     {
@@ -279,9 +279,11 @@ AFSTearDownFcbExtents( IN AFSFcb *Fcb,
                 le = le->Flink;
                 AFSExFreePool( pEntry);
 
-                InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+                lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
 
-                if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+                lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+                if( lCount == 0)
                 {
 
                     KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
@@ -798,6 +800,34 @@ AFSRequestExtentsAsync( IN AFSFcb *Fcb,
                                           NULL,
                                           NULL);
 
+            if (  ntStatus == STATUS_ACCESS_DENIED)
+            {
+                GUID                 stAuthGroup;
+                DWORD                ntStatus2;
+
+                ntStatus2 = AFSRetrieveValidAuthGroup( Fcb,
+                                                      NULL,
+                                                      TRUE,
+                                                      &stAuthGroup);
+
+                if ( NT_SUCCESS( ntStatus2) &&
+                     RtlCompareMemory( &stAuthGroup,
+                                       &Ccb->AuthGroup,
+                                       sizeof( GUID)) != sizeof( GUID))
+                {
+
+                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS,
+                                                  0,
+                                                  &stAuthGroup,
+                                                  NULL,
+                                                  &Fcb->ObjectInformation->FileId,
+                                                  &request,
+                                                  sizeof( AFSRequestExtentsCB ),
+                                                  NULL,
+                                                  NULL);
+                }
+            }
+
             if( NT_SUCCESS( ntStatus))
             {
 
@@ -832,6 +862,7 @@ AFSProcessExtentsResult( IN AFSFcb *Fcb,
     BOOLEAN           bFoundExtent = FALSE;
     LIST_ENTRY       *pSkipEntries[AFS_NUM_EXTENT_LISTS] = { 0 };
     AFSDeviceExt     *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+    LONG              lCount;
 
     //
     // Grab the extents exclusive for the duration
@@ -1009,9 +1040,11 @@ AFSProcessExtentsResult( IN AFSFcb *Fcb,
 
                 InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, (LONG)(pExtent->Size/1024));
 
-                InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
+                lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentCount);
+
+                lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount);
 
-                if( InterlockedIncrement( &pControlDevExt->Specific.Control.ExtentCount) == 1)
+                if( lCount == 1)
                 {
 
                     KeClearEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent);
@@ -1219,6 +1252,7 @@ AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     ULONGLONG     ullIndex = 0;
     AFSObjectInfoCB *pObjectInfo = NULL;
+    LONG          lCount;
 
     __Enter
     {
@@ -1258,7 +1292,7 @@ AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
                           pVolumeCB->ObjectInfoTree.TreeLock,
                           PsGetCurrentThread());
 
-            InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
         }
 
         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
@@ -1282,7 +1316,7 @@ AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
                           TRUE);
 
-        InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
         //
         // Now locate the Object in this volume
@@ -1301,13 +1335,13 @@ AFSProcessSetFileExtents( IN AFSSetFileExtentsCB *SetExtents )
             // Reference the node so it won't be torn down
             //
 
-            InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+            lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSProcessSetFileExtents Increment count on object %08lX Cnt %d\n",
                           pObjectInfo,
-                          pObjectInfo->ObjectReferenceCount);
+                          lCount);
         }
 
         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
@@ -1382,13 +1416,13 @@ try_exit:
         if( pObjectInfo != NULL)
         {
 
-            InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
+            lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSProcessSetFileExtents Decrement count on object %08lX Cnt %d\n",
                           pObjectInfo,
-                          pObjectInfo->ObjectReferenceCount);
+                          lCount);
         }
     }
 
@@ -1413,6 +1447,7 @@ AFSReleaseSpecifiedExtents( IN  AFSReleaseFileExtentsCB *Extents,
     NTSTATUS             ntStatus = STATUS_SUCCESS;
     BOOLEAN              bReleaseAll = FALSE;
     AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+    LONG                 lCount;
 
     __Enter
     {
@@ -1590,7 +1625,7 @@ AFSReleaseSpecifiedExtents( IN  AFSReleaseFileExtentsCB *Extents,
 
                     FileExtents[*ExtentCount].Flags |= AFS_EXTENT_FLAG_DIRTY;
 
-                    InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
+                    lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
 
                     *DirtyExtents = TRUE;
                 }
@@ -1625,9 +1660,11 @@ AFSReleaseSpecifiedExtents( IN  AFSReleaseFileExtentsCB *Extents,
             //
             AFSExFreePool( pExtent);
 
-            InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+            lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
 
-            if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+            lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+            if( lCount == 0)
             {
 
                 KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
@@ -1655,6 +1692,7 @@ AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
     BOOLEAN bLocatedEntry = FALSE;
     AFSObjectInfoCB *pCurrentObject = NULL;
     BOOLEAN bReleaseVolumeListLock = FALSE;
+    LONG lCount;
 
     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
@@ -1685,7 +1723,7 @@ AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
                       pVolumeCB->ObjectInfoTree.TreeLock,
                       PsGetCurrentThread());
 
-        InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+        lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
 
         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
 
@@ -1694,7 +1732,7 @@ AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
                           TRUE);
 
-        InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
         if( NULL == LastFcb)
         {
@@ -1812,13 +1850,13 @@ AFSFindFcbToClean(ULONG IgnoreTime, AFSFcb *LastFcb, BOOLEAN Block)
                 // A hit a very palpable hit.  Pin it
                 //
 
-                InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
+                lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSFindFcbToClean Increment count on Fcb %08lX Cnt %d\n",
                               pCurrentObject,
-                              pCurrentObject->ObjectReferenceCount);
+                              lCount);
 
                 bLocatedEntry = TRUE;
 
@@ -1864,6 +1902,7 @@ AFSProcessExtentFailure( PIRP Irp)
     AFSVolumeCB                       *pVolumeCB = NULL;
     ULONGLONG                          ullIndex = 0;
     AFSObjectInfoCB                   *pObjectInfo = NULL;
+    LONG                               lCount;
 
     __Enter
     {
@@ -1909,7 +1948,7 @@ AFSProcessExtentFailure( PIRP Irp)
                           pVolumeCB->ObjectInfoTree.TreeLock,
                           PsGetCurrentThread());
 
-            InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
         }
 
         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
@@ -1929,7 +1968,7 @@ AFSProcessExtentFailure( PIRP Irp)
         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
                           TRUE);
 
-        InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+        lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
         //
         // Now locate the Object in this volume
@@ -1949,13 +1988,13 @@ AFSProcessExtentFailure( PIRP Irp)
             // Reference the node so it won't be torn down
             //
 
-            InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+            lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSProcessExtentFailure Increment count on object %08lX Cnt %d\n",
                           pObjectInfo,
-                          pObjectInfo->ObjectReferenceCount);
+                          lCount);
         }
 
         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
@@ -2010,13 +2049,13 @@ AFSProcessExtentFailure( PIRP Irp)
 
         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
 
-        InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
+        lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSProcessExtentFailure Decrement count on object %08lX Cnt %d\n",
                       pObjectInfo,
-                      pObjectInfo->ObjectReferenceCount);
+                      lCount);
 
 try_exit:
 
@@ -2044,6 +2083,7 @@ AFSProcessReleaseFileExtents( IN PIRP Irp)
     BOOLEAN                            bLocked = FALSE;
     BOOLEAN                            bDirtyExtents = FALSE;
     GUID                               stAuthGroup;
+    LONG                               lCount;
 
     __Enter
     {
@@ -2147,7 +2187,7 @@ AFSProcessReleaseFileExtents( IN PIRP Irp)
                               pVolumeCB->ObjectInfoTree.TreeLock,
                               PsGetCurrentThread());
 
-                InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
+                lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
             }
 
             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
@@ -2167,7 +2207,7 @@ AFSProcessReleaseFileExtents( IN PIRP Irp)
             AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
                               TRUE);
 
-            InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
+            lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
 
             //
             // Now locate the Object in this volume
@@ -2186,13 +2226,13 @@ AFSProcessReleaseFileExtents( IN PIRP Irp)
                 // Reference the node so it won't be torn down
                 //
 
-                InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
+                lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSProcessReleaseFileExtents Increment count on object %08lX Cnt %d\n",
                               pObjectInfo,
-                              pObjectInfo->ObjectReferenceCount);
+                              lCount);
             }
 
             AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
@@ -2411,13 +2451,13 @@ try_exit:
         if( pObjectInfo != NULL)
         {
 
-            InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
+            lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSProcessReleaseFileExtents Decrement count on object %08lX Cnt %d\n",
                           pObjectInfo,
-                          pObjectInfo->ObjectReferenceCount);
+                          lCount);
         }
     }
 
@@ -2528,6 +2568,7 @@ AFSFlushExtents( IN AFSFcb *Fcb,
     AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
     GUID                *pAuthGroup = AuthGroup;
     GUID                 stAuthGroup;
+    LONG                 lCount;
 
     ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
 
@@ -2573,7 +2614,7 @@ AFSFlushExtents( IN AFSFcb *Fcb,
 
         bExtentsLocked = TRUE;
 
-        InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
+        lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
 
         //
         // Clear our queued flush event
@@ -2650,7 +2691,7 @@ AFSFlushExtents( IN AFSFcb *Fcb,
                 pExtent->DirtyList.fLink = NULL;
                 pExtent->DirtyList.bLink = NULL;
 
-                InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
+                lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
 
                 //
                 // Clear the flag in advance of the write. If we do
@@ -2708,9 +2749,11 @@ AFSFlushExtents( IN AFSFcb *Fcb,
 
                 AFSExFreePool( pExtent);
 
-                InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+                lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
 
-                if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+                lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+                if( lCount == 0)
                 {
 
                     KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
@@ -2795,7 +2838,9 @@ AFSFlushExtents( IN AFSFcb *Fcb,
 
 try_exit:
 
-        if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
+        lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
+
+        if( lCount == 0)
         {
 
             KeSetEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
@@ -2847,6 +2892,7 @@ AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
     AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
     GUID                *pAuthGroup = AuthGroup;
     GUID                 stAuthGroup;
+    LONG                 lCount;
 
     ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
 
@@ -2992,7 +3038,7 @@ AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
 
                         pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_DIRTY;
 
-                        InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
+                        lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentsDirtyCount);
                     }
 
                     AFSReleaseResource( &pNPFcb->Specific.File.DirtyExtentsListLock);
@@ -3016,9 +3062,11 @@ AFSReleaseExtentsWithFlush( IN AFSFcb *Fcb,
 
                 AFSExFreePool( pExtent);
 
-                InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+                lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
 
-                if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+                lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+                if( lCount == 0)
                 {
 
                     KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
@@ -3120,6 +3168,264 @@ try_exit:
     return ntStatus;
 }
 
+NTSTATUS
+AFSReleaseCleanExtents( IN AFSFcb *Fcb,
+                        IN GUID *AuthGroup)
+{
+    AFSNonPagedFcb      *pNPFcb = Fcb->NPFcb;
+    AFSExtent           *pExtent;
+    LIST_ENTRY          *le;
+    AFSReleaseExtentsCB *pRelease = NULL;
+    ULONG                count = 0;
+    ULONG                initialDirtyCount = 0;
+    BOOLEAN              bExtentsLocked = FALSE;
+    ULONG                total = 0;
+    ULONG                sz = 0;
+    NTSTATUS             ntStatus = STATUS_SUCCESS;
+    LARGE_INTEGER        liLastFlush;
+    ULONG                ulRemainingExtentLength = 0;
+    AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+    GUID                *pAuthGroup = AuthGroup;
+    GUID                 stAuthGroup;
+
+    ASSERT( Fcb->Header.NodeTypeCode == AFS_FILE_FCB);
+
+    //
+    // Save, then reset the flush time
+    //
+
+    liLastFlush = Fcb->Specific.File.LastServerFlush;
+
+    KeQueryTickCount( &Fcb->Specific.File.LastServerFlush);
+
+    __Enter
+    {
+
+        if( pAuthGroup == NULL ||
+            RtlCompareMemory( pAuthGroup,
+                              &Fcb->NPFcb->Specific.File.ExtentsRequestAuthGroup,
+                              sizeof( GUID)) == sizeof( GUID))
+        {
+
+            RtlZeroMemory( &stAuthGroup,
+                           sizeof( GUID));
+
+            ntStatus = AFSRetrieveValidAuthGroup( Fcb,
+                                                  NULL,
+                                                  TRUE,
+                                                  &stAuthGroup);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+                try_return( ntStatus);
+            }
+
+            pAuthGroup = &stAuthGroup;
+        }
+
+        //
+        // Look for a start in the list to flush entries
+        //
+
+        total = count;
+
+        sz = sizeof( AFSReleaseExtentsCB ) + (AFS_MAXIMUM_EXTENT_RELEASE_COUNT * sizeof ( AFSFileExtentCB ));
+
+        pRelease = (AFSReleaseExtentsCB*) AFSExAllocatePoolWithTag( NonPagedPool,
+                                                                    sz,
+                                                                    AFS_EXTENT_RELEASE_TAG);
+        if( NULL == pRelease)
+        {
+
+            try_return ( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
+        }
+
+        while( Fcb->Specific.File.ExtentLength > (LONG)ulRemainingExtentLength)
+        {
+
+            AFSLockForExtentsTrim( Fcb);
+
+            bExtentsLocked = TRUE;
+
+            pRelease->Flags = AFS_EXTENT_FLAG_RELEASE;
+
+            //
+            // Update the metadata for this call
+            //
+
+            pRelease->AllocationSize = Fcb->ObjectInformation->EndOfFile;
+            pRelease->CreateTime = Fcb->ObjectInformation->CreationTime;
+            pRelease->ChangeTime = Fcb->ObjectInformation->ChangeTime;
+            pRelease->LastAccessTime = Fcb->ObjectInformation->LastAccessTime;
+            pRelease->LastWriteTime = Fcb->ObjectInformation->LastWriteTime;
+
+            count = 0;
+
+            le = Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
+
+            while( count < AFS_MAXIMUM_EXTENT_RELEASE_COUNT &&
+                   le != &Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST])
+            {
+
+                pExtent = ExtentFor( le, AFS_EXTENTS_LIST);
+
+                le = le->Flink;
+
+                if( pExtent->ActiveCount > 0 ||
+                    BooleanFlagOn( pExtent->Flags, AFS_EXTENT_DIRTY))
+                {
+                    continue;
+                }
+
+                pRelease->FileExtents[count].Flags = AFS_EXTENT_FLAG_RELEASE;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSReleaseCleanExtents Releasing extent %p fid %08lX-%08lX-%08lX-%08lX Offset %I64X Len %08lX\n",
+                              pExtent,
+                              Fcb->ObjectInformation->FileId.Cell,
+                              Fcb->ObjectInformation->FileId.Volume,
+                              Fcb->ObjectInformation->FileId.Vnode,
+                              Fcb->ObjectInformation->FileId.Unique,
+                              pExtent->FileOffset.QuadPart,
+                              pExtent->Size);
+
+                pRelease->FileExtents[count].Length = pExtent->Size;
+                pRelease->FileExtents[count].DirtyLength = pExtent->Size;
+                pRelease->FileExtents[count].DirtyOffset = 0;
+                pRelease->FileExtents[count].CacheOffset = pExtent->CacheOffset;
+                pRelease->FileExtents[count].FileOffset = pExtent->FileOffset;
+
+#if GEN_MD5
+                RtlCopyMemory( pRelease->FileExtents[count].MD5,
+                               pExtent->MD5,
+                               sizeof(pExtent->MD5));
+
+                pRelease->FileExtents[count].Flags |= AFS_EXTENT_FLAG_MD5_SET;
+#endif
+
+                //
+                // Need to pull this extent from the main list as well
+                //
+
+                for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i ++)
+                {
+                    if (NULL != pExtent->Lists[i].Flink && !IsListEmpty(&pExtent->Lists[i]))
+                    {
+                        RemoveEntryList( &pExtent->Lists[i] );
+                    }
+                }
+
+                InterlockedExchangeAdd( &pControlDevExt->Specific.Control.ExtentsHeldLength, -((LONG)(pExtent->Size/1024)));
+
+                InterlockedExchangeAdd( &Fcb->Specific.File.ExtentLength, -((LONG)(pExtent->Size/1024)));
+
+                AFSExFreePool( pExtent);
+
+                InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+
+                if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+                {
+
+                    KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
+                                0,
+                                FALSE);
+                }
+
+                count ++;
+            }
+
+            //
+            // If we are done then get out
+            //
+
+            if( count == 0)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSReleaseCleanExtents No more dirty extents found\n");
+
+                break;
+            }
+
+            //
+            // Fire off the request synchronously
+            //
+
+            sz = sizeof( AFSReleaseExtentsCB ) + (count * sizeof ( AFSFileExtentCB ));
+
+            pRelease->ExtentCount = count;
+
+            //
+            // Drop the extents lock for the duration of the call to
+            // the network.  We have pinned the extents so, even
+            // though we might get extents added during this period,
+            // but none will be removed.  Hence we can carry on from
+            // le.
+            //
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
+                          &pNPFcb->Specific.File.ExtentsResource,
+                          PsGetCurrentThread());
+
+            AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource);
+            bExtentsLocked = FALSE;
+
+            ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS,
+                                          AFS_REQUEST_FLAG_SYNCHRONOUS,
+                                          pAuthGroup,
+                                          NULL,
+                                          &Fcb->ObjectInformation->FileId,
+                                          pRelease,
+                                          sz,
+                                          NULL,
+                                          NULL);
+
+            if( !NT_SUCCESS(ntStatus))
+            {
+
+                //
+                // Regardless of whether or not the AFSProcessRequest() succeeded, the extents
+                // were released (if AFS_EXTENT_FLAG_RELEASE was set).  Log the error so it is known.
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSReleaseCleanExtents AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS failed fid %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                              Fcb->ObjectInformation->FileId.Cell,
+                              Fcb->ObjectInformation->FileId.Volume,
+                              Fcb->ObjectInformation->FileId.Vnode,
+                              Fcb->ObjectInformation->FileId.Unique,
+                              ntStatus);
+            }
+        }
+
+try_exit:
+
+        if (bExtentsLocked)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSReleaseCleanExtents Releasing Fcb extents lock %08lX thread %08lX\n",
+                          &pNPFcb->Specific.File.ExtentsResource,
+                          PsGetCurrentThread());
+
+            AFSReleaseResource( &pNPFcb->Specific.File.ExtentsResource );
+        }
+
+        if (pRelease)
+        {
+            AFSExFreePool( pRelease);
+        }
+    }
+
+    return ntStatus;
+}
+
 VOID
 AFSMarkDirty( IN AFSFcb *Fcb,
               IN AFSExtent *StartExtent,
@@ -3132,6 +3438,7 @@ AFSMarkDirty( IN AFSFcb *Fcb,
     AFSExtent     *pNextExtent, *pCurrentExtent = NULL;
     ULONG ulCount = 0;
     BOOLEAN bInsertTail = FALSE, bInsertHead = FALSE;
+    LONG lCount;
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
@@ -3255,7 +3562,7 @@ AFSMarkDirty( IN AFSFcb *Fcb,
             // Up the dirty count
             //
 
-            InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
+            lCount = InterlockedIncrement( &Fcb->Specific.File.ExtentsDirtyCount);
         }
         else
         {
@@ -3271,7 +3578,7 @@ AFSMarkDirty( IN AFSFcb *Fcb,
 
         ASSERT( pExtent->ActiveCount > 0);
 
-        InterlockedDecrement( &pExtent->ActiveCount);
+        lCount = InterlockedDecrement( &pExtent->ActiveCount);
 
         pExtent = pNextExtent;
 
@@ -3295,7 +3602,8 @@ AFSMarkDirty( IN AFSFcb *Fcb,
 // Helper functions
 //
 
-static AFSExtent *ExtentFor(PLIST_ENTRY le, ULONG SkipList)
+AFSExtent *
+ExtentFor(PLIST_ENTRY le, ULONG SkipList)
 {
     return CONTAINING_RECORD( le, AFSExtent, Lists[SkipList] );
 }
@@ -3379,6 +3687,7 @@ AFSTrimExtents( IN AFSFcb *Fcb,
     LARGE_INTEGER        liAlignedOffset = {0,0};
     AFSDeviceExt        *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+    LONG                 lCount;
 
     __Enter
     {
@@ -3518,9 +3827,11 @@ AFSTrimExtents( IN AFSFcb *Fcb,
                 //
                 AFSExFreePool( pExtent);
 
-                InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+                lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
 
-                if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+                lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+                if( lCount == 0)
                 {
 
                     KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
@@ -3567,6 +3878,7 @@ AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
     NTSTATUS             ntStatus = STATUS_SUCCESS;
     AFSDeviceExt        *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     AFSDeviceExt        *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
+    LONG                 lCount;
 
     __Enter
     {
@@ -3642,9 +3954,11 @@ AFSTrimSpecifiedExtents( IN AFSFcb *Fcb,
                 //
                 AFSExFreePool( pExtent);
 
-                InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
+                lCount = InterlockedDecrement( &Fcb->Specific.File.ExtentCount);
 
-                if( InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount) == 0)
+                lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.ExtentCount);
+
+                if( lCount == 0)
                 {
 
                     KeSetEvent( &pControlDevExt->Specific.Control.ExtentsHeldEvent,
@@ -3680,19 +3994,20 @@ AFSReferenceActiveExtents( IN AFSExtent *StartExtent,
     AFSExtent     *pExtent = StartExtent;
     AFSExtent     *pNextExtent;
     ULONG          ulCount = 0;
+    LONG           lCount;
 
     while( ulCount < ExtentsCount)
     {
 
         pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
 
-        InterlockedIncrement( &pExtent->ActiveCount);
+        lCount = InterlockedIncrement( &pExtent->ActiveCount);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSReferenceActiveExtents Increment count on extent %08lX Cnt %d\n",
                       pExtent,
-                      pExtent->ActiveCount);
+                      lCount);
 
         pExtent = pNextExtent;
 
@@ -3710,21 +4025,22 @@ AFSDereferenceActiveExtents( IN AFSExtent *StartExtent,
     AFSExtent     *pExtent = StartExtent;
     AFSExtent     *pNextExtent;
     ULONG          ulCount = 0;
+    LONG            lCount;
 
     while( ulCount < ExtentsCount)
     {
 
         pNextExtent = NextExtent( pExtent, AFS_EXTENTS_LIST);
 
+        ASSERT( pExtent->ActiveCount > 0);
+
+        lCount = InterlockedDecrement( &pExtent->ActiveCount);
+
         AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_ACTIVE_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSDereferenceActiveExtents Decrement count on extent %08lX Cnt %d\n",
                       pExtent,
-                      pExtent->ActiveCount);
-
-        ASSERT( pExtent->ActiveCount > 0);
-
-        InterlockedDecrement( &pExtent->ActiveCount);
+                      lCount);
 
         pExtent = pNextExtent;