2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSWorker.cpp
39 #include "AFSCommon.h"
42 // Function: AFSInitializeWorkerPool
46 // This function initializes the worker thread pool
50 // A status is returned for the function
54 AFSInitializeWorkerPool()
57 NTSTATUS ntStatus = STATUS_SUCCESS;
58 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
59 AFSDeviceExt *pDevExt = NULL;
64 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
67 // Initialize the worker threads.
70 pDevExt->Specific.Library.WorkerCount = 0;
72 KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
77 // Initialize the queue resource
80 ExInitializeResourceLite( &pDevExt->Specific.Library.QueueLock);
82 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
85 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
86 sizeof( AFSWorkQueueContext),
89 if( pCurrentWorker == NULL)
92 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
93 AFS_TRACE_LEVEL_ERROR,
94 "AFSInitializeWorkerPool Failed to allocate worker context\n");
96 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
101 RtlZeroMemory( pCurrentWorker,
102 sizeof( AFSWorkQueueContext));
104 ntStatus = AFSInitWorkerThread( pCurrentWorker,
105 (PKSTART_ROUTINE)AFSWorkerThread);
107 if( !NT_SUCCESS( ntStatus))
110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
111 AFS_TRACE_LEVEL_ERROR,
112 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
114 ExFreePool( pCurrentWorker);
119 if( pDevExt->Specific.Library.PoolHead == NULL)
122 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
127 pLastWorker->fLink = pCurrentWorker;
130 pLastWorker = pCurrentWorker;
132 pDevExt->Specific.Library.WorkerCount++;
136 // If there was a failure but there is at least one worker, then go with it.
139 if( !NT_SUCCESS( ntStatus) &&
140 pDevExt->Specific.Library.WorkerCount == 0)
143 try_return( ntStatus);
146 ntStatus = STATUS_SUCCESS;
149 // Now our IO Worker queue
152 pDevExt->Specific.Library.IOWorkerCount = 0;
154 KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
155 SynchronizationEvent,
159 // Initialize the queue resource
162 ExInitializeResourceLite( &pDevExt->Specific.Library.IOQueueLock);
164 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
167 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
168 sizeof( AFSWorkQueueContext),
171 if( pCurrentWorker == NULL)
174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
178 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
183 RtlZeroMemory( pCurrentWorker,
184 sizeof( AFSWorkQueueContext));
186 ntStatus = AFSInitWorkerThread( pCurrentWorker,
187 (PKSTART_ROUTINE)AFSIOWorkerThread);
189 if( !NT_SUCCESS( ntStatus))
192 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
193 AFS_TRACE_LEVEL_ERROR,
194 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
196 ExFreePool( pCurrentWorker);
201 if( pDevExt->Specific.Library.IOPoolHead == NULL)
204 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
209 pLastWorker->fLink = pCurrentWorker;
212 pLastWorker = pCurrentWorker;
214 pDevExt->Specific.Library.IOWorkerCount++;
218 // If there was a failure but there is at least one worker, then go with it.
221 if( !NT_SUCCESS( ntStatus) &&
222 pDevExt->Specific.Library.IOWorkerCount == 0)
225 try_return( ntStatus);
230 if( !NT_SUCCESS( ntStatus))
234 // Failed to initialize the pool so tear it down
237 AFSRemoveWorkerPool();
245 // Function: AFSRemoveWorkerPool
249 // This function tears down the worker thread pool
253 // A status is returned for the function
257 AFSRemoveWorkerPool()
260 NTSTATUS ntStatus = STATUS_SUCCESS;
262 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
263 AFSDeviceExt *pDevExt = NULL;
265 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
268 // Loop through the workers shutting them down in two stages.
269 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
270 // stop processing requests. Second, call AFSShutdownWorkerThread()
271 // to wake the workers and wait for them to exit.
274 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
276 while( index < pDevExt->Specific.Library.WorkerCount)
279 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
281 pCurrentWorker = pCurrentWorker->fLink;
283 if ( pCurrentWorker == NULL)
292 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
296 while( index < pDevExt->Specific.Library.WorkerCount)
299 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
301 pNextWorker = pCurrentWorker->fLink;
303 ExFreePool( pCurrentWorker);
305 pCurrentWorker = pNextWorker;
307 if( pCurrentWorker == NULL)
316 pDevExt->Specific.Library.PoolHead = NULL;
318 ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
321 // Loop through the IO workers shutting them down in two stages.
322 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
323 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
324 // to wake the workers and wait for them to exit.
327 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
331 while( index < pDevExt->Specific.Library.IOWorkerCount)
334 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
336 pCurrentWorker = pCurrentWorker->fLink;
338 if ( pCurrentWorker == NULL)
347 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
351 while( index < pDevExt->Specific.Library.IOWorkerCount)
354 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
356 pNextWorker = pCurrentWorker->fLink;
358 ExFreePool( pCurrentWorker);
360 pCurrentWorker = pNextWorker;
362 if( pCurrentWorker == NULL)
371 pDevExt->Specific.Library.IOPoolHead = NULL;
373 ExDeleteResourceLite( &pDevExt->Specific.Library.IOQueueLock);
379 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
382 NTSTATUS ntStatus = STATUS_SUCCESS;
383 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
385 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
386 PKSTART_ROUTINE pStartRoutine = NULL;
392 if ( VolumeCB != AFSGlobalRoot)
395 return STATUS_INVALID_PARAMETER;
398 pStartRoutine = AFSPrimaryVolumeWorkerThread;
401 // Initialize the worker thread
404 KeInitializeEvent( &pWorker->WorkerThreadReady,
409 // Set the worker to process requests
412 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
418 ntStatus = PsCreateSystemThread( &hThread,
426 if( NT_SUCCESS( ntStatus))
429 ObReferenceObjectByHandle( hThread,
430 GENERIC_READ | GENERIC_WRITE,
433 (PVOID *)&pWorker->WorkerThreadObject,
436 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
442 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
447 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
458 // Function: AFSInitWorkerThread
462 // This function initializes a worker thread in the pool
466 // A status is returned for the function
470 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
471 IN PKSTART_ROUTINE WorkerRoutine)
474 NTSTATUS ntStatus = STATUS_SUCCESS;
478 // INitialize the worker signal thread
481 KeInitializeEvent( &PoolContext->WorkerThreadReady,
486 // Set the worker to process requests
489 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
495 ntStatus = PsCreateSystemThread( &Handle,
501 (void *)PoolContext);
503 if( NT_SUCCESS( ntStatus))
506 ObReferenceObjectByHandle( Handle,
507 GENERIC_READ | GENERIC_WRITE,
510 (PVOID *)&PoolContext->WorkerThreadObject,
513 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
526 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
529 NTSTATUS ntStatus = STATUS_SUCCESS;
530 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
533 // Clear the 'keep processing' flag
536 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
538 if( pWorker->WorkerThreadObject != NULL)
540 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
543 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
550 ObDereferenceObject( pWorker->WorkerThreadObject);
552 pWorker->WorkerThreadObject = NULL;
559 // Function: AFSShutdownWorkerThread
563 // This function shutsdown a worker thread in the pool
567 // A status is returned for the function
571 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
574 NTSTATUS ntStatus = STATUS_SUCCESS;
575 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
577 if( PoolContext->WorkerThreadObject != NULL)
580 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
584 // Wake up the thread if it is a sleep
587 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
591 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
598 ObDereferenceObject( PoolContext->WorkerThreadObject);
600 PoolContext->WorkerThreadObject = NULL;
607 // Function: AFSShutdownIOWorkerThread
611 // This function shutsdown an IO worker thread in the pool
615 // A status is returned for the function
619 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
622 NTSTATUS ntStatus = STATUS_SUCCESS;
623 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
625 if( PoolContext->WorkerThreadObject != NULL)
628 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
632 // Wake up the thread if it is a sleep
635 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
639 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
646 ObDereferenceObject( PoolContext->WorkerThreadObject);
648 PoolContext->WorkerThreadObject = NULL;
655 // Function: AFSWorkerThread
659 // This is the worker thread entry point.
663 // A status is returned for the function
667 AFSWorkerThread( IN PVOID Context)
670 NTSTATUS ntStatus = STATUS_SUCCESS;
671 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
672 AFSWorkItem *pWorkItem;
673 BOOLEAN freeWorkItem = TRUE;
674 AFSDeviceExt *pLibraryDevExt = NULL;
677 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
680 // Indicate that we are initialized and ready
683 KeSetEvent( &pPoolContext->WorkerThreadReady,
688 // Indicate we are initialized
691 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
693 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
699 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
702 if( !NT_SUCCESS( ntStatus))
705 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
706 AFS_TRACE_LEVEL_ERROR,
707 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
709 ntStatus = STATUS_SUCCESS;
714 pWorkItem = AFSRemoveWorkItem();
716 if( pWorkItem == NULL)
719 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
731 // Switch on the type of work item to process
734 switch( pWorkItem->RequestType)
737 case AFS_WORK_FLUSH_FCB:
740 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
741 &pWorkItem->AuthGroup);
743 if( !NT_SUCCESS( ntStatus))
746 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
747 &pWorkItem->AuthGroup,
751 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
753 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
758 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
761 AFSEnumerateGlobalRoot( NULL);
766 case AFS_WORK_INVALIDATE_OBJECT:
769 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
770 pWorkItem->Specific.Invalidate.InvalidateReason);
777 case AFS_WORK_START_IOS:
787 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
788 AFS_TRACE_LEVEL_ERROR,
789 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
797 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
800 ntStatus = STATUS_SUCCESS;
803 } // worker thread loop
805 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
807 // Wake up another worker so they too can exit
809 KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
813 PsTerminateSystemThread( 0);
819 AFSIOWorkerThread( IN PVOID Context)
822 NTSTATUS ntStatus = STATUS_SUCCESS;
823 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
824 AFSWorkItem *pWorkItem;
825 BOOLEAN freeWorkItem = TRUE;
826 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
828 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
831 // Indicate that we are initialized and ready
834 KeSetEvent( &pPoolContext->WorkerThreadReady,
840 // Indicate we are initialized
843 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
845 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
851 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
854 if( !NT_SUCCESS( ntStatus))
857 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
858 AFS_TRACE_LEVEL_ERROR,
859 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
861 ntStatus = STATUS_SUCCESS;
866 pWorkItem = AFSRemoveIOWorkItem();
868 if( pWorkItem == NULL)
871 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
883 // Switch on the type of work item to process
886 switch( pWorkItem->RequestType)
889 case AFS_WORK_START_IOS:
892 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
895 // The final status is in the gather io
898 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
899 pWorkItem->Specific.CacheAccess.FunctionCode,
900 pWorkItem->Specific.CacheAccess.RequestFlags,
901 pWorkItem->Specific.CacheAccess.IoRuns,
902 pWorkItem->Specific.CacheAccess.RunCount,
903 pWorkItem->Specific.CacheAccess.GatherIo);
906 // Regardless of the status we we do the complete - there may
908 // Decrement the count - setting the event if we were told
909 // to. This may trigger completion.
912 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
922 AFS_TRACE_LEVEL_ERROR,
923 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
931 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
934 ntStatus = STATUS_SUCCESS;
937 } // worker thread loop
939 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
941 // Wake up another IOWorker so they too can exit
943 KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
947 PsTerminateSystemThread( 0);
953 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
956 UNREFERENCED_PARAMETER(Context);
957 NTSTATUS ntStatus = STATUS_SUCCESS;
958 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
959 AFSDeviceExt *pControlDeviceExt = NULL;
960 AFSDeviceExt *pRDRDeviceExt = NULL;
961 LARGE_INTEGER DueTime;
964 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
965 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
966 BOOLEAN bReleaseVolumeLock = FALSE;
967 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
969 LARGE_INTEGER liCurrentTime;
970 BOOLEAN bVolumeObject = FALSE;
971 BOOLEAN bFcbBusy = FALSE;
974 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
976 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
978 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
979 AFS_TRACE_LEVEL_VERBOSE,
980 "AFSPrimaryVolumeWorkerThread Initialized\n");
983 // Initialize the timer for the worker thread
986 DueTime.QuadPart = -(5000);
990 KeInitializeTimerEx( &Timer,
991 SynchronizationTimer);
993 KeSetTimerEx( &Timer,
999 // Indicate that we are initialized and ready
1002 KeSetEvent( &pPoolContext->WorkerThreadReady,
1007 // Indicate we are initialized
1010 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1012 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1015 if ( bFcbBusy == FALSE)
1018 KeWaitForSingleObject( &Timer,
1031 // This is the primary volume worker so it will traverse the volume list
1032 // looking for cleanup or volumes requiring private workers
1035 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1038 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1040 while( pVolumeCB != NULL)
1043 if( pVolumeCB == AFSGlobalRoot ||
1044 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1048 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1053 if( pVolumeCB->ObjectInfoListHead == NULL)
1056 AFSReleaseResource( pVolumeCB->VolumeLock);
1058 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1060 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1063 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1066 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1070 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1072 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1074 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1079 KeQueryTickCount( &liCurrentTime);
1081 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1083 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1086 if( pVolumeCB->ObjectInfoListHead == NULL &&
1087 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1088 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1089 pVolumeCB->VolumeReferenceCount == 1 &&
1090 ( pVolumeCB->RootFcb == NULL ||
1091 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1092 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1095 if( pVolumeCB->RootFcb != NULL)
1098 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1101 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1103 AFSRemoveVolume( pVolumeCB);
1108 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1110 AFSReleaseResource( pVolumeCB->VolumeLock);
1113 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1115 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1117 pVolumeCB = pNextVolume;
1123 // Don't need this lock anymore now that we have a volume cb to work with
1126 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1129 // For now we only need the volume lock shared
1132 AFSConvertToShared( pVolumeCB->VolumeLock);
1134 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1138 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1142 bReleaseVolumeLock = TRUE;
1144 while( pCurrentObject != NULL)
1147 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1150 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1152 if( pNextObject == NULL &&
1153 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1156 pNextObject = &pVolumeCB->ObjectInformation;
1159 bVolumeObject = FALSE;
1166 bVolumeObject = TRUE;
1169 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1170 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1174 // If this object is deleted then remove it from the parent, if we can
1177 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1178 pCurrentObject->ObjectReferenceCount <= 0 &&
1179 ( pCurrentObject->Fcb == NULL ||
1180 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1181 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1182 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1185 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1188 // Dropping the TreeLock permits the
1189 // pCurrentObject->ObjectReferenceCount to change
1192 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1196 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1199 if ( pCurrentObject->ObjectReferenceCount <= 0)
1202 AFSRemoveFcb( &pCurrentObject->Fcb);
1204 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1207 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1210 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1212 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1214 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1216 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1218 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1220 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1223 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1225 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1226 AFS_TRACE_LEVEL_VERBOSE,
1227 "AFSPrimaryVolumeWorkerThread Deleting deleted object %p\n",
1230 AFSDeleteObjectInfo( pCurrentObject);
1235 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1238 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1240 pCurrentObject = pNextObject;
1247 bReleaseVolumeLock = FALSE;
1253 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1254 ( pCurrentObject->Fcb != NULL &&
1255 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1256 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1259 pCurrentObject = pNextObject;
1264 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1268 pCurrentObject = pNextObject;
1273 KeQueryTickCount( &liCurrentTime);
1275 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1277 while( pCurrentDirEntry != NULL)
1280 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1281 pCurrentDirEntry->NameArrayReferenceCount > 0 ||
1282 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1283 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1284 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1285 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1286 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1287 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1288 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1289 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1290 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1291 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1292 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1298 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1301 if( pCurrentDirEntry != NULL)
1304 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1306 pCurrentObject = pNextObject;
1311 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1313 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1316 // Now acquire the locks excl
1319 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1323 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1327 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1330 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1332 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1334 pCurrentObject = pNextObject;
1339 KeQueryTickCount( &liCurrentTime);
1341 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1343 while( pCurrentDirEntry != NULL)
1346 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1347 pCurrentDirEntry->NameArrayReferenceCount > 0 ||
1348 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1349 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1350 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1351 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1352 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1353 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1354 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1355 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1356 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1357 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1358 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1364 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1367 if( pCurrentDirEntry != NULL)
1370 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1372 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1374 pCurrentObject = pNextObject;
1379 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1381 while( pCurrentDirEntry != NULL)
1384 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1386 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1390 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1391 AFS_TRACE_LEVEL_VERBOSE,
1392 "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %p\n",
1393 &pCurrentDirEntry->NameInformation.FileName,
1394 pCurrentChildObject);
1396 AFSDeleteDirEntry( pCurrentObject,
1401 // Acquire ObjectInfoLock shared here so as not to deadlock
1402 // with an invalidation call from the service during AFSCleanupFcb
1405 lCount = AFSObjectInfoIncrement( pCurrentChildObject,
1406 AFS_OBJECT_REFERENCE_WORKER);
1408 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1409 AFS_TRACE_LEVEL_VERBOSE,
1410 "AFSPrimaryVolumeWorkerThread Increment count on object %p Cnt %d\n",
1411 pCurrentChildObject,
1415 pCurrentChildObject->Fcb != NULL &&
1416 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1420 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
1421 // across an AFSCleanupFcb call since it can deadlock with an
1422 // invalidation call from the service.
1425 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1428 // Cannot hold a TreeLock across an AFSCleanupFcb call
1429 // as it can deadlock with an invalidation ioctl initiated
1430 // from the service.
1432 // Dropping the TreeLock permits the
1433 // pCurrentObject->ObjectReferenceCount to change
1436 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1439 if ( ntStatus == STATUS_RETRY)
1445 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1449 lCount = AFSObjectInfoDecrement( pCurrentChildObject,
1450 AFS_OBJECT_REFERENCE_WORKER);
1452 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1453 AFS_TRACE_LEVEL_VERBOSE,
1454 "AFSPrimaryVolumeWorkerThread Decrement1 count on object %p Cnt %d\n",
1455 pCurrentChildObject,
1458 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1461 if( pCurrentChildObject->ObjectReferenceCount <= 0)
1464 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1466 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1467 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1470 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1473 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1475 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1477 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1479 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1481 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1483 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1486 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1488 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1489 AFS_TRACE_LEVEL_VERBOSE,
1490 "AFSPrimaryVolumeWorkerThread Deleting object %p\n",
1491 pCurrentChildObject);
1493 AFSDeleteObjectInfo( pCurrentChildObject);
1498 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1501 pCurrentDirEntry = pNextDirEntry;
1505 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1507 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1509 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1511 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1513 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1515 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1517 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1518 AFS_TRACE_LEVEL_VERBOSE,
1519 "AFSPrimaryVolumeWorkerThread Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1520 pCurrentObject->FileId.Cell,
1521 pCurrentObject->FileId.Volume,
1522 pCurrentObject->FileId.Vnode,
1523 pCurrentObject->FileId.Unique);
1526 // Clear our enumerated flag on this object so we retrieve info again on next access
1529 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1531 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1533 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1538 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1540 bReleaseVolumeLock = FALSE;
1549 // Try to grab the volume lock again ... no problem if we don't
1552 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1556 bReleaseVolumeLock = FALSE;
1562 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1565 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1567 if( pCurrentObject == NULL &&
1568 pVolumeCB != AFSGlobalRoot)
1571 pCurrentObject = &pVolumeCB->ObjectInformation;
1577 pCurrentObject = NULL;
1582 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1585 lCount = AFSObjectInfoIncrement( pCurrentObject,
1586 AFS_OBJECT_REFERENCE_WORKER);
1588 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1589 AFS_TRACE_LEVEL_VERBOSE,
1590 "AFSPrimaryVolumeWorkerThread Increment2 count on object %p Cnt %d\n",
1594 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1596 if( pCurrentObject->Fcb != NULL)
1600 // Dropping the TreeLock permits the
1601 // pCurrentObject->ObjectReferenceCount to change
1604 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1607 if ( ntStatus == STATUS_RETRY)
1614 lCount = AFSObjectInfoDecrement( pCurrentObject,
1615 AFS_OBJECT_REFERENCE_WORKER);
1617 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1618 AFS_TRACE_LEVEL_VERBOSE,
1619 "AFSPrimaryVolumeWorkerThread Decrement2 count on object %p Cnt %d\n",
1623 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1627 bReleaseVolumeLock = FALSE;
1632 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1635 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1636 pCurrentObject->ObjectReferenceCount <= 0)
1639 AFSRemoveFcb( &pCurrentObject->Fcb);
1641 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1643 AFSDeleteObjectInfo( pCurrentObject);
1648 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1651 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1653 pCurrentObject = pNextObject;
1658 pCurrentObject = pNextObject;
1661 if( bReleaseVolumeLock)
1664 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1672 AFSReleaseResource( pVolumeCB->VolumeLock);
1674 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1677 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1680 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1682 } // worker thread loop
1684 KeCancelTimer( &Timer);
1686 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1688 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1689 AFS_TRACE_LEVEL_VERBOSE,
1690 "AFSPrimaryVolumeWorkerThread Exiting\n");
1692 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1697 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1702 PsTerminateSystemThread( 0);
1708 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1711 NTSTATUS ntStatus = STATUS_SUCCESS;
1712 AFSDeviceExt *pDevExt = NULL;
1715 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1717 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1718 AFS_TRACE_LEVEL_VERBOSE,
1719 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1720 &pDevExt->Specific.Library.QueueLock,
1721 PsGetCurrentThread());
1723 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1726 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1728 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1729 AFS_TRACE_LEVEL_VERBOSE,
1730 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1734 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1737 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1742 pDevExt->Specific.Library.QueueHead = WorkItem;
1745 WorkItem->next = NULL;
1746 pDevExt->Specific.Library.QueueTail = WorkItem;
1748 // indicate that the queue has nodes
1749 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1753 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1759 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1762 NTSTATUS ntStatus = STATUS_SUCCESS;
1763 AFSDeviceExt *pDevExt = NULL;
1766 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1768 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1769 AFS_TRACE_LEVEL_VERBOSE,
1770 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1771 &pDevExt->Specific.Library.IOQueueLock,
1772 PsGetCurrentThread());
1774 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1777 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
1779 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1780 AFS_TRACE_LEVEL_VERBOSE,
1781 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
1785 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1788 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1793 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1796 WorkItem->next = NULL;
1797 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1799 // indicate that the queue has nodes
1800 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1804 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1810 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1813 NTSTATUS ntStatus = STATUS_SUCCESS;
1814 AFSDeviceExt *pDevExt = NULL;
1817 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1819 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1820 AFS_TRACE_LEVEL_VERBOSE,
1821 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
1822 &pDevExt->Specific.Library.QueueLock,
1823 PsGetCurrentThread());
1825 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1828 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1830 pDevExt->Specific.Library.QueueHead = WorkItem;
1832 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1834 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1835 AFS_TRACE_LEVEL_VERBOSE,
1836 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
1841 // indicate that the queue has nodes
1844 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1848 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1857 AFSWorkItem *pWorkItem = NULL;
1858 AFSDeviceExt *pDevExt = NULL;
1861 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1866 &pDevExt->Specific.Library.QueueLock,
1867 PsGetCurrentThread());
1869 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1872 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1875 pWorkItem = pDevExt->Specific.Library.QueueHead;
1877 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
1879 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1880 AFS_TRACE_LEVEL_VERBOSE,
1881 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
1884 PsGetCurrentThreadId());
1886 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1888 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1891 pDevExt->Specific.Library.QueueTail = NULL;
1897 // Wake up another worker
1900 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1906 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1912 AFSRemoveIOWorkItem()
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 %p 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 %p Count %d 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 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1977 // Submit the work item to the worker
1980 ntStatus = AFSInsertWorkitem( WorkItem);
1986 // Sync request so block on the work item event
1989 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2000 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2003 NTSTATUS ntStatus = STATUS_SUCCESS;
2004 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2007 // Submit the work item to the worker
2010 ntStatus = AFSInsertIOWorkitem( WorkItem);
2016 // Sync request so block on the work item event
2019 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2030 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2033 NTSTATUS ntStatus = STATUS_SUCCESS;
2034 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2037 // Submit the work item to the worker
2040 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2046 // Sync request so block on the work item event
2049 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2060 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2064 NTSTATUS ntStatus = STATUS_SUCCESS;
2065 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2066 AFSWorkItem *pWorkItem = NULL;
2072 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2073 AFS_TRACE_LEVEL_VERBOSE,
2074 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2075 Fcb->ObjectInformation->FileId.Cell,
2076 Fcb->ObjectInformation->FileId.Volume,
2077 Fcb->ObjectInformation->FileId.Vnode,
2078 Fcb->ObjectInformation->FileId.Unique);
2081 // Increment our flush count here just to keep the number of items in the
2082 // queue down. We'll decrement it just below.
2085 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2090 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2091 AFS_TRACE_LEVEL_VERBOSE,
2092 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2093 Fcb->ObjectInformation->FileId.Cell,
2094 Fcb->ObjectInformation->FileId.Volume,
2095 Fcb->ObjectInformation->FileId.Vnode,
2096 Fcb->ObjectInformation->FileId.Unique);
2098 try_return( ntStatus);
2101 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2104 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2105 AFS_TRACE_LEVEL_ERROR,
2106 "AFSQueueFlushExtents Failing request, in shutdown\n");
2108 try_return( ntStatus = STATUS_TOO_LATE);
2112 // Allocate our request structure and send it to the worker
2115 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2116 sizeof( AFSWorkItem),
2119 if( pWorkItem == NULL)
2122 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2123 AFS_TRACE_LEVEL_ERROR,
2124 "AFSQueueFlushExtents Failed to allocate work item\n");
2126 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2129 RtlZeroMemory( pWorkItem,
2130 sizeof( AFSWorkItem));
2132 pWorkItem->Size = sizeof( AFSWorkItem);
2134 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2136 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2138 if ( AuthGroup == NULL)
2141 RtlZeroMemory( &pWorkItem->AuthGroup,
2144 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2147 &pWorkItem->AuthGroup);
2151 RtlCopyMemory( &pWorkItem->AuthGroup,
2156 pWorkItem->Specific.Fcb.Fcb = Fcb;
2158 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2160 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2161 AFS_TRACE_LEVEL_VERBOSE,
2162 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2166 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2167 AFS_TRACE_LEVEL_VERBOSE,
2168 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2170 Fcb->ObjectInformation->FileId.Cell,
2171 Fcb->ObjectInformation->FileId.Volume,
2172 Fcb->ObjectInformation->FileId.Vnode,
2173 Fcb->ObjectInformation->FileId.Unique);
2175 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2179 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2180 AFS_TRACE_LEVEL_VERBOSE,
2181 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2182 Fcb->ObjectInformation->FileId.Cell,
2183 Fcb->ObjectInformation->FileId.Volume,
2184 Fcb->ObjectInformation->FileId.Vnode,
2185 Fcb->ObjectInformation->FileId.Unique,
2189 // Remove the count we added above
2192 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2194 ASSERT( lCount >= 0);
2199 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2204 if( !NT_SUCCESS( ntStatus))
2207 if( pWorkItem != NULL)
2210 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2212 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2215 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2216 AFS_TRACE_LEVEL_ERROR,
2217 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2220 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2225 "EXCEPTION - AFSQueueFlushExtents\n");
2227 AFSDumpTraceFilesFnc();
2234 AFSQueueGlobalRootEnumeration()
2237 NTSTATUS ntStatus = STATUS_SUCCESS;
2238 AFSWorkItem *pWorkItem = NULL;
2243 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2244 sizeof(AFSWorkItem),
2246 if (NULL == pWorkItem)
2249 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2250 AFS_TRACE_LEVEL_ERROR,
2251 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2253 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2256 RtlZeroMemory( pWorkItem,
2257 sizeof(AFSWorkItem));
2259 pWorkItem->Size = sizeof( AFSWorkItem);
2261 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2263 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2264 AFS_TRACE_LEVEL_VERBOSE,
2265 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2268 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2272 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2273 AFS_TRACE_LEVEL_VERBOSE,
2274 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2277 if( !NT_SUCCESS( ntStatus))
2280 if( pWorkItem != NULL)
2283 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2286 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2287 AFS_TRACE_LEVEL_ERROR,
2288 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2292 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2297 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2299 AFSDumpTraceFilesFnc();
2306 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2307 IN UCHAR FunctionCode,
2308 IN ULONG RequestFlags,
2309 IN AFSIoRun *IoRuns,
2311 IN AFSGatherIo *GatherIo)
2314 NTSTATUS ntStatus = STATUS_SUCCESS;
2315 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2316 AFSWorkItem *pWorkItem = NULL;
2321 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2324 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2325 AFS_TRACE_LEVEL_ERROR,
2326 "AFSQueueStartIos Failing request, in shutdown\n");
2328 try_return( ntStatus = STATUS_TOO_LATE);
2332 // Allocate our request structure and send it to the worker
2335 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2336 sizeof( AFSWorkItem),
2339 if( pWorkItem == NULL)
2342 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2343 AFS_TRACE_LEVEL_ERROR,
2344 "AFSQueueStartIos Failed to allocate work item\n");
2346 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2349 RtlZeroMemory( pWorkItem,
2350 sizeof( AFSWorkItem));
2352 KeInitializeEvent( &pWorkItem->Event,
2356 pWorkItem->Size = sizeof( AFSWorkItem);
2358 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2360 pWorkItem->RequestType = AFS_WORK_START_IOS;
2362 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2364 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2366 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2368 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2370 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2372 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2374 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2375 AFS_TRACE_LEVEL_VERBOSE,
2376 "AFSQueueStartIos Queuing IO Workitem %p\n",
2379 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2383 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2384 AFS_TRACE_LEVEL_VERBOSE,
2385 "AFSQueueStartIos Request complete Status %08lX\n",
2388 if( !NT_SUCCESS( ntStatus))
2391 if( pWorkItem != NULL)
2394 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2398 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2403 "EXCEPTION - AFSQueueStartIos\n");
2405 AFSDumpTraceFilesFnc();
2412 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2413 IN ULONG InvalidateReason)
2416 NTSTATUS ntStatus = STATUS_SUCCESS;
2417 AFSWorkItem *pWorkItem = NULL;
2422 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2423 sizeof(AFSWorkItem),
2425 if (NULL == pWorkItem)
2428 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2429 AFS_TRACE_LEVEL_ERROR,
2430 "AFSQueueInvalidateObject Failed to allocate work item\n");
2432 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2435 RtlZeroMemory( pWorkItem,
2436 sizeof(AFSWorkItem));
2438 pWorkItem->Size = sizeof( AFSWorkItem);
2440 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2442 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2444 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2446 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2447 AFS_TRACE_LEVEL_VERBOSE,
2448 "AFSQueueInvalidateObject Workitem %p\n",
2451 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2455 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2456 AFS_TRACE_LEVEL_VERBOSE,
2457 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2460 if( !NT_SUCCESS( ntStatus))
2463 if( pWorkItem != NULL)
2465 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2468 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2469 AFS_TRACE_LEVEL_ERROR,
2470 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2474 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2479 "EXCEPTION - AFSQueueInvalidateObject\n");
2481 AFSDumpTraceFilesFnc();