Windows: AFSTearDownExtents may experience active extents
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSWorker.cpp
index 7507a57..b33658d 100644 (file)
@@ -70,7 +70,7 @@ AFSInitializeWorkerPool()
         pDevExt->Specific.Library.WorkerCount = 0;
 
         KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
-                           NotificationEvent,
+                           SynchronizationEvent,
                            FALSE);
 
         //
@@ -152,7 +152,7 @@ AFSInitializeWorkerPool()
         pDevExt->Specific.Library.IOWorkerCount = 0;
 
         KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
-                           NotificationEvent,
+                           SynchronizationEvent,
                            FALSE);
 
         //
@@ -265,7 +265,10 @@ AFSRemoveWorkerPool()
     pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
     //
-    // Loop through the workers shutting them down
+    // Loop through the workers shutting them down in two stages.
+    // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
+    // stop processing requests.  Second, call AFSShutdownWorkerThread()
+    // to wake the workers and wait for them to exit.
     //
 
     pCurrentWorker = pDevExt->Specific.Library.PoolHead;
@@ -273,6 +276,26 @@ AFSRemoveWorkerPool()
     while( index < pDevExt->Specific.Library.WorkerCount)
     {
 
+        ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
+
+        pCurrentWorker = pCurrentWorker->fLink;
+
+        if ( pCurrentWorker == NULL)
+        {
+
+            break;
+        }
+
+        index++;
+    }
+
+    pCurrentWorker = pDevExt->Specific.Library.PoolHead;
+
+    index = 0;
+
+    while( index < pDevExt->Specific.Library.WorkerCount)
+    {
+
         ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
 
         pNextWorker = pCurrentWorker->fLink;
@@ -295,7 +318,10 @@ AFSRemoveWorkerPool()
     ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
 
     //
-    // Loop through the IO workers shutting them down
+    // Loop through the IO workers shutting them down in two stages.
+    // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
+    // stop processing requests.  Second, call AFSShutdownWorkerThread()
+    // to wake the workers and wait for them to exit.
     //
 
     pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
@@ -305,6 +331,26 @@ AFSRemoveWorkerPool()
     while( index < pDevExt->Specific.Library.IOWorkerCount)
     {
 
+        ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
+
+        pCurrentWorker = pCurrentWorker->fLink;
+
+        if ( pCurrentWorker == NULL)
+        {
+
+            break;
+        }
+
+        index++;
+    }
+
+    pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
+
+    index = 0;
+
+    while( index < pDevExt->Specific.Library.IOWorkerCount)
+    {
+
         ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
 
         pNextWorker = pCurrentWorker->fLink;
@@ -515,7 +561,7 @@ AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
 //
 // Description:
 //
-//      This function shusdown a worker thread in the pool
+//      This function shutsdown a worker thread in the pool
 //
 // Return:
 //
@@ -534,12 +580,6 @@ AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
     {
 
         //
-        // Clear the 'keep processing' flag
-        //
-
-        ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
-
-        //
         // Wake up the thread if it is a sleep
         //
 
@@ -585,12 +625,6 @@ AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
     {
 
         //
-        // Clear the 'keep processing' flag
-        //
-
-        ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
-
-        //
         // Wake up the thread if it is a sleep
         //
 
@@ -632,7 +666,6 @@ AFSWorkerThread( IN PVOID Context)
     AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
     AFSWorkItem *pWorkItem;
     BOOLEAN freeWorkItem = TRUE;
-    BOOLEAN exitThread = FALSE;
     AFSDeviceExt *pLibraryDevExt = NULL;
     LONG lCount;
 
@@ -646,35 +679,45 @@ AFSWorkerThread( IN PVOID Context)
                 0,
                 FALSE);
 
-
     //
     // Indicate we are initialized
     //
 
     SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
 
+    ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
+                                      Executive,
+                                      KernelMode,
+                                      FALSE,
+                                      NULL);
+
     while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
     {
 
-        ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL);
-
         if( !NT_SUCCESS( ntStatus))
         {
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
                           "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
+
+            ntStatus = STATUS_SUCCESS;
         }
         else
         {
 
             pWorkItem = AFSRemoveWorkItem();
 
-            if( pWorkItem != NULL)
+            if( pWorkItem == NULL)
+            {
+
+                ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
+                                                  Executive,
+                                                  KernelMode,
+                                                  FALSE,
+                                                  NULL);
+            }
+            else
             {
 
                 freeWorkItem = TRUE;
@@ -770,10 +813,20 @@ AFSWorkerThread( IN PVOID Context)
 
                     ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
                 }
+
+                ntStatus = STATUS_SUCCESS;
             }
         }
     } // worker thread loop
 
+    ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+
+    // Wake up another worker so they too can exit
+
+    KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
+                0,
+                FALSE);
+
     PsTerminateSystemThread( 0);
 
     return;
@@ -787,7 +840,6 @@ AFSIOWorkerThread( IN PVOID Context)
     AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
     AFSWorkItem *pWorkItem;
     BOOLEAN freeWorkItem = TRUE;
-    BOOLEAN exitThread = FALSE;
     AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
 
     pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
@@ -807,28 +859,39 @@ AFSIOWorkerThread( IN PVOID Context)
 
     SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
 
+    ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
+                                      Executive,
+                                      KernelMode,
+                                      FALSE,
+                                      NULL);
+
     while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
     {
 
-        ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL);
-
         if( !NT_SUCCESS( ntStatus))
         {
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
                           "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
+
+            ntStatus = STATUS_SUCCESS;
         }
         else
         {
 
             pWorkItem = AFSRemoveIOWorkItem();
 
-            if( pWorkItem != NULL)
+            if( pWorkItem == NULL)
+            {
+
+                ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
+                                                  Executive,
+                                                  KernelMode,
+                                                  FALSE,
+                                                  NULL);
+            }
+            else
             {
 
                 freeWorkItem = TRUE;
@@ -884,10 +947,20 @@ AFSIOWorkerThread( IN PVOID Context)
 
                     ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
                 }
+
+                ntStatus = STATUS_SUCCESS;
             }
         }
     } // worker thread loop
 
+    ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+
+    // Wake up another IOWorker so they too can exit
+
+    KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
+                0,
+                FALSE);
+
     PsTerminateSystemThread( 0);
 
     return;
@@ -901,7 +974,6 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
     AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
     AFSDeviceExt *pControlDeviceExt = NULL;
     AFSDeviceExt *pRDRDeviceExt = NULL;
-    BOOLEAN exitThread = FALSE;
     LARGE_INTEGER DueTime;
     LONG TimeOut;
     KTIMER Timer;
@@ -910,6 +982,8 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
     BOOLEAN bReleaseVolumeLock = FALSE;
     AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
+    AFSFcb *pFcb = NULL;
+    LONG lFileType;
     LARGE_INTEGER liCurrentTime;
     BOOLEAN bVolumeObject = FALSE;
     LONG lCount;
@@ -984,8 +1058,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                 continue;
             }
 
-            if( pVolumeCB->ObjectInfoListHead == NULL &&
-                pVolumeCB != AFSGlobalRoot)
+            if( pVolumeCB->ObjectInfoListHead == NULL)
             {
 
                 AFSReleaseResource( pVolumeCB->VolumeLock);
@@ -1020,7 +1093,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                     pVolumeCB->VolumeReferenceCount == 1 &&
                     ( pVolumeCB->RootFcb == NULL ||
                       pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
-                    pVolumeCB->ObjectInformation.ObjectReferenceCount == 0)
+                    pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
                 {
 
                     if( pVolumeCB->RootFcb != NULL)
@@ -1102,7 +1175,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                         //
 
                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
-                            pCurrentObject->ObjectReferenceCount == 0 &&
+                            pCurrentObject->ObjectReferenceCount <= 0 &&
                             ( pCurrentObject->Fcb == NULL ||
                               pCurrentObject->Fcb->OpenReferenceCount == 0) &&
                             pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
@@ -1111,53 +1184,50 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                             AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
 
+                            //
+                            // Dropping the TreeLock permits the
+                            // pCurrentObject->ObjectReferenceCount to change
+                            //
+
                             if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
                                                 FALSE))
                             {
 
-                                if( pCurrentObject->Fcb != NULL)
+                                if ( pCurrentObject->ObjectReferenceCount <= 0)
                                 {
 
-                                    //
-                                    // Acquire and drop the Fcb resource to synchronize
-                                    // with a potentially active AFSCleanup() which sets
-                                    // the OpenReferenceCount to zero while holding the
-                                    // resource.
-                                    //
+                                    if( pCurrentObject->Fcb != NULL)
+                                    {
 
-                                    AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
-                                                    TRUE);
+                                        AFSRemoveFcb( &pCurrentObject->Fcb);
+                                    }
 
-                                    AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
+                                    if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
+                                    {
 
-                                    AFSRemoveFcb( pCurrentObject->Fcb);
-                                }
+                                        if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
+                                        {
 
-                                if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
-                                {
+                                            AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+                                        }
 
-                                    if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
-                                    {
+                                        AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
 
-                                        AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
-                                    }
+                                        ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
 
-                                    AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
+                                        AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
 
-                                    ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
+                                        AFSExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
+                                    }
 
-                                    AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
+                                    AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSPrimaryVolumeWorkerThread Deleting deleted object %08lX\n",
+                                                  pCurrentObject);
 
-                                    AFSExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
+                                    AFSDeleteObjectInfo( pCurrentObject);
                                 }
 
-                                AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
-                                              AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSPrimaryWorker Deleting deleted object %08lX\n",
-                                              pCurrentObject);
-
-                                AFSDeleteObjectInfo( pCurrentObject);
-
                                 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
 
                                 pCurrentObject = pNextObject;
@@ -1306,41 +1376,52 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                                     pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
 
+                                    pFcb = NULL;
+
                                     AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                                   AFS_TRACE_LEVEL_VERBOSE,
-                                                  "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
+                                                  "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %08lX\n",
                                                   &pCurrentDirEntry->NameInformation.FileName,
                                                   pCurrentChildObject);
 
                                     AFSDeleteDirEntry( pCurrentObject,
                                                        pCurrentDirEntry);
 
-                                    if( pCurrentChildObject->ObjectReferenceCount == 0)
+                                    if( pCurrentChildObject->ObjectReferenceCount <= 0 &&
+                                        pCurrentChildObject->Fcb != NULL &&
+                                        pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
                                     {
 
-                                        if( pCurrentChildObject->Fcb != NULL)
-                                        {
+                                        //
+                                        // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
+                                        // across an AFSCleanupFcb call since it can deadlock with an
+                                        // invalidation call from the service.
+                                        //
 
-                                            if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
-                                            {
+                                        AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
 
-                                                AFSCleanupFcb( pCurrentChildObject->Fcb,
-                                                               TRUE);
-                                            }
+                                        //
+                                        // Dropping the TreeLock permits the
+                                        // pCurrentObject->ObjectReferenceCount to change
+                                        //
 
-                                            //
-                                            // Acquire and drop the Fcb resource to synchronize
-                                            // with a potentially active AFSCleanup() which sets
-                                            // the OpenReferenceCount to zero while holding the
-                                            // resource.
-                                            //
+                                        AFSCleanupFcb( pCurrentChildObject->Fcb,
+                                                       TRUE);
 
-                                            AFSAcquireExcl( &pCurrentChildObject->Fcb->NPFcb->Resource,
-                                                            TRUE);
+                                        AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
+                                                        TRUE);
+                                    }
 
-                                            AFSReleaseResource( &pCurrentChildObject->Fcb->NPFcb->Resource);
+                                    if( pCurrentChildObject->ObjectReferenceCount <= 0 &&
+                                        ( pCurrentChildObject->Fcb == NULL ||
+                                          pCurrentChildObject->Fcb->OpenReferenceCount == 0 &&
+                                          pCurrentChildObject->Fcb->Specific.File.ExtentCount == 0))
+                                    {
 
-                                            AFSRemoveFcb( pCurrentChildObject->Fcb);
+                                        if( pCurrentChildObject->Fcb != NULL)
+                                        {
+                                        
+                                            AFSRemoveFcb( &pCurrentChildObject->Fcb);
                                         }
 
                                         if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
@@ -1350,7 +1431,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                                             if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
                                             {
 
-                                                AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+                                                AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
                                             }
 
                                             AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
@@ -1364,13 +1445,14 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                                         AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                                       AFS_TRACE_LEVEL_VERBOSE,
-                                                      "AFSPrimaryWorker Deleting object %08lX\n",
+                                                      "AFSPrimaryVolumeWorkerThread Deleting object %08lX\n",
                                                       pCurrentChildObject);
 
                                         AFSDeleteObjectInfo( pCurrentChildObject);
                                     }
 
                                     pCurrentDirEntry = pNextDirEntry;
+
                                 }
 
                                 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
@@ -1387,13 +1469,12 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
                                               AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSPrimaryWorker Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
+                                              "AFSPrimaryVolumeWorkerThread Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
                                               pCurrentObject->FileId.Cell,
                                               pCurrentObject->FileId.Volume,
                                               pCurrentObject->FileId.Vnode,
                                               pCurrentObject->FileId.Unique);
 
-
                                 //
                                 // Clear our enumerated flag on this object so we retrieve info again on next access
                                 //
@@ -1401,6 +1482,8 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
 
                                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                                AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
                             }
                             else
                             {
@@ -1411,8 +1494,6 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                                 break;
                             }
-
-                            AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
                         }
                         else
                         {
@@ -1454,81 +1535,50 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                     else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
                     {
 
-                        if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
-                            pCurrentObject->ObjectReferenceCount == 0 &&
-                            ( pCurrentObject->Fcb == NULL ||
-                              pCurrentObject->Fcb->OpenReferenceCount == 0))
-                        {
-
-                            AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
-
-                            if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
-                                                FALSE))
-                            {
-
-                                if( pCurrentObject->Fcb != NULL)
-                                {
-
-                                    AFSCleanupFcb( pCurrentObject->Fcb,
-                                                   TRUE);
-
-                                    //
-                                    // Acquire and drop the Fcb resource to synchronize
-                                    // with a potentially active AFSCleanup() which sets
-                                    // the OpenReferenceCount to zero while holding the
-                                    // resource.
-                                    //
-
-                                    AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
-                                                    TRUE);
-
-                                    AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
-
-                                    AFSRemoveFcb( pCurrentObject->Fcb);
-                                }
+                        AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
 
-                                AFSDeleteObjectInfo( pCurrentObject);
+                        if( pCurrentObject->Fcb != NULL)
+                        {
 
-                                AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
+                            //
+                            // Dropping the TreeLock permits the
+                            // pCurrentObject->ObjectReferenceCount to change
+                            //
 
-                                pCurrentObject = pNextObject;
+                            AFSCleanupFcb( pCurrentObject->Fcb,
+                                           TRUE);
+                        }
 
-                                continue;
-                            }
-                            else
-                            {
+                        if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
+                                             FALSE))
+                        {
 
-                                bReleaseVolumeLock = FALSE;
+                            bReleaseVolumeLock = FALSE;
 
-                                break;
-                            }
+                            break;
                         }
-                        else if( pCurrentObject->Fcb != NULL)
-                        {
 
-                            AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
+                        if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
+                            pCurrentObject->ObjectReferenceCount <= 0 &&
+                            ( pCurrentObject->Fcb == NULL ||
+                              pCurrentObject->Fcb->OpenReferenceCount == 0 &&
+                              pCurrentObject->Fcb->Specific.File.ExtentCount == 0))
+                        {
 
-                            if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
-                                                FALSE))
+                            if( pCurrentObject->Fcb != NULL)
                             {
 
-                                AFSCleanupFcb( pCurrentObject->Fcb,
-                                               FALSE);
-
-                                AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
+                                AFSRemoveFcb( &pCurrentObject->Fcb);
+                            }
 
-                                pCurrentObject = pNextObject;
+                            AFSDeleteObjectInfo( pCurrentObject);
+                        }
 
-                                continue;
-                            }
-                            else
-                            {
+                        AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
 
-                                bReleaseVolumeLock = FALSE;
+                        pCurrentObject = pNextObject;
 
-                                break;
-                            }
-                        }
+                        continue;
                     }
 
                     pCurrentObject = pNextObject;
@@ -1861,14 +1911,19 @@ AFSRemoveWorkItem()
         {
 
             pDevExt->Specific.Library.QueueTail = NULL;
+        }
+        else
+        {
+
+            //
+            // Wake up another worker
+            //
 
-            KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
+            KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
+                        0,
+                        FALSE);
         }
     }
-    else
-    {
-        KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
-    }
 
     AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
 
@@ -1915,14 +1970,19 @@ AFSRemoveIOWorkItem()
         {
 
             pDevExt->Specific.Library.IOQueueTail = NULL;
+        }
+        else
+        {
 
-            KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
+            //
+            // Wake up another worker
+            //
+
+            KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
+                        0,
+                        FALSE);
         }
     }
-    else
-    {
-        KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
-    }
 
     AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
 
@@ -2101,9 +2161,23 @@ AFSQueueFlushExtents( IN AFSFcb *Fcb,
 
         pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
 
-        RtlCopyMemory( &pWorkItem->AuthGroup,
-                       AuthGroup,
-                       sizeof( GUID));
+        if ( AuthGroup == NULL)
+        {
+
+            RtlZeroMemory( &pWorkItem->AuthGroup,
+                           sizeof( GUID));
+
+            ntStatus = AFSRetrieveValidAuthGroup( Fcb,
+                                                  NULL,
+                                                  TRUE,
+                                                  &pWorkItem->AuthGroup);
+        }
+        else
+        {
+            RtlCopyMemory( &pWorkItem->AuthGroup,
+                           AuthGroup,
+                           sizeof( GUID));
+        }
 
         pWorkItem->Specific.Fcb.Fcb = Fcb;
 
@@ -2167,12 +2241,14 @@ try_exit:
                           "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSQueueFlushExtents\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -2251,12 +2327,14 @@ try_exit:
                           "AFSQueueAsyncRead Failed to queue request Status %08lX\n", ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSQueueAsyncRead\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -2335,12 +2413,14 @@ try_exit:
                           "AFSQueueAsyncWrite Failed to queue request Status %08lX\n", ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSQueueAsyncWrite\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -2405,12 +2485,14 @@ try_exit:
                           ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -2509,12 +2591,14 @@ try_exit:
             }
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSQueueStartIos\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -2583,12 +2667,14 @@ try_exit:
                           ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSQueueInvalidateObject\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;