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,
746 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
748 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
753 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
756 AFSEnumerateGlobalRoot( NULL);
761 case AFS_WORK_INVALIDATE_OBJECT:
764 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
765 pWorkItem->Specific.Invalidate.InvalidateReason);
772 case AFS_WORK_START_IOS:
782 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
783 AFS_TRACE_LEVEL_ERROR,
784 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
792 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
795 ntStatus = STATUS_SUCCESS;
798 } // worker thread loop
800 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
802 // Wake up another worker so they too can exit
804 KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
808 PsTerminateSystemThread( 0);
814 AFSIOWorkerThread( IN PVOID Context)
817 NTSTATUS ntStatus = STATUS_SUCCESS;
818 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
819 AFSWorkItem *pWorkItem;
820 BOOLEAN freeWorkItem = TRUE;
821 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
823 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
826 // Indicate that we are initialized and ready
829 KeSetEvent( &pPoolContext->WorkerThreadReady,
835 // Indicate we are initialized
838 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
840 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
846 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
849 if( !NT_SUCCESS( ntStatus))
852 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
853 AFS_TRACE_LEVEL_ERROR,
854 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
856 ntStatus = STATUS_SUCCESS;
861 pWorkItem = AFSRemoveIOWorkItem();
863 if( pWorkItem == NULL)
866 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
878 // Switch on the type of work item to process
881 switch( pWorkItem->RequestType)
884 case AFS_WORK_START_IOS:
887 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
890 // The final status is in the gather io
893 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
894 pWorkItem->Specific.CacheAccess.FunctionCode,
895 pWorkItem->Specific.CacheAccess.RequestFlags,
896 pWorkItem->Specific.CacheAccess.IoRuns,
897 pWorkItem->Specific.CacheAccess.RunCount,
898 pWorkItem->Specific.CacheAccess.GatherIo);
901 // Regardless of the status we we do the complete - there may
903 // Decrement the count - setting the event if we were told
904 // to. This may trigger completion.
907 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
916 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
917 AFS_TRACE_LEVEL_ERROR,
918 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
926 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
929 ntStatus = STATUS_SUCCESS;
932 } // worker thread loop
934 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
936 // Wake up another IOWorker so they too can exit
938 KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
942 PsTerminateSystemThread( 0);
948 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
951 NTSTATUS ntStatus = STATUS_SUCCESS;
952 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
953 AFSDeviceExt *pControlDeviceExt = NULL;
954 AFSDeviceExt *pRDRDeviceExt = NULL;
955 LARGE_INTEGER DueTime;
958 BOOLEAN bFoundOpenEntry = FALSE;
959 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
960 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
961 BOOLEAN bReleaseVolumeLock = FALSE;
962 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
965 LARGE_INTEGER liCurrentTime;
966 BOOLEAN bVolumeObject = FALSE;
967 BOOLEAN bFcbBusy = FALSE;
970 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
972 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
974 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
975 AFS_TRACE_LEVEL_VERBOSE,
976 "AFSPrimaryVolumeWorkerThread Initialized\n");
979 // Initialize the timer for the worker thread
982 DueTime.QuadPart = -(5000);
986 KeInitializeTimerEx( &Timer,
987 SynchronizationTimer);
989 KeSetTimerEx( &Timer,
995 // Indicate that we are initialized and ready
998 KeSetEvent( &pPoolContext->WorkerThreadReady,
1003 // Indicate we are initialized
1006 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1008 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1011 if ( bFcbBusy == FALSE)
1014 KeWaitForSingleObject( &Timer,
1027 // This is the primary volume worker so it will traverse the volume list
1028 // looking for cleanup or volumes requiring private workers
1031 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1034 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1036 while( pVolumeCB != NULL)
1039 if( pVolumeCB == AFSGlobalRoot ||
1040 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1044 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1049 if( pVolumeCB->ObjectInfoListHead == NULL)
1052 AFSReleaseResource( pVolumeCB->VolumeLock);
1054 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1056 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1059 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1062 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1066 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1068 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1070 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1075 KeQueryTickCount( &liCurrentTime);
1077 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1079 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1082 if( pVolumeCB->ObjectInfoListHead == NULL &&
1083 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1084 pVolumeCB->VolumeReferenceCount == 1 &&
1085 ( pVolumeCB->RootFcb == NULL ||
1086 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1087 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1090 if( pVolumeCB->RootFcb != NULL)
1093 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1096 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1098 AFSRemoveVolume( pVolumeCB);
1103 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1105 AFSReleaseResource( pVolumeCB->VolumeLock);
1108 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1110 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1112 pVolumeCB = pNextVolume;
1118 // Don't need this lock anymore now that we have a volume cb to work with
1121 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1124 // For now we only need the volume lock shared
1127 AFSConvertToShared( pVolumeCB->VolumeLock);
1129 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1133 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1137 bReleaseVolumeLock = TRUE;
1139 while( pCurrentObject != NULL)
1142 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1145 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1147 if( pNextObject == NULL &&
1148 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1151 pNextObject = &pVolumeCB->ObjectInformation;
1154 bVolumeObject = FALSE;
1161 bVolumeObject = TRUE;
1164 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1165 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1169 // If this object is deleted then remove it from the parent, if we can
1172 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1173 pCurrentObject->ObjectReferenceCount <= 0 &&
1174 ( pCurrentObject->Fcb == NULL ||
1175 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1176 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1177 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1180 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1183 // Dropping the TreeLock permits the
1184 // pCurrentObject->ObjectReferenceCount to change
1187 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1191 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1194 if ( pCurrentObject->ObjectReferenceCount <= 0 &&
1195 ( pCurrentObject->Fcb == NULL ||
1196 pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1197 pCurrentObject->Fcb->Specific.File.ExtentCount == 0))
1200 AFSRemoveFcb( &pCurrentObject->Fcb);
1202 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1205 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1208 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1210 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1212 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1214 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1216 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1218 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1221 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1223 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1224 AFS_TRACE_LEVEL_VERBOSE,
1225 "AFSPrimaryVolumeWorkerThread Deleting deleted object %08lX\n",
1228 AFSDeleteObjectInfo( pCurrentObject);
1233 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1236 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1238 pCurrentObject = pNextObject;
1245 bReleaseVolumeLock = FALSE;
1251 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1252 ( pCurrentObject->Fcb != NULL &&
1253 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1254 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1257 pCurrentObject = pNextObject;
1262 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1266 pCurrentObject = pNextObject;
1271 KeQueryTickCount( &liCurrentTime);
1273 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1275 while( pCurrentDirEntry != NULL)
1278 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1279 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1280 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1281 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1282 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1283 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1284 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1285 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1286 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1287 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1288 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1289 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1295 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1298 if( pCurrentDirEntry != NULL)
1301 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1303 pCurrentObject = pNextObject;
1308 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1310 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1313 // Now acquire the locks excl
1316 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1320 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1324 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1327 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1329 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1331 pCurrentObject = pNextObject;
1336 KeQueryTickCount( &liCurrentTime);
1338 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1340 while( pCurrentDirEntry != NULL)
1343 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1344 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1345 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1346 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1347 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1348 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1349 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1350 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1351 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1352 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1353 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1354 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1360 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1363 if( pCurrentDirEntry != NULL)
1366 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1368 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1370 pCurrentObject = pNextObject;
1375 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1377 while( pCurrentDirEntry != NULL)
1380 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1382 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1386 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1387 AFS_TRACE_LEVEL_VERBOSE,
1388 "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %08lX\n",
1389 &pCurrentDirEntry->NameInformation.FileName,
1390 pCurrentChildObject);
1392 AFSDeleteDirEntry( pCurrentObject,
1397 // Acquire ObjectInfoLock shared here so as not to deadlock
1398 // with an invalidation call from the service during AFSCleanupFcb
1401 lCount = AFSObjectInfoIncrement( pCurrentChildObject);
1404 pCurrentChildObject->Fcb != NULL &&
1405 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1409 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
1410 // across an AFSCleanupFcb call since it can deadlock with an
1411 // invalidation call from the service.
1414 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1417 // Cannot hold a TreeLock across an AFSCleanupFcb call
1418 // as it can deadlock with an invalidation ioctl initiated
1419 // from the service.
1421 // Dropping the TreeLock permits the
1422 // pCurrentObject->ObjectReferenceCount to change
1425 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1428 if ( ntStatus == STATUS_RETRY)
1434 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1438 lCount = AFSObjectInfoDecrement( pCurrentChildObject);
1440 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1443 if( pCurrentChildObject->ObjectReferenceCount <= 0 &&
1444 ( pCurrentChildObject->Fcb == NULL ||
1445 pCurrentChildObject->Fcb->OpenReferenceCount == 0 &&
1446 pCurrentChildObject->Fcb->Specific.File.ExtentCount == 0))
1449 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1451 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1452 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1455 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1458 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1460 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1462 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1464 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1466 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1468 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1471 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1473 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1474 AFS_TRACE_LEVEL_VERBOSE,
1475 "AFSPrimaryVolumeWorkerThread Deleting object %08lX\n",
1476 pCurrentChildObject);
1478 AFSDeleteObjectInfo( pCurrentChildObject);
1483 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1486 pCurrentDirEntry = pNextDirEntry;
1490 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1492 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1494 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1496 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1498 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1500 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1502 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1503 AFS_TRACE_LEVEL_VERBOSE,
1504 "AFSPrimaryVolumeWorkerThread Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1505 pCurrentObject->FileId.Cell,
1506 pCurrentObject->FileId.Volume,
1507 pCurrentObject->FileId.Vnode,
1508 pCurrentObject->FileId.Unique);
1511 // Clear our enumerated flag on this object so we retrieve info again on next access
1514 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1516 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1518 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1523 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1525 bReleaseVolumeLock = FALSE;
1534 // Try to grab the volume lock again ... no problem if we don't
1537 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1541 bReleaseVolumeLock = FALSE;
1547 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1550 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1552 if( pCurrentObject == NULL &&
1553 pVolumeCB != AFSGlobalRoot)
1556 pCurrentObject = &pVolumeCB->ObjectInformation;
1562 pCurrentObject = NULL;
1567 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1570 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1572 lCount = AFSObjectInfoIncrement( pCurrentObject);
1575 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 &&
1609 ( pCurrentObject->Fcb == NULL ||
1610 pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1611 pCurrentObject->Fcb->Specific.File.ExtentCount == 0))
1614 AFSRemoveFcb( &pCurrentObject->Fcb);
1616 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1618 AFSDeleteObjectInfo( pCurrentObject);
1623 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1626 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1628 pCurrentObject = pNextObject;
1633 pCurrentObject = pNextObject;
1636 if( bReleaseVolumeLock)
1639 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1647 AFSReleaseResource( pVolumeCB->VolumeLock);
1649 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1652 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1655 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1657 } // worker thread loop
1659 KeCancelTimer( &Timer);
1661 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1662 AFS_TRACE_LEVEL_VERBOSE,
1663 "AFSPrimaryVolumeWorkerThread Exiting\n");
1665 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1670 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1675 PsTerminateSystemThread( 0);
1681 AFSVolumeWorkerThread( IN PVOID Context)
1684 NTSTATUS ntStatus = STATUS_SUCCESS;
1685 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1686 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1687 AFSDeviceExt *pControlDeviceExt = NULL;
1688 AFSDeviceExt *pRDRDeviceExt = NULL;
1689 BOOLEAN exitThread = FALSE;
1690 LARGE_INTEGER DueTime;
1695 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1697 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1700 // Initialize the timer for the worker thread
1703 DueTime.QuadPart = -(5000);
1707 KeInitializeTimerEx( &Timer,
1708 SynchronizationTimer);
1710 KeSetTimerEx( &Timer,
1716 // Indicate that we are initialized and ready
1719 KeSetEvent( &pPoolContext->WorkerThreadReady,
1724 // Indicate we are initialized
1727 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1729 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1732 ntStatus = KeWaitForSingleObject( &Timer,
1738 if( !NT_SUCCESS( ntStatus))
1741 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1742 AFS_TRACE_LEVEL_ERROR,
1743 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1749 // If we are in shutdown mode and the dirty flag is clear then get out now
1752 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1758 } // worker thread loop
1760 KeCancelTimer( &Timer);
1762 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1767 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1772 PsTerminateSystemThread( 0);
1778 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1781 NTSTATUS ntStatus = STATUS_SUCCESS;
1782 AFSDeviceExt *pDevExt = NULL;
1785 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1787 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1788 AFS_TRACE_LEVEL_VERBOSE,
1789 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1790 &pDevExt->Specific.Library.QueueLock,
1791 PsGetCurrentThread());
1793 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1796 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1798 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1799 AFS_TRACE_LEVEL_VERBOSE,
1800 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1804 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1807 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1812 pDevExt->Specific.Library.QueueHead = WorkItem;
1815 WorkItem->next = NULL;
1816 pDevExt->Specific.Library.QueueTail = WorkItem;
1818 // indicate that the queue has nodes
1819 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1823 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1829 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1832 NTSTATUS ntStatus = STATUS_SUCCESS;
1833 AFSDeviceExt *pDevExt = NULL;
1836 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1838 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1839 AFS_TRACE_LEVEL_VERBOSE,
1840 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1841 &pDevExt->Specific.Library.IOQueueLock,
1842 PsGetCurrentThread());
1844 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1847 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
1849 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1850 AFS_TRACE_LEVEL_VERBOSE,
1851 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1855 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1858 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1863 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1866 WorkItem->next = NULL;
1867 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1869 // indicate that the queue has nodes
1870 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1874 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1880 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1883 NTSTATUS ntStatus = STATUS_SUCCESS;
1884 AFSDeviceExt *pDevExt = NULL;
1887 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1889 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1890 AFS_TRACE_LEVEL_VERBOSE,
1891 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1892 &pDevExt->Specific.Library.QueueLock,
1893 PsGetCurrentThread());
1895 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1898 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1900 pDevExt->Specific.Library.QueueHead = WorkItem;
1902 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1904 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1905 AFS_TRACE_LEVEL_VERBOSE,
1906 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1911 // indicate that the queue has nodes
1914 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1918 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1927 NTSTATUS ntStatus = STATUS_SUCCESS;
1928 AFSWorkItem *pWorkItem = NULL;
1929 AFSDeviceExt *pDevExt = NULL;
1932 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1934 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1935 AFS_TRACE_LEVEL_VERBOSE,
1936 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1937 &pDevExt->Specific.Library.QueueLock,
1938 PsGetCurrentThread());
1940 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1943 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1946 pWorkItem = pDevExt->Specific.Library.QueueHead;
1948 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
1950 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1951 AFS_TRACE_LEVEL_VERBOSE,
1952 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1955 PsGetCurrentThreadId());
1957 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1959 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1962 pDevExt->Specific.Library.QueueTail = NULL;
1968 // Wake up another worker
1971 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1977 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1983 AFSRemoveIOWorkItem()
1986 NTSTATUS ntStatus = STATUS_SUCCESS;
1987 AFSWorkItem *pWorkItem = NULL;
1988 AFSDeviceExt *pDevExt = NULL;
1991 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1993 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1994 AFS_TRACE_LEVEL_VERBOSE,
1995 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1996 &pDevExt->Specific.Library.IOQueueLock,
1997 PsGetCurrentThread());
1999 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
2002 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
2005 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
2007 lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
2009 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2010 AFS_TRACE_LEVEL_VERBOSE,
2011 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
2014 PsGetCurrentThreadId());
2016 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
2018 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
2021 pDevExt->Specific.Library.IOQueueTail = NULL;
2027 // Wake up another worker
2030 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
2036 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
2042 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2045 NTSTATUS ntStatus = STATUS_SUCCESS;
2046 AFSDeviceExt *pDevExt = NULL;
2047 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2050 // Submit the work item to the worker
2053 ntStatus = AFSInsertWorkitem( WorkItem);
2059 // Sync request so block on the work item event
2062 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2073 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2076 NTSTATUS ntStatus = STATUS_SUCCESS;
2077 AFSDeviceExt *pDevExt = NULL;
2078 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2081 // Submit the work item to the worker
2084 ntStatus = AFSInsertIOWorkitem( WorkItem);
2090 // Sync request so block on the work item event
2093 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2104 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2107 NTSTATUS ntStatus = STATUS_SUCCESS;
2108 AFSDeviceExt *pDevExt = NULL;
2109 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2112 // Submit the work item to the worker
2115 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2121 // Sync request so block on the work item event
2124 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2135 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2139 NTSTATUS ntStatus = STATUS_SUCCESS;
2140 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2141 AFSWorkItem *pWorkItem = NULL;
2147 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2148 AFS_TRACE_LEVEL_VERBOSE,
2149 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2150 Fcb->ObjectInformation->FileId.Cell,
2151 Fcb->ObjectInformation->FileId.Volume,
2152 Fcb->ObjectInformation->FileId.Vnode,
2153 Fcb->ObjectInformation->FileId.Unique);
2156 // Increment our flush count here just to keep the number of items in the
2157 // queue down. We'll decrement it just below.
2160 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2165 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2166 AFS_TRACE_LEVEL_VERBOSE,
2167 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2168 Fcb->ObjectInformation->FileId.Cell,
2169 Fcb->ObjectInformation->FileId.Volume,
2170 Fcb->ObjectInformation->FileId.Vnode,
2171 Fcb->ObjectInformation->FileId.Unique);
2173 try_return( ntStatus);
2176 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2179 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2180 AFS_TRACE_LEVEL_ERROR,
2181 "AFSQueueFlushExtents Failing request, in shutdown\n");
2183 try_return( ntStatus = STATUS_TOO_LATE);
2187 // Allocate our request structure and send it to the worker
2190 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2191 sizeof( AFSWorkItem),
2194 if( pWorkItem == NULL)
2197 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2198 AFS_TRACE_LEVEL_ERROR,
2199 "AFSQueueFlushExtents Failed to allocate work item\n");
2201 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2204 RtlZeroMemory( pWorkItem,
2205 sizeof( AFSWorkItem));
2207 pWorkItem->Size = sizeof( AFSWorkItem);
2209 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2211 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2213 if ( AuthGroup == NULL)
2216 RtlZeroMemory( &pWorkItem->AuthGroup,
2219 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2222 &pWorkItem->AuthGroup);
2226 RtlCopyMemory( &pWorkItem->AuthGroup,
2231 pWorkItem->Specific.Fcb.Fcb = Fcb;
2233 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2235 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2236 AFS_TRACE_LEVEL_VERBOSE,
2237 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2241 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2242 AFS_TRACE_LEVEL_VERBOSE,
2243 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2245 Fcb->ObjectInformation->FileId.Cell,
2246 Fcb->ObjectInformation->FileId.Volume,
2247 Fcb->ObjectInformation->FileId.Vnode,
2248 Fcb->ObjectInformation->FileId.Unique);
2250 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2255 AFS_TRACE_LEVEL_VERBOSE,
2256 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2257 Fcb->ObjectInformation->FileId.Cell,
2258 Fcb->ObjectInformation->FileId.Volume,
2259 Fcb->ObjectInformation->FileId.Vnode,
2260 Fcb->ObjectInformation->FileId.Unique,
2264 // Remove the count we added above
2267 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2269 ASSERT( lCount >= 0);
2274 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2279 if( !NT_SUCCESS( ntStatus))
2282 if( pWorkItem != NULL)
2285 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2287 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2290 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2291 AFS_TRACE_LEVEL_ERROR,
2292 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2295 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2300 "EXCEPTION - AFSQueueFlushExtents\n");
2302 AFSDumpTraceFilesFnc();
2309 AFSQueueGlobalRootEnumeration()
2312 NTSTATUS ntStatus = STATUS_SUCCESS;
2313 AFSWorkItem *pWorkItem = NULL;
2318 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2319 sizeof(AFSWorkItem),
2321 if (NULL == pWorkItem)
2324 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2325 AFS_TRACE_LEVEL_ERROR,
2326 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2328 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2331 RtlZeroMemory( pWorkItem,
2332 sizeof(AFSWorkItem));
2334 pWorkItem->Size = sizeof( AFSWorkItem);
2336 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2338 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2339 AFS_TRACE_LEVEL_VERBOSE,
2340 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2343 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2347 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2348 AFS_TRACE_LEVEL_VERBOSE,
2349 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2352 if( !NT_SUCCESS( ntStatus))
2355 if( pWorkItem != NULL)
2358 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2361 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2362 AFS_TRACE_LEVEL_ERROR,
2363 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2367 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2372 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2374 AFSDumpTraceFilesFnc();
2381 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2382 IN UCHAR FunctionCode,
2383 IN ULONG RequestFlags,
2384 IN AFSIoRun *IoRuns,
2386 IN AFSGatherIo *GatherIo)
2389 NTSTATUS ntStatus = STATUS_SUCCESS;
2390 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2391 AFSWorkItem *pWorkItem = NULL;
2396 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2399 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2400 AFS_TRACE_LEVEL_ERROR,
2401 "AFSQueueStartIos Failing request, in shutdown\n");
2403 try_return( ntStatus = STATUS_TOO_LATE);
2407 // Allocate our request structure and send it to the worker
2410 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2411 sizeof( AFSWorkItem),
2414 if( pWorkItem == NULL)
2417 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2418 AFS_TRACE_LEVEL_ERROR,
2419 "AFSQueueStartIos Failed to allocate work item\n");
2421 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2424 RtlZeroMemory( pWorkItem,
2425 sizeof( AFSWorkItem));
2427 KeInitializeEvent( &pWorkItem->Event,
2431 pWorkItem->Size = sizeof( AFSWorkItem);
2433 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2435 pWorkItem->RequestType = AFS_WORK_START_IOS;
2437 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2439 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2441 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2443 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2445 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2447 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2449 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2450 AFS_TRACE_LEVEL_VERBOSE,
2451 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2454 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2458 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2459 AFS_TRACE_LEVEL_VERBOSE,
2460 "AFSQueueStartIos Request complete Status %08lX\n",
2463 if( !NT_SUCCESS( ntStatus))
2466 if( pWorkItem != NULL)
2469 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2473 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2478 "EXCEPTION - AFSQueueStartIos\n");
2480 AFSDumpTraceFilesFnc();
2487 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2488 IN ULONG InvalidateReason)
2491 NTSTATUS ntStatus = STATUS_SUCCESS;
2492 AFSWorkItem *pWorkItem = NULL;
2497 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2498 sizeof(AFSWorkItem),
2500 if (NULL == pWorkItem)
2503 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2504 AFS_TRACE_LEVEL_ERROR,
2505 "AFSQueueInvalidateObject Failed to allocate work item\n");
2507 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2510 RtlZeroMemory( pWorkItem,
2511 sizeof(AFSWorkItem));
2513 pWorkItem->Size = sizeof( AFSWorkItem);
2515 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2517 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2519 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2521 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2522 AFS_TRACE_LEVEL_VERBOSE,
2523 "AFSQueueInvalidateObject Workitem %08lX\n",
2526 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2530 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2531 AFS_TRACE_LEVEL_VERBOSE,
2532 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2535 if( !NT_SUCCESS( ntStatus))
2538 if( pWorkItem != NULL)
2540 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2543 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2544 AFS_TRACE_LEVEL_ERROR,
2545 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2549 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2554 "EXCEPTION - AFSQueueInvalidateObject\n");
2556 AFSDumpTraceFilesFnc();