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 AFSShutdownWorkerThread()
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;
535 if( pWorker->WorkerThreadObject != NULL &&
536 BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED))
540 // Clear the 'keep processing' flag
543 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
545 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
551 ObDereferenceObject( pWorker->WorkerThreadObject);
553 pWorker->WorkerThreadObject = NULL;
560 // Function: AFSShutdownWorkerThread
564 // This function shutsdown a worker thread in the pool
568 // A status is returned for the function
572 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
575 NTSTATUS ntStatus = STATUS_SUCCESS;
576 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
578 if( PoolContext->WorkerThreadObject != NULL &&
579 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
583 // Wake up the thread if it is a sleep
586 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
590 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
596 ObDereferenceObject( PoolContext->WorkerThreadObject);
598 PoolContext->WorkerThreadObject = NULL;
605 // Function: AFSShutdownIOWorkerThread
609 // This function shutsdown an IO worker thread in the pool
613 // A status is returned for the function
617 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
620 NTSTATUS ntStatus = STATUS_SUCCESS;
621 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
623 if( PoolContext->WorkerThreadObject != NULL &&
624 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
628 // Wake up the thread if it is a sleep
631 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
635 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
641 ObDereferenceObject( PoolContext->WorkerThreadObject);
643 PoolContext->WorkerThreadObject = NULL;
650 // Function: AFSWorkerThread
654 // This is the worker thread entry point.
658 // A status is returned for the function
662 AFSWorkerThread( IN PVOID Context)
665 NTSTATUS ntStatus = STATUS_SUCCESS;
666 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
667 AFSWorkItem *pWorkItem;
668 BOOLEAN freeWorkItem = TRUE;
669 AFSDeviceExt *pLibraryDevExt = NULL;
672 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
675 // Indicate that we are initialized and ready
678 KeSetEvent( &pPoolContext->WorkerThreadReady,
683 // Indicate we are initialized
686 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
688 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
694 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
697 if( !NT_SUCCESS( ntStatus))
700 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
701 AFS_TRACE_LEVEL_ERROR,
702 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
704 ntStatus = STATUS_SUCCESS;
709 pWorkItem = AFSRemoveWorkItem();
711 if( pWorkItem == NULL)
714 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
726 // Switch on the type of work item to process
729 switch( pWorkItem->RequestType)
732 case AFS_WORK_FLUSH_FCB:
735 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
736 &pWorkItem->AuthGroup);
738 if( !NT_SUCCESS( ntStatus))
741 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
742 &pWorkItem->AuthGroup);
745 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
747 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
752 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
755 AFSEnumerateGlobalRoot( NULL);
760 case AFS_WORK_INVALIDATE_OBJECT:
763 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
764 pWorkItem->Specific.Invalidate.InvalidateReason);
771 case AFS_WORK_START_IOS:
781 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
782 AFS_TRACE_LEVEL_ERROR,
783 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
791 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
794 ntStatus = STATUS_SUCCESS;
797 } // worker thread loop
799 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
801 // Wake up another worker so they too can exit
803 KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
807 PsTerminateSystemThread( 0);
813 AFSIOWorkerThread( IN PVOID Context)
816 NTSTATUS ntStatus = STATUS_SUCCESS;
817 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
818 AFSWorkItem *pWorkItem;
819 BOOLEAN freeWorkItem = TRUE;
820 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
822 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
825 // Indicate that we are initialized and ready
828 KeSetEvent( &pPoolContext->WorkerThreadReady,
834 // Indicate we are initialized
837 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
839 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
845 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
848 if( !NT_SUCCESS( ntStatus))
851 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
852 AFS_TRACE_LEVEL_ERROR,
853 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
855 ntStatus = STATUS_SUCCESS;
860 pWorkItem = AFSRemoveIOWorkItem();
862 if( pWorkItem == NULL)
865 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
877 // Switch on the type of work item to process
880 switch( pWorkItem->RequestType)
883 case AFS_WORK_START_IOS:
886 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
889 // The final status is in the gather io
892 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
893 pWorkItem->Specific.CacheAccess.FunctionCode,
894 pWorkItem->Specific.CacheAccess.RequestFlags,
895 pWorkItem->Specific.CacheAccess.IoRuns,
896 pWorkItem->Specific.CacheAccess.RunCount,
897 pWorkItem->Specific.CacheAccess.GatherIo);
900 // Regardless of the status we we do the complete - there may
902 // Decrement the count - setting the event if we were told
903 // to. This may trigger completion.
906 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
915 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
916 AFS_TRACE_LEVEL_ERROR,
917 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
925 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
928 ntStatus = STATUS_SUCCESS;
931 } // worker thread loop
933 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
935 // Wake up another IOWorker so they too can exit
937 KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
941 PsTerminateSystemThread( 0);
947 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
950 NTSTATUS ntStatus = STATUS_SUCCESS;
951 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
952 AFSDeviceExt *pControlDeviceExt = NULL;
953 AFSDeviceExt *pRDRDeviceExt = NULL;
954 LARGE_INTEGER DueTime;
957 BOOLEAN bFoundOpenEntry = FALSE;
958 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
959 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
960 BOOLEAN bReleaseVolumeLock = FALSE;
961 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
964 LARGE_INTEGER liCurrentTime;
965 BOOLEAN bVolumeObject = FALSE;
968 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
970 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
972 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
973 AFS_TRACE_LEVEL_VERBOSE,
974 "AFSPrimaryVolumeWorkerThread Initialized\n");
977 // Initialize the timer for the worker thread
980 DueTime.QuadPart = -(5000);
984 KeInitializeTimerEx( &Timer,
985 SynchronizationTimer);
987 KeSetTimerEx( &Timer,
993 // Indicate that we are initialized and ready
996 KeSetEvent( &pPoolContext->WorkerThreadReady,
1001 // Indicate we are initialized
1004 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1006 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1009 KeWaitForSingleObject( &Timer,
1016 // This is the primary volume worker so it will traverse the volume list
1017 // looking for cleanup or volumes requiring private workers
1020 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1023 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1025 while( pVolumeCB != NULL)
1028 if( pVolumeCB == AFSGlobalRoot ||
1029 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1033 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1038 if( pVolumeCB->ObjectInfoListHead == NULL)
1041 AFSReleaseResource( pVolumeCB->VolumeLock);
1043 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1045 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1048 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1051 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1055 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1057 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1059 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1064 KeQueryTickCount( &liCurrentTime);
1066 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1068 if( pVolumeCB->ObjectInfoListHead == NULL &&
1069 pVolumeCB->DirectoryCB->OpenReferenceCount == 0 &&
1070 pVolumeCB->VolumeReferenceCount == 1 &&
1071 ( pVolumeCB->RootFcb == NULL ||
1072 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1073 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1076 if( pVolumeCB->RootFcb != NULL)
1079 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1082 AFSRemoveVolume( pVolumeCB);
1087 AFSReleaseResource( pVolumeCB->VolumeLock);
1090 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1092 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1094 pVolumeCB = pNextVolume;
1100 // Don't need this lock anymore now that we have a volume cb to work with
1103 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1106 // For now we only need the volume lock shared
1109 AFSConvertToShared( pVolumeCB->VolumeLock);
1111 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1115 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1119 bReleaseVolumeLock = TRUE;
1121 while( pCurrentObject != NULL)
1124 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1127 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1129 if( pNextObject == NULL &&
1130 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1133 pNextObject = &pVolumeCB->ObjectInformation;
1136 bVolumeObject = FALSE;
1143 bVolumeObject = TRUE;
1146 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1147 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1151 // If this object is deleted then remove it from the parent, if we can
1154 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1155 pCurrentObject->ObjectReferenceCount <= 0 &&
1156 ( pCurrentObject->Fcb == NULL ||
1157 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1158 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1159 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1162 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1165 // Dropping the TreeLock permits the
1166 // pCurrentObject->ObjectReferenceCount to change
1169 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1173 if ( pCurrentObject->ObjectReferenceCount <= 0)
1176 if( pCurrentObject->Fcb != NULL)
1179 AFSRemoveFcb( &pCurrentObject->Fcb);
1182 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1185 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1188 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1191 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1193 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1195 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1197 AFSExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1200 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1201 AFS_TRACE_LEVEL_VERBOSE,
1202 "AFSPrimaryVolumeWorkerThread Deleting deleted object %08lX\n",
1205 AFSDeleteObjectInfo( pCurrentObject);
1208 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1210 pCurrentObject = pNextObject;
1217 bReleaseVolumeLock = FALSE;
1223 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1224 ( pCurrentObject->Fcb != NULL &&
1225 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1226 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1229 pCurrentObject = pNextObject;
1234 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1238 pCurrentObject = pNextObject;
1243 KeQueryTickCount( &liCurrentTime);
1245 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1247 while( pCurrentDirEntry != NULL)
1250 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1251 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1252 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1253 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1254 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1255 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1256 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1257 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1258 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1259 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1260 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1261 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1267 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1270 if( pCurrentDirEntry != NULL)
1273 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1275 pCurrentObject = pNextObject;
1280 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1282 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1285 // Now acquire the locks excl
1288 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1292 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1296 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1299 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1301 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1303 pCurrentObject = pNextObject;
1308 KeQueryTickCount( &liCurrentTime);
1310 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1312 while( pCurrentDirEntry != NULL)
1315 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1316 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1317 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1318 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1319 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1320 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1321 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1322 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1323 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1324 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1325 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1326 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1332 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1335 if( pCurrentDirEntry != NULL)
1338 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1340 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1342 pCurrentObject = pNextObject;
1347 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1349 while( pCurrentDirEntry != NULL)
1352 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1354 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1358 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1359 AFS_TRACE_LEVEL_VERBOSE,
1360 "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %08lX\n",
1361 &pCurrentDirEntry->NameInformation.FileName,
1362 pCurrentChildObject);
1364 AFSDeleteDirEntry( pCurrentObject,
1367 if( pCurrentChildObject->ObjectReferenceCount <= 0 &&
1368 pCurrentChildObject->Fcb != NULL &&
1369 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1373 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
1374 // across an AFSCleanupFcb call since it can deadlock with an
1375 // invalidation call from the service.
1378 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1381 // Dropping the TreeLock permits the
1382 // pCurrentObject->ObjectReferenceCount to change
1385 AFSCleanupFcb( pCurrentChildObject->Fcb,
1388 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1392 if( pCurrentChildObject->ObjectReferenceCount <= 0 &&
1393 ( pCurrentChildObject->Fcb == NULL ||
1394 pCurrentChildObject->Fcb->OpenReferenceCount == 0 &&
1395 pCurrentChildObject->Fcb->Specific.File.ExtentCount == 0))
1398 if( pCurrentChildObject->Fcb != NULL)
1401 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1404 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1405 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1408 if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1411 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1414 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1416 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1418 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1420 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1423 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1424 AFS_TRACE_LEVEL_VERBOSE,
1425 "AFSPrimaryVolumeWorkerThread Deleting object %08lX\n",
1426 pCurrentChildObject);
1428 AFSDeleteObjectInfo( pCurrentChildObject);
1431 pCurrentDirEntry = pNextDirEntry;
1435 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1437 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1439 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1441 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1443 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1445 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1447 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1448 AFS_TRACE_LEVEL_VERBOSE,
1449 "AFSPrimaryVolumeWorkerThread Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1450 pCurrentObject->FileId.Cell,
1451 pCurrentObject->FileId.Volume,
1452 pCurrentObject->FileId.Vnode,
1453 pCurrentObject->FileId.Unique);
1456 // Clear our enumerated flag on this object so we retrieve info again on next access
1459 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1461 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1463 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1468 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1470 bReleaseVolumeLock = FALSE;
1479 // Try to grab the volume lock again ... no problem if we don't
1482 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1486 bReleaseVolumeLock = FALSE;
1492 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1495 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1497 if( pCurrentObject == NULL &&
1498 pVolumeCB != AFSGlobalRoot)
1501 pCurrentObject = &pVolumeCB->ObjectInformation;
1507 pCurrentObject = NULL;
1512 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1515 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1517 if( pCurrentObject->Fcb != NULL)
1521 // Dropping the TreeLock permits the
1522 // pCurrentObject->ObjectReferenceCount to change
1525 AFSCleanupFcb( pCurrentObject->Fcb,
1529 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1533 bReleaseVolumeLock = FALSE;
1538 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1539 pCurrentObject->ObjectReferenceCount <= 0 &&
1540 ( pCurrentObject->Fcb == NULL ||
1541 pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1542 pCurrentObject->Fcb->Specific.File.ExtentCount == 0))
1545 if( pCurrentObject->Fcb != NULL)
1548 AFSRemoveFcb( &pCurrentObject->Fcb);
1551 AFSDeleteObjectInfo( pCurrentObject);
1554 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1556 pCurrentObject = pNextObject;
1561 pCurrentObject = pNextObject;
1564 if( bReleaseVolumeLock)
1567 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1575 AFSReleaseResource( pVolumeCB->VolumeLock);
1577 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1580 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1583 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1585 } // worker thread loop
1587 KeCancelTimer( &Timer);
1589 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1590 AFS_TRACE_LEVEL_VERBOSE,
1591 "AFSPrimaryVolumeWorkerThread Exiting\n");
1593 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1598 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1603 PsTerminateSystemThread( 0);
1609 AFSVolumeWorkerThread( IN PVOID Context)
1612 NTSTATUS ntStatus = STATUS_SUCCESS;
1613 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1614 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1615 AFSDeviceExt *pControlDeviceExt = NULL;
1616 AFSDeviceExt *pRDRDeviceExt = NULL;
1617 BOOLEAN exitThread = FALSE;
1618 LARGE_INTEGER DueTime;
1623 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1625 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1628 // Initialize the timer for the worker thread
1631 DueTime.QuadPart = -(5000);
1635 KeInitializeTimerEx( &Timer,
1636 SynchronizationTimer);
1638 KeSetTimerEx( &Timer,
1644 // Indicate that we are initialized and ready
1647 KeSetEvent( &pPoolContext->WorkerThreadReady,
1652 // Indicate we are initialized
1655 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1657 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1660 ntStatus = KeWaitForSingleObject( &Timer,
1666 if( !NT_SUCCESS( ntStatus))
1669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1670 AFS_TRACE_LEVEL_ERROR,
1671 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1677 // If we are in shutdown mode and the dirty flag is clear then get out now
1680 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1686 } // worker thread loop
1688 KeCancelTimer( &Timer);
1690 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1695 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1700 PsTerminateSystemThread( 0);
1706 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1709 NTSTATUS ntStatus = STATUS_SUCCESS;
1710 AFSDeviceExt *pDevExt = NULL;
1713 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1715 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1716 AFS_TRACE_LEVEL_VERBOSE,
1717 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1718 &pDevExt->Specific.Library.QueueLock,
1719 PsGetCurrentThread());
1721 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1724 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1726 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1727 AFS_TRACE_LEVEL_VERBOSE,
1728 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1732 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1735 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1740 pDevExt->Specific.Library.QueueHead = WorkItem;
1743 WorkItem->next = NULL;
1744 pDevExt->Specific.Library.QueueTail = WorkItem;
1746 // indicate that the queue has nodes
1747 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1751 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1757 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1760 NTSTATUS ntStatus = STATUS_SUCCESS;
1761 AFSDeviceExt *pDevExt = NULL;
1764 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1766 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1767 AFS_TRACE_LEVEL_VERBOSE,
1768 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1769 &pDevExt->Specific.Library.IOQueueLock,
1770 PsGetCurrentThread());
1772 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1775 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
1777 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1778 AFS_TRACE_LEVEL_VERBOSE,
1779 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1783 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1786 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1791 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1794 WorkItem->next = NULL;
1795 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1797 // indicate that the queue has nodes
1798 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1802 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1808 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1811 NTSTATUS ntStatus = STATUS_SUCCESS;
1812 AFSDeviceExt *pDevExt = NULL;
1815 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1817 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1818 AFS_TRACE_LEVEL_VERBOSE,
1819 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1820 &pDevExt->Specific.Library.QueueLock,
1821 PsGetCurrentThread());
1823 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1826 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1828 pDevExt->Specific.Library.QueueHead = WorkItem;
1830 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1832 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1833 AFS_TRACE_LEVEL_VERBOSE,
1834 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1839 // indicate that the queue has nodes
1842 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1846 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1855 NTSTATUS ntStatus = STATUS_SUCCESS;
1856 AFSWorkItem *pWorkItem = NULL;
1857 AFSDeviceExt *pDevExt = NULL;
1860 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1862 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1863 AFS_TRACE_LEVEL_VERBOSE,
1864 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1865 &pDevExt->Specific.Library.QueueLock,
1866 PsGetCurrentThread());
1868 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1871 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1874 pWorkItem = pDevExt->Specific.Library.QueueHead;
1876 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
1878 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1879 AFS_TRACE_LEVEL_VERBOSE,
1880 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1883 PsGetCurrentThreadId());
1885 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1887 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1890 pDevExt->Specific.Library.QueueTail = NULL;
1896 // Wake up another worker
1899 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1905 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1911 AFSRemoveIOWorkItem()
1914 NTSTATUS ntStatus = STATUS_SUCCESS;
1915 AFSWorkItem *pWorkItem = NULL;
1916 AFSDeviceExt *pDevExt = NULL;
1919 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1922 AFS_TRACE_LEVEL_VERBOSE,
1923 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1924 &pDevExt->Specific.Library.IOQueueLock,
1925 PsGetCurrentThread());
1927 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1930 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
1933 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
1935 lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
1937 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1938 AFS_TRACE_LEVEL_VERBOSE,
1939 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1942 PsGetCurrentThreadId());
1944 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
1946 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
1949 pDevExt->Specific.Library.IOQueueTail = NULL;
1955 // Wake up another worker
1958 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1964 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1970 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
1973 NTSTATUS ntStatus = STATUS_SUCCESS;
1974 AFSDeviceExt *pDevExt = NULL;
1975 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1978 // Submit the work item to the worker
1981 ntStatus = AFSInsertWorkitem( WorkItem);
1987 // Sync request so block on the work item event
1990 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2001 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2004 NTSTATUS ntStatus = STATUS_SUCCESS;
2005 AFSDeviceExt *pDevExt = NULL;
2006 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2009 // Submit the work item to the worker
2012 ntStatus = AFSInsertIOWorkitem( WorkItem);
2018 // Sync request so block on the work item event
2021 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2032 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2035 NTSTATUS ntStatus = STATUS_SUCCESS;
2036 AFSDeviceExt *pDevExt = NULL;
2037 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2040 // Submit the work item to the worker
2043 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2049 // Sync request so block on the work item event
2052 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2063 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2067 NTSTATUS ntStatus = STATUS_SUCCESS;
2068 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2069 AFSWorkItem *pWorkItem = NULL;
2075 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2076 AFS_TRACE_LEVEL_VERBOSE,
2077 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2078 Fcb->ObjectInformation->FileId.Cell,
2079 Fcb->ObjectInformation->FileId.Volume,
2080 Fcb->ObjectInformation->FileId.Vnode,
2081 Fcb->ObjectInformation->FileId.Unique);
2084 // Increment our flush count here just to keep the number of items in the
2085 // queue down. We'll decrement it just below.
2088 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2093 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2094 AFS_TRACE_LEVEL_VERBOSE,
2095 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2096 Fcb->ObjectInformation->FileId.Cell,
2097 Fcb->ObjectInformation->FileId.Volume,
2098 Fcb->ObjectInformation->FileId.Vnode,
2099 Fcb->ObjectInformation->FileId.Unique);
2101 try_return( ntStatus);
2104 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2107 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2108 AFS_TRACE_LEVEL_ERROR,
2109 "AFSQueueFlushExtents Failing request, in shutdown\n");
2111 try_return( ntStatus = STATUS_TOO_LATE);
2115 // Allocate our request structure and send it to the worker
2118 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2119 sizeof( AFSWorkItem),
2122 if( pWorkItem == NULL)
2125 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2126 AFS_TRACE_LEVEL_ERROR,
2127 "AFSQueueFlushExtents Failed to allocate work item\n");
2129 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2132 RtlZeroMemory( pWorkItem,
2133 sizeof( AFSWorkItem));
2135 pWorkItem->Size = sizeof( AFSWorkItem);
2137 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2139 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2141 if ( AuthGroup == NULL)
2144 RtlZeroMemory( &pWorkItem->AuthGroup,
2147 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2150 &pWorkItem->AuthGroup);
2154 RtlCopyMemory( &pWorkItem->AuthGroup,
2159 pWorkItem->Specific.Fcb.Fcb = Fcb;
2161 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2163 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2164 AFS_TRACE_LEVEL_VERBOSE,
2165 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2169 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2170 AFS_TRACE_LEVEL_VERBOSE,
2171 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2173 Fcb->ObjectInformation->FileId.Cell,
2174 Fcb->ObjectInformation->FileId.Volume,
2175 Fcb->ObjectInformation->FileId.Vnode,
2176 Fcb->ObjectInformation->FileId.Unique);
2178 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2182 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2183 AFS_TRACE_LEVEL_VERBOSE,
2184 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2185 Fcb->ObjectInformation->FileId.Cell,
2186 Fcb->ObjectInformation->FileId.Volume,
2187 Fcb->ObjectInformation->FileId.Vnode,
2188 Fcb->ObjectInformation->FileId.Unique,
2192 // Remove the count we added above
2195 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2200 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2205 if( !NT_SUCCESS( ntStatus))
2208 if( pWorkItem != NULL)
2211 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2213 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2216 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2217 AFS_TRACE_LEVEL_ERROR,
2218 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2221 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2226 "EXCEPTION - AFSQueueFlushExtents\n");
2228 AFSDumpTraceFilesFnc();
2235 AFSQueueGlobalRootEnumeration()
2238 NTSTATUS ntStatus = STATUS_SUCCESS;
2239 AFSWorkItem *pWorkItem = NULL;
2244 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2245 sizeof(AFSWorkItem),
2247 if (NULL == pWorkItem)
2250 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2251 AFS_TRACE_LEVEL_ERROR,
2252 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2254 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2257 RtlZeroMemory( pWorkItem,
2258 sizeof(AFSWorkItem));
2260 pWorkItem->Size = sizeof( AFSWorkItem);
2262 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2264 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2265 AFS_TRACE_LEVEL_VERBOSE,
2266 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2269 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2273 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2274 AFS_TRACE_LEVEL_VERBOSE,
2275 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2278 if( !NT_SUCCESS( ntStatus))
2281 if( pWorkItem != NULL)
2284 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2287 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2288 AFS_TRACE_LEVEL_ERROR,
2289 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2293 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2298 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2300 AFSDumpTraceFilesFnc();
2307 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2308 IN UCHAR FunctionCode,
2309 IN ULONG RequestFlags,
2310 IN AFSIoRun *IoRuns,
2312 IN AFSGatherIo *GatherIo)
2315 NTSTATUS ntStatus = STATUS_SUCCESS;
2316 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2317 AFSWorkItem *pWorkItem = NULL;
2322 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2325 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2326 AFS_TRACE_LEVEL_ERROR,
2327 "AFSQueueStartIos Failing request, in shutdown\n");
2329 try_return( ntStatus = STATUS_TOO_LATE);
2333 // Allocate our request structure and send it to the worker
2336 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2337 sizeof( AFSWorkItem),
2340 if( pWorkItem == NULL)
2343 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2344 AFS_TRACE_LEVEL_ERROR,
2345 "AFSQueueStartIos Failed to allocate work item\n");
2347 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2350 RtlZeroMemory( pWorkItem,
2351 sizeof( AFSWorkItem));
2353 KeInitializeEvent( &pWorkItem->Event,
2357 pWorkItem->Size = sizeof( AFSWorkItem);
2359 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2361 pWorkItem->RequestType = AFS_WORK_START_IOS;
2363 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2365 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2367 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2369 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2371 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2373 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2375 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2376 AFS_TRACE_LEVEL_VERBOSE,
2377 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2380 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2384 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2385 AFS_TRACE_LEVEL_VERBOSE,
2386 "AFSQueueStartIos Request complete Status %08lX\n",
2389 if( !NT_SUCCESS( ntStatus))
2392 if( pWorkItem != NULL)
2395 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2399 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2404 "EXCEPTION - AFSQueueStartIos\n");
2406 AFSDumpTraceFilesFnc();
2413 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2414 IN ULONG InvalidateReason)
2417 NTSTATUS ntStatus = STATUS_SUCCESS;
2418 AFSWorkItem *pWorkItem = NULL;
2423 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2424 sizeof(AFSWorkItem),
2426 if (NULL == pWorkItem)
2429 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2430 AFS_TRACE_LEVEL_ERROR,
2431 "AFSQueueInvalidateObject Failed to allocate work item\n");
2433 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2436 RtlZeroMemory( pWorkItem,
2437 sizeof(AFSWorkItem));
2439 pWorkItem->Size = sizeof( AFSWorkItem);
2441 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2443 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2445 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2447 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2448 AFS_TRACE_LEVEL_VERBOSE,
2449 "AFSQueueInvalidateObject Workitem %08lX\n",
2452 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2456 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2457 AFS_TRACE_LEVEL_VERBOSE,
2458 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2461 if( !NT_SUCCESS( ntStatus))
2464 if( pWorkItem != NULL)
2466 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2469 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2470 AFS_TRACE_LEVEL_ERROR,
2471 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2475 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2480 "EXCEPTION - AFSQueueInvalidateObject\n");
2482 AFSDumpTraceFilesFnc();