2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSWorker.cpp
39 #include "AFSCommon.h"
42 // Function: AFSInitializeWorkerPool
46 // This function initializes the worker thread pool
50 // A status is returned for the function
54 AFSInitializeWorkerPool()
57 NTSTATUS ntStatus = STATUS_SUCCESS;
58 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
59 AFSDeviceExt *pDevExt = NULL;
64 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
67 // Initialize the worker threads.
70 pDevExt->Specific.Library.WorkerCount = 0;
72 KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
77 // Initialize the queue resource
80 ExInitializeResourceLite( &pDevExt->Specific.Library.QueueLock);
82 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
85 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
86 sizeof( AFSWorkQueueContext),
89 if( pCurrentWorker == NULL)
92 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
93 AFS_TRACE_LEVEL_ERROR,
94 "AFSInitializeWorkerPool Failed to allocate worker context\n");
96 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
101 RtlZeroMemory( pCurrentWorker,
102 sizeof( AFSWorkQueueContext));
104 ntStatus = AFSInitWorkerThread( pCurrentWorker,
105 (PKSTART_ROUTINE)AFSWorkerThread);
107 if( !NT_SUCCESS( ntStatus))
110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
111 AFS_TRACE_LEVEL_ERROR,
112 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
114 ExFreePool( pCurrentWorker);
119 if( pDevExt->Specific.Library.PoolHead == NULL)
122 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
127 pLastWorker->fLink = pCurrentWorker;
130 pLastWorker = pCurrentWorker;
132 pDevExt->Specific.Library.WorkerCount++;
136 // If there was a failure but there is at least one worker, then go with it.
139 if( !NT_SUCCESS( ntStatus) &&
140 pDevExt->Specific.Library.WorkerCount == 0)
143 try_return( ntStatus);
146 ntStatus = STATUS_SUCCESS;
149 // Now our IO Worker queue
152 pDevExt->Specific.Library.IOWorkerCount = 0;
154 KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
159 // Initialize the queue resource
162 ExInitializeResourceLite( &pDevExt->Specific.Library.IOQueueLock);
164 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
167 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
168 sizeof( AFSWorkQueueContext),
171 if( pCurrentWorker == NULL)
174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
178 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
183 RtlZeroMemory( pCurrentWorker,
184 sizeof( AFSWorkQueueContext));
186 ntStatus = AFSInitWorkerThread( pCurrentWorker,
187 (PKSTART_ROUTINE)AFSIOWorkerThread);
189 if( !NT_SUCCESS( ntStatus))
192 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
193 AFS_TRACE_LEVEL_ERROR,
194 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
196 ExFreePool( pCurrentWorker);
201 if( pDevExt->Specific.Library.IOPoolHead == NULL)
204 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
209 pLastWorker->fLink = pCurrentWorker;
212 pLastWorker = pCurrentWorker;
214 pDevExt->Specific.Library.IOWorkerCount++;
218 // If there was a failure but there is at least one worker, then go with it.
221 if( !NT_SUCCESS( ntStatus) &&
222 pDevExt->Specific.Library.IOWorkerCount == 0)
225 try_return( ntStatus);
230 if( !NT_SUCCESS( ntStatus))
234 // Failed to initialize the pool so tear it down
237 AFSRemoveWorkerPool();
245 // Function: AFSRemoveWorkerPool
249 // This function tears down the worker thread pool
253 // A status is returned for the function
257 AFSRemoveWorkerPool()
260 NTSTATUS ntStatus = STATUS_SUCCESS;
262 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
263 AFSDeviceExt *pDevExt = NULL;
265 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
268 // Loop through the workers shutting them down
271 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
273 while( index < pDevExt->Specific.Library.WorkerCount)
276 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
278 pNextWorker = pCurrentWorker->fLink;
280 ExFreePool( pCurrentWorker);
282 pCurrentWorker = pNextWorker;
284 if( pCurrentWorker == NULL)
293 pDevExt->Specific.Library.PoolHead = NULL;
295 ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
298 // Loop through the IO workers shutting them down
301 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
305 while( index < pDevExt->Specific.Library.IOWorkerCount)
308 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
310 pNextWorker = pCurrentWorker->fLink;
312 ExFreePool( pCurrentWorker);
314 pCurrentWorker = pNextWorker;
316 if( pCurrentWorker == NULL)
325 pDevExt->Specific.Library.IOPoolHead = NULL;
327 ExDeleteResourceLite( &pDevExt->Specific.Library.IOQueueLock);
333 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
336 NTSTATUS ntStatus = STATUS_SUCCESS;
337 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
339 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
340 PKSTART_ROUTINE pStartRoutine = NULL;
345 if( VolumeCB == AFSGlobalRoot)
348 pStartRoutine = AFSPrimaryVolumeWorkerThread;
353 pStartRoutine = AFSVolumeWorkerThread;
357 // Initialize the worker thread
360 KeInitializeEvent( &pWorker->WorkerThreadReady,
365 // Set the worker to process requests
368 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
374 ntStatus = PsCreateSystemThread( &hThread,
382 if( NT_SUCCESS( ntStatus))
385 ObReferenceObjectByHandle( hThread,
386 GENERIC_READ | GENERIC_WRITE,
389 (PVOID *)&pWorker->WorkerThreadObject,
392 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
398 if( InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) > 0)
401 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
412 // Function: AFSInitWorkerThread
416 // This function initializes a worker thread in the pool
420 // A status is returned for the function
424 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
425 IN PKSTART_ROUTINE WorkerRoutine)
428 NTSTATUS ntStatus = STATUS_SUCCESS;
432 // INitialize the worker signal thread
435 KeInitializeEvent( &PoolContext->WorkerThreadReady,
440 // Set the worker to process requests
443 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
449 ntStatus = PsCreateSystemThread( &Handle,
455 (void *)PoolContext);
457 if( NT_SUCCESS( ntStatus))
460 ObReferenceObjectByHandle( Handle,
461 GENERIC_READ | GENERIC_WRITE,
464 (PVOID *)&PoolContext->WorkerThreadObject,
467 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
480 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
483 NTSTATUS ntStatus = STATUS_SUCCESS;
484 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
486 if( pWorker->WorkerThreadObject != NULL &&
487 BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED))
491 // Clear the 'keep processing' flag
494 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
496 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
502 ObDereferenceObject( pWorker->WorkerThreadObject);
504 pWorker->WorkerThreadObject = NULL;
511 // Function: AFSShutdownWorkerThread
515 // This function shusdown a worker thread in the pool
519 // A status is returned for the function
523 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
526 NTSTATUS ntStatus = STATUS_SUCCESS;
527 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
529 if( PoolContext->WorkerThreadObject != NULL &&
530 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
534 // Clear the 'keep processing' flag
537 ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
540 // Wake up the thread if it is a sleep
543 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
547 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
553 ObDereferenceObject( PoolContext->WorkerThreadObject);
555 PoolContext->WorkerThreadObject = NULL;
562 // Function: AFSShutdownIOWorkerThread
566 // This function shutsdown an IO worker thread in the pool
570 // A status is returned for the function
574 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
577 NTSTATUS ntStatus = STATUS_SUCCESS;
578 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
580 if( PoolContext->WorkerThreadObject != NULL &&
581 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
585 // Clear the 'keep processing' flag
588 ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
591 // Wake up the thread if it is a sleep
594 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
598 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
604 ObDereferenceObject( PoolContext->WorkerThreadObject);
606 PoolContext->WorkerThreadObject = NULL;
613 // Function: AFSWorkerThread
617 // This is the worker thread entry point.
621 // A status is returned for the function
625 AFSWorkerThread( IN PVOID Context)
628 NTSTATUS ntStatus = STATUS_SUCCESS;
629 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
630 AFSWorkItem *pWorkItem;
631 BOOLEAN freeWorkItem = TRUE;
632 BOOLEAN exitThread = FALSE;
633 AFSDeviceExt *pLibraryDevExt = NULL;
635 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
638 // Indicate that we are initialized and ready
641 KeSetEvent( &pPoolContext->WorkerThreadReady,
647 // Indicate we are initialized
650 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
652 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
655 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
661 if( !NT_SUCCESS( ntStatus))
664 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
665 AFS_TRACE_LEVEL_ERROR,
666 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
671 pWorkItem = AFSRemoveWorkItem();
673 if( pWorkItem != NULL)
679 // Switch on the type of work item to process
682 switch( pWorkItem->RequestType)
685 case AFS_WORK_FLUSH_FCB:
688 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb);
690 if( !NT_SUCCESS( ntStatus))
693 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb);
696 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
698 InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
703 case AFS_WORK_ASYNCH_READ:
706 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
708 (VOID) AFSCommonRead( pWorkItem->Specific.AsynchIo.Device,
709 pWorkItem->Specific.AsynchIo.Irp,
710 pWorkItem->Specific.AsynchIo.CallingProcess);
715 case AFS_WORK_ASYNCH_WRITE:
718 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
720 (VOID) AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
721 pWorkItem->Specific.AsynchIo.Irp,
722 pWorkItem->Specific.AsynchIo.CallingProcess);
726 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
729 AFSEnumerateGlobalRoot( NULL);
734 case AFS_WORK_START_IOS:
744 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
745 AFS_TRACE_LEVEL_ERROR,
746 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
754 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
758 } // worker thread loop
760 PsTerminateSystemThread( 0);
766 AFSIOWorkerThread( IN PVOID Context)
769 NTSTATUS ntStatus = STATUS_SUCCESS;
770 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
771 AFSWorkItem *pWorkItem;
772 BOOLEAN freeWorkItem = TRUE;
773 BOOLEAN exitThread = FALSE;
774 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
776 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
779 // Indicate that we are initialized and ready
782 KeSetEvent( &pPoolContext->WorkerThreadReady,
788 // Indicate we are initialized
791 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
793 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
796 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
802 if( !NT_SUCCESS( ntStatus))
805 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
806 AFS_TRACE_LEVEL_ERROR,
807 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
812 pWorkItem = AFSRemoveIOWorkItem();
814 if( pWorkItem != NULL)
820 // Switch on the type of work item to process
823 switch( pWorkItem->RequestType)
826 case AFS_WORK_START_IOS:
829 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
832 // The final status is in the gather io
835 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
836 pWorkItem->Specific.CacheAccess.FunctionCode,
837 pWorkItem->Specific.CacheAccess.RequestFlags,
838 pWorkItem->Specific.CacheAccess.IoRuns,
839 pWorkItem->Specific.CacheAccess.RunCount,
840 pWorkItem->Specific.CacheAccess.GatherIo);
843 // Regardless of the status we we do the complete - there may
845 // Decrement the count - setting the event if we were told
846 // to. This may trigger completion.
849 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
858 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
859 AFS_TRACE_LEVEL_ERROR,
860 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
868 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
872 } // worker thread loop
874 PsTerminateSystemThread( 0);
880 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
883 NTSTATUS ntStatus = STATUS_SUCCESS;
884 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
885 AFSDeviceExt *pControlDeviceExt = NULL;
886 AFSDeviceExt *pRDRDeviceExt = NULL;
887 BOOLEAN exitThread = FALSE;
888 LARGE_INTEGER DueTime;
891 BOOLEAN bFoundOpenEntry = FALSE;
892 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
893 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
894 BOOLEAN bReleaseVolumeLock = FALSE;
895 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
896 LARGE_INTEGER liCurrentTime;
897 BOOLEAN bVolumeObject = FALSE;
899 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
901 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
903 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
904 AFS_TRACE_LEVEL_VERBOSE,
905 "AFSPrimaryVolumeWorkerThread Initialized\n");
908 // Initialize the timer for the worker thread
911 DueTime.QuadPart = -(5000);
915 KeInitializeTimerEx( &Timer,
916 SynchronizationTimer);
918 KeSetTimerEx( &Timer,
924 // Indicate that we are initialized and ready
927 KeSetEvent( &pPoolContext->WorkerThreadReady,
932 // Indicate we are initialized
935 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
937 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
940 KeWaitForSingleObject( &Timer,
947 // This is the primary volume worker so it will traverse the volume list
948 // looking for cleanup or volumes requiring private workers
951 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
954 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
956 while( pVolumeCB != NULL)
959 if( pVolumeCB == AFSGlobalRoot ||
960 !AFSAcquireExcl( pVolumeCB->VolumeLock,
964 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
969 if( pVolumeCB->ObjectInfoListHead == NULL &&
970 pVolumeCB != AFSGlobalRoot)
973 AFSReleaseResource( pVolumeCB->VolumeLock);
975 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
977 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
980 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
983 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
987 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
989 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
991 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
996 KeQueryTickCount( &liCurrentTime);
998 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1000 if( pVolumeCB->ObjectInfoListHead == NULL &&
1001 pVolumeCB->DirectoryCB->OpenReferenceCount == 0 &&
1002 pVolumeCB->VolumeReferenceCount == 1 &&
1003 ( pVolumeCB->RootFcb == NULL ||
1004 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1005 pVolumeCB->ObjectInformation.ObjectReferenceCount == 0)
1008 if( pVolumeCB->RootFcb != NULL)
1011 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1014 AFSRemoveVolume( pVolumeCB);
1019 AFSReleaseResource( pVolumeCB->VolumeLock);
1022 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1024 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1026 pVolumeCB = pNextVolume;
1032 // Don't need this lock anymore now that we have a volume cb to work with
1035 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1038 // For now we only need the volume lock shared
1041 AFSConvertToShared( pVolumeCB->VolumeLock);
1043 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1047 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1051 bReleaseVolumeLock = TRUE;
1053 while( pCurrentObject != NULL)
1056 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1059 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1061 if( pNextObject == NULL &&
1062 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1065 pNextObject = &pVolumeCB->ObjectInformation;
1068 bVolumeObject = FALSE;
1075 bVolumeObject = TRUE;
1078 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1079 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1083 // If this object is deleted then remove it from the parent, if we can
1086 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1087 pCurrentObject->ObjectReferenceCount == 0 &&
1088 ( pCurrentObject->Fcb == NULL ||
1089 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1090 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1091 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1094 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1096 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1100 if( pCurrentObject->Fcb != NULL)
1103 AFSRemoveFcb( pCurrentObject->Fcb);
1106 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1109 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1112 AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1115 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1117 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1119 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1121 AFSExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1124 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1125 AFS_TRACE_LEVEL_VERBOSE,
1126 "AFSPrimaryWorker Deleting deleted object %08lX\n",
1129 AFSDeleteObjectInfo( pCurrentObject);
1131 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1133 pCurrentObject = pNextObject;
1140 bReleaseVolumeLock = FALSE;
1146 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1147 ( pCurrentObject->Fcb != NULL &&
1148 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1149 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1152 pCurrentObject = pNextObject;
1157 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1161 pCurrentObject = pNextObject;
1166 KeQueryTickCount( &liCurrentTime);
1168 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1170 while( pCurrentDirEntry != NULL)
1173 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1174 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1175 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1176 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1177 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1178 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1179 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1180 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1181 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1182 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1183 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1184 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1190 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1193 if( pCurrentDirEntry != NULL)
1196 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1198 pCurrentObject = pNextObject;
1203 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1205 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1208 // Now acquire the locks excl
1211 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1215 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1219 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1222 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1224 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1226 pCurrentObject = pNextObject;
1231 KeQueryTickCount( &liCurrentTime);
1233 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1235 while( pCurrentDirEntry != NULL)
1238 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1239 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1240 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1241 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1242 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1243 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1244 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1245 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1246 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1247 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1248 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1249 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1255 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1258 if( pCurrentDirEntry != NULL)
1261 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1263 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1265 pCurrentObject = pNextObject;
1270 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1272 while( pCurrentDirEntry != NULL)
1275 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1277 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1279 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1280 AFS_TRACE_LEVEL_VERBOSE,
1281 "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
1282 &pCurrentDirEntry->NameInformation.FileName,
1283 pCurrentChildObject);
1285 AFSDeleteDirEntry( pCurrentObject,
1288 if( pCurrentChildObject->ObjectReferenceCount == 0)
1291 if( pCurrentChildObject->Fcb != NULL)
1294 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1297 AFSCleanupFcb( pCurrentChildObject->Fcb,
1301 AFSRemoveFcb( pCurrentChildObject->Fcb);
1304 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1305 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1308 if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1311 AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1314 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1316 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1318 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1320 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1323 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1324 AFS_TRACE_LEVEL_VERBOSE,
1325 "AFSPrimaryWorker Deleting object %08lX\n",
1326 pCurrentChildObject);
1328 AFSDeleteObjectInfo( pCurrentChildObject);
1331 pCurrentDirEntry = pNextDirEntry;
1334 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1336 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1338 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1340 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1342 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1344 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1346 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1347 AFS_TRACE_LEVEL_VERBOSE,
1348 "AFSPrimaryWorker Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1349 pCurrentObject->FileId.Cell,
1350 pCurrentObject->FileId.Volume,
1351 pCurrentObject->FileId.Vnode,
1352 pCurrentObject->FileId.Unique);
1356 // Clear our enumerated flag on this object so we retrieve info again on next access
1359 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1361 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1366 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1368 bReleaseVolumeLock = FALSE;
1373 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1379 // Try to grab the volume lock again ... no problem if we don't
1382 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1386 bReleaseVolumeLock = FALSE;
1392 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1395 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1397 if( pCurrentObject == NULL &&
1398 pVolumeCB != AFSGlobalRoot)
1401 pCurrentObject = &pVolumeCB->ObjectInformation;
1407 pCurrentObject = NULL;
1412 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1415 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1416 pCurrentObject->ObjectReferenceCount == 0 &&
1417 ( pCurrentObject->Fcb == NULL ||
1418 pCurrentObject->Fcb->OpenReferenceCount == 0))
1421 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1423 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1427 if( pCurrentObject->Fcb != NULL)
1430 AFSCleanupFcb( pCurrentObject->Fcb,
1433 AFSRemoveFcb( pCurrentObject->Fcb);
1436 AFSDeleteObjectInfo( pCurrentObject);
1438 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1440 pCurrentObject = pNextObject;
1447 bReleaseVolumeLock = FALSE;
1452 else if( pCurrentObject->Fcb != NULL)
1455 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1457 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1461 AFSCleanupFcb( pCurrentObject->Fcb,
1464 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1466 pCurrentObject = pNextObject;
1473 bReleaseVolumeLock = FALSE;
1480 pCurrentObject = pNextObject;
1483 if( bReleaseVolumeLock)
1486 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1494 AFSReleaseResource( pVolumeCB->VolumeLock);
1496 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1499 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1502 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1504 } // worker thread loop
1506 KeCancelTimer( &Timer);
1508 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1509 AFS_TRACE_LEVEL_VERBOSE,
1510 "AFSPrimaryVolumeWorkerThread Exiting\n");
1512 if( InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) == 0)
1515 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1520 PsTerminateSystemThread( 0);
1526 AFSVolumeWorkerThread( IN PVOID Context)
1529 NTSTATUS ntStatus = STATUS_SUCCESS;
1530 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1531 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1532 AFSDeviceExt *pControlDeviceExt = NULL;
1533 AFSDeviceExt *pRDRDeviceExt = NULL;
1534 BOOLEAN exitThread = FALSE;
1535 LARGE_INTEGER DueTime;
1539 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1541 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1544 // Initialize the timer for the worker thread
1547 DueTime.QuadPart = -(5000);
1551 KeInitializeTimerEx( &Timer,
1552 SynchronizationTimer);
1554 KeSetTimerEx( &Timer,
1560 // Indicate that we are initialized and ready
1563 KeSetEvent( &pPoolContext->WorkerThreadReady,
1568 // Indicate we are initialized
1571 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1573 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1576 ntStatus = KeWaitForSingleObject( &Timer,
1582 if( !NT_SUCCESS( ntStatus))
1585 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1586 AFS_TRACE_LEVEL_ERROR,
1587 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1593 // If we are in shutdown mode and the dirty flag is clear then get out now
1596 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1602 } // worker thread loop
1604 KeCancelTimer( &Timer);
1606 if( InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) == 0)
1609 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1614 PsTerminateSystemThread( 0);
1620 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1623 NTSTATUS ntStatus = STATUS_SUCCESS;
1624 AFSDeviceExt *pDevExt = NULL;
1626 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1628 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1629 AFS_TRACE_LEVEL_VERBOSE,
1630 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1631 &pDevExt->Specific.Library.QueueLock,
1632 PsGetCurrentThread());
1634 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1637 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1638 AFS_TRACE_LEVEL_VERBOSE,
1639 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1641 InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount));
1643 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1646 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1651 pDevExt->Specific.Library.QueueHead = WorkItem;
1654 WorkItem->next = NULL;
1655 pDevExt->Specific.Library.QueueTail = WorkItem;
1657 // indicate that the queue has nodes
1658 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1662 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1668 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1671 NTSTATUS ntStatus = STATUS_SUCCESS;
1672 AFSDeviceExt *pDevExt = NULL;
1674 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1676 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1677 AFS_TRACE_LEVEL_VERBOSE,
1678 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1679 &pDevExt->Specific.Library.IOQueueLock,
1680 PsGetCurrentThread());
1682 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1685 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1686 AFS_TRACE_LEVEL_VERBOSE,
1687 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1689 InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount));
1691 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1694 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1699 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1702 WorkItem->next = NULL;
1703 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1705 // indicate that the queue has nodes
1706 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1710 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1716 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1719 NTSTATUS ntStatus = STATUS_SUCCESS;
1720 AFSDeviceExt *pDevExt = NULL;
1722 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1724 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1725 AFS_TRACE_LEVEL_VERBOSE,
1726 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1727 &pDevExt->Specific.Library.QueueLock,
1728 PsGetCurrentThread());
1730 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1733 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1735 pDevExt->Specific.Library.QueueHead = WorkItem;
1737 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1738 AFS_TRACE_LEVEL_VERBOSE,
1739 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1741 InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount));
1744 // indicate that the queue has nodes
1747 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1751 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1760 NTSTATUS ntStatus = STATUS_SUCCESS;
1761 AFSWorkItem *pWorkItem = NULL;
1762 AFSDeviceExt *pDevExt = NULL;
1764 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1766 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1767 AFS_TRACE_LEVEL_VERBOSE,
1768 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1769 &pDevExt->Specific.Library.QueueLock,
1770 PsGetCurrentThread());
1772 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1775 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1778 pWorkItem = pDevExt->Specific.Library.QueueHead;
1780 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1781 AFS_TRACE_LEVEL_VERBOSE,
1782 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1784 InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount),
1785 PsGetCurrentThreadId());
1787 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1789 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1792 pDevExt->Specific.Library.QueueTail = NULL;
1794 KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
1799 KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
1802 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1808 AFSRemoveIOWorkItem()
1811 NTSTATUS ntStatus = STATUS_SUCCESS;
1812 AFSWorkItem *pWorkItem = NULL;
1813 AFSDeviceExt *pDevExt = NULL;
1815 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1817 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1818 AFS_TRACE_LEVEL_VERBOSE,
1819 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1820 &pDevExt->Specific.Library.IOQueueLock,
1821 PsGetCurrentThread());
1823 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1826 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
1829 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
1831 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1832 AFS_TRACE_LEVEL_VERBOSE,
1833 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1835 InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount),
1836 PsGetCurrentThreadId());
1838 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
1840 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
1843 pDevExt->Specific.Library.IOQueueTail = NULL;
1845 KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
1850 KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
1853 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1859 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
1862 NTSTATUS ntStatus = STATUS_SUCCESS;
1863 AFSDeviceExt *pDevExt = NULL;
1864 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1867 // Submit the work item to the worker
1870 ntStatus = AFSInsertWorkitem( WorkItem);
1876 // Sync request so block on the work item event
1879 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1890 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
1893 NTSTATUS ntStatus = STATUS_SUCCESS;
1894 AFSDeviceExt *pDevExt = NULL;
1895 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1898 // Submit the work item to the worker
1901 ntStatus = AFSInsertIOWorkitem( WorkItem);
1907 // Sync request so block on the work item event
1910 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1921 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
1924 NTSTATUS ntStatus = STATUS_SUCCESS;
1925 AFSDeviceExt *pDevExt = NULL;
1926 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1929 // Submit the work item to the worker
1932 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
1938 // Sync request so block on the work item event
1941 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1952 AFSQueueFlushExtents( IN AFSFcb *Fcb)
1955 NTSTATUS ntStatus = STATUS_SUCCESS;
1956 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1957 AFSWorkItem *pWorkItem = NULL;
1962 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1963 AFS_TRACE_LEVEL_VERBOSE,
1964 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
1965 Fcb->ObjectInformation->FileId.Cell,
1966 Fcb->ObjectInformation->FileId.Volume,
1967 Fcb->ObjectInformation->FileId.Vnode,
1968 Fcb->ObjectInformation->FileId.Unique);
1971 // Increment our flush count here just to keep the number of items in the
1972 // queue down. We'll decrement it just below.
1975 if( InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount) > 3)
1978 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1979 AFS_TRACE_LEVEL_VERBOSE,
1980 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
1981 Fcb->ObjectInformation->FileId.Cell,
1982 Fcb->ObjectInformation->FileId.Volume,
1983 Fcb->ObjectInformation->FileId.Vnode,
1984 Fcb->ObjectInformation->FileId.Unique);
1986 try_return( ntStatus);
1989 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1992 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1993 AFS_TRACE_LEVEL_ERROR,
1994 "AFSQueueFlushExtents Failing request, in shutdown\n");
1996 try_return( ntStatus = STATUS_TOO_LATE);
2000 // Allocate our request structure and send it to the worker
2003 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2004 sizeof( AFSWorkItem),
2007 if( pWorkItem == NULL)
2010 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2011 AFS_TRACE_LEVEL_ERROR,
2012 "AFSQueueFlushExtents Failed to allocate work item\n");
2014 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2017 RtlZeroMemory( pWorkItem,
2018 sizeof( AFSWorkItem));
2020 pWorkItem->Size = sizeof( AFSWorkItem);
2022 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2024 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2026 pWorkItem->Specific.Fcb.Fcb = Fcb;
2028 InterlockedIncrement( &Fcb->OpenReferenceCount);
2030 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2031 AFS_TRACE_LEVEL_VERBOSE,
2032 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2034 Fcb->OpenReferenceCount);
2036 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2037 AFS_TRACE_LEVEL_VERBOSE,
2038 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2040 Fcb->ObjectInformation->FileId.Cell,
2041 Fcb->ObjectInformation->FileId.Volume,
2042 Fcb->ObjectInformation->FileId.Vnode,
2043 Fcb->ObjectInformation->FileId.Unique);
2045 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2049 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2050 AFS_TRACE_LEVEL_VERBOSE,
2051 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2052 Fcb->ObjectInformation->FileId.Cell,
2053 Fcb->ObjectInformation->FileId.Volume,
2054 Fcb->ObjectInformation->FileId.Vnode,
2055 Fcb->ObjectInformation->FileId.Unique,
2059 // Remove the count we added above
2062 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2065 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2070 if( !NT_SUCCESS( ntStatus))
2073 if( pWorkItem != NULL)
2076 InterlockedDecrement( &Fcb->OpenReferenceCount);
2078 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2081 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2082 AFS_TRACE_LEVEL_ERROR,
2083 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2086 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2091 "EXCEPTION - AFSQueueFlushExtents\n");
2098 AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
2100 IN HANDLE CallerProcess)
2103 NTSTATUS ntStatus = STATUS_SUCCESS;
2104 AFSWorkItem *pWorkItem = NULL;
2109 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2110 AFS_TRACE_LEVEL_VERBOSE,
2111 "AFSQueueAsyncRead Queuing request for Irp %08lX\n",
2114 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2115 sizeof(AFSWorkItem),
2117 if (NULL == pWorkItem)
2120 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2121 AFS_TRACE_LEVEL_ERROR,
2122 "AFSQueueAsyncRead Failed to allocate work item\n");
2124 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2127 RtlZeroMemory( pWorkItem,
2128 sizeof(AFSWorkItem));
2130 pWorkItem->Size = sizeof( AFSWorkItem);
2132 pWorkItem->RequestType = AFS_WORK_ASYNCH_READ;
2134 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2136 pWorkItem->Specific.AsynchIo.Irp = Irp;
2138 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2140 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2141 AFS_TRACE_LEVEL_VERBOSE,
2142 "AFSQueueAsyncRead Workitem %08lX for Irp %08lX\n",
2146 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2150 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2151 AFS_TRACE_LEVEL_VERBOSE,
2152 "AFSQueueAsyncRead Request for Irp %08lX complete Status %08lX\n",
2156 if( !NT_SUCCESS( ntStatus))
2159 if( pWorkItem != NULL)
2162 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2165 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2166 AFS_TRACE_LEVEL_ERROR,
2167 "AFSQueueAsyncRead Failed to queue request Status %08lX\n", ntStatus);
2170 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2175 "EXCEPTION - AFSQueueAsyncRead\n");
2182 AFSQueueAsyncWrite( IN PDEVICE_OBJECT DeviceObject,
2184 IN HANDLE CallerProcess)
2187 NTSTATUS ntStatus = STATUS_SUCCESS;
2188 AFSWorkItem *pWorkItem = NULL;
2193 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2194 AFS_TRACE_LEVEL_VERBOSE,
2195 "AFSQueueAsyncWrite Queuing request for Irp %08lX\n",
2198 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2199 sizeof(AFSWorkItem),
2201 if (NULL == pWorkItem)
2204 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2205 AFS_TRACE_LEVEL_ERROR,
2206 "AFSQueueAsyncWrite Failed to allocate work item\n");
2208 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2211 RtlZeroMemory( pWorkItem,
2212 sizeof(AFSWorkItem));
2214 pWorkItem->Size = sizeof( AFSWorkItem);
2216 pWorkItem->RequestType = AFS_WORK_ASYNCH_WRITE;
2218 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2220 pWorkItem->Specific.AsynchIo.Irp = Irp;
2222 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2224 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2225 AFS_TRACE_LEVEL_VERBOSE,
2226 "AFSQueueAsyncWrite Workitem %08lX for Irp %08lX\n",
2230 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2234 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2235 AFS_TRACE_LEVEL_VERBOSE,
2236 "AFSQueueAsyncWrite Request for Irp %08lX complete Status %08lX\n",
2240 if( !NT_SUCCESS( ntStatus))
2243 if( pWorkItem != NULL)
2246 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2249 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2250 AFS_TRACE_LEVEL_ERROR,
2251 "AFSQueueAsyncWrite Failed to queue request Status %08lX\n", ntStatus);
2254 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2259 "EXCEPTION - AFSQueueAsyncWrite\n");
2266 AFSQueueGlobalRootEnumeration()
2269 NTSTATUS ntStatus = STATUS_SUCCESS;
2270 AFSWorkItem *pWorkItem = NULL;
2275 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2276 sizeof(AFSWorkItem),
2278 if (NULL == pWorkItem)
2281 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2282 AFS_TRACE_LEVEL_ERROR,
2283 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2285 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2288 RtlZeroMemory( pWorkItem,
2289 sizeof(AFSWorkItem));
2291 pWorkItem->Size = sizeof( AFSWorkItem);
2293 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2295 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2296 AFS_TRACE_LEVEL_VERBOSE,
2297 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2300 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2304 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2305 AFS_TRACE_LEVEL_VERBOSE,
2306 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2309 if( !NT_SUCCESS( ntStatus))
2312 if( pWorkItem != NULL)
2315 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2318 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2319 AFS_TRACE_LEVEL_ERROR,
2320 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2324 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2329 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2336 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2337 IN UCHAR FunctionCode,
2338 IN ULONG RequestFlags,
2339 IN AFSIoRun *IoRuns,
2341 IN AFSGatherIo *GatherIo)
2344 NTSTATUS ntStatus = STATUS_SUCCESS;
2345 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2346 AFSWorkItem *pWorkItem = NULL;
2351 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2354 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2355 AFS_TRACE_LEVEL_ERROR,
2356 "AFSQueueStartIos Failing request, in shutdown\n");
2358 try_return( ntStatus = STATUS_TOO_LATE);
2362 // Allocate our request structure and send it to the worker
2365 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2366 sizeof( AFSWorkItem),
2369 if( pWorkItem == NULL)
2372 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2373 AFS_TRACE_LEVEL_ERROR,
2374 "AFSQueueStartIos Failed to allocate work item\n");
2376 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2379 RtlZeroMemory( pWorkItem,
2380 sizeof( AFSWorkItem));
2382 KeInitializeEvent( &pWorkItem->Event,
2386 pWorkItem->Size = sizeof( AFSWorkItem);
2388 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2390 pWorkItem->RequestType = AFS_WORK_START_IOS;
2392 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2394 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2396 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2398 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2400 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2402 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2404 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2405 AFS_TRACE_LEVEL_VERBOSE,
2406 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2409 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2413 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2414 AFS_TRACE_LEVEL_VERBOSE,
2415 "AFSQueueStartIos Request complete Status %08lX\n",
2418 if( !NT_SUCCESS( ntStatus))
2421 if( pWorkItem != NULL)
2424 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2428 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2433 "EXCEPTION - AFSQueueStartIos\n");