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,
155 SynchronizationEvent,
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 in two stages.
269 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
270 // stop processing requests. Second, call AFSShutdownWorkerThread()
271 // to wake the workers and wait for them to exit.
274 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
276 while( index < pDevExt->Specific.Library.WorkerCount)
279 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
281 pCurrentWorker = pCurrentWorker->fLink;
283 if ( pCurrentWorker == NULL)
292 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
296 while( index < pDevExt->Specific.Library.WorkerCount)
299 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
301 pNextWorker = pCurrentWorker->fLink;
303 ExFreePool( pCurrentWorker);
305 pCurrentWorker = pNextWorker;
307 if( pCurrentWorker == NULL)
316 pDevExt->Specific.Library.PoolHead = NULL;
318 ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
321 // Loop through the IO workers shutting them down in two stages.
322 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
323 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
324 // to wake the workers and wait for them to exit.
327 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
331 while( index < pDevExt->Specific.Library.IOWorkerCount)
334 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
336 pCurrentWorker = pCurrentWorker->fLink;
338 if ( pCurrentWorker == NULL)
347 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
351 while( index < pDevExt->Specific.Library.IOWorkerCount)
354 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
356 pNextWorker = pCurrentWorker->fLink;
358 ExFreePool( pCurrentWorker);
360 pCurrentWorker = pNextWorker;
362 if( pCurrentWorker == NULL)
371 pDevExt->Specific.Library.IOPoolHead = NULL;
373 ExDeleteResourceLite( &pDevExt->Specific.Library.IOQueueLock);
379 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
382 NTSTATUS ntStatus = STATUS_SUCCESS;
383 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
385 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
386 PKSTART_ROUTINE pStartRoutine = NULL;
392 if( VolumeCB == AFSGlobalRoot)
395 pStartRoutine = AFSPrimaryVolumeWorkerThread;
400 pStartRoutine = AFSVolumeWorkerThread;
404 // Initialize the worker thread
407 KeInitializeEvent( &pWorker->WorkerThreadReady,
412 // Set the worker to process requests
415 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
421 ntStatus = PsCreateSystemThread( &hThread,
429 if( NT_SUCCESS( ntStatus))
432 ObReferenceObjectByHandle( hThread,
433 GENERIC_READ | GENERIC_WRITE,
436 (PVOID *)&pWorker->WorkerThreadObject,
439 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
445 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
450 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
461 // Function: AFSInitWorkerThread
465 // This function initializes a worker thread in the pool
469 // A status is returned for the function
473 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
474 IN PKSTART_ROUTINE WorkerRoutine)
477 NTSTATUS ntStatus = STATUS_SUCCESS;
481 // INitialize the worker signal thread
484 KeInitializeEvent( &PoolContext->WorkerThreadReady,
489 // Set the worker to process requests
492 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
498 ntStatus = PsCreateSystemThread( &Handle,
504 (void *)PoolContext);
506 if( NT_SUCCESS( ntStatus))
509 ObReferenceObjectByHandle( Handle,
510 GENERIC_READ | GENERIC_WRITE,
513 (PVOID *)&PoolContext->WorkerThreadObject,
516 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
529 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
532 NTSTATUS ntStatus = STATUS_SUCCESS;
533 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
536 // Clear the 'keep processing' flag
539 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
541 if( pWorker->WorkerThreadObject != NULL)
543 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
546 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
553 ObDereferenceObject( pWorker->WorkerThreadObject);
555 pWorker->WorkerThreadObject = NULL;
562 // Function: AFSShutdownWorkerThread
566 // This function shutsdown a worker thread in the pool
570 // A status is returned for the function
574 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
577 NTSTATUS ntStatus = STATUS_SUCCESS;
578 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
580 if( PoolContext->WorkerThreadObject != NULL)
583 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
587 // Wake up the thread if it is a sleep
590 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
594 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
601 ObDereferenceObject( PoolContext->WorkerThreadObject);
603 PoolContext->WorkerThreadObject = NULL;
610 // Function: AFSShutdownIOWorkerThread
614 // This function shutsdown an IO worker thread in the pool
618 // A status is returned for the function
622 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
625 NTSTATUS ntStatus = STATUS_SUCCESS;
626 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
628 if( PoolContext->WorkerThreadObject != NULL)
631 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
635 // Wake up the thread if it is a sleep
638 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
642 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
649 ObDereferenceObject( PoolContext->WorkerThreadObject);
651 PoolContext->WorkerThreadObject = NULL;
658 // Function: AFSWorkerThread
662 // This is the worker thread entry point.
666 // A status is returned for the function
670 AFSWorkerThread( IN PVOID Context)
673 NTSTATUS ntStatus = STATUS_SUCCESS;
674 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
675 AFSWorkItem *pWorkItem;
676 BOOLEAN freeWorkItem = TRUE;
677 AFSDeviceExt *pLibraryDevExt = NULL;
680 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
683 // Indicate that we are initialized and ready
686 KeSetEvent( &pPoolContext->WorkerThreadReady,
691 // Indicate we are initialized
694 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
696 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
702 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
705 if( !NT_SUCCESS( ntStatus))
708 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
709 AFS_TRACE_LEVEL_ERROR,
710 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
712 ntStatus = STATUS_SUCCESS;
717 pWorkItem = AFSRemoveWorkItem();
719 if( pWorkItem == NULL)
722 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
734 // Switch on the type of work item to process
737 switch( pWorkItem->RequestType)
740 case AFS_WORK_FLUSH_FCB:
743 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
744 &pWorkItem->AuthGroup);
746 if( !NT_SUCCESS( ntStatus))
749 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
750 &pWorkItem->AuthGroup,
754 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
756 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
761 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
764 AFSEnumerateGlobalRoot( NULL);
769 case AFS_WORK_INVALIDATE_OBJECT:
772 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
773 pWorkItem->Specific.Invalidate.InvalidateReason);
780 case AFS_WORK_START_IOS:
790 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
791 AFS_TRACE_LEVEL_ERROR,
792 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
800 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
803 ntStatus = STATUS_SUCCESS;
806 } // worker thread loop
808 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
810 // Wake up another worker so they too can exit
812 KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
816 PsTerminateSystemThread( 0);
822 AFSIOWorkerThread( IN PVOID Context)
825 NTSTATUS ntStatus = STATUS_SUCCESS;
826 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
827 AFSWorkItem *pWorkItem;
828 BOOLEAN freeWorkItem = TRUE;
829 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
831 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
834 // Indicate that we are initialized and ready
837 KeSetEvent( &pPoolContext->WorkerThreadReady,
843 // Indicate we are initialized
846 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
848 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
854 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
857 if( !NT_SUCCESS( ntStatus))
860 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
861 AFS_TRACE_LEVEL_ERROR,
862 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
864 ntStatus = STATUS_SUCCESS;
869 pWorkItem = AFSRemoveIOWorkItem();
871 if( pWorkItem == NULL)
874 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
886 // Switch on the type of work item to process
889 switch( pWorkItem->RequestType)
892 case AFS_WORK_START_IOS:
895 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
898 // The final status is in the gather io
901 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
902 pWorkItem->Specific.CacheAccess.FunctionCode,
903 pWorkItem->Specific.CacheAccess.RequestFlags,
904 pWorkItem->Specific.CacheAccess.IoRuns,
905 pWorkItem->Specific.CacheAccess.RunCount,
906 pWorkItem->Specific.CacheAccess.GatherIo);
909 // Regardless of the status we we do the complete - there may
911 // Decrement the count - setting the event if we were told
912 // to. This may trigger completion.
915 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
924 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
925 AFS_TRACE_LEVEL_ERROR,
926 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
934 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
937 ntStatus = STATUS_SUCCESS;
940 } // worker thread loop
942 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
944 // Wake up another IOWorker so they too can exit
946 KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
950 PsTerminateSystemThread( 0);
956 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
959 UNREFERENCED_PARAMETER(Context);
960 NTSTATUS ntStatus = STATUS_SUCCESS;
961 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
962 AFSDeviceExt *pControlDeviceExt = NULL;
963 AFSDeviceExt *pRDRDeviceExt = NULL;
964 LARGE_INTEGER DueTime;
967 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
968 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
969 BOOLEAN bReleaseVolumeLock = FALSE;
970 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
972 LARGE_INTEGER liCurrentTime;
973 BOOLEAN bVolumeObject = FALSE;
974 BOOLEAN bFcbBusy = FALSE;
977 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
979 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
981 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
982 AFS_TRACE_LEVEL_VERBOSE,
983 "AFSPrimaryVolumeWorkerThread Initialized\n");
986 // Initialize the timer for the worker thread
989 DueTime.QuadPart = -(5000);
993 KeInitializeTimerEx( &Timer,
994 SynchronizationTimer);
996 KeSetTimerEx( &Timer,
1002 // Indicate that we are initialized and ready
1005 KeSetEvent( &pPoolContext->WorkerThreadReady,
1010 // Indicate we are initialized
1013 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1015 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1018 if ( bFcbBusy == FALSE)
1021 KeWaitForSingleObject( &Timer,
1034 // This is the primary volume worker so it will traverse the volume list
1035 // looking for cleanup or volumes requiring private workers
1038 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1041 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1043 while( pVolumeCB != NULL)
1046 if( pVolumeCB == AFSGlobalRoot ||
1047 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1051 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1056 if( pVolumeCB->ObjectInfoListHead == NULL)
1059 AFSReleaseResource( pVolumeCB->VolumeLock);
1061 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1063 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1066 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1069 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1073 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1075 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1077 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1082 KeQueryTickCount( &liCurrentTime);
1084 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1086 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1089 if( pVolumeCB->ObjectInfoListHead == NULL &&
1090 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1091 pVolumeCB->VolumeReferenceCount == 1 &&
1092 ( pVolumeCB->RootFcb == NULL ||
1093 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1094 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1097 if( pVolumeCB->RootFcb != NULL)
1100 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1103 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1105 AFSRemoveVolume( pVolumeCB);
1110 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1112 AFSReleaseResource( pVolumeCB->VolumeLock);
1115 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1117 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1119 pVolumeCB = pNextVolume;
1125 // Don't need this lock anymore now that we have a volume cb to work with
1128 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1131 // For now we only need the volume lock shared
1134 AFSConvertToShared( pVolumeCB->VolumeLock);
1136 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1140 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1144 bReleaseVolumeLock = TRUE;
1146 while( pCurrentObject != NULL)
1149 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1152 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1154 if( pNextObject == NULL &&
1155 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1158 pNextObject = &pVolumeCB->ObjectInformation;
1161 bVolumeObject = FALSE;
1168 bVolumeObject = TRUE;
1171 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1172 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1176 // If this object is deleted then remove it from the parent, if we can
1179 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1180 pCurrentObject->ObjectReferenceCount <= 0 &&
1181 ( pCurrentObject->Fcb == NULL ||
1182 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1183 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1184 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1187 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1190 // Dropping the TreeLock permits the
1191 // pCurrentObject->ObjectReferenceCount to change
1194 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1198 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1201 if ( pCurrentObject->ObjectReferenceCount <= 0)
1204 AFSRemoveFcb( &pCurrentObject->Fcb);
1206 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1209 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1212 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1214 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1216 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1218 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1220 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1222 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1225 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1227 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1228 AFS_TRACE_LEVEL_VERBOSE,
1229 "AFSPrimaryVolumeWorkerThread Deleting deleted object %08lX\n",
1232 AFSDeleteObjectInfo( pCurrentObject);
1237 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1240 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1242 pCurrentObject = pNextObject;
1249 bReleaseVolumeLock = FALSE;
1255 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1256 ( pCurrentObject->Fcb != NULL &&
1257 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1258 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1261 pCurrentObject = pNextObject;
1266 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1270 pCurrentObject = pNextObject;
1275 KeQueryTickCount( &liCurrentTime);
1277 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1279 while( pCurrentDirEntry != NULL)
1282 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1283 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1284 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1285 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1286 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1287 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1288 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1289 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1290 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1291 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1292 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1293 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1299 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1302 if( pCurrentDirEntry != NULL)
1305 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1307 pCurrentObject = pNextObject;
1312 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1314 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1317 // Now acquire the locks excl
1320 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1324 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1328 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1331 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1333 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1335 pCurrentObject = pNextObject;
1340 KeQueryTickCount( &liCurrentTime);
1342 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1344 while( pCurrentDirEntry != NULL)
1347 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1348 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1349 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1350 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1351 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1352 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1353 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1354 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1355 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1356 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1357 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1358 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1364 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1367 if( pCurrentDirEntry != NULL)
1370 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1372 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1374 pCurrentObject = pNextObject;
1379 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1381 while( pCurrentDirEntry != NULL)
1384 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1386 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1390 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1391 AFS_TRACE_LEVEL_VERBOSE,
1392 "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %08lX\n",
1393 &pCurrentDirEntry->NameInformation.FileName,
1394 pCurrentChildObject);
1396 AFSDeleteDirEntry( pCurrentObject,
1401 // Acquire ObjectInfoLock shared here so as not to deadlock
1402 // with an invalidation call from the service during AFSCleanupFcb
1405 lCount = AFSObjectInfoIncrement( pCurrentChildObject);
1408 pCurrentChildObject->Fcb != NULL &&
1409 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1413 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
1414 // across an AFSCleanupFcb call since it can deadlock with an
1415 // invalidation call from the service.
1418 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1421 // Cannot hold a TreeLock across an AFSCleanupFcb call
1422 // as it can deadlock with an invalidation ioctl initiated
1423 // from the service.
1425 // Dropping the TreeLock permits the
1426 // pCurrentObject->ObjectReferenceCount to change
1429 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1432 if ( ntStatus == STATUS_RETRY)
1438 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1442 lCount = AFSObjectInfoDecrement( pCurrentChildObject);
1444 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1447 if( pCurrentChildObject->ObjectReferenceCount <= 0)
1450 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1452 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1453 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1456 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1459 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1461 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1463 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1465 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1467 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1469 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1472 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1474 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1475 AFS_TRACE_LEVEL_VERBOSE,
1476 "AFSPrimaryVolumeWorkerThread Deleting object %08lX\n",
1477 pCurrentChildObject);
1479 AFSDeleteObjectInfo( pCurrentChildObject);
1484 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1487 pCurrentDirEntry = pNextDirEntry;
1491 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1493 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1495 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1497 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1499 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1501 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1503 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1504 AFS_TRACE_LEVEL_VERBOSE,
1505 "AFSPrimaryVolumeWorkerThread Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1506 pCurrentObject->FileId.Cell,
1507 pCurrentObject->FileId.Volume,
1508 pCurrentObject->FileId.Vnode,
1509 pCurrentObject->FileId.Unique);
1512 // Clear our enumerated flag on this object so we retrieve info again on next access
1515 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1517 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1519 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1524 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1526 bReleaseVolumeLock = FALSE;
1535 // Try to grab the volume lock again ... no problem if we don't
1538 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1542 bReleaseVolumeLock = FALSE;
1548 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1551 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1553 if( pCurrentObject == NULL &&
1554 pVolumeCB != AFSGlobalRoot)
1557 pCurrentObject = &pVolumeCB->ObjectInformation;
1563 pCurrentObject = NULL;
1568 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1571 lCount = AFSObjectInfoIncrement( pCurrentObject);
1573 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1575 if( pCurrentObject->Fcb != NULL)
1579 // Dropping the TreeLock permits the
1580 // pCurrentObject->ObjectReferenceCount to change
1583 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1586 if ( ntStatus == STATUS_RETRY)
1593 lCount = AFSObjectInfoDecrement( pCurrentObject);
1595 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1599 bReleaseVolumeLock = FALSE;
1604 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1607 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1608 pCurrentObject->ObjectReferenceCount <= 0)
1611 AFSRemoveFcb( &pCurrentObject->Fcb);
1613 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1615 AFSDeleteObjectInfo( pCurrentObject);
1620 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1623 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1625 pCurrentObject = pNextObject;
1630 pCurrentObject = pNextObject;
1633 if( bReleaseVolumeLock)
1636 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1644 AFSReleaseResource( pVolumeCB->VolumeLock);
1646 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1649 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1652 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1654 } // worker thread loop
1656 KeCancelTimer( &Timer);
1658 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1660 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1661 AFS_TRACE_LEVEL_VERBOSE,
1662 "AFSPrimaryVolumeWorkerThread Exiting\n");
1664 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1669 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1674 PsTerminateSystemThread( 0);
1680 AFSVolumeWorkerThread( IN PVOID Context)
1683 NTSTATUS ntStatus = STATUS_SUCCESS;
1684 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1685 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1686 AFSDeviceExt *pControlDeviceExt = NULL;
1687 AFSDeviceExt *pRDRDeviceExt = NULL;
1688 LARGE_INTEGER DueTime;
1693 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1695 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1698 // Initialize the timer for the worker thread
1701 DueTime.QuadPart = -(5000);
1705 KeInitializeTimerEx( &Timer,
1706 SynchronizationTimer);
1708 KeSetTimerEx( &Timer,
1714 // Indicate that we are initialized and ready
1717 KeSetEvent( &pPoolContext->WorkerThreadReady,
1722 // Indicate we are initialized
1725 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1727 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1730 ntStatus = KeWaitForSingleObject( &Timer,
1736 if( !NT_SUCCESS( ntStatus))
1739 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1740 AFS_TRACE_LEVEL_ERROR,
1741 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1747 // If we are in shutdown mode and the dirty flag is clear then get out now
1750 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1756 } // worker thread loop
1758 KeCancelTimer( &Timer);
1760 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1765 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1770 PsTerminateSystemThread( 0);
1776 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1779 NTSTATUS ntStatus = STATUS_SUCCESS;
1780 AFSDeviceExt *pDevExt = NULL;
1783 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1785 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1786 AFS_TRACE_LEVEL_VERBOSE,
1787 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1788 &pDevExt->Specific.Library.QueueLock,
1789 PsGetCurrentThread());
1791 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1794 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1796 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1797 AFS_TRACE_LEVEL_VERBOSE,
1798 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1802 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1805 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1810 pDevExt->Specific.Library.QueueHead = WorkItem;
1813 WorkItem->next = NULL;
1814 pDevExt->Specific.Library.QueueTail = WorkItem;
1816 // indicate that the queue has nodes
1817 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1821 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1827 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1830 NTSTATUS ntStatus = STATUS_SUCCESS;
1831 AFSDeviceExt *pDevExt = NULL;
1834 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1836 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1837 AFS_TRACE_LEVEL_VERBOSE,
1838 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1839 &pDevExt->Specific.Library.IOQueueLock,
1840 PsGetCurrentThread());
1842 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1845 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
1847 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1848 AFS_TRACE_LEVEL_VERBOSE,
1849 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1853 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1856 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1861 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1864 WorkItem->next = NULL;
1865 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1867 // indicate that the queue has nodes
1868 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1872 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1878 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1881 NTSTATUS ntStatus = STATUS_SUCCESS;
1882 AFSDeviceExt *pDevExt = NULL;
1885 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1887 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1888 AFS_TRACE_LEVEL_VERBOSE,
1889 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1890 &pDevExt->Specific.Library.QueueLock,
1891 PsGetCurrentThread());
1893 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1896 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1898 pDevExt->Specific.Library.QueueHead = WorkItem;
1900 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1902 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1903 AFS_TRACE_LEVEL_VERBOSE,
1904 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1909 // indicate that the queue has nodes
1912 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1916 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1925 AFSWorkItem *pWorkItem = NULL;
1926 AFSDeviceExt *pDevExt = NULL;
1929 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1931 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1932 AFS_TRACE_LEVEL_VERBOSE,
1933 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1934 &pDevExt->Specific.Library.QueueLock,
1935 PsGetCurrentThread());
1937 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1940 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1943 pWorkItem = pDevExt->Specific.Library.QueueHead;
1945 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
1947 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1948 AFS_TRACE_LEVEL_VERBOSE,
1949 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1952 PsGetCurrentThreadId());
1954 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1956 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1959 pDevExt->Specific.Library.QueueTail = NULL;
1965 // Wake up another worker
1968 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1974 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1980 AFSRemoveIOWorkItem()
1983 AFSWorkItem *pWorkItem = NULL;
1984 AFSDeviceExt *pDevExt = NULL;
1987 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1989 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1990 AFS_TRACE_LEVEL_VERBOSE,
1991 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1992 &pDevExt->Specific.Library.IOQueueLock,
1993 PsGetCurrentThread());
1995 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1998 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
2001 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
2003 lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
2005 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2006 AFS_TRACE_LEVEL_VERBOSE,
2007 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
2010 PsGetCurrentThreadId());
2012 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
2014 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
2017 pDevExt->Specific.Library.IOQueueTail = NULL;
2023 // Wake up another worker
2026 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
2032 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
2038 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2041 NTSTATUS ntStatus = STATUS_SUCCESS;
2042 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2045 // Submit the work item to the worker
2048 ntStatus = AFSInsertWorkitem( WorkItem);
2054 // Sync request so block on the work item event
2057 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2068 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2071 NTSTATUS ntStatus = STATUS_SUCCESS;
2072 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2075 // Submit the work item to the worker
2078 ntStatus = AFSInsertIOWorkitem( WorkItem);
2084 // Sync request so block on the work item event
2087 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2098 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2101 NTSTATUS ntStatus = STATUS_SUCCESS;
2102 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2105 // Submit the work item to the worker
2108 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2114 // Sync request so block on the work item event
2117 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2128 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2132 NTSTATUS ntStatus = STATUS_SUCCESS;
2133 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2134 AFSWorkItem *pWorkItem = NULL;
2140 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2141 AFS_TRACE_LEVEL_VERBOSE,
2142 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2143 Fcb->ObjectInformation->FileId.Cell,
2144 Fcb->ObjectInformation->FileId.Volume,
2145 Fcb->ObjectInformation->FileId.Vnode,
2146 Fcb->ObjectInformation->FileId.Unique);
2149 // Increment our flush count here just to keep the number of items in the
2150 // queue down. We'll decrement it just below.
2153 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2158 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2159 AFS_TRACE_LEVEL_VERBOSE,
2160 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2161 Fcb->ObjectInformation->FileId.Cell,
2162 Fcb->ObjectInformation->FileId.Volume,
2163 Fcb->ObjectInformation->FileId.Vnode,
2164 Fcb->ObjectInformation->FileId.Unique);
2166 try_return( ntStatus);
2169 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2173 AFS_TRACE_LEVEL_ERROR,
2174 "AFSQueueFlushExtents Failing request, in shutdown\n");
2176 try_return( ntStatus = STATUS_TOO_LATE);
2180 // Allocate our request structure and send it to the worker
2183 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2184 sizeof( AFSWorkItem),
2187 if( pWorkItem == NULL)
2190 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2191 AFS_TRACE_LEVEL_ERROR,
2192 "AFSQueueFlushExtents Failed to allocate work item\n");
2194 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2197 RtlZeroMemory( pWorkItem,
2198 sizeof( AFSWorkItem));
2200 pWorkItem->Size = sizeof( AFSWorkItem);
2202 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2204 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2206 if ( AuthGroup == NULL)
2209 RtlZeroMemory( &pWorkItem->AuthGroup,
2212 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2215 &pWorkItem->AuthGroup);
2219 RtlCopyMemory( &pWorkItem->AuthGroup,
2224 pWorkItem->Specific.Fcb.Fcb = Fcb;
2226 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2228 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2229 AFS_TRACE_LEVEL_VERBOSE,
2230 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2234 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2235 AFS_TRACE_LEVEL_VERBOSE,
2236 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2238 Fcb->ObjectInformation->FileId.Cell,
2239 Fcb->ObjectInformation->FileId.Volume,
2240 Fcb->ObjectInformation->FileId.Vnode,
2241 Fcb->ObjectInformation->FileId.Unique);
2243 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2247 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2248 AFS_TRACE_LEVEL_VERBOSE,
2249 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2250 Fcb->ObjectInformation->FileId.Cell,
2251 Fcb->ObjectInformation->FileId.Volume,
2252 Fcb->ObjectInformation->FileId.Vnode,
2253 Fcb->ObjectInformation->FileId.Unique,
2257 // Remove the count we added above
2260 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2262 ASSERT( lCount >= 0);
2267 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2272 if( !NT_SUCCESS( ntStatus))
2275 if( pWorkItem != NULL)
2278 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2280 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2283 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2284 AFS_TRACE_LEVEL_ERROR,
2285 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2288 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2293 "EXCEPTION - AFSQueueFlushExtents\n");
2295 AFSDumpTraceFilesFnc();
2302 AFSQueueGlobalRootEnumeration()
2305 NTSTATUS ntStatus = STATUS_SUCCESS;
2306 AFSWorkItem *pWorkItem = NULL;
2311 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2312 sizeof(AFSWorkItem),
2314 if (NULL == pWorkItem)
2317 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2318 AFS_TRACE_LEVEL_ERROR,
2319 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2321 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2324 RtlZeroMemory( pWorkItem,
2325 sizeof(AFSWorkItem));
2327 pWorkItem->Size = sizeof( AFSWorkItem);
2329 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2331 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2332 AFS_TRACE_LEVEL_VERBOSE,
2333 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2336 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2340 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2341 AFS_TRACE_LEVEL_VERBOSE,
2342 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2345 if( !NT_SUCCESS( ntStatus))
2348 if( pWorkItem != NULL)
2351 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2354 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2355 AFS_TRACE_LEVEL_ERROR,
2356 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2360 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2365 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2367 AFSDumpTraceFilesFnc();
2374 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2375 IN UCHAR FunctionCode,
2376 IN ULONG RequestFlags,
2377 IN AFSIoRun *IoRuns,
2379 IN AFSGatherIo *GatherIo)
2382 NTSTATUS ntStatus = STATUS_SUCCESS;
2383 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2384 AFSWorkItem *pWorkItem = NULL;
2389 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2392 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2393 AFS_TRACE_LEVEL_ERROR,
2394 "AFSQueueStartIos Failing request, in shutdown\n");
2396 try_return( ntStatus = STATUS_TOO_LATE);
2400 // Allocate our request structure and send it to the worker
2403 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2404 sizeof( AFSWorkItem),
2407 if( pWorkItem == NULL)
2410 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2411 AFS_TRACE_LEVEL_ERROR,
2412 "AFSQueueStartIos Failed to allocate work item\n");
2414 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2417 RtlZeroMemory( pWorkItem,
2418 sizeof( AFSWorkItem));
2420 KeInitializeEvent( &pWorkItem->Event,
2424 pWorkItem->Size = sizeof( AFSWorkItem);
2426 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2428 pWorkItem->RequestType = AFS_WORK_START_IOS;
2430 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2432 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2434 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2436 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2438 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2440 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2442 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2443 AFS_TRACE_LEVEL_VERBOSE,
2444 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2447 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2451 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2452 AFS_TRACE_LEVEL_VERBOSE,
2453 "AFSQueueStartIos Request complete Status %08lX\n",
2456 if( !NT_SUCCESS( ntStatus))
2459 if( pWorkItem != NULL)
2462 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2466 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2471 "EXCEPTION - AFSQueueStartIos\n");
2473 AFSDumpTraceFilesFnc();
2480 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2481 IN ULONG InvalidateReason)
2484 NTSTATUS ntStatus = STATUS_SUCCESS;
2485 AFSWorkItem *pWorkItem = NULL;
2490 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2491 sizeof(AFSWorkItem),
2493 if (NULL == pWorkItem)
2496 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2497 AFS_TRACE_LEVEL_ERROR,
2498 "AFSQueueInvalidateObject Failed to allocate work item\n");
2500 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2503 RtlZeroMemory( pWorkItem,
2504 sizeof(AFSWorkItem));
2506 pWorkItem->Size = sizeof( AFSWorkItem);
2508 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2510 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2512 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2514 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2515 AFS_TRACE_LEVEL_VERBOSE,
2516 "AFSQueueInvalidateObject Workitem %08lX\n",
2519 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2523 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2524 AFS_TRACE_LEVEL_VERBOSE,
2525 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2528 if( !NT_SUCCESS( ntStatus))
2531 if( pWorkItem != NULL)
2533 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2536 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2537 AFS_TRACE_LEVEL_ERROR,
2538 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2542 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2547 "EXCEPTION - AFSQueueInvalidateObject\n");
2549 AFSDumpTraceFilesFnc();