Windows: Move VolumeWorkerContext to NonPaged pool
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSWorker.cpp
index a2b4022..f9b1019 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 AFSShutdownIOWorkerThread()
+    // 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;
@@ -334,24 +380,22 @@ AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
+    AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
     HANDLE hThread;
     AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
     PKSTART_ROUTINE pStartRoutine = NULL;
+    LONG lCount;
 
     __Enter
     {
 
-        if( VolumeCB == AFSGlobalRoot)
+        if ( VolumeCB != AFSGlobalRoot)
         {
 
-            pStartRoutine = AFSPrimaryVolumeWorkerThread;
+            return STATUS_INVALID_PARAMETER;
         }
-        else
-        {
 
-            pStartRoutine = AFSVolumeWorkerThread;
-        }
+        pStartRoutine = AFSPrimaryVolumeWorkerThread;
 
         //
         // Initialize the worker thread
@@ -395,7 +439,9 @@ AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
                                               FALSE,
                                               NULL);
 
-            if( InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) > 0)
+            lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
+
+            if( lCount > 0)
             {
 
                 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
@@ -481,23 +527,25 @@ AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
+    AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
 
-    if( pWorker->WorkerThreadObject != NULL &&
-        BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED))
-    {
+    //
+    // Clear the 'keep processing' flag
+    //
 
-        //
-        // Clear the 'keep processing' flag
-        //
+    ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
 
-        ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
+    if( pWorker->WorkerThreadObject != NULL)
+    {
+        while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
+        {
 
-        ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL);
+            ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
+                                              Executive,
+                                              KernelMode,
+                                              FALSE,
+                                              NULL);
+        }
 
         ObDereferenceObject( pWorker->WorkerThreadObject);
 
@@ -512,7 +560,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:
 //
@@ -526,29 +574,26 @@ AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
-    if( PoolContext->WorkerThreadObject != NULL &&
-        BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
+    if( PoolContext->WorkerThreadObject != NULL)
     {
 
-        //
-        // Clear the 'keep processing' flag
-        //
-
-        ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
+        while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
+        {
 
-        //
-        // Wake up the thread if it is a sleep
-        //
+            //
+            // Wake up the thread if it is a sleep
+            //
 
-        KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
-                    0,
-                    FALSE);
+            KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
+                        0,
+                        FALSE);
 
-        ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL);
+            ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
+                                              Executive,
+                                              KernelMode,
+                                              FALSE,
+                                              NULL);
+        }
 
         ObDereferenceObject( PoolContext->WorkerThreadObject);
 
@@ -577,29 +622,26 @@ AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
-    if( PoolContext->WorkerThreadObject != NULL &&
-        BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
+    if( PoolContext->WorkerThreadObject != NULL)
     {
 
-        //
-        // Clear the 'keep processing' flag
-        //
-
-        ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
+        while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
+        {
 
-        //
-        // Wake up the thread if it is a sleep
-        //
+            //
+            // Wake up the thread if it is a sleep
+            //
 
-        KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
-                    0,
-                    FALSE);
+            KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
+                        0,
+                        FALSE);
 
-        ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL);
+            ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
+                                              Executive,
+                                              KernelMode,
+                                              FALSE,
+                                              NULL);
+        }
 
         ObDereferenceObject( PoolContext->WorkerThreadObject);
 
@@ -629,8 +671,8 @@ AFSWorkerThread( IN PVOID Context)
     AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
     AFSWorkItem *pWorkItem;
     BOOLEAN freeWorkItem = TRUE;
-    BOOLEAN exitThread = FALSE;
     AFSDeviceExt *pLibraryDevExt = NULL;
+    LONG lCount;
 
     pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
@@ -642,35 +684,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;
@@ -685,48 +737,39 @@ AFSWorkerThread( IN PVOID Context)
                     case AFS_WORK_FLUSH_FCB:
                     {
 
-                        ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb);
+                        ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
+                                                    &pWorkItem->AuthGroup);
 
                         if( !NT_SUCCESS( ntStatus))
                         {
 
-                            AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb);
+                            AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
+                                                        &pWorkItem->AuthGroup,
+                                                        FALSE);
                         }
 
                         ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
 
-                        InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
+                        lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
 
                         break;
                     }
 
-                    case AFS_WORK_ASYNCH_READ:
+                    case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
                     {
 
-                        ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
-
-                        (VOID) AFSCommonRead( pWorkItem->Specific.AsynchIo.Device,
-                                              pWorkItem->Specific.AsynchIo.Irp,
-                                              pWorkItem->Specific.AsynchIo.CallingProcess);
+                        AFSEnumerateGlobalRoot( NULL);
 
                         break;
                     }
 
-                    case AFS_WORK_ASYNCH_WRITE:
+                    case AFS_WORK_INVALIDATE_OBJECT:
                     {
 
-                        ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
-
-                        (VOID) AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
-                                               pWorkItem->Specific.AsynchIo.Irp,
-                                               pWorkItem->Specific.AsynchIo.CallingProcess);
-                        break;
-                    }
-
-                    case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
-                    {
+                        AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
+                                                    pWorkItem->Specific.Invalidate.InvalidateReason);
 
-                        AFSEnumerateGlobalRoot( NULL);
+                        freeWorkItem = TRUE;
 
                         break;
                     }
@@ -753,10 +796,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;
@@ -770,7 +823,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;
@@ -790,28 +842,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;
@@ -867,10 +930,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;
@@ -880,21 +953,23 @@ void
 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 {
 
+    UNREFERENCED_PARAMETER(Context);
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
+    AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
     AFSDeviceExt *pControlDeviceExt = NULL;
     AFSDeviceExt *pRDRDeviceExt = NULL;
-    BOOLEAN exitThread = FALSE;
     LARGE_INTEGER DueTime;
     LONG TimeOut;
     KTIMER Timer;
-    BOOLEAN bFoundOpenEntry = FALSE;
     AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
     BOOLEAN bReleaseVolumeLock = FALSE;
     AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
+    AFSFcb *pFcb = NULL;
     LARGE_INTEGER liCurrentTime;
     BOOLEAN bVolumeObject = FALSE;
+    BOOLEAN bFcbBusy = FALSE;
+    LONG lCount;
 
     pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
 
@@ -937,11 +1012,20 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
     while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
     {
 
-        KeWaitForSingleObject( &Timer,
-                               Executive,
-                               KernelMode,
-                               FALSE,
-                               NULL);
+        if ( bFcbBusy == FALSE)
+        {
+
+            KeWaitForSingleObject( &Timer,
+                                   Executive,
+                                   KernelMode,
+                                   FALSE,
+                                   NULL);
+        }
+        else
+        {
+
+            bFcbBusy = FALSE;
+        }
 
         //
         // This is the primary volume worker so it will traverse the volume list
@@ -966,8 +1050,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                 continue;
             }
 
-            if( pVolumeCB->ObjectInfoListHead == NULL &&
-                pVolumeCB != AFSGlobalRoot)
+            if( pVolumeCB->ObjectInfoListHead == NULL)
             {
 
                 AFSReleaseResource( pVolumeCB->VolumeLock);
@@ -997,12 +1080,15 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
 
+                AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
+                                  TRUE);
+
                 if( pVolumeCB->ObjectInfoListHead == NULL &&
-                    pVolumeCB->DirectoryCB->OpenReferenceCount == 0 &&
+                    pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
                     pVolumeCB->VolumeReferenceCount == 1 &&
                     ( pVolumeCB->RootFcb == NULL ||
                       pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
-                    pVolumeCB->ObjectInformation.ObjectReferenceCount == 0)
+                    pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
                 {
 
                     if( pVolumeCB->RootFcb != NULL)
@@ -1011,11 +1097,15 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                         AFSRemoveRootFcb( pVolumeCB->RootFcb);
                     }
 
+                    AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
+
                     AFSRemoveVolume( pVolumeCB);
                 }
                 else
                 {
 
+                    AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
+
                     AFSReleaseResource( pVolumeCB->VolumeLock);
                 }
 
@@ -1084,7 +1174,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 &&
@@ -1093,36 +1183,56 @@ 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)
-                                {
-
-                                    AFSRemoveFcb( pCurrentObject->Fcb);
-                                }
+                                AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
+                                                TRUE);
 
-                                if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
+                                if ( pCurrentObject->ObjectReferenceCount <= 0)
                                 {
 
-                                    if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
+                                    AFSRemoveFcb( &pCurrentObject->Fcb);
+
+                                    if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
                                     {
 
-                                        AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+                                        AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
+                                                        TRUE);
+
+                                        AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+
+                                        AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
+
+                                        AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
+
+                                        ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
+
+                                        AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
+
+                                        AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
                                     }
 
-                                    AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
+                                    AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
 
-                                    ExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
-                                }
+                                    AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSPrimaryVolumeWorkerThread Deleting deleted object %p\n",
+                                                  pCurrentObject);
 
-                                AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
-                                              AFS_TRACE_LEVEL_VERBOSE,
-                                              "AFSPrimaryWorker Deleting deleted object %08lX\n",
-                                              pCurrentObject);
+                                    AFSDeleteObjectInfo( pCurrentObject);
+                                }
+                                else
+                                {
 
-                                AFSDeleteObjectInfo( pCurrentObject);
+                                    AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
+                                }
 
                                 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
 
@@ -1166,7 +1276,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                         while( pCurrentDirEntry != NULL)
                         {
 
-                            if( pCurrentDirEntry->OpenReferenceCount > 0 ||
+                            if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
                                 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
                                   pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
                                 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
@@ -1231,7 +1341,7 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                                 while( pCurrentDirEntry != NULL)
                                 {
 
-                                    if( pCurrentDirEntry->OpenReferenceCount > 0 ||
+                                    if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
                                         ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
                                           pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
                                         liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
@@ -1272,59 +1382,121 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                                     pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
 
-                                    AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+                                    pFcb = NULL;
+
+                                    AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                                                   AFS_TRACE_LEVEL_VERBOSE,
-                                                  "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
+                                                  "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %p\n",
                                                   &pCurrentDirEntry->NameInformation.FileName,
                                                   pCurrentChildObject);
 
                                     AFSDeleteDirEntry( pCurrentObject,
                                                        pCurrentDirEntry);
 
-                                    if( pCurrentChildObject->ObjectReferenceCount == 0)
+
+                                    //
+                                    // Acquire ObjectInfoLock shared here so as not to deadlock
+                                    // with an invalidation call from the service during AFSCleanupFcb
+                                    //
+
+                                    lCount = AFSObjectInfoIncrement( pCurrentChildObject,
+                                                                     AFS_OBJECT_REFERENCE_WORKER);
+
+                                    AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSPrimaryVolumeWorkerThread Increment count on object %p Cnt %d\n",
+                                                  pCurrentChildObject,
+                                                  lCount);
+
+                                    if( lCount == 1 &&
+                                        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.
+                                        //
+
+                                        AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
+
+                                        //
+                                        // Cannot hold a TreeLock across an AFSCleanupFcb call
+                                        // as it can deadlock with an invalidation ioctl initiated
+                                        // from the service.
+                                        //
+                                        // Dropping the TreeLock permits the
+                                        // pCurrentObject->ObjectReferenceCount to change
+                                        //
 
-                                            if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
-                                            {
+                                        ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
+                                                                  TRUE);
 
-                                                AFSCleanupFcb( pCurrentChildObject->Fcb,
-                                                               TRUE);
-                                            }
+                                        if ( ntStatus == STATUS_RETRY)
+                                        {
 
-                                            AFSRemoveFcb( pCurrentChildObject->Fcb);
+                                            bFcbBusy = TRUE;
                                         }
 
+                                        AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
+                                                        TRUE);
+                                    }
+
+                                    lCount = AFSObjectInfoDecrement( pCurrentChildObject,
+                                                                     AFS_OBJECT_REFERENCE_WORKER);
+
+                                    AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                                  AFS_TRACE_LEVEL_VERBOSE,
+                                                  "AFSPrimaryVolumeWorkerThread Decrement1 count on object %p Cnt %d\n",
+                                                  pCurrentChildObject,
+                                                  lCount);
+
+                                    AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
+                                                    TRUE);
+
+                                    if( pCurrentChildObject->ObjectReferenceCount <= 0)
+                                    {
+
+                                        AFSRemoveFcb( &pCurrentChildObject->Fcb);
+
                                         if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
                                             pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
                                         {
 
-                                            if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
-                                            {
+                                            AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
+                                                            TRUE);
 
-                                                AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
-                                            }
+                                            AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+
+                                            AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
 
                                             AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
 
                                             ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
 
-                                            ExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
+                                            AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
 
-                                            ExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
+                                            AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
                                         }
 
+                                        AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
+
                                         AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                                       AFS_TRACE_LEVEL_VERBOSE,
-                                                      "AFSPrimaryWorker Deleting object %08lX\n",
+                                                      "AFSPrimaryVolumeWorkerThread Deleting object %p\n",
                                                       pCurrentChildObject);
 
                                         AFSDeleteObjectInfo( pCurrentChildObject);
                                     }
+                                    else
+                                    {
+
+                                        AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
+                                    }
 
                                     pCurrentDirEntry = pNextDirEntry;
+
                                 }
 
                                 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
@@ -1341,13 +1513,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
                                 //
@@ -1355,6 +1526,8 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
                                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
 
                                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                                AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
                             }
                             else
                             {
@@ -1365,8 +1538,6 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
                                 break;
                             }
-
-                            AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
                         }
                         else
                         {
@@ -1408,72 +1579,80 @@ 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)
-                                {
+                        lCount = AFSObjectInfoIncrement( pCurrentObject,
+                                                         AFS_OBJECT_REFERENCE_WORKER);
 
-                                    AFSCleanupFcb( pCurrentObject->Fcb,
-                                                   TRUE);
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSPrimaryVolumeWorkerThread Increment2 count on object %p Cnt %d\n",
+                                      pCurrentObject,
+                                      lCount);
 
-                                    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;
+                            ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
+                                                      FALSE);
 
-                                continue;
-                            }
-                            else
+                            if ( ntStatus == STATUS_RETRY)
                             {
 
-                                bReleaseVolumeLock = FALSE;
-
-                                break;
+                                bFcbBusy = TRUE;
                             }
                         }
-                        else if( pCurrentObject->Fcb != NULL)
+
+                        lCount = AFSObjectInfoDecrement( pCurrentObject,
+                                                         AFS_OBJECT_REFERENCE_WORKER);
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSPrimaryVolumeWorkerThread Decrement2 count on object %p Cnt %d\n",
+                                      pCurrentObject,
+                                      lCount);
+
+                        if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
+                                             FALSE))
                         {
 
-                            AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
+                            bReleaseVolumeLock = FALSE;
 
-                            if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
-                                                FALSE))
-                            {
+                            break;
+                        }
 
-                                AFSCleanupFcb( pCurrentObject->Fcb,
-                                               FALSE);
+                        AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
+                                        TRUE);
 
-                                AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
+                        if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
+                            pCurrentObject->ObjectReferenceCount <= 0)
+                        {
 
-                                pCurrentObject = pNextObject;
+                            AFSRemoveFcb( &pCurrentObject->Fcb);
 
-                                continue;
-                            }
-                            else
-                            {
+                            AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
 
-                                bReleaseVolumeLock = FALSE;
+                            AFSDeleteObjectInfo( pCurrentObject);
+                        }
+                        else
+                        {
 
-                                break;
-                            }
+                            AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
                         }
-                    }
 
-                    pCurrentObject = pNextObject;
+                        AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
+
+                        pCurrentObject = pNextObject;
+
+                        continue;
+                    }
+
+                    pCurrentObject = pNextObject;
                 }
 
                 if( bReleaseVolumeLock)
@@ -1501,105 +1680,15 @@ AFSPrimaryVolumeWorkerThread( IN PVOID Context)
 
     KeCancelTimer( &Timer);
 
+    ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+
     AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
                   "AFSPrimaryVolumeWorkerThread Exiting\n");
 
-    if( InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) == 0)
-    {
-
-        KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
-                    0,
-                    FALSE);
-    }
-
-    PsTerminateSystemThread( 0);
-
-    return;
-}
-
-void
-AFSVolumeWorkerThread( IN PVOID Context)
-{
+    lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
 
-    NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
-    AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
-    AFSDeviceExt *pControlDeviceExt = NULL;
-    AFSDeviceExt *pRDRDeviceExt = NULL;
-    BOOLEAN exitThread = FALSE;
-    LARGE_INTEGER DueTime;
-    LONG TimeOut;
-    KTIMER Timer;
-
-    pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
-
-    pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
-
-    //
-    // Initialize the timer for the worker thread
-    //
-
-    DueTime.QuadPart = -(5000);
-
-    TimeOut = 5000;
-
-    KeInitializeTimerEx( &Timer,
-                         SynchronizationTimer);
-
-    KeSetTimerEx( &Timer,
-                  DueTime,
-                  TimeOut,
-                  NULL);
-
-    //
-    // Indicate that we are initialized and ready
-    //
-
-    KeSetEvent( &pPoolContext->WorkerThreadReady,
-                0,
-                FALSE);
-
-    //
-    // Indicate we are initialized
-    //
-
-    SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
-
-    while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
-    {
-
-        ntStatus = KeWaitForSingleObject( &Timer,
-                                          Executive,
-                                          KernelMode,
-                                          FALSE,
-                                          NULL);
-
-        if( !NT_SUCCESS( ntStatus))
-        {
-
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_ERROR,
-                          "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
-        }
-        else
-        {
-
-            //
-            // If we are in shutdown mode and the dirty flag is clear then get out now
-            //
-
-            if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
-            {
-
-                break;
-            }
-        }
-    } // worker thread loop
-
-    KeCancelTimer( &Timer);
-
-    if( InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) == 0)
+    if( lCount == 0)
     {
 
         KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
@@ -1618,23 +1707,26 @@ AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDevExt = NULL;
+    LONG lCount;
 
     pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
+                  "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
                   &pDevExt->Specific.Library.QueueLock,
                   PsGetCurrentThread());
 
     AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
                     TRUE);
 
+    lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
+
     AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
+                  "AFSInsertWorkitem Inserting work item %p Count %d\n",
                   WorkItem,
-                  InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount));
+                  lCount);
 
     if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
     {
@@ -1666,23 +1758,26 @@ AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDevExt = NULL;
+    LONG lCount;
 
     pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
+                  "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
                   &pDevExt->Specific.Library.IOQueueLock,
                   PsGetCurrentThread());
 
     AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
                     TRUE);
 
+    lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
+
     AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
+                  "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
                   WorkItem,
-                  InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount));
+                  lCount);
 
     if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
     {
@@ -1714,12 +1809,13 @@ AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDevExt = NULL;
+    LONG lCount;
 
     pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
+                  "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
                   &pDevExt->Specific.Library.QueueLock,
                   PsGetCurrentThread());
 
@@ -1730,11 +1826,13 @@ AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
 
     pDevExt->Specific.Library.QueueHead = WorkItem;
 
+    lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
+
     AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
+                  "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
                   WorkItem,
-                  InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount));
+                  lCount);
 
     //
     // indicate that the queue has nodes
@@ -1753,15 +1851,15 @@ AFSWorkItem *
 AFSRemoveWorkItem()
 {
 
-    NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSWorkItem        *pWorkItem = NULL;
     AFSDeviceExt *pDevExt = NULL;
+    LONG lCount;
 
     pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
+                  "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
                   &pDevExt->Specific.Library.QueueLock,
                   PsGetCurrentThread());
 
@@ -1773,11 +1871,13 @@ AFSRemoveWorkItem()
 
         pWorkItem = pDevExt->Specific.Library.QueueHead;
 
+        lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
+
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
+                      "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
                       pWorkItem,
-                      InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount),
+                      lCount,
                       PsGetCurrentThreadId());
 
         pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
@@ -1786,14 +1886,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);
 
@@ -1804,15 +1909,15 @@ AFSWorkItem *
 AFSRemoveIOWorkItem()
 {
 
-    NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSWorkItem        *pWorkItem = NULL;
     AFSDeviceExt *pDevExt = NULL;
+    LONG lCount;
 
     pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
 
     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                   AFS_TRACE_LEVEL_VERBOSE,
-                  "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
+                  "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
                   &pDevExt->Specific.Library.IOQueueLock,
                   PsGetCurrentThread());
 
@@ -1824,11 +1929,13 @@ AFSRemoveIOWorkItem()
 
         pWorkItem = pDevExt->Specific.Library.IOQueueHead;
 
+        lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
+
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
+                      "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
                       pWorkItem,
-                      InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount),
+                      lCount,
                       PsGetCurrentThreadId());
 
         pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
@@ -1837,14 +1944,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);
 
@@ -1856,7 +1968,6 @@ AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDevExt = NULL;
     BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
 
     //
@@ -1887,7 +1998,6 @@ AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDevExt = NULL;
     BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
 
     //
@@ -1918,7 +2028,6 @@ AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDevExt = NULL;
     BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
 
     //
@@ -1945,12 +2054,14 @@ AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
 }
 
 NTSTATUS
-AFSQueueFlushExtents( IN AFSFcb *Fcb)
+AFSQueueFlushExtents( IN AFSFcb *Fcb,
+                      IN GUID *AuthGroup)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     AFSWorkItem *pWorkItem = NULL;
+    LONG lCount;
 
     __try
     {
@@ -1968,7 +2079,9 @@ AFSQueueFlushExtents( IN AFSFcb *Fcb)
         // queue down. We'll decrement it just below.
         //
 
-        if( InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount) > 3)
+        lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
+
+        if( lCount > 3)
         {
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
@@ -2019,19 +2132,37 @@ AFSQueueFlushExtents( IN AFSFcb *Fcb)
 
         pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
 
+        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;
 
-        InterlockedIncrement( &Fcb->OpenReferenceCount);
+        lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
-                                                    Fcb,
-                                                    Fcb->OpenReferenceCount);
+                      "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
+                      Fcb,
+                      lCount);
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
+                      "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
                       pWorkItem,
                       Fcb->ObjectInformation->FileId.Cell,
                       Fcb->ObjectInformation->FileId.Volume,
@@ -2055,7 +2186,11 @@ try_exit:
         // Remove the count we added above
         //
 
-        if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
+        lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
+
+        ASSERT( lCount >= 0);
+
+        if( lCount == 0)
         {
 
             KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
@@ -2069,9 +2204,9 @@ try_exit:
             if( pWorkItem != NULL)
             {
 
-                InterlockedDecrement( &Fcb->OpenReferenceCount);
+                lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
 
-                ExFreePool( pWorkItem);
+                ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
             }
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -2079,21 +2214,21 @@ 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;
 }
 
 NTSTATUS
-AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
-                   IN PIRP Irp,
-                   IN HANDLE CallerProcess)
+AFSQueueGlobalRootEnumeration()
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
@@ -2102,11 +2237,6 @@ AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
     __try
     {
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueAsyncRead Queuing request for Irp %08lX\n",
-                      Irp);
-
         pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
                                                                  sizeof(AFSWorkItem),
                                                                  AFS_WORK_ITEM_TAG);
@@ -2115,7 +2245,7 @@ AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueAsyncRead Failed to allocate work item\n");
+                          "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
 
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
         }
@@ -2125,19 +2255,12 @@ AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
 
         pWorkItem->Size = sizeof( AFSWorkItem);
 
-        pWorkItem->RequestType = AFS_WORK_ASYNCH_READ;
-
-        pWorkItem->Specific.AsynchIo.Device = DeviceObject;
-
-        pWorkItem->Specific.AsynchIo.Irp = Irp;
-
-        pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
+        pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueAsyncRead Workitem %08lX for Irp %08lX\n",
-                      pWorkItem,
-                      Irp);
+                      "AFSQueueGlobalRootEnumeration Workitem %p\n",
+                      pWorkItem);
 
         ntStatus = AFSQueueWorkerRequest( pWorkItem);
 
@@ -2145,8 +2268,7 @@ try_exit:
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueAsyncRead Request for Irp %08lX complete Status %08lX\n",
-                      Irp,
+                      "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
                       ntStatus);
 
         if( !NT_SUCCESS( ntStatus))
@@ -2155,151 +2277,109 @@ try_exit:
             if( pWorkItem != NULL)
             {
 
-                ExFreePool( pWorkItem);
+                ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
             }
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueAsyncRead Failed to queue request Status %08lX\n", ntStatus);
+                          "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
+                          ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
-                      "EXCEPTION - AFSQueueAsyncRead\n");
+                      "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
 }
 
 NTSTATUS
-AFSQueueAsyncWrite( IN PDEVICE_OBJECT DeviceObject,
-                    IN PIRP Irp,
-                    IN HANDLE CallerProcess)
+AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
+                  IN UCHAR FunctionCode,
+                  IN ULONG RequestFlags,
+                  IN AFSIoRun *IoRuns,
+                  IN ULONG RunCount,
+                  IN AFSGatherIo *GatherIo)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     AFSWorkItem *pWorkItem = NULL;
 
     __try
     {
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueAsyncWrite Queuing request for Irp %08lX\n",
-                      Irp);
-
-        pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
-                                                                 sizeof(AFSWorkItem),
-                                                                 AFS_WORK_ITEM_TAG);
-        if (NULL == pWorkItem)
+        if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueAsyncWrite Failed to allocate work item\n");
+                          "AFSQueueStartIos Failing request, in shutdown\n");
 
-            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
+            try_return( ntStatus = STATUS_TOO_LATE);
         }
 
-        RtlZeroMemory( pWorkItem,
-                       sizeof(AFSWorkItem));
-
-        pWorkItem->Size = sizeof( AFSWorkItem);
-
-        pWorkItem->RequestType = AFS_WORK_ASYNCH_WRITE;
-
-        pWorkItem->Specific.AsynchIo.Device = DeviceObject;
-
-        pWorkItem->Specific.AsynchIo.Irp = Irp;
-
-        pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
-
-        AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueAsyncWrite Workitem %08lX for Irp %08lX\n",
-                      pWorkItem,
-                      Irp);
-
-        ntStatus = AFSQueueWorkerRequest( pWorkItem);
-
-try_exit:
+        //
+        // Allocate our request structure and send it to the worker
+        //
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
-                      AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueAsyncWrite Request for Irp %08lX complete Status %08lX\n",
-                      Irp,
-                      ntStatus);
+        pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
+                                                                sizeof( AFSWorkItem),
+                                                                AFS_WORK_ITEM_TAG);
 
-        if( !NT_SUCCESS( ntStatus))
+        if( pWorkItem == NULL)
         {
 
-            if( pWorkItem != NULL)
-            {
-
-                ExFreePool( pWorkItem);
-            }
-
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueAsyncWrite Failed to queue request Status %08lX\n", ntStatus);
+                          "AFSQueueStartIos Failed to allocate work item\n");
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
-    }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
-    {
 
-        AFSDbgLogMsg( 0,
-                      0,
-                      "EXCEPTION - AFSQueueAsyncWrite\n");
-    }
+        RtlZeroMemory( pWorkItem,
+                       sizeof( AFSWorkItem));
 
-    return ntStatus;
-}
+        KeInitializeEvent( &pWorkItem->Event,
+                           NotificationEvent,
+                           FALSE);
 
-NTSTATUS
-AFSQueueGlobalRootEnumeration()
-{
+        pWorkItem->Size = sizeof( AFSWorkItem);
 
-    NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSWorkItem *pWorkItem = NULL;
+        pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
 
-    __try
-    {
+        pWorkItem->RequestType = AFS_WORK_START_IOS;
 
-        pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
-                                                                 sizeof(AFSWorkItem),
-                                                                 AFS_WORK_ITEM_TAG);
-        if (NULL == pWorkItem)
-        {
+        pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
-                          AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
+        pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
 
-            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
-        }
+        pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
 
-        RtlZeroMemory( pWorkItem,
-                       sizeof(AFSWorkItem));
+        pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
 
-        pWorkItem->Size = sizeof( AFSWorkItem);
+        pWorkItem->Specific.CacheAccess.RunCount = RunCount;
 
-        pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
+        pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
+                      "AFSQueueStartIos Queuing IO Workitem %p\n",
                       pWorkItem);
 
-        ntStatus = AFSQueueWorkerRequest( pWorkItem);
+        ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
 
 try_exit:
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
+                      "AFSQueueStartIos Request complete Status %08lX\n",
                       ntStatus);
 
         if( !NT_SUCCESS( ntStatus))
@@ -2308,107 +2388,70 @@ try_exit:
             if( pWorkItem != NULL)
             {
 
-                ExFreePool( pWorkItem);
+                ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
             }
-
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
-                          ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
-                      "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
+                      "EXCEPTION - AFSQueueStartIos\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
 }
 
 NTSTATUS
-AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
-                  IN UCHAR FunctionCode,
-                  IN ULONG RequestFlags,
-                  IN AFSIoRun *IoRuns,
-                  IN ULONG RunCount,
-                  IN AFSGatherIo *GatherIo)
+AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
+                          IN ULONG InvalidateReason)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     AFSWorkItem *pWorkItem = NULL;
 
     __try
     {
 
-        if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
-        {
-
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueStartIos Failing request, in shutdown\n");
-
-            try_return( ntStatus = STATUS_TOO_LATE);
-        }
-
-        //
-        // Allocate our request structure and send it to the worker
-        //
-
-        pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
-                                                                sizeof( AFSWorkItem),
-                                                                AFS_WORK_ITEM_TAG);
-
-        if( pWorkItem == NULL)
+        pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
+                                                                 sizeof(AFSWorkItem),
+                                                                 AFS_WORK_ITEM_TAG);
+        if (NULL == pWorkItem)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueueStartIos Failed to allocate work item\n");
+                          "AFSQueueInvalidateObject Failed to allocate work item\n");
 
-            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
         }
 
         RtlZeroMemory( pWorkItem,
-                       sizeof( AFSWorkItem));
-
-        KeInitializeEvent( &pWorkItem->Event,
-                           NotificationEvent,
-                           FALSE);
+                       sizeof(AFSWorkItem));
 
         pWorkItem->Size = sizeof( AFSWorkItem);
 
-        pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
-
-        pWorkItem->RequestType = AFS_WORK_START_IOS;
-
-        pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
-
-        pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
-
-        pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
+        pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
 
-        pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
+        pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
 
-        pWorkItem->Specific.CacheAccess.RunCount = RunCount;
-
-        pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
+        pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueStartIos Queuing IO Workitem %08lX\n",
+                      "AFSQueueInvalidateObject Workitem %p\n",
                       pWorkItem);
 
-        ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
+        ntStatus = AFSQueueWorkerRequest( pWorkItem);
 
 try_exit:
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueueStartIos Request complete Status %08lX\n",
+                      "AFSQueueInvalidateObject Request complete Status %08lX\n",
                       ntStatus);
 
         if( !NT_SUCCESS( ntStatus))
@@ -2416,17 +2459,23 @@ try_exit:
 
             if( pWorkItem != NULL)
             {
-
-                ExFreePool( pWorkItem);
+                ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
             }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
+                          ntStatus);
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
-                      "EXCEPTION - AFSQueueStartIos\n");
+                      "EXCEPTION - AFSQueueInvalidateObject\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;